Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

enhance OTLP Exporter configuration #1373

Merged
merged 5 commits into from
Jun 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/**
Expand All @@ -41,13 +50,21 @@
* <ul>
* <li>{@code otel.otlp.span.timeout}: to set the max waiting time allowed to send each span
* batch.
* <li>{@code otel.otlp.endpoint}: to set the endpoint to connect to.
* <li>{@code otel.otlp.use.tls}: to set use or not TLS.
* <li>{@code otel.otlp.metadata} to set key-value pairs separated by semicolon to pass as request
* metadata.
* </ul>
*
* <p>For environment variables, {@link OtlpGrpcSpanExporter} will look for the following names:
*
* <ul>
* <li>{@code OTEL_OTLP_SPAN_TIMEOUT}: to set the max waiting time allowed to send each span
* batch.
* <li>{@code OTEL_OTLP_ENDPOINT}: to set the endpoint to connect to.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a proposal in the specs to standardize environment variables for this sort of thing. Can you please add a comment to https://github.com/open-telemetry/opentelemetry-specification/pull/666/files with the needs here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

* <li>{@code OTEL_OTLP_USE_TLS}: to set use or not TLS.
* <li>{@code OTEL_OTLP_METADATA}: to set key-value pairs separated by semicolon to pass as
* request metadata.
* </ul>
*/
@ThreadSafe
Expand Down Expand Up @@ -146,11 +163,18 @@ public void shutdown() {
/** Builder utility for this exporter. */
public static class Builder extends ConfigBuilder<Builder> {
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
Expand All @@ -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);
}

Expand All @@ -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<String> keyValue = Splitter.on('=').splitToList(keyValueString);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Believe you can use Splitter.withKeyValueSeparator

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be good to create a static final with the splitter

`private static final Splitter.MapSplitter METADATA_PROPERTY_SPLITTER = Splitter.on(';').trimResults().omitEmptyStrings().withKeyValueSplitter('=');

Copy link
Contributor Author

@malafeev malafeev Jun 26, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

withKeyValueSeparator is annotated by @Beta, should we use it?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oof - good catch, I always forget that. Yeah let's not use it.

if (keyValue.size() == 2) {
addHeader(keyValue.get(0), keyValue.get(1));
}
}
}

return this;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@
* <ul>
* <li>{@code otel.otlp.metric.timeout}: to set the max waiting time allowed to send each metric
* batch.
* <li>{@code otel.otlp.endpoint}: to set the endpoint to connect to.
* <li>{@code otel.otlp.use.tls}: to set use or not TLS.
* <li>{@code otel.otlp.metadata} to set key-value pairs separated by semicolon to pass as request
* metadata.
* </ul>
*
* <p>For environment variables, {@link io.opentelemetry.exporters.otlp.OtlpGrpcMetricExporter} will
Expand All @@ -48,6 +52,10 @@
* <ul>
* <li>{@code OTEL_OTLP_METRIC_TIMEOUT}: to set the max waiting time allowed to send each metric
* batch.
* <li>{@code OTEL_OTLP_ENDPOINT}: to set the endpoint to connect to.
* <li>{@code OTEL_OTLP_USE_TLS}: to set use or not TLS.
* <li>{@code OTEL_OTLP_METADATA}: to set key-value pairs separated by semicolon to pass as
* request metadata.
* </ul>
*
* <h2>{@link io.opentelemetry.exporters.otlp.OtlpGrpcSpanExporter}</h2>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,16 @@ public class OtlpGrpcSpanExporterTest {
public void configTest() {
Map<String, String> 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
Expand Down