diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpExporterProperties.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpExporterProperties.java index a8f4b9543901..e4f678213d6a 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpExporterProperties.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpExporterProperties.java @@ -27,6 +27,8 @@ public final class OtlpExporterProperties { private boolean enabled = true; @Nullable private String endpoint; + @Nullable private String protocol; + private final Map headers = new HashMap<>(); @Nullable private Duration timeout; @@ -51,6 +53,15 @@ public void setEndpoint(String endpoint) { this.endpoint = endpoint; } + @Nullable + public String getProtocol() { + return protocol; + } + + public void setProtocol(@Nullable String protocol) { + this.protocol = protocol; + } + public Map getHeaders() { return headers; } @@ -81,6 +92,8 @@ public static class SignalProperties { private boolean enabled = true; @Nullable private String endpoint; + @Nullable private String protocol; + private final Map headers = new HashMap<>(); @Nullable private Duration timeout; @@ -102,6 +115,15 @@ public void setEndpoint(@Nullable String endpoint) { this.endpoint = endpoint; } + @Nullable + public String getProtocol() { + return protocol; + } + + public void setProtocol(@Nullable String protocol) { + this.protocol = protocol; + } + public Map getHeaders() { return headers; } diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpExporterUtil.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpExporterUtil.java index 1d07402c6b4e..df9e7dab509d 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpExporterUtil.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpExporterUtil.java @@ -5,40 +5,101 @@ package io.opentelemetry.instrumentation.spring.autoconfigure.exporters.otlp; +import io.opentelemetry.exporter.otlp.internal.OtlpConfigUtil; import java.time.Duration; import java.util.Map; +import java.util.Objects; import java.util.function.BiConsumer; -import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; class OtlpExporterUtil { private OtlpExporterUtil() {} - static void applySignalProperties( + static Exporter applySignalProperties( + String dataType, OtlpExporterProperties properties, OtlpExporterProperties.SignalProperties signalProperties, - Consumer setEndpoint, - BiConsumer addHeader, - Consumer setTimeout) { - String endpoint = properties.getLogs().getEndpoint(); + Supplier newGrpcBuilder, + Supplier newHttpBuilder, + BiConsumer setGrpcEndpoint, + BiConsumer setHttpEndpoint, + BiConsumer> addGrpcHeader, + BiConsumer> addHttpHeader, + BiConsumer setGrpcTimeout, + BiConsumer setHttpTimeout, + Function buildGrpcExporter, + Function buildHttpExporter) { + + String protocol = signalProperties.getProtocol(); + if (protocol == null) { + protocol = properties.getProtocol(); + } + + GrpcBuilder grpcBuilder = newGrpcBuilder.get(); + HttpBuilder httpBuilder = newHttpBuilder.get(); + + boolean isHttpProtobuf = Objects.equals(protocol, OtlpConfigUtil.PROTOCOL_HTTP_PROTOBUF); + + String endpoint = signalProperties.getEndpoint(); if (endpoint == null) { endpoint = properties.getEndpoint(); } if (endpoint != null) { - setEndpoint.accept(endpoint); + if (isHttpProtobuf) { + if (!endpoint.endsWith("/")) { + endpoint += "/"; + } + endpoint += signalPath(dataType); + } + + if (isHttpProtobuf) { + setHttpEndpoint.accept(httpBuilder, endpoint); + } else { + setGrpcEndpoint.accept(grpcBuilder, endpoint); + } } Map headers = signalProperties.getHeaders(); if (headers.isEmpty()) { headers = properties.getHeaders(); } - headers.forEach(addHeader); + for (Map.Entry entry : headers.entrySet()) { + if (isHttpProtobuf) { + addHttpHeader.accept(httpBuilder, entry); + } else { + addGrpcHeader.accept(grpcBuilder, entry); + } + } Duration timeout = signalProperties.getTimeout(); if (timeout == null) { timeout = properties.getTimeout(); } if (timeout != null) { - setTimeout.accept(timeout); + if (isHttpProtobuf) { + setHttpTimeout.accept(httpBuilder, timeout); + } else { + setGrpcTimeout.accept(grpcBuilder, timeout); + } + } + + return isHttpProtobuf + ? buildHttpExporter.apply(httpBuilder) + : buildGrpcExporter.apply(grpcBuilder); + } + + private static String signalPath(String dataType) { + switch (dataType) { + case OtlpConfigUtil.DATA_TYPE_METRICS: + return "v1/metrics"; + case OtlpConfigUtil.DATA_TYPE_TRACES: + return "v1/traces"; + case OtlpConfigUtil.DATA_TYPE_LOGS: + return "v1/logs"; + default: + throw new IllegalArgumentException( + "Cannot determine signal path for unrecognized data type: " + dataType); } } } diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpLoggerExporterAutoConfiguration.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpLoggerExporterAutoConfiguration.java index 38122861eb4a..2abe847024c7 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpLoggerExporterAutoConfiguration.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpLoggerExporterAutoConfiguration.java @@ -5,9 +5,13 @@ package io.opentelemetry.instrumentation.spring.autoconfigure.exporters.otlp; +import io.opentelemetry.exporter.otlp.http.logs.OtlpHttpLogRecordExporter; +import io.opentelemetry.exporter.otlp.http.logs.OtlpHttpLogRecordExporterBuilder; +import io.opentelemetry.exporter.otlp.internal.OtlpConfigUtil; import io.opentelemetry.exporter.otlp.logs.OtlpGrpcLogRecordExporter; import io.opentelemetry.exporter.otlp.logs.OtlpGrpcLogRecordExporterBuilder; import io.opentelemetry.instrumentation.spring.autoconfigure.OpenTelemetryAutoConfiguration; +import io.opentelemetry.sdk.logs.export.LogRecordExporter; import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; @@ -26,17 +30,25 @@ public class OtlpLoggerExporterAutoConfiguration { @Bean @ConditionalOnMissingBean - public OtlpGrpcLogRecordExporter otelOtlpGrpcLogRecordExporter( - OtlpExporterProperties properties) { - OtlpGrpcLogRecordExporterBuilder builder = OtlpGrpcLogRecordExporter.builder(); + public LogRecordExporter otelOtlpGrpcLogRecordExporter(OtlpExporterProperties properties) { - OtlpExporterUtil.applySignalProperties( + return OtlpExporterUtil.applySignalProperties( + OtlpConfigUtil.DATA_TYPE_LOGS, properties, properties.getLogs(), - builder::setEndpoint, - builder::addHeader, - builder::setTimeout); - - return builder.build(); + OtlpGrpcLogRecordExporter::builder, + OtlpHttpLogRecordExporter::builder, + OtlpGrpcLogRecordExporterBuilder::setEndpoint, + OtlpHttpLogRecordExporterBuilder::setEndpoint, + (builder, entry) -> { + builder.addHeader(entry.getKey(), entry.getValue()); + }, + (builder, entry) -> { + builder.addHeader(entry.getKey(), entry.getValue()); + }, + OtlpGrpcLogRecordExporterBuilder::setTimeout, + OtlpHttpLogRecordExporterBuilder::setTimeout, + OtlpGrpcLogRecordExporterBuilder::build, + OtlpHttpLogRecordExporterBuilder::build); } } diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpMetricExporterAutoConfiguration.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpMetricExporterAutoConfiguration.java index 5f4d57bf713c..42564bc7ea48 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpMetricExporterAutoConfiguration.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpMetricExporterAutoConfiguration.java @@ -5,9 +5,13 @@ package io.opentelemetry.instrumentation.spring.autoconfigure.exporters.otlp; +import io.opentelemetry.exporter.otlp.http.metrics.OtlpHttpMetricExporter; +import io.opentelemetry.exporter.otlp.http.metrics.OtlpHttpMetricExporterBuilder; +import io.opentelemetry.exporter.otlp.internal.OtlpConfigUtil; import io.opentelemetry.exporter.otlp.metrics.OtlpGrpcMetricExporter; import io.opentelemetry.exporter.otlp.metrics.OtlpGrpcMetricExporterBuilder; import io.opentelemetry.instrumentation.spring.autoconfigure.OpenTelemetryAutoConfiguration; +import io.opentelemetry.sdk.metrics.export.MetricExporter; import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; @@ -28,16 +32,24 @@ public class OtlpMetricExporterAutoConfiguration { @Bean @ConditionalOnMissingBean - public OtlpGrpcMetricExporter otelOtlpGrpcMetricExporter(OtlpExporterProperties properties) { - OtlpGrpcMetricExporterBuilder builder = OtlpGrpcMetricExporter.builder(); - - OtlpExporterUtil.applySignalProperties( + public MetricExporter otelOtlpGrpcMetricExporter(OtlpExporterProperties properties) { + return OtlpExporterUtil.applySignalProperties( + OtlpConfigUtil.DATA_TYPE_METRICS, properties, - properties.getMetrics(), - builder::setEndpoint, - builder::addHeader, - builder::setTimeout); - - return builder.build(); + properties.getLogs(), + OtlpGrpcMetricExporter::builder, + OtlpHttpMetricExporter::builder, + OtlpGrpcMetricExporterBuilder::setEndpoint, + OtlpHttpMetricExporterBuilder::setEndpoint, + (builder, entry) -> { + builder.addHeader(entry.getKey(), entry.getValue()); + }, + (builder, entry) -> { + builder.addHeader(entry.getKey(), entry.getValue()); + }, + OtlpGrpcMetricExporterBuilder::setTimeout, + OtlpHttpMetricExporterBuilder::setTimeout, + OtlpGrpcMetricExporterBuilder::build, + OtlpHttpMetricExporterBuilder::build); } } diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpSpanExporterAutoConfiguration.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpSpanExporterAutoConfiguration.java index c525465fc27d..c0203c29c3f5 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpSpanExporterAutoConfiguration.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpSpanExporterAutoConfiguration.java @@ -5,9 +5,13 @@ package io.opentelemetry.instrumentation.spring.autoconfigure.exporters.otlp; +import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporter; +import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporterBuilder; +import io.opentelemetry.exporter.otlp.internal.OtlpConfigUtil; import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter; import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporterBuilder; import io.opentelemetry.instrumentation.spring.autoconfigure.OpenTelemetryAutoConfiguration; +import io.opentelemetry.sdk.trace.export.SpanExporter; import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; @@ -33,16 +37,24 @@ public class OtlpSpanExporterAutoConfiguration { @Bean @ConditionalOnMissingBean - public OtlpGrpcSpanExporter otelOtlpGrpcSpanExporter(OtlpExporterProperties properties) { - OtlpGrpcSpanExporterBuilder builder = OtlpGrpcSpanExporter.builder(); - - OtlpExporterUtil.applySignalProperties( + public SpanExporter otelOtlpGrpcSpanExporter(OtlpExporterProperties properties) { + return OtlpExporterUtil.applySignalProperties( + OtlpConfigUtil.DATA_TYPE_TRACES, properties, - properties.getTraces(), - builder::setEndpoint, - builder::addHeader, - builder::setTimeout); - - return builder.build(); + properties.getLogs(), + OtlpGrpcSpanExporter::builder, + OtlpHttpSpanExporter::builder, + OtlpGrpcSpanExporterBuilder::setEndpoint, + OtlpHttpSpanExporterBuilder::setEndpoint, + (builder, entry) -> { + builder.addHeader(entry.getKey(), entry.getValue()); + }, + (builder, entry) -> { + builder.addHeader(entry.getKey(), entry.getValue()); + }, + OtlpGrpcSpanExporterBuilder::setTimeout, + OtlpHttpSpanExporterBuilder::setTimeout, + OtlpGrpcSpanExporterBuilder::build, + OtlpHttpSpanExporterBuilder::build); } }