Fix Jaeger exporter system property config (#1461)

* Fix Jaeger exporter system property config

* Address feedback

* feedback

* oops

* javadoc

* javadoc
This commit is contained in:
Trask Stalnaker 2020-07-25 13:46:40 -07:00 committed by GitHub
parent 0b8858205b
commit 84571612b3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 100 additions and 42 deletions

View File

@ -6,19 +6,45 @@ This is the OpenTelemetry exporter, sending span data to Jaeger via gRPC.
## Configuration
Jaeger exporter can be configured by system properties and environmental variables.
These configuration properties work only for `Jaeger.GrpcSpanExporter.installDefault()`.
The Jaeger gRPC span exporter can be configured programmatically.
* `JAEGER_ENDPOINT` - agents's gRPC endpoint e.g. `localhost:14250`
* `JAEGER_SERVICE_NAME` - service name e.g. `my-deployment`
An example of simple Jaeger gRPC exporter initialization. In this case
spans will be sent to a Jaeger gRPC endpoint running on `localhost`:
An example of simples Jaeger gRPC exporter initialization. In this case
spans will be sent to Jaeger agent running on `localhost`:
```java
Builder builder = JaegerGrpcSpanExporter.Builder.fromEnv();
builder.install(OpenTelemetrySdk.getTracerProvider());
JaegerGrpcSpanExporter exporter =
JaegerGrpcSpanExporter.newBuilder()
.setEndpoint("localhost:14250")
.setServiceName("my-service")
.build();
```
Service name and Endpoint can be also configured via environment variables or system properties.
```java
// Using environment variables
JaegerGrpcSpanExporter exporter =
JaegerGrpcSpanExporter.newBuilder()
.readEnvironmentVariables()
.build()
```
```java
// Using system properties
JaegerGrpcSpanExporter exporter =
JaegerGrpcSpanExporter.newBuilder()
.readSystemProperties()
.build()
```
The Jaeger gRPC span exporter will look for the following environment variables / system properties:
* `OTEL_JAEGER_SERVICE_NAME` / `otel.jaeger.service.name`
* `OTEL_JAEGER_ENDPOINT` / `otel.jaeger.endpoint`
## Compatibility
As with the OpenTelemetry SDK itself, this exporter is compatible with Java 7+ and Android API level 24+.
## Proto files
The proto files in this repository were copied over from the [Jaeger main repository][proto-origin]. At this moment, they have to be manually synchronize, but a [discussion exists][proto-discussion] on how to properly consume them in a more appropriate manner.

View File

@ -21,13 +21,13 @@ import io.grpc.ManagedChannelBuilder;
import io.opentelemetry.exporters.jaeger.proto.api_v2.Collector;
import io.opentelemetry.exporters.jaeger.proto.api_v2.CollectorServiceGrpc;
import io.opentelemetry.exporters.jaeger.proto.api_v2.Model;
import io.opentelemetry.sdk.trace.TracerSdkProvider;
import io.opentelemetry.sdk.common.export.ConfigBuilder;
import io.opentelemetry.sdk.trace.data.SpanData;
import io.opentelemetry.sdk.trace.export.BatchSpanProcessor;
import io.opentelemetry.sdk.trace.export.SpanExporter;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
@ -37,8 +37,6 @@ import javax.annotation.concurrent.ThreadSafe;
@ThreadSafe
public final class JaegerGrpcSpanExporter implements SpanExporter {
private static final Logger logger = Logger.getLogger(JaegerGrpcSpanExporter.class.getName());
private static final String JAEGER_SERVICE_NAME = "JAEGER_SERVICE_NAME";
private static final String JAEGER_ENDPOINT = "JAEGER_ENDPOINT";
private static final String CLIENT_VERSION_KEY = "jaeger.version";
private static final String CLIENT_VERSION_VALUE = "opentelemetry-java";
private static final String DEFAULT_JAEGER_ENDPOINT = "localhost:14250";
@ -165,8 +163,12 @@ public final class JaegerGrpcSpanExporter implements SpanExporter {
}
/** Builder utility for this exporter. */
public static class Builder {
private String serviceName;
public static class Builder extends ConfigBuilder<Builder> {
private static final String KEY_SERVICE_NAME = "otel.jaeger.service.name";
private static final String KEY_ENDPOINT = "otel.jaeger.endpoint";
private String serviceName = UNKNOWN;
private String endpoint = DEFAULT_JAEGER_ENDPOINT;
private ManagedChannel channel;
private long deadlineMs = 1_000; // 1 second
@ -182,7 +184,8 @@ public final class JaegerGrpcSpanExporter implements SpanExporter {
}
/**
* Sets the managed chanel to use when communicating with the backend. Required.
* Sets the managed chanel to use when communicating with the backend. Takes precedence over
* {@link #setEndpoint(String)} if both are called.
*
* @param channel the channel to use.
* @return this.
@ -192,6 +195,18 @@ public final class JaegerGrpcSpanExporter implements SpanExporter {
return this;
}
/**
* Sets the Jaeger endpoint to connect to. Optional, defaults to "localhost:14250".
*
* @param endpoint The Jaeger endpoint URL, ex. "jaegerhost:14250".
* @return this.
* @since 0.7.0
*/
public Builder setEndpoint(String endpoint) {
this.endpoint = endpoint;
return this;
}
/**
* Sets the max waiting time for the collector to process each span batch. Optional.
*
@ -204,17 +219,25 @@ public final class JaegerGrpcSpanExporter implements SpanExporter {
}
/**
* Creates builder from system properties and environmental variables: {@code JAEGER_ENDPOINT}
* e.g. {@code localhost:14250} and {@code JAEGER_SERVICE_NAME} e.g. {@code my-deployment}.
* Sets the configuration values from the given configuration map for only the available keys.
*
* @return thes builder's instance
* @param configMap {@link Map} holding the configuration values.
* @return this.
* @since 0.7.0
*/
public static Builder fromEnv() {
Builder builder = new Builder();
String host = getProperty(JAEGER_ENDPOINT, DEFAULT_JAEGER_ENDPOINT);
builder.channel = ManagedChannelBuilder.forTarget(host).usePlaintext().build();
builder.serviceName = getProperty(JAEGER_SERVICE_NAME, UNKNOWN);
return builder;
@Override
protected Builder fromConfigMap(
Map<String, String> configMap, NamingConvention namingConvention) {
configMap = namingConvention.normalize(configMap);
String stringValue = getStringProperty(KEY_SERVICE_NAME, configMap);
if (stringValue != null) {
this.setServiceName(stringValue);
}
stringValue = getStringProperty(KEY_ENDPOINT, configMap);
if (stringValue != null) {
this.setEndpoint(stringValue);
}
return this;
}
/**
@ -223,27 +246,12 @@ public final class JaegerGrpcSpanExporter implements SpanExporter {
* @return a new exporter's instance.
*/
public JaegerGrpcSpanExporter build() {
if (channel == null) {
channel = ManagedChannelBuilder.forTarget(endpoint).usePlaintext().build();
}
return new JaegerGrpcSpanExporter(serviceName, channel, deadlineMs);
}
/**
* Installs exporter into tracer SDK provider with batching span processor.
*
* @param tracerSdkProvider tracer SDK provider
*/
public void install(TracerSdkProvider tracerSdkProvider) {
BatchSpanProcessor spansProcessor = BatchSpanProcessor.newBuilder(this.build()).build();
tracerSdkProvider.addSpanProcessor(spansProcessor);
}
private Builder() {}
}
private static String getProperty(String name, String defaultValue) {
String val = System.getProperty(name, System.getenv(name));
if (val == null || val.isEmpty()) {
return defaultValue;
}
return val;
}
}

View File

@ -31,6 +31,7 @@ import io.opentelemetry.exporters.jaeger.proto.api_v2.Collector;
import io.opentelemetry.exporters.jaeger.proto.api_v2.Collector.PostSpansRequest;
import io.opentelemetry.exporters.jaeger.proto.api_v2.CollectorServiceGrpc;
import io.opentelemetry.exporters.jaeger.proto.api_v2.Model;
import io.opentelemetry.sdk.common.export.ConfigBuilder;
import io.opentelemetry.sdk.extensions.otproto.TraceProtoUtils;
import io.opentelemetry.sdk.trace.data.SpanData;
import io.opentelemetry.sdk.trace.data.test.TestSpanData;
@ -40,6 +41,8 @@ import io.opentelemetry.trace.Status;
import io.opentelemetry.trace.TraceId;
import java.net.InetAddress;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import org.junit.Rule;
import org.junit.Test;
@ -47,6 +50,7 @@ import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.mockito.ArgumentCaptor;
import org.mockito.ArgumentMatchers;
import org.mockito.Mockito;
/** Unit tests for {@link JaegerGrpcSpanExporter}. */
@RunWith(JUnit4.class)
@ -139,6 +143,26 @@ public class JaegerGrpcSpanExporterTest {
assertTrue("a hostname tag should have been present", foundHostname);
}
@Test
public void configTest() {
Map<String, String> options = new HashMap<>();
String serviceName = "myGreatService";
String endpoint = "127.0.0.1:9090";
options.put("otel.jaeger.service.name", serviceName);
options.put("otel.jaeger.endpoint", endpoint);
JaegerGrpcSpanExporter.Builder config = JaegerGrpcSpanExporter.newBuilder();
JaegerGrpcSpanExporter.Builder spy = Mockito.spy(config);
spy.fromConfigMap(options, ConfigBuilderTest.getNaming()).build();
Mockito.verify(spy).setServiceName(serviceName);
Mockito.verify(spy).setEndpoint(endpoint);
}
abstract static class ConfigBuilderTest extends ConfigBuilder<ConfigBuilderTest> {
public static NamingConvention getNaming() {
return NamingConvention.DOT;
}
}
static class MockCollectorService extends CollectorServiceGrpc.CollectorServiceImplBase {
@Override
public void postSpans(