-
Notifications
You must be signed in to change notification settings - Fork 139
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add xray propagators that prioritizes xray environment variable
This will allow support for AWS's environment variable with no additional config keys and no changes to instrumentation required. I included a propagator that did just the env var propagation without the standard xray propagation as well as one that does both but prioritizes xray env propagation first.
- Loading branch information
1 parent
43cabe4
commit d2c846a
Showing
9 changed files
with
463 additions
and
39 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
26 changes: 26 additions & 0 deletions
26
...in/java/io/opentelemetry/contrib/awsxray/propagator/AwsXrayEnvConfigurablePropagator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
/* | ||
* Copyright The OpenTelemetry Authors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.opentelemetry.contrib.awsxray.propagator; | ||
|
||
import io.opentelemetry.context.propagation.TextMapPropagator; | ||
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; | ||
import io.opentelemetry.sdk.autoconfigure.spi.ConfigurablePropagatorProvider; | ||
|
||
/** | ||
* A {@link ConfigurablePropagatorProvider} which allows enabling the {@link AwsXrayEnvPropagator} | ||
* with the propagator name {@code xray-env}. | ||
*/ | ||
public final class AwsXrayEnvConfigurablePropagator implements ConfigurablePropagatorProvider { | ||
@Override | ||
public TextMapPropagator getPropagator(ConfigProperties config) { | ||
return AwsXrayEnvPropagator.getInstance(); | ||
} | ||
|
||
@Override | ||
public String getName() { | ||
return "xray-env"; | ||
} | ||
} |
93 changes: 93 additions & 0 deletions
93
...gator/src/main/java/io/opentelemetry/contrib/awsxray/propagator/AwsXrayEnvPropagator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
/* | ||
* Copyright The OpenTelemetry Authors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.opentelemetry.contrib.awsxray.propagator; | ||
|
||
import io.opentelemetry.context.Context; | ||
import io.opentelemetry.context.propagation.TextMapGetter; | ||
import io.opentelemetry.context.propagation.TextMapPropagator; | ||
import io.opentelemetry.context.propagation.TextMapSetter; | ||
import java.util.Collections; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.Set; | ||
import javax.annotation.Nullable; | ||
|
||
/** | ||
* Implementation of the AWS X-Ray Trace Header propagation protocol only uses Lambda's {@code | ||
* _X_AMZN_TRACE_ID} environment variable and {@code com.amazonaws.xray.traceHeader} system property | ||
* as the carrier. Carrier passed into {@link #inject(Context, Object, TextMapSetter)} and {@link | ||
* #extract(Context, Object, TextMapGetter)} are ignored. | ||
* | ||
* <p>To register the X-Ray propagator together with default propagator when using the SDK: | ||
* | ||
* <pre>{@code | ||
* OpenTelemetrySdk.builder() | ||
* .setPropagators( | ||
* ContextPropagators.create( | ||
* TextMapPropagator.composite( | ||
* W3CTraceContextPropagator.getInstance(), | ||
* AwsXrayEnvPropagator.getInstance()))) | ||
* .build(); | ||
* }</pre> | ||
*/ | ||
public final class AwsXrayEnvPropagator implements TextMapPropagator { | ||
|
||
private static final String AWS_TRACE_HEADER_ENV_KEY = "_X_AMZN_TRACE_ID"; | ||
private static final String AWS_TRACE_HEADER_PROP = "com.amazonaws.xray.traceHeader"; | ||
private final AwsXrayPropagator xrayPropagator = AwsXrayPropagator.getInstance(); | ||
|
||
private static final AwsXrayEnvPropagator INSTANCE = new AwsXrayEnvPropagator(); | ||
|
||
private AwsXrayEnvPropagator() { | ||
// singleton | ||
} | ||
|
||
public static AwsXrayEnvPropagator getInstance() { | ||
return INSTANCE; | ||
} | ||
|
||
@Override | ||
public List<String> fields() { | ||
return xrayPropagator.fields(); | ||
} | ||
|
||
@Override | ||
public <C> void inject(Context context, @Nullable C carrier, TextMapSetter<C> setter) {} | ||
|
||
@Override | ||
public <C> Context extract(Context context, @Nullable C carrier, TextMapGetter<C> ignored) { | ||
String traceHeader = System.getProperty(AWS_TRACE_HEADER_PROP); | ||
if (isEmptyOrNull(traceHeader)) { | ||
traceHeader = System.getenv(AWS_TRACE_HEADER_ENV_KEY); | ||
} | ||
if (isEmptyOrNull(traceHeader)) { | ||
return context; | ||
} | ||
return xrayPropagator.extract( | ||
context, | ||
Collections.singletonMap(AwsXrayPropagator.TRACE_HEADER_KEY, traceHeader), | ||
MapGetter.INSTANCE); | ||
} | ||
|
||
private static boolean isEmptyOrNull(@Nullable String value) { | ||
return value == null || value.isEmpty(); | ||
} | ||
|
||
private enum MapGetter implements TextMapGetter<Map<String, String>> { | ||
INSTANCE; | ||
|
||
@Override | ||
public Set<String> keys(Map<String, String> map) { | ||
return map.keySet(); | ||
} | ||
|
||
@Override | ||
@Nullable | ||
public String get(@Nullable Map<String, String> map, String s) { | ||
return map == null ? null : map.get(s); | ||
} | ||
} | ||
} |
26 changes: 26 additions & 0 deletions
26
...java/io/opentelemetry/contrib/awsxray/propagator/AwsXrayLambdaConfigurablePropagator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
/* | ||
* Copyright The OpenTelemetry Authors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.opentelemetry.contrib.awsxray.propagator; | ||
|
||
import io.opentelemetry.context.propagation.TextMapPropagator; | ||
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; | ||
import io.opentelemetry.sdk.autoconfigure.spi.ConfigurablePropagatorProvider; | ||
|
||
/** | ||
* A {@link ConfigurablePropagatorProvider} which allows enabling the {@link | ||
* AwsXrayLambdaPropagator} with the propagator name {@code aws}. | ||
*/ | ||
public final class AwsXrayLambdaConfigurablePropagator implements ConfigurablePropagatorProvider { | ||
@Override | ||
public TextMapPropagator getPropagator(ConfigProperties config) { | ||
return AwsXrayLambdaPropagator.getInstance(); | ||
} | ||
|
||
@Override | ||
public String getName() { | ||
return "aws"; | ||
} | ||
} |
63 changes: 63 additions & 0 deletions
63
...or/src/main/java/io/opentelemetry/contrib/awsxray/propagator/AwsXrayLambdaPropagator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
/* | ||
* Copyright The OpenTelemetry Authors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.opentelemetry.contrib.awsxray.propagator; | ||
|
||
import io.opentelemetry.context.Context; | ||
import io.opentelemetry.context.propagation.TextMapGetter; | ||
import io.opentelemetry.context.propagation.TextMapPropagator; | ||
import io.opentelemetry.context.propagation.TextMapSetter; | ||
import java.util.List; | ||
import javax.annotation.Nullable; | ||
|
||
/** | ||
* Implementation of the AWS X-Ray Trace Header propagation protocol but with special handling for | ||
* Lambda's {@code _X_AMZN_TRACE_ID} environment variable and {@code com.amazonaws.xray.traceHeader} | ||
* system property. | ||
* | ||
* <p>To register the X-Ray propagator together with default propagator when using the SDK: | ||
* | ||
* <pre>{@code | ||
* OpenTelemetrySdk.builder() | ||
* .setPropagators( | ||
* ContextPropagators.create( | ||
* TextMapPropagator.composite( | ||
* W3CTraceContextPropagator.getInstance(), | ||
* AwsXrayLambdaPropagator.getInstance()))) | ||
* .build(); | ||
* }</pre> | ||
*/ | ||
public final class AwsXrayLambdaPropagator implements TextMapPropagator { | ||
private static final AwsXrayPropagator XRAY = AwsXrayPropagator.getInstance(); | ||
private static final AwsXrayEnvPropagator XRAY_ENV = AwsXrayEnvPropagator.getInstance(); | ||
private static final AwsXrayLambdaPropagator INSTANCE = new AwsXrayLambdaPropagator(); | ||
|
||
private AwsXrayLambdaPropagator() { | ||
// singleton | ||
} | ||
|
||
public static AwsXrayLambdaPropagator getInstance() { | ||
return INSTANCE; | ||
} | ||
|
||
@Override | ||
public List<String> fields() { | ||
return XRAY.fields(); | ||
} | ||
|
||
@Override | ||
public <C> void inject(Context context, @Nullable C carrier, TextMapSetter<C> setter) { | ||
XRAY.inject(context, carrier, setter); | ||
// XRAY_ENV.inject is a no-op, so no need to invoke. | ||
} | ||
|
||
@Override | ||
public <C> Context extract(Context context, @Nullable C carrier, TextMapGetter<C> getter) { | ||
context = XRAY.extract(context, carrier, getter); | ||
// Currently last one wins, so invoke XRAY_ENV second to allow parent to be overwritten. | ||
context = XRAY_ENV.extract(context, carrier, getter); | ||
return context; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
112 changes: 112 additions & 0 deletions
112
...r/src/test/java/io/opentelemetry/contrib/awsxray/propagator/AwsXrayEnvPropagatorTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
/* | ||
* Copyright The OpenTelemetry Authors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.opentelemetry.contrib.awsxray.propagator; | ||
|
||
import static io.opentelemetry.contrib.awsxray.propagator.AwsXrayPropagator.TRACE_HEADER_KEY; | ||
import static io.opentelemetry.contrib.awsxray.propagator.AwsXrayPropagatorTest.GETTER; | ||
import static io.opentelemetry.contrib.awsxray.propagator.AwsXrayPropagatorTest.SETTER; | ||
import static io.opentelemetry.contrib.awsxray.propagator.AwsXrayPropagatorTest.SPAN_ID; | ||
import static io.opentelemetry.contrib.awsxray.propagator.AwsXrayPropagatorTest.TRACE_ID; | ||
import static io.opentelemetry.contrib.awsxray.propagator.AwsXrayPropagatorTest.getSpanContext; | ||
import static io.opentelemetry.contrib.awsxray.propagator.AwsXrayPropagatorTest.withSpanContext; | ||
import static org.assertj.core.api.Assertions.assertThat; | ||
|
||
import io.opentelemetry.api.trace.SpanContext; | ||
import io.opentelemetry.api.trace.TraceFlags; | ||
import io.opentelemetry.api.trace.TraceState; | ||
import io.opentelemetry.context.Context; | ||
import java.util.Collections; | ||
import java.util.LinkedHashMap; | ||
import java.util.Map; | ||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.api.extension.ExtendWith; | ||
import uk.org.webcompere.systemstubs.environment.EnvironmentVariables; | ||
import uk.org.webcompere.systemstubs.jupiter.SystemStub; | ||
import uk.org.webcompere.systemstubs.jupiter.SystemStubsExtension; | ||
import uk.org.webcompere.systemstubs.properties.SystemProperties; | ||
|
||
@ExtendWith(SystemStubsExtension.class) | ||
class AwsXrayEnvPropagatorTest { | ||
private final AwsXrayEnvPropagator subject = AwsXrayEnvPropagator.getInstance(); | ||
|
||
@SystemStub final EnvironmentVariables environmentVariables = new EnvironmentVariables(); | ||
@SystemStub final SystemProperties systemProperties = new SystemProperties(); | ||
|
||
@Test | ||
void fields_valid() { | ||
assertThat(subject.fields()).containsOnly("X-Amzn-Trace-Id"); | ||
} | ||
|
||
@Test | ||
void inject_doesNothing() { | ||
Map<String, String> carrier = new LinkedHashMap<>(); | ||
subject.inject( | ||
withSpanContext( | ||
SpanContext.create(TRACE_ID, SPAN_ID, TraceFlags.getSampled(), TraceState.getDefault()), | ||
Context.current()), | ||
carrier, | ||
SETTER); | ||
|
||
assertThat(carrier).isEmpty(); | ||
} | ||
|
||
@Test | ||
void extract_carrierIgnored() { | ||
Map<String, String> carrier = | ||
Collections.singletonMap( | ||
TRACE_HEADER_KEY, | ||
"Root=1-8a3c60f7-d188f8fa79d48a391a778fa6;Parent=53995c3f42cd8ad8;Sampled=1"); | ||
assertThat(subject.extract(Context.current(), carrier, GETTER)).isEqualTo(Context.current()); | ||
} | ||
|
||
@Test | ||
void extract_fromEnvironmentVariable() { | ||
environmentVariables.set( | ||
"_X_AMZN_TRACE_ID", | ||
"Root=1-00000000-d188f8fa79d48a391a778fa6;Parent=53995c3f42cd8ad8;Sampled=1;Foo=Bar"); | ||
|
||
assertThat(getSpanContext(subject.extract(Context.current(), Collections.emptyMap(), GETTER))) | ||
.isEqualTo( | ||
SpanContext.createFromRemoteParent( | ||
"00000000d188f8fa79d48a391a778fa6", | ||
SPAN_ID, | ||
TraceFlags.getSampled(), | ||
TraceState.getDefault())); | ||
} | ||
|
||
@Test | ||
void extract_fromSystemProperty() { | ||
systemProperties.set( | ||
"com.amazonaws.xray.traceHeader", | ||
"Root=1-00000000-d188f8fa79d48a391a778fa6;Parent=53995c3f42cd8ad8;Sampled=1;Foo=Bar"); | ||
|
||
assertThat(getSpanContext(subject.extract(Context.current(), Collections.emptyMap(), GETTER))) | ||
.isEqualTo( | ||
SpanContext.createFromRemoteParent( | ||
"00000000d188f8fa79d48a391a778fa6", | ||
SPAN_ID, | ||
TraceFlags.getSampled(), | ||
TraceState.getDefault())); | ||
} | ||
|
||
@Test | ||
void extract_systemPropertyBeforeEnvironmentVariable() { | ||
environmentVariables.set( | ||
"_X_AMZN_TRACE_ID", | ||
"Root=1-00000000-240000000000000000000001;Parent=1600000000000001;Sampled=1;Foo=Bar"); | ||
systemProperties.set( | ||
"com.amazonaws.xray.traceHeader", | ||
"Root=1-00000000-240000000000000000000002;Parent=1600000000000002;Sampled=1;Foo=Baz"); | ||
|
||
assertThat(getSpanContext(subject.extract(Context.current(), Collections.emptyMap(), GETTER))) | ||
.isEqualTo( | ||
SpanContext.createFromRemoteParent( | ||
"00000000240000000000000000000002", | ||
"1600000000000002", | ||
TraceFlags.getSampled(), | ||
TraceState.getDefault())); | ||
} | ||
} |
Oops, something went wrong.