Skip to content

Commit

Permalink
Add OTEL Config Params
Browse files Browse the repository at this point in the history
  • Loading branch information
luneo7 committed Jun 4, 2021
1 parent cc94f11 commit 9c503dc
Show file tree
Hide file tree
Showing 11 changed files with 310 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,17 @@ void registerOpenTelemetryContextStorage(

@BuildStep(onlyIf = OpenTelemetryEnabled.class)
@Record(ExecutionTime.STATIC_INIT)
void createOpenTelemetry(OpenTelemetryRecorder recorder, Optional<TracerProviderBuildItem> tracerProviderBuildItem,
void createOpenTelemetry(OpenTelemetryConfig openTelemetryConfig,
OpenTelemetryRecorder recorder,
Optional<TracerProviderBuildItem> tracerProviderBuildItem,
LaunchModeBuildItem launchMode) {
if (launchMode.getLaunchMode() == LaunchMode.DEVELOPMENT) {
recorder.resetGlobalOpenTelemetryForDevMode();
}

RuntimeValue<SdkTracerProvider> tracerProvider = tracerProviderBuildItem.map(TracerProviderBuildItem::getTracerProvider)
.orElse(null);
recorder.createOpenTelemetry(tracerProvider);
recorder.createOpenTelemetry(tracerProvider, openTelemetryConfig);
recorder.eagerlyCreateContextStorage();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,11 +113,13 @@ VertxOptionsConsumerBuildItem vertxTracingOptions(TracerRecorder recorder) {
@Record(ExecutionTime.STATIC_INIT)
TracerProviderBuildItem createTracerProvider(TracerRecorder recorder,
ApplicationInfoBuildItem appInfo,
OpenTelemetryConfig config,
ShutdownContextBuildItem shutdownContext,
BeanContainerBuildItem beanContainerBuildItem) {
String serviceName = appInfo.getName();
String serviceVersion = appInfo.getVersion();
return new TracerProviderBuildItem(recorder.createTracerProvider(serviceName, serviceVersion, shutdownContext));
return new TracerProviderBuildItem(
recorder.createTracerProvider(config.tracer, serviceName, serviceVersion, shutdownContext));
}

@BuildStep(onlyIf = TracerEnabled.class)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.quarkus.opentelemetry.deployment;

import static io.opentelemetry.api.common.AttributeKey.stringKey;
import static io.opentelemetry.semconv.resource.attributes.ResourceAttributes.SERVICE_NAME;
import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.HTTP_CLIENT_IP;
import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.HTTP_FLAVOR;
import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.HTTP_HOST;
Expand All @@ -12,6 +13,7 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
Expand All @@ -21,12 +23,18 @@
import javax.enterprise.event.Observes;
import javax.inject.Inject;

import org.hamcrest.MatcherAssert;
import org.hamcrest.collection.ArrayMatching;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.baggage.propagation.W3CBaggagePropagator;
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator;
import io.opentelemetry.context.propagation.TextMapPropagator;
import io.opentelemetry.sdk.common.CompletableResultCode;
import io.opentelemetry.sdk.trace.data.SpanData;
import io.opentelemetry.sdk.trace.export.SpanExporter;
Expand All @@ -38,19 +46,29 @@
public class VertxOpenTelemetryTest {
@RegisterExtension
static final QuarkusUnitTest unitTest = new QuarkusUnitTest()
.overrideConfigKey("quarkus.opentelemetry.propagators", "trace-context,baggage")
.overrideConfigKey("quarkus.opentelemetry.tracer.resource-attributes", "service.name=test")
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class));

@Inject
MyExporter myExporter;

@Inject
OpenTelemetry openTelemetry;

@Test
void trace() {
void trace() throws NoSuchFieldException, IllegalAccessException {
RestAssured.when().get("/tracer").then()
.statusCode(200)
.body(is("Hello Tracer!"));

List<SpanData> spans = myExporter.getFinishedSpanItems();

TextMapPropagator textMapPropagator = openTelemetry.getPropagators().getTextMapPropagator();
Field privatePropagatorsField = textMapPropagator.getClass().getDeclaredField("textPropagators");
privatePropagatorsField.setAccessible(true);
TextMapPropagator[] textMapPropagators = (TextMapPropagator[]) privatePropagatorsField.get(textMapPropagator);

assertEquals(2, spans.size());
assertEquals("io.quarkus.vertx.opentelemetry", spans.get(0).getName());
assertEquals("hello!", spans.get(0).getAttributes().get(stringKey("test.message")));
Expand All @@ -60,6 +78,10 @@ void trace() {
assertEquals("http", spans.get(1).getAttributes().get(HTTP_SCHEME));
assertEquals("localhost:8081", spans.get(1).getAttributes().get(HTTP_HOST));
assertEquals("127.0.0.1", spans.get(1).getAttributes().get(HTTP_CLIENT_IP));
assertEquals("test", spans.get(1).getResource().getAttributes().get(SERVICE_NAME));
MatcherAssert.assertThat(textMapPropagators,
ArrayMatching.arrayContainingInAnyOrder(W3CTraceContextPropagator.getInstance(),
W3CBaggagePropagator.getInstance()));
assertNotNull(spans.get(1).getAttributes().get(HTTP_USER_AGENT));
}

Expand Down
20 changes: 20 additions & 0 deletions extensions/opentelemetry/opentelemetry/runtime/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,30 @@
<optional>true</optional>
</dependency>

<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-extension-aws</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-extension-trace-propagators</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-sdk</artifactId>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-sdk-extension-aws</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-sdk-extension-resources</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-semconv</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package io.quarkus.opentelemetry.runtime;

public final class ClassUtil {
private ClassUtil() {
}

public static void checkAwsSdkExtension(String feature) {
ClassUtil.checkClassExists("io.opentelemetry.sdk.extension.aws.resource.BeanstalkResource",
feature,
"opentelemetry-sdk-extension-aws");
}

public static void checkAwsExtension(String feature) {
ClassUtil.checkClassExists("io.opentelemetry.extension.aws.AwsXrayPropagator",
feature,
"opentelemetry-extension-aws");
}

public static void checkPropagatorsExtension(String feature) {
ClassUtil.checkClassExists(
"io.opentelemetry.extension.trace.propagation.B3Propagator",
feature,
"opentelemetry-extension-trace-propagators");
}

public static void checkResourcesExtension(String feature) {
ClassUtil.checkClassExists("io.opentelemetry.sdk.extension.resources.HostResource",
feature,
"opentelemetry-sdk-extension-resources");
}

public static void checkClassExists(String className, String featureName, String requiredLibrary) {
try {
Class.forName(className, true, Thread.currentThread().getContextClassLoader());
} catch (ClassNotFoundException unused) {
throw new IllegalArgumentException(
featureName
+ " enabled but "
+ requiredLibrary
+ " not found on classpath. "
+ "Make sure to add it as a dependency to enable this feature.");
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package io.quarkus.opentelemetry.runtime;

import java.util.List;

import io.quarkus.opentelemetry.runtime.tracing.TracerConfig;
import io.quarkus.runtime.annotations.ConfigItem;
import io.quarkus.runtime.annotations.ConfigRoot;
Expand All @@ -15,6 +17,26 @@ public final class OpenTelemetryConfig {
@ConfigItem(defaultValue = "true")
public boolean enabled;

/**
* Comma separated list of OpenTelemetry propagators which must be supported.
* <p>
* Valid values are {@code b3, b3-multi, baggage, jaeger, ot-trace, trace-context, xray}.
* <p>
* Default value is {@code traceContext}
*/
@ConfigItem(defaultValue = "traceContext")
public List<Propagator> propagators;

/** Build / static runtime config for tracer */
public TracerConfig tracer;

public enum Propagator {
B3,
B3_MULTI,
BAGGAGE,
JAEGER,
OT_TRACE,
TRACE_CONTEXT,
XRAY
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package io.quarkus.opentelemetry.runtime;

import java.util.function.Supplier;
import java.util.stream.Collectors;

import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator;
import io.opentelemetry.context.ContextStorage;
import io.opentelemetry.context.propagation.ContextPropagators;
import io.opentelemetry.context.propagation.TextMapPropagator;
import io.opentelemetry.sdk.OpenTelemetrySdk;
import io.opentelemetry.sdk.OpenTelemetrySdkBuilder;
import io.opentelemetry.sdk.trace.SdkTracerProvider;
Expand All @@ -23,16 +24,19 @@ public void resetGlobalOpenTelemetryForDevMode() {
}

/* STATIC INIT */
public void createOpenTelemetry(RuntimeValue<SdkTracerProvider> tracerProvider) {
public void createOpenTelemetry(RuntimeValue<SdkTracerProvider> tracerProvider, OpenTelemetryConfig openTelemetryConfig) {
OpenTelemetrySdkBuilder builder = OpenTelemetrySdk.builder();

// Set tracer provider if present
if (tracerProvider != null) {
builder.setTracerProvider(tracerProvider.getValue());
}

// Add propagators. //TODO Need a way to handle this with config
builder.setPropagators(ContextPropagators.create(W3CTraceContextPropagator.getInstance()));
builder.setPropagators(
ContextPropagators.create(
TextMapPropagator.composite(openTelemetryConfig.propagators.stream()
.map(OpenTelemetryUtil::mapPropagator)
.collect(Collectors.toSet()))));

builder.buildAndRegisterGlobal();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package io.quarkus.opentelemetry.runtime;

import static io.quarkus.opentelemetry.runtime.OpenTelemetryConfig.Propagator.BAGGAGE;
import static io.quarkus.opentelemetry.runtime.OpenTelemetryConfig.Propagator.TRACE_CONTEXT;
import static io.quarkus.opentelemetry.runtime.OpenTelemetryConfig.Propagator.XRAY;

import io.opentelemetry.api.baggage.propagation.W3CBaggagePropagator;
import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator;
import io.opentelemetry.context.propagation.TextMapPropagator;
import io.opentelemetry.extension.aws.AwsXrayPropagator;
import io.opentelemetry.extension.trace.propagation.B3Propagator;
import io.opentelemetry.extension.trace.propagation.JaegerPropagator;
import io.opentelemetry.extension.trace.propagation.OtTracePropagator;

public final class OpenTelemetryUtil {
private OpenTelemetryUtil() {
}

public static TextMapPropagator mapPropagator(OpenTelemetryConfig.Propagator propagator) {
if (BAGGAGE == propagator) {
return W3CBaggagePropagator.getInstance();
}
if (TRACE_CONTEXT == propagator) {
return W3CTraceContextPropagator.getInstance();
}
if (XRAY == propagator) {
ClassUtil.checkAwsExtension(propagator.name() + " propagator");
return AwsXrayPropagator.getInstance();
}
// Other propagators are in the extension artifact. Check one of the propagators.
ClassUtil.checkPropagatorsExtension(propagator.name() + " propagator");

switch (propagator) {
case B3:
return B3Propagator.injectingSingleHeader();
case B3_MULTI:
return B3Propagator.injectingMultiHeaders();
case JAEGER:
return JaegerPropagator.getInstance();
case OT_TRACE:
return OtTracePropagator.getInstance();
default:
throw new IllegalStateException("Unrecognized value for propagator: " + propagator);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.quarkus.opentelemetry.runtime.tracing;

import java.util.List;
import java.util.Optional;

import io.quarkus.runtime.annotations.ConfigGroup;
Expand All @@ -19,8 +20,51 @@ public class TracerConfig {
/** Build / static runtime config for span exporters */
public SpanExporterConfig exporter;

/**
* Tracing ID generator.
* <p>
* Valid values are {@code xray}.
*/
@ConfigItem
public Optional<IdGenerator> idGenerator;

/**
* A comma separated list of name = value resource attributes that
* represents the entity producing telemetry
* (eg. {@code service.name=authservice}).
*/
@ConfigItem
public Optional<List<String>> resourceAttributes;

/**
* Comma separated list of resources that represents the entity that is
* producing telemetry.
* <p>
* Valid values are {@code beanstalk, ec2, ecs, eks, host, lambda, os,
* process, process_runtime}.
*/
@ConfigItem
public Optional<List<Resource>> resources;

/** Build / static runtime config for span exporters */
@ConfigGroup
public static class SpanExporterConfig {
}

public enum IdGenerator {
DEFAULT,
XRAY
}

public enum Resource {
BEANSTALK,
EC2,
ECS,
EKS,
HOST,
LAMBDA,
OS,
PROCESS,
PROCESS_RUNTIME
}
}
Loading

0 comments on commit 9c503dc

Please sign in to comment.