From 5159b9c0a54e66b1402fa02acfc5fb3f9bb4e131 Mon Sep 17 00:00:00 2001 From: Jason Lee Date: Mon, 18 Nov 2024 15:40:20 -0600 Subject: [PATCH] Add TLS support Add configuration constants for property names Move constants to a holder class Port HttpClientOptionsConsumer from Quarkus Modify HCOP to use ConfigProperties General code cleanup --- .../AbstractVertxExporterProvider.java | 126 +++------------- .../implementation/exporters/Constants.java | 47 ++++++ .../exporters/HttpClientOptionsConsumer.java | 141 ++++++++++++++++++ .../exporters/OtlpExporterUtil.java | 91 +++++++++-- .../logs/VertxLogsExporterProvider.java | 7 +- .../metrics/VertxMetricsExporterProvider.java | 10 +- .../exporters/sender/VertxGrpcSender.java | 47 +----- .../exporters/sender/VertxHttpSender.java | 2 + .../traces/VertxSpanExporterProvider.java | 7 +- .../exporters/VertxExportersTest.java | 10 +- 10 files changed, 320 insertions(+), 168 deletions(-) create mode 100644 implementation/exporters/src/main/java/io/smallrye/opentelemetry/implementation/exporters/Constants.java create mode 100644 implementation/exporters/src/main/java/io/smallrye/opentelemetry/implementation/exporters/HttpClientOptionsConsumer.java diff --git a/implementation/exporters/src/main/java/io/smallrye/opentelemetry/implementation/exporters/AbstractVertxExporterProvider.java b/implementation/exporters/src/main/java/io/smallrye/opentelemetry/implementation/exporters/AbstractVertxExporterProvider.java index 310bcff3..971aff73 100644 --- a/implementation/exporters/src/main/java/io/smallrye/opentelemetry/implementation/exporters/AbstractVertxExporterProvider.java +++ b/implementation/exporters/src/main/java/io/smallrye/opentelemetry/implementation/exporters/AbstractVertxExporterProvider.java @@ -1,13 +1,17 @@ package io.smallrye.opentelemetry.implementation.exporters; -import static io.smallrye.opentelemetry.implementation.exporters.OtlpExporterUtil.OTEL_EXPORTER_OTLP_ENDPOINT; -import static io.smallrye.opentelemetry.implementation.exporters.OtlpExporterUtil.OTLP_GRPC_ENDPOINT; -import static io.smallrye.opentelemetry.implementation.exporters.OtlpExporterUtil.OTLP_HTTP_PROTOBUF_ENDPOINT; -import static io.smallrye.opentelemetry.implementation.exporters.OtlpExporterUtil.PROTOCOL_GRPC; +import static io.smallrye.opentelemetry.implementation.exporters.Constants.MIMETYPE_PROTOBUF; +import static io.smallrye.opentelemetry.implementation.exporters.Constants.OTEL_EXPORTER_OTLP_ENDPOINT; +import static io.smallrye.opentelemetry.implementation.exporters.Constants.OTEL_EXPORTER_OTLP_SIGNAL_ENDPOINT; +import static io.smallrye.opentelemetry.implementation.exporters.Constants.OTEL_EXPORTER_VERTX_CDI_QUALIFIER; +import static io.smallrye.opentelemetry.implementation.exporters.Constants.OTLP_GRPC_ENDPOINT; +import static io.smallrye.opentelemetry.implementation.exporters.Constants.OTLP_HTTP_PROTOBUF_ENDPOINT; +import static io.smallrye.opentelemetry.implementation.exporters.OtlpExporterUtil.getCompression; +import static io.smallrye.opentelemetry.implementation.exporters.OtlpExporterUtil.getOtlpEndpoint; +import static io.smallrye.opentelemetry.implementation.exporters.OtlpExporterUtil.getTimeout; import java.net.URI; import java.net.URISyntaxException; -import java.time.Duration; import java.util.logging.Level; import java.util.logging.Logger; @@ -25,26 +29,11 @@ import io.vertx.core.Vertx; public abstract class AbstractVertxExporterProvider { - private static final String OTEL_EXPORTER_OTLP_PROTOCOL = "otel.exporter.otlp.protocol"; - private static final String OTEL_EXPORTER_OTLP_SIGNAL_PROTOCOL = "otel.exporter.otlp.%s.protocol"; - - private static final String OTEL_EXPORTER_OTLP_TIMEOUT = "otel.exporter.otlp.timeout"; - private static final String OTEL_EXPORTER_OTLP_SIGNAL_TIMEOUT = "otel.exporter.otlp.%s.timeout"; - - private static final String OTEL_EXPORTER_OTLP_SIGNAL_ENDPOINT = "otel.exporter.otlp.%s.endpoint"; - - private static final String OTEL_EXPORTER_OTLP_COMPRESSION = "otel.exporter.otlp.compression"; - private static final String OTEL_EXPORTER_OTLP_SIGNAL_COMPRESSION = "otel.exporter.otlp.%s.compression"; - - private static final String MIMETYPE_PROTOBUF = "application/x-protobuf"; - - private static final String OTEL_EXPORTER_VERTX_CDI_QUALIFIER = "otel.exporter.vertx.cdi.identifier"; - - private static final Logger logger = Logger.getLogger(AbstractVertxExporterProvider.class.getName()); - private final String signalType; private final String exporterName; + private static final Logger logger = Logger.getLogger(AbstractVertxExporterProvider.class.getName()); + public AbstractVertxExporterProvider(String signalType, String exporterName) { this.signalType = signalType; this.exporterName = exporterName; @@ -88,23 +77,28 @@ private Vertx getVertx(ConfigProperties config) { } protected VertxGrpcSender createGrpcSender(ConfigProperties config, String grpcEndpointPath) throws URISyntaxException { + URI baseUri = new URI(getOtlpEndpoint(config, OTLP_GRPC_ENDPOINT, signalType)); return new VertxGrpcSender<>( - new URI(getOtlpEndpoint(config, OTLP_GRPC_ENDPOINT)), + signalType, + baseUri, grpcEndpointPath, - getCompression(config), - getTimeout(config), + getCompression(config, signalType), + getTimeout(config, signalType), OtlpExporterUtil.populateTracingExportHttpHeaders(), + new HttpClientOptionsConsumer(config, baseUri, signalType), getVertx(config)); } protected VertxHttpSender createHttpSender(ConfigProperties config, String httpEndpointPath) throws URISyntaxException { + URI baseUri = new URI(getOtlpEndpoint(config, OTLP_HTTP_PROTOBUF_ENDPOINT, signalType)); return new VertxHttpSender( - new URI(getOtlpEndpoint(config, OTLP_HTTP_PROTOBUF_ENDPOINT)), + baseUri, httpEndpointPath, - getCompression(config), - getTimeout(config), + getCompression(config, signalType), + getTimeout(config, signalType), OtlpExporterUtil.populateTracingExportHttpHeaders(), MIMETYPE_PROTOBUF, + new HttpClientOptionsConsumer(config, baseUri, signalType), getVertx(config)); } @@ -114,80 +108,4 @@ protected IllegalArgumentException buildUnsupportedProtocolException(String prot return new IllegalArgumentException(String.format("Unsupported OTLP protocol %s specified. ", protocol) + String.format("Please check the `%s` and/or '%s' properties", signalProperty, OTEL_EXPORTER_OTLP_ENDPOINT)); } - - /** - * Given the OpenTelemetry config, lookup a value using the given keys, stopping with the first non-null value. If - * no keys are found, return the defaultValue. Since the OpenTelemetry API offers signal-specific settings, as well - * as one overarching property key for a variety of configuration options, this allows the caller to specify - * signal-specific keys to search, then defaulting to the "top-level" property, then finally defaulting to a - * SmallRye-specific default value. - * - * @param config OpenTelemetry config - * @param defaultValue The default value for the property. - * @param keys The keys to iterate over - * @return either the configured or default value - */ - protected String getConfig(ConfigProperties config, String defaultValue, String... keys) { - String value = null; - for (String key : keys) { - value = config.getString(key); - if (value != null) { - break; - } - } - - return value != null ? value : defaultValue; - } - - /** - * Determine the wire protocol for sending signal data to the remote - * - * @param config OpenTelemetry configuration - * @return either the configured or default value - */ - protected String getProtocol(ConfigProperties config) { - // The otel API uses "span" and "traces" in various places, so we need to modify that case here - String signalKey = signalType.replace("span", "traces"); - - return getConfig(config, PROTOCOL_GRPC, - String.format(OTEL_EXPORTER_OTLP_SIGNAL_PROTOCOL, signalKey), OTEL_EXPORTER_OTLP_PROTOCOL); - } - - /** - * Determine whether to enable compression - * - * @param config OpenTelemetry configuration - * @return either the configured or default value - */ - protected boolean getCompression(ConfigProperties config) { - return Boolean.parseBoolean(getConfig(config, "true", - String.format(OTEL_EXPORTER_OTLP_SIGNAL_COMPRESSION, signalType), - OTEL_EXPORTER_OTLP_COMPRESSION)); - } - - /** - * Return timeout, in seconds, for sending data to the remote - * - * @param config OpenTelemetry configuration - * @return either the configured or default value - */ - protected Duration getTimeout(ConfigProperties config) { - return Duration.ofSeconds(Integer.parseInt( - getConfig(config, "10", - String.format(OTEL_EXPORTER_OTLP_SIGNAL_TIMEOUT, signalType), OTEL_EXPORTER_OTLP_TIMEOUT))); - } - - /** - * Gets the OTLP traces endpoint, if defined. If it is not, it returns the OTLP endpoint. If that is not defined, - * it returns defaultEndpoint. - * - * @param config OpenTelemetry configuration - * @param defaultEndpoint The default endpoint for the desired protocol - * @return either the configured or default value - */ - protected String getOtlpEndpoint(ConfigProperties config, String defaultEndpoint) { - return getConfig(config, defaultEndpoint, - String.format(OTEL_EXPORTER_OTLP_SIGNAL_ENDPOINT, signalType), - OTEL_EXPORTER_OTLP_ENDPOINT); - } } diff --git a/implementation/exporters/src/main/java/io/smallrye/opentelemetry/implementation/exporters/Constants.java b/implementation/exporters/src/main/java/io/smallrye/opentelemetry/implementation/exporters/Constants.java new file mode 100644 index 00000000..a820e14f --- /dev/null +++ b/implementation/exporters/src/main/java/io/smallrye/opentelemetry/implementation/exporters/Constants.java @@ -0,0 +1,47 @@ +package io.smallrye.opentelemetry.implementation.exporters; + +public class Constants { + private Constants() { + } + + public static final String PROTOCOL_GRPC = "grpc"; + public static final String PROTOCOL_HTTP_PROTOBUF = "http/protobuf"; + + public static final String OTLP_GRPC_ENDPOINT = "http://localhost:4317"; + public static final String OTLP_HTTP_PROTOBUF_ENDPOINT = "http://localhost:4318"; + + public static final String OTEL_EXPORTER_OTLP_ENDPOINT = "otel.exporter.otlp.endpoint"; + public static final String OTEL_EXPORTER_OTLP_TRACES_PROTOCOL = "otel.exporter.otlp.traces.protocol"; + + static final String OTEL_EXPORTER_VERTX_CDI_QUALIFIER = "otel.exporter.vertx.cdi.identifier"; + + static final String OTEL_EXPORTER_OTLP_CERTIFICATE = "otel.exporter.otlp.certificate"; + static final String OTEL_EXPORTER_OTLP_SIGNAL_CERTIFICATE = "otel.exporter.otlp.%s.certificate"; + + static final String OTEL_EXPORTER_OTLP_CLIENT_KEY = "otel.exporter.otlp.client.key"; + static final String OTEL_EXPORTER_OTLP_SIGNAL_CLIENT_KEY = "otel.exporter.otlp.%s.client.key"; + + static final String OTEL_EXPORTER_OTLP_CLIENT_CERTIFICATE = "otel.exporter.otlp.client.certificate"; + static final String OTEL_EXPORTER_OTLP_SIGNAL_CLIENT_CERTIFICATE = "otel.exporter.otlp.%s.client.certificate"; + + static final String OTEL_EXPORTER_OTLP_PROTOCOL = "otel.exporter.otlp.protocol"; + static final String OTEL_EXPORTER_OTLP_SIGNAL_PROTOCOL = "otel.exporter.otlp.%s.protocol"; + + static final String OTEL_EXPORTER_OTLP_TIMEOUT = "otel.exporter.otlp.timeout"; + static final String OTEL_EXPORTER_OTLP_SIGNAL_TIMEOUT = "otel.exporter.otlp.%s.timeout"; + + static final String OTEL_EXPORTER_OTLP_SIGNAL_ENDPOINT = "otel.exporter.otlp.%s.endpoint"; + + static final String OTEL_EXPORTER_OTLP_COMPRESSION = "otel.exporter.otlp.compression"; + static final String OTEL_EXPORTER_OTLP_SIGNAL_COMPRESSION = "otel.exporter.otlp.%s.compression"; + + static final String MIMETYPE_PROTOBUF = "application/x-protobuf"; + + static final String SROTEL_TLS_TRUST_ALL = "otel.exporter.tls.trustAll"; + // Proxy options + static final String SROTEL_PROXY_ENABLED = "otel.exporter.proxy.enabled"; + static final String SROTEL_PROXY_USERNAME = "otel.exporter.proxy.username"; + static final String SROTEL_PROXY_PASSWORD = "otel.exporter.proxy.password"; + static final String SROTEL_PROXY_HOST = "otel.exporter.proxy.host"; + static final String SROTEL_PROXY_PORT = "otel.exporter.proxy.port"; +} diff --git a/implementation/exporters/src/main/java/io/smallrye/opentelemetry/implementation/exporters/HttpClientOptionsConsumer.java b/implementation/exporters/src/main/java/io/smallrye/opentelemetry/implementation/exporters/HttpClientOptionsConsumer.java new file mode 100644 index 00000000..66cb3c2d --- /dev/null +++ b/implementation/exporters/src/main/java/io/smallrye/opentelemetry/implementation/exporters/HttpClientOptionsConsumer.java @@ -0,0 +1,141 @@ +package io.smallrye.opentelemetry.implementation.exporters; + +import static io.smallrye.opentelemetry.implementation.exporters.Constants.OTEL_EXPORTER_OTLP_CERTIFICATE; +import static io.smallrye.opentelemetry.implementation.exporters.Constants.OTEL_EXPORTER_OTLP_CLIENT_CERTIFICATE; +import static io.smallrye.opentelemetry.implementation.exporters.Constants.OTEL_EXPORTER_OTLP_CLIENT_KEY; +import static io.smallrye.opentelemetry.implementation.exporters.Constants.OTEL_EXPORTER_OTLP_SIGNAL_CERTIFICATE; +import static io.smallrye.opentelemetry.implementation.exporters.Constants.OTEL_EXPORTER_OTLP_SIGNAL_CLIENT_CERTIFICATE; +import static io.smallrye.opentelemetry.implementation.exporters.Constants.OTEL_EXPORTER_OTLP_SIGNAL_CLIENT_KEY; +import static io.smallrye.opentelemetry.implementation.exporters.Constants.SROTEL_PROXY_ENABLED; +import static io.smallrye.opentelemetry.implementation.exporters.Constants.SROTEL_PROXY_HOST; +import static io.smallrye.opentelemetry.implementation.exporters.Constants.SROTEL_PROXY_PASSWORD; +import static io.smallrye.opentelemetry.implementation.exporters.Constants.SROTEL_PROXY_PORT; +import static io.smallrye.opentelemetry.implementation.exporters.Constants.SROTEL_PROXY_USERNAME; +import static io.smallrye.opentelemetry.implementation.exporters.Constants.SROTEL_TLS_TRUST_ALL; +import static io.smallrye.opentelemetry.implementation.exporters.OtlpExporterUtil.getConfig; + +import java.net.URI; +import java.util.function.Consumer; + +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import io.vertx.core.http.HttpClientOptions; +import io.vertx.core.net.PemKeyCertOptions; +import io.vertx.core.net.PemTrustOptions; +import io.vertx.core.net.ProxyOptions; + +class HttpClientOptionsConsumer implements Consumer { + private final ConfigProperties config; + private final URI baseUri; + private final String signalType; + + public HttpClientOptionsConsumer(ConfigProperties config, URI baseUri, String signalType) { + this.config = config; + this.baseUri = baseUri; + this.signalType = signalType; + } + + @Override + public void accept(HttpClientOptions options) { + configureTLS(options); + + if (Boolean.parseBoolean(getConfig(config, "false", SROTEL_PROXY_ENABLED))) { + configureProxyOptions(options); + } + } + + private void configureTLS(HttpClientOptions options) { + configureKeyCertOptions(options); + configureTrustOptions(options); + + if (OtlpExporterUtil.isHttps(baseUri)) { + options.setSsl(true); + options.setUseAlpn(true); + } + + if (Boolean.parseBoolean(getConfig(config, "false", SROTEL_TLS_TRUST_ALL))) { + options.setTrustAll(true); + options.setVerifyHost(false); + } + } + + private void configureProxyOptions(HttpClientOptions options) { + var proxyHost = getConfig(config, "", SROTEL_PROXY_HOST); + if (!proxyHost.isBlank()) { + ProxyOptions proxyOptions = new ProxyOptions() + .setHost(proxyHost); + var proxyPort = getConfig(config, "", SROTEL_PROXY_PORT); + var proxyUsername = getConfig(config, "", SROTEL_PROXY_USERNAME); + var proxyPassword = getConfig(config, "", SROTEL_PROXY_PASSWORD); + + if (!proxyPort.isBlank()) { + proxyOptions.setPort(Integer.parseInt(proxyPort)); + } + if (!proxyUsername.isBlank()) { + proxyOptions.setUsername(proxyUsername); + } + if (!proxyPassword.isBlank()) { + proxyOptions.setPassword(proxyPassword); + } + options.setProxyOptions(proxyOptions); + } else { + configureProxyOptionsFromJDKSysProps(options); + } + } + + private void configureProxyOptionsFromJDKSysProps(HttpClientOptions options) { + var proxyHost = options.isSsl() + ? System.getProperty("https.proxyHost", "none") + : System.getProperty("http.proxyHost", "none"); + var proxyPortAsString = options.isSsl() + ? System.getProperty("https.proxyPort", "443") + : System.getProperty("http.proxyPort", "80"); + var proxyPort = Integer.parseInt(proxyPortAsString); + + if (!"none".equals(proxyHost)) { + ProxyOptions proxyOptions = new ProxyOptions().setHost(proxyHost).setPort(proxyPort); + var proxyUser = options.isSsl() + ? System.getProperty("https.proxyUser") + : System.getProperty("http.proxyUser"); + if (proxyUser != null && !proxyUser.isBlank()) { + proxyOptions.setUsername(proxyUser); + } + var proxyPassword = options.isSsl() + ? System.getProperty("https.proxyPassword") + : System.getProperty("http.proxyPassword"); + if (proxyPassword != null && !proxyPassword.isBlank()) { + proxyOptions.setPassword(proxyPassword); + } + options.setProxyOptions(proxyOptions); + } + } + + private void configureKeyCertOptions(HttpClientOptions options) { + var pemKeyCertOptions = new PemKeyCertOptions(); + + var certificate = getConfig(config, "", + String.format(OTEL_EXPORTER_OTLP_SIGNAL_CLIENT_CERTIFICATE, signalType), + OTEL_EXPORTER_OTLP_CLIENT_CERTIFICATE); + var key = getConfig(config, "", + String.format(OTEL_EXPORTER_OTLP_SIGNAL_CLIENT_KEY, signalType), OTEL_EXPORTER_OTLP_CLIENT_KEY); + + if (!certificate.isEmpty()) { + pemKeyCertOptions.addCertPath(certificate); + } + + if (!key.isEmpty()) { + pemKeyCertOptions.addKeyPath(key); + } + options.setKeyCertOptions(pemKeyCertOptions); + } + + private void configureTrustOptions(HttpClientOptions options) { + var certificate = getConfig(config, "", + String.format(OTEL_EXPORTER_OTLP_SIGNAL_CERTIFICATE, signalType), OTEL_EXPORTER_OTLP_CERTIFICATE); + + if (!certificate.isEmpty()) { + var pemTrustOptions = new PemTrustOptions() + .addCertPath(certificate); + options.setPemTrustOptions(pemTrustOptions); + } + } +} diff --git a/implementation/exporters/src/main/java/io/smallrye/opentelemetry/implementation/exporters/OtlpExporterUtil.java b/implementation/exporters/src/main/java/io/smallrye/opentelemetry/implementation/exporters/OtlpExporterUtil.java index 6c63be10..0b66b3b1 100644 --- a/implementation/exporters/src/main/java/io/smallrye/opentelemetry/implementation/exporters/OtlpExporterUtil.java +++ b/implementation/exporters/src/main/java/io/smallrye/opentelemetry/implementation/exporters/OtlpExporterUtil.java @@ -1,22 +1,24 @@ package io.smallrye.opentelemetry.implementation.exporters; +import static io.smallrye.opentelemetry.implementation.exporters.Constants.OTEL_EXPORTER_OTLP_COMPRESSION; +import static io.smallrye.opentelemetry.implementation.exporters.Constants.OTEL_EXPORTER_OTLP_PROTOCOL; +import static io.smallrye.opentelemetry.implementation.exporters.Constants.OTEL_EXPORTER_OTLP_SIGNAL_COMPRESSION; +import static io.smallrye.opentelemetry.implementation.exporters.Constants.OTEL_EXPORTER_OTLP_SIGNAL_ENDPOINT; +import static io.smallrye.opentelemetry.implementation.exporters.Constants.OTEL_EXPORTER_OTLP_SIGNAL_PROTOCOL; +import static io.smallrye.opentelemetry.implementation.exporters.Constants.OTEL_EXPORTER_OTLP_SIGNAL_TIMEOUT; + import java.net.URI; +import java.time.Duration; +import java.util.Arrays; import java.util.HashMap; import java.util.Locale; import java.util.Map; +import java.util.Objects; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.smallrye.opentelemetry.api.OpenTelemetryConfig; public final class OtlpExporterUtil { - public static final String PROTOCOL_GRPC = "grpc"; - public static final String PROTOCOL_HTTP_PROTOBUF = "http/protobuf"; - - public static final String OTLP_GRPC_ENDPOINT = "http://localhost:4317"; - public static final String OTLP_HTTP_PROTOBUF_ENDPOINT = "http://localhost:4318"; - - public static final String OTEL_EXPORTER_OTLP_ENDPOINT = "otel.exporter.otlp.endpoint"; - public static final String OTEL_EXPORTER_OTLP_TRACES_PROTOCOL = "otel.exporter.otlp.traces.protocol"; - private OtlpExporterUtil() { } @@ -42,4 +44,75 @@ public static Map populateTracingExportHttpHeaders() { public static boolean isHttps(URI uri) { return "https".equals(uri.getScheme().toLowerCase(Locale.ROOT)); } + + /** + * Given the OpenTelemetry config, lookup a value using the given keys, stopping with the first non-null value. If + * no keys are found, return the defaultValue. Since the OpenTelemetry API offers signal-specific settings, as well + * as one overarching property key for a variety of configuration options, this allows the caller to specify + * signal-specific keys to search, then defaulting to the "top-level" property, then finally defaulting to a + * SmallRye-specific default value. + * + * @param config OpenTelemetry config + * @param defaultValue The default value for the property. + * @param keys The keys to iterate over + * @return either the configured or default value + */ + public static String getConfig(ConfigProperties config, String defaultValue, String... keys) { + return Arrays.stream(keys).map(config::getString) + .filter(Objects::nonNull) + .findFirst() + .orElse(defaultValue); + } + + /** + * Determine the wire protocol for sending signal data to the remote + * + * @param config OpenTelemetry configuration + * @return either the configured or default value + */ + public static String getProtocol(ConfigProperties config, String signalType) { + // The otel API uses "span" and "traces" in various places, so we need to modify that case here + var signalKey = signalType.replace("span", "traces"); + + return getConfig(config, Constants.PROTOCOL_GRPC, + String.format(OTEL_EXPORTER_OTLP_SIGNAL_PROTOCOL, signalKey), OTEL_EXPORTER_OTLP_PROTOCOL); + } + + /** + * Determine whether to enable compression + * + * @param config OpenTelemetry configuration + * @return either the configured or default value + */ + public static boolean getCompression(ConfigProperties config, String signalType) { + return Boolean.parseBoolean(getConfig(config, "true", + String.format(OTEL_EXPORTER_OTLP_SIGNAL_COMPRESSION, signalType), + OTEL_EXPORTER_OTLP_COMPRESSION)); + } + + /** + * Return timeout, in seconds, for sending data to the remote + * + * @param config OpenTelemetry configuration + * @return either the configured or default value + */ + public static Duration getTimeout(ConfigProperties config, String signalType) { + return Duration.ofSeconds(Integer.parseInt( + getConfig(config, "10", + String.format(OTEL_EXPORTER_OTLP_SIGNAL_TIMEOUT, signalType), Constants.OTEL_EXPORTER_OTLP_TIMEOUT))); + } + + /** + * Gets the OTLP traces endpoint, if defined. If it is not, it returns the OTLP endpoint. If that is not defined, + * it returns defaultEndpoint. + * + * @param config OpenTelemetry configuration + * @param defaultEndpoint The default endpoint for the desired protocol + * @return either the configured or default value + */ + public static String getOtlpEndpoint(ConfigProperties config, String defaultEndpoint, String signalType) { + return getConfig(config, defaultEndpoint, + String.format(OTEL_EXPORTER_OTLP_SIGNAL_ENDPOINT, signalType), + Constants.OTEL_EXPORTER_OTLP_ENDPOINT); + } } diff --git a/implementation/exporters/src/main/java/io/smallrye/opentelemetry/implementation/exporters/logs/VertxLogsExporterProvider.java b/implementation/exporters/src/main/java/io/smallrye/opentelemetry/implementation/exporters/logs/VertxLogsExporterProvider.java index d18fe7cd..557a9e0c 100644 --- a/implementation/exporters/src/main/java/io/smallrye/opentelemetry/implementation/exporters/logs/VertxLogsExporterProvider.java +++ b/implementation/exporters/src/main/java/io/smallrye/opentelemetry/implementation/exporters/logs/VertxLogsExporterProvider.java @@ -1,7 +1,8 @@ package io.smallrye.opentelemetry.implementation.exporters.logs; -import static io.smallrye.opentelemetry.implementation.exporters.OtlpExporterUtil.PROTOCOL_GRPC; -import static io.smallrye.opentelemetry.implementation.exporters.OtlpExporterUtil.PROTOCOL_HTTP_PROTOBUF; +import static io.smallrye.opentelemetry.implementation.exporters.Constants.PROTOCOL_GRPC; +import static io.smallrye.opentelemetry.implementation.exporters.Constants.PROTOCOL_HTTP_PROTOBUF; +import static io.smallrye.opentelemetry.implementation.exporters.OtlpExporterUtil.getProtocol; import java.net.URISyntaxException; @@ -22,7 +23,7 @@ public VertxLogsExporterProvider() { @Override public LogRecordExporter createExporter(ConfigProperties config) { try { - final String protocol = getProtocol(config); + final String protocol = getProtocol(config, getSignalType()); if (PROTOCOL_GRPC.equals(protocol)) { return new VertxGrpcLogsExporter(createGrpcExporter(config, VertxGrpcSender.GRPC_TRACE_SERVICE_NAME)); diff --git a/implementation/exporters/src/main/java/io/smallrye/opentelemetry/implementation/exporters/metrics/VertxMetricsExporterProvider.java b/implementation/exporters/src/main/java/io/smallrye/opentelemetry/implementation/exporters/metrics/VertxMetricsExporterProvider.java index f3a9e884..003f53ae 100644 --- a/implementation/exporters/src/main/java/io/smallrye/opentelemetry/implementation/exporters/metrics/VertxMetricsExporterProvider.java +++ b/implementation/exporters/src/main/java/io/smallrye/opentelemetry/implementation/exporters/metrics/VertxMetricsExporterProvider.java @@ -1,7 +1,9 @@ package io.smallrye.opentelemetry.implementation.exporters.metrics; -import static io.smallrye.opentelemetry.implementation.exporters.OtlpExporterUtil.PROTOCOL_GRPC; -import static io.smallrye.opentelemetry.implementation.exporters.OtlpExporterUtil.PROTOCOL_HTTP_PROTOBUF; +import static io.smallrye.opentelemetry.implementation.exporters.Constants.PROTOCOL_GRPC; +import static io.smallrye.opentelemetry.implementation.exporters.Constants.PROTOCOL_HTTP_PROTOBUF; +import static io.smallrye.opentelemetry.implementation.exporters.OtlpExporterUtil.getConfig; +import static io.smallrye.opentelemetry.implementation.exporters.OtlpExporterUtil.getProtocol; import java.net.URISyntaxException; @@ -29,7 +31,7 @@ public VertxMetricsExporterProvider() { @Override public MetricExporter createExporter(ConfigProperties config) { try { - final String protocol = getProtocol(config); + final String protocol = getProtocol(config, getSignalType()); if (PROTOCOL_GRPC.equals(protocol)) { return new VertxGrpcMetricExporter( @@ -81,4 +83,4 @@ private AggregationTemporalitySelector aggregationTemporalityResolver(ConfigProp throw new ConfigurationException("Unrecognized aggregation temporality: " + temporalityValue); } } -} \ No newline at end of file +} diff --git a/implementation/exporters/src/main/java/io/smallrye/opentelemetry/implementation/exporters/sender/VertxGrpcSender.java b/implementation/exporters/src/main/java/io/smallrye/opentelemetry/implementation/exporters/sender/VertxGrpcSender.java index e290d27b..dba941bf 100644 --- a/implementation/exporters/src/main/java/io/smallrye/opentelemetry/implementation/exporters/sender/VertxGrpcSender.java +++ b/implementation/exporters/src/main/java/io/smallrye/opentelemetry/implementation/exporters/sender/VertxGrpcSender.java @@ -58,17 +58,21 @@ public final class VertxGrpcSender implements GrpcSender private final SocketAddress server; private final boolean compressionEnabled; private final Map headers; + private final String signalType; private final String grpcEndpointPath; private final GrpcClient client; public VertxGrpcSender( + String signalType, URI grpcBaseUri, String grpcEndpointPath, boolean compressionEnabled, Duration timeout, Map headersMap, + Consumer clientOptionsCustomizer, Vertx vertx) { + this.signalType = signalType; this.grpcEndpointPath = grpcEndpointPath; this.server = SocketAddress.inetSocketAddress(OtlpExporterUtil.getPort(grpcBaseUri), grpcBaseUri.getHost()); this.compressionEnabled = compressionEnabled; @@ -77,6 +81,7 @@ public VertxGrpcSender( .setHttp2ClearTextUpgrade(false) // needed otherwise connections get closed immediately .setReadIdleTimeout((int) timeout.getSeconds()) .setTracingPolicy(TracingPolicy.IGNORE); // needed to avoid tracing the calls from this gRPC client + clientOptionsCustomizer.accept(httpClientOptions); this.client = GrpcClient.client(vertx, httpClientOptions); } @@ -165,48 +170,6 @@ private void failOnClientRequest(String type, Throwable t, BiConsumer onError) { onError.accept(GrpcResponse.create(2 /* UNKNOWN */, message), t); } - /* - * private static final MethodDescriptor.Marshaller REQUEST_MARSHALLER = new MethodDescriptor.Marshaller<>() { - * - * @Override - * public InputStream stream(Marshaler value) { - * return new MarshalerInputStream(value); - * } - * - * @Override - * public Marshaler parse(InputStream stream) { - * throw new UnsupportedOperationException("Only for serializing"); - * } - * }; - * - * private static final MethodDescriptor.Marshaller RESPONSE_MARSHALER = new - * MethodDescriptor.Marshaller<>() { - * - * @Override - * public InputStream stream(ServiceResponse value) { - * throw new UnsupportedOperationException("Only for parsing"); - * } - * - * @Override - * public ServiceResponse parse(InputStream stream) { - * return ServiceResponse.INSTANCE; - * } - * }; - * - * private MethodDescriptor getExportMethod() { - * return MethodDescriptor. newBuilder() - * .setType(io.grpc.MethodDescriptor.MethodType.UNARY) - * .setFullMethodName(generateFullMethodName(grpcEndpointPath, "Export")) - * .setRequestMarshaller(REQUEST_MARSHALLER) - * .setResponseMarshaller(RESPONSE_MARSHALER) - * .build(); - * } - * - * private enum ServiceResponse { - * INSTANCE; - * } - */ - private final class ClientRequestOnSuccessHandler implements Handler> { private final GrpcClient client; diff --git a/implementation/exporters/src/main/java/io/smallrye/opentelemetry/implementation/exporters/sender/VertxHttpSender.java b/implementation/exporters/src/main/java/io/smallrye/opentelemetry/implementation/exporters/sender/VertxHttpSender.java index 1d8af9e8..2a3aae2e 100644 --- a/implementation/exporters/src/main/java/io/smallrye/opentelemetry/implementation/exporters/sender/VertxHttpSender.java +++ b/implementation/exporters/src/main/java/io/smallrye/opentelemetry/implementation/exporters/sender/VertxHttpSender.java @@ -59,6 +59,7 @@ public VertxHttpSender( Duration timeout, Map headersMap, String contentType, + Consumer clientOptionsCustomizer, Vertx vertx) { this.basePath = determineBasePath(baseUri); this.signalPath = signalPath; @@ -70,6 +71,7 @@ public VertxHttpSender( .setDefaultHost(baseUri.getHost()) .setDefaultPort(getPort(baseUri)) .setTracingPolicy(TracingPolicy.IGNORE); // needed to avoid tracing the calls from this http client + clientOptionsCustomizer.accept(httpClientOptions); this.client = vertx.createHttpClient(httpClientOptions); } diff --git a/implementation/exporters/src/main/java/io/smallrye/opentelemetry/implementation/exporters/traces/VertxSpanExporterProvider.java b/implementation/exporters/src/main/java/io/smallrye/opentelemetry/implementation/exporters/traces/VertxSpanExporterProvider.java index 5e428690..af5166c7 100644 --- a/implementation/exporters/src/main/java/io/smallrye/opentelemetry/implementation/exporters/traces/VertxSpanExporterProvider.java +++ b/implementation/exporters/src/main/java/io/smallrye/opentelemetry/implementation/exporters/traces/VertxSpanExporterProvider.java @@ -1,7 +1,8 @@ package io.smallrye.opentelemetry.implementation.exporters.traces; -import static io.smallrye.opentelemetry.implementation.exporters.OtlpExporterUtil.PROTOCOL_GRPC; -import static io.smallrye.opentelemetry.implementation.exporters.OtlpExporterUtil.PROTOCOL_HTTP_PROTOBUF; +import static io.smallrye.opentelemetry.implementation.exporters.Constants.PROTOCOL_GRPC; +import static io.smallrye.opentelemetry.implementation.exporters.Constants.PROTOCOL_HTTP_PROTOBUF; +import static io.smallrye.opentelemetry.implementation.exporters.OtlpExporterUtil.getProtocol; import java.net.URISyntaxException; @@ -23,7 +24,7 @@ public VertxSpanExporterProvider() { @Override public SpanExporter createExporter(final ConfigProperties config) { try { - final String protocol = getProtocol(config); + final String protocol = getProtocol(config, getSignalType()); if (PROTOCOL_GRPC.equals(protocol)) { return new VertxGrpcSpanExporter(createGrpcExporter(config, VertxGrpcSender.GRPC_TRACE_SERVICE_NAME)); diff --git a/implementation/exporters/src/test/java/io/smallrye/opentelemetry/implementation/exporters/VertxExportersTest.java b/implementation/exporters/src/test/java/io/smallrye/opentelemetry/implementation/exporters/VertxExportersTest.java index 13929281..fc51f46c 100644 --- a/implementation/exporters/src/test/java/io/smallrye/opentelemetry/implementation/exporters/VertxExportersTest.java +++ b/implementation/exporters/src/test/java/io/smallrye/opentelemetry/implementation/exporters/VertxExportersTest.java @@ -1,5 +1,9 @@ package io.smallrye.opentelemetry.implementation.exporters; +import static io.smallrye.opentelemetry.implementation.exporters.Constants.OTEL_EXPORTER_OTLP_ENDPOINT; +import static io.smallrye.opentelemetry.implementation.exporters.Constants.OTEL_EXPORTER_OTLP_TRACES_PROTOCOL; +import static io.smallrye.opentelemetry.implementation.exporters.Constants.PROTOCOL_GRPC; + import java.util.Map; import org.junit.jupiter.api.AfterAll; @@ -55,13 +59,13 @@ public void testHttpExporter() { } private void testExporterByProtocol(String protocol) { - String endpoint = OtlpExporterUtil.PROTOCOL_GRPC.equals(protocol) ? otelCollector.getOtlpGrpcEndpoint() + String endpoint = PROTOCOL_GRPC.equals(protocol) ? otelCollector.getOtlpGrpcEndpoint() : otelCollector.getOtlpHttpEndpoint(); Map config = Map.of( "otel.traces.exporter", "otlp", - OtlpExporterUtil.OTEL_EXPORTER_OTLP_TRACES_PROTOCOL, protocol, + OTEL_EXPORTER_OTLP_TRACES_PROTOCOL, protocol, "otel.bsp.schedule.delay", "1", - OtlpExporterUtil.OTEL_EXPORTER_OTLP_ENDPOINT, endpoint); + OTEL_EXPORTER_OTLP_ENDPOINT, endpoint); final String tracerName = "smallrye.opentelemetry.test." + protocol; final String spanName = protocol + " test trace"; final String eventName = protocol + " test event";