diff --git a/exporters/otlp/src/main/java/io/opentelemetry/exporters/otlp/OtlpGrpcSpanExporter.java b/exporters/otlp/src/main/java/io/opentelemetry/exporters/otlp/OtlpGrpcSpanExporter.java
index ab88e1095fc..11a515db34b 100644
--- a/exporters/otlp/src/main/java/io/opentelemetry/exporters/otlp/OtlpGrpcSpanExporter.java
+++ b/exporters/otlp/src/main/java/io/opentelemetry/exporters/otlp/OtlpGrpcSpanExporter.java
@@ -16,17 +16,26 @@
package io.opentelemetry.exporters.otlp;
+import static io.grpc.Metadata.ASCII_STRING_MARSHALLER;
+
+import com.google.common.base.Splitter;
import io.grpc.ManagedChannel;
+import io.grpc.ManagedChannelBuilder;
+import io.grpc.Metadata;
+import io.grpc.Metadata.Key;
+import io.grpc.stub.MetadataUtils;
import io.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest;
import io.opentelemetry.proto.collector.trace.v1.TraceServiceGrpc;
import io.opentelemetry.sdk.common.export.ConfigBuilder;
import io.opentelemetry.sdk.trace.data.SpanData;
import io.opentelemetry.sdk.trace.export.SpanExporter;
import java.util.Collection;
+import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
+import javax.annotation.Nullable;
import javax.annotation.concurrent.ThreadSafe;
/**
@@ -41,6 +50,10 @@
*
* - {@code otel.otlp.span.timeout}: to set the max waiting time allowed to send each span
* batch.
+ *
- {@code otel.otlp.endpoint}: to set the endpoint to connect to.
+ *
- {@code otel.otlp.use.tls}: to set use or not TLS.
+ *
- {@code otel.otlp.metadata} to set key-value pairs separated by semicolon to pass as request
+ * metadata.
*
*
* For environment variables, {@link OtlpGrpcSpanExporter} will look for the following names:
@@ -48,6 +61,10 @@
*
* - {@code OTEL_OTLP_SPAN_TIMEOUT}: to set the max waiting time allowed to send each span
* batch.
+ *
- {@code OTEL_OTLP_ENDPOINT}: to set the endpoint to connect to.
+ *
- {@code OTEL_OTLP_USE_TLS}: to set use or not TLS.
+ *
- {@code OTEL_OTLP_METADATA}: to set key-value pairs separated by semicolon to pass as
+ * request metadata.
*
*/
@ThreadSafe
@@ -146,11 +163,18 @@ public void shutdown() {
/** Builder utility for this exporter. */
public static class Builder extends ConfigBuilder {
private static final String KEY_SPAN_TIMEOUT = "otel.otlp.span.timeout";
+ private static final String KEY_ENDPOINT = "otel.otlp.endpoint";
+ private static final String KEY_USE_TLS = "otel.otlp.use.tls";
+ private static final String KEY_METADATA = "otel.otlp.metadata";
private ManagedChannel channel;
private long deadlineMs = 1_000; // 1 second
+ @Nullable private String endpoint;
+ private boolean useTls;
+ @Nullable private Metadata metadata;
/**
- * Sets the managed chanel to use when communicating with the backend. Required.
+ * Sets the managed chanel to use when communicating with the backend. Required if {@link
+ * Builder#endpoint} is not set. If {@link Builder#endpoint} is set then build the channel.
*
* @param channel the channel to use
* @return this builder's instance
@@ -171,12 +195,67 @@ public Builder setDeadlineMs(long deadlineMs) {
return this;
}
+ /**
+ * Sets the OTLP endpoint to connect to. Optional.
+ *
+ * @param endpoint endpoint to connect to
+ * @return this builder's instance
+ */
+ public Builder setEndpoint(String endpoint) {
+ this.endpoint = endpoint;
+ return this;
+ }
+
+ /**
+ * Sets use or not TLS, default is false. Optional. Applicable only if {@link Builder#endpoint}
+ * is set to build channel.
+ *
+ * @param useTls use TLS or not
+ * @return this builder's instance
+ */
+ public Builder setUseTls(boolean useTls) {
+ this.useTls = useTls;
+ return this;
+ }
+
+ /**
+ * Add header to request. Optional. Applicable only if {@link Builder#endpoint} is set to build
+ * channel.
+ *
+ * @param key header key
+ * @param value header value
+ * @return this builder's instance
+ */
+ public Builder addHeader(String key, String value) {
+ if (metadata == null) {
+ metadata = new Metadata();
+ }
+ metadata.put(Key.of(key, ASCII_STRING_MARSHALLER), value);
+ return this;
+ }
+
/**
* Constructs a new instance of the exporter based on the builder's values.
*
* @return a new exporter's instance
*/
public OtlpGrpcSpanExporter build() {
+ if (endpoint != null) {
+ final ManagedChannelBuilder> managedChannelBuilder =
+ ManagedChannelBuilder.forTarget(endpoint);
+
+ if (useTls) {
+ managedChannelBuilder.useTransportSecurity();
+ } else {
+ managedChannelBuilder.usePlaintext();
+ }
+
+ if (metadata != null) {
+ managedChannelBuilder.intercept(MetadataUtils.newAttachHeadersInterceptor(metadata));
+ }
+
+ channel = managedChannelBuilder.build();
+ }
return new OtlpGrpcSpanExporter(channel, deadlineMs);
}
@@ -196,6 +275,26 @@ protected Builder fromConfigMap(
if (value != null) {
this.setDeadlineMs(value);
}
+ String endpointValue = getStringProperty(KEY_ENDPOINT, configMap);
+ if (endpointValue != null) {
+ this.setEndpoint(endpointValue);
+ }
+
+ Boolean useTlsValue = getBooleanProperty(KEY_USE_TLS, configMap);
+ if (useTlsValue != null) {
+ this.setUseTls(useTlsValue);
+ }
+
+ String metadataValue = getStringProperty(KEY_METADATA, configMap);
+ if (metadataValue != null) {
+ for (String keyValueString : Splitter.on(';').split(metadataValue)) {
+ final List keyValue = Splitter.on('=').splitToList(keyValueString);
+ if (keyValue.size() == 2) {
+ addHeader(keyValue.get(0), keyValue.get(1));
+ }
+ }
+ }
+
return this;
}
}
diff --git a/exporters/otlp/src/main/java/io/opentelemetry/exporters/otlp/package-info.java b/exporters/otlp/src/main/java/io/opentelemetry/exporters/otlp/package-info.java
index d9111845f7e..a56a0462073 100644
--- a/exporters/otlp/src/main/java/io/opentelemetry/exporters/otlp/package-info.java
+++ b/exporters/otlp/src/main/java/io/opentelemetry/exporters/otlp/package-info.java
@@ -40,6 +40,10 @@
*
* - {@code otel.otlp.metric.timeout}: to set the max waiting time allowed to send each metric
* batch.
+ *
- {@code otel.otlp.endpoint}: to set the endpoint to connect to.
+ *
- {@code otel.otlp.use.tls}: to set use or not TLS.
+ *
- {@code otel.otlp.metadata} to set key-value pairs separated by semicolon to pass as request
+ * metadata.
*
*
* For environment variables, {@link io.opentelemetry.exporters.otlp.OtlpGrpcMetricExporter} will
@@ -48,6 +52,10 @@
*
* - {@code OTEL_OTLP_METRIC_TIMEOUT}: to set the max waiting time allowed to send each metric
* batch.
+ *
- {@code OTEL_OTLP_ENDPOINT}: to set the endpoint to connect to.
+ *
- {@code OTEL_OTLP_USE_TLS}: to set use or not TLS.
+ *
- {@code OTEL_OTLP_METADATA}: to set key-value pairs separated by semicolon to pass as
+ * request metadata.
*
*
* {@link io.opentelemetry.exporters.otlp.OtlpGrpcSpanExporter}
diff --git a/exporters/otlp/src/test/java/io/opentelemetry/exporters/otlp/OtlpGrpcSpanExporterTest.java b/exporters/otlp/src/test/java/io/opentelemetry/exporters/otlp/OtlpGrpcSpanExporterTest.java
index 4b0f30fa9df..8196f8f063e 100644
--- a/exporters/otlp/src/test/java/io/opentelemetry/exporters/otlp/OtlpGrpcSpanExporterTest.java
+++ b/exporters/otlp/src/test/java/io/opentelemetry/exporters/otlp/OtlpGrpcSpanExporterTest.java
@@ -66,10 +66,16 @@ public class OtlpGrpcSpanExporterTest {
public void configTest() {
Map options = new HashMap<>();
options.put("otel.otlp.span.timeout", "12");
+ options.put("otel.otlp.endpoint", "http://localhost:6553");
+ options.put("otel.otlp.use.tls", "true");
+ options.put("otel.otlp.metadata", "key=value");
OtlpGrpcSpanExporter.Builder config = OtlpGrpcSpanExporter.newBuilder();
OtlpGrpcSpanExporter.Builder spy = Mockito.spy(config);
spy.fromConfigMap(options, ConfigBuilderTest.getNaming());
Mockito.verify(spy).setDeadlineMs(12);
+ Mockito.verify(spy).setEndpoint("http://localhost:6553");
+ Mockito.verify(spy).setUseTls(true);
+ Mockito.verify(spy).addHeader("key", "value");
}
@Before