Skip to content

Commit a5ff6f5

Browse files
committed
Add AWS X-Ray Propagator support in OpenTelemetry tracing module, enhance TracingOpenTelemetry for additional span operations, and update dependencies.
1 parent df7fae0 commit a5ff6f5

5 files changed

Lines changed: 45 additions & 131 deletions

File tree

pom.xml

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
-->
1515

1616
<project xmlns="http://maven.apache.org/POM/4.0.0"
17-
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
18-
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
17+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
18+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
1919
<modelVersion>4.0.0</modelVersion>
2020

2121
<groupId>software.amazon.lambda</groupId>
@@ -25,7 +25,8 @@
2525

2626
<name>Powertools for AWS Lambda (Java) - Parent</name>
2727
<description>
28-
A suite of utilities for AWS Lambda Functions that makes tracing with AWS X-Ray, structured logging and creating custom metrics asynchronously easier.
28+
A suite of utilities for AWS Lambda Functions that makes tracing with AWS X-Ray, structured logging and creating
29+
custom metrics asynchronously easier.
2930
</description>
3031
<scm>
3132
<url>https://github.com/aws-powertools/powertools-lambda-java</url>
@@ -121,6 +122,7 @@
121122
<crac.version>1.5.0</crac.version>
122123
<native-maven-plugin.version>0.11.5</native-maven-plugin.version>
123124
<opentelemetry-api.version>1.65.0</opentelemetry-api.version>
125+
<opentelemetry.aws.xray.propagator.version>1.59.0-alpha</opentelemetry.aws.xray.propagator.version>
124126

125127
<!-- As we have a .mvn directory at the root of the project, this will evaluate to the root directory
126128
regardless of where maven is run - sub-module, or root. -->
@@ -473,7 +475,8 @@
473475
<enabled>true</enabled>
474476
<options>
475477
<enableExperimentalPredefinedClasses>true</enableExperimentalPredefinedClasses>
476-
<enableExperimentalUnsafeAllocationTracing>true</enableExperimentalUnsafeAllocationTracing>
478+
<enableExperimentalUnsafeAllocationTracing>true
479+
</enableExperimentalUnsafeAllocationTracing>
477480
</options>
478481
<metadataCopy>
479482
<disabledStages>
@@ -694,7 +697,9 @@
694697
<artifactId>maven-surefire-plugin</artifactId>
695698
<configuration>
696699
<environmentVariables>
697-
<JDK_JAVA_OPTIONS>--add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED</JDK_JAVA_OPTIONS>
700+
<JDK_JAVA_OPTIONS>--add-opens java.base/java.util=ALL-UNNAMED --add-opens
701+
java.base/java.lang=ALL-UNNAMED
702+
</JDK_JAVA_OPTIONS>
698703
</environmentVariables>
699704
</configuration>
700705
</plugin>

powertools-tracing-opentelemetry/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,11 @@
4848
<artifactId>opentelemetry-exporter-otlp</artifactId>
4949
<version>${opentelemetry-api.version}</version>
5050
</dependency>
51+
<dependency>
52+
<groupId>io.opentelemetry.contrib</groupId>
53+
<artifactId>opentelemetry-aws-xray-propagator</artifactId>
54+
<version>${opentelemetry.aws.xray.propagator.version}</version>
55+
</dependency>
5156
<dependency>
5257
<groupId>org.aspectj</groupId>
5358
<artifactId>aspectjrt</artifactId>

powertools-tracing-opentelemetry/src/main/java/software/amazon/lambda/powertools/tracing/opentelemetry/TracingOpenTelemetry.java

Lines changed: 22 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,7 @@
2929
import java.util.Collections;
3030
import java.util.List;
3131
import java.util.Objects;
32-
import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor;
3332
import software.amazon.lambda.powertools.tracing.opentelemetry.context.LambdaEventContextExtractorResolver;
34-
import software.amazon.lambda.powertools.tracing.opentelemetry.internal.AttributesConstants;
3533
import software.amazon.lambda.powertools.tracing.opentelemetry.internal.SpanOperation;
3634
import software.amazon.lambda.powertools.tracing.opentelemetry.internal.SpanScope;
3735
import software.amazon.lambda.powertools.tracing.opentelemetry.provider.OpenTelemetryProvider;
@@ -76,6 +74,10 @@ public TracingOpenTelemetry(
7674
);
7775
}
7876

77+
public Tracer tracer() {
78+
return tracer;
79+
}
80+
7981
public TextMapPropagator propagator() {
8082
return propagator;
8183
}
@@ -99,33 +101,33 @@ public SpanScope addSpan(String name, SpanKind kind) {
99101
return addSpan(name, kind, Attributes.empty());
100102
}
101103

102-
103104
public SpanScope addSpan(String name, SpanKind kind, Attributes attributes) {
104105

105-
Objects.requireNonNull(name, "name must not be null");
106-
Objects.requireNonNull(kind, "kind must not be null");
107-
Objects.requireNonNull(attributes, "attributes must not be null");
108106
return addSpan(name, kind, attributes, Context.current());
109107
}
110108

111-
112109
public SpanScope addSpan(String name, SpanKind kind, Attributes attributes, Context parentContext) {
113110

114-
Objects.requireNonNull(parentContext, "parentContext must not be null");
115111
return addSpan(name, kind, attributes, parentContext, Collections.emptyList());
116112
}
117113

118114
public SpanScope addSpan(
119-
String spanName,
120-
SpanKind spanKind,
115+
String name,
116+
SpanKind kind,
121117
Attributes attributes,
122118
Context parentContext,
123119
List<SpanContext> spanContexts
124120
) {
125121

122+
Objects.requireNonNull(name, "name must not be null");
123+
Objects.requireNonNull(kind, "kind must not be null");
124+
Objects.requireNonNull(attributes, "attributes must not be null");
125+
Objects.requireNonNull(parentContext, "parentContext must not be null");
126+
Objects.requireNonNull(spanContexts, "spanContexts must not be null");
127+
126128
SpanBuilder spanBuilder = tracer
127-
.spanBuilder(spanName)
128-
.setSpanKind(spanKind)
129+
.spanBuilder(name)
130+
.setSpanKind(kind)
129131
.setParent(parentContext)
130132
.setAllAttributes(attributes);
131133

@@ -137,43 +139,20 @@ public SpanScope addSpan(
137139

138140
public <T> T withSpan(String name, SpanOperation<T> operation) throws Exception {
139141

140-
Objects.requireNonNull(operation, "operation must not be null");
141-
142-
try (SpanScope scope = addSpan(name)) {
143-
try {
144-
return operation.execute(scope.span());
145-
} catch (Exception exception) {
146-
scope.recordException(exception);
147-
throw exception;
148-
}
149-
}
142+
return withSpan(name, SpanKind.INTERNAL, Attributes.empty(), operation);
150143
}
151144

152-
public <T> T captureLambdaHandler(
145+
public <T> T withSpan(
153146
String name,
154-
com.amazonaws.services.lambda.runtime.Context lambdaContext,
155-
io.opentelemetry.context.Context parentContext,
147+
SpanKind kind,
148+
Attributes attributes,
156149
SpanOperation<T> operation
157150
) throws Exception {
158-
159-
Objects.requireNonNull(name, "name must not be null");
160-
Objects.requireNonNull(parentContext, "parentContext must not be null");
161151
Objects.requireNonNull(operation, "operation must not be null");
162152

163-
Span span = tracer.spanBuilder(name)
164-
.setParent(parentContext)
165-
.setSpanKind(SpanKind.SERVER)
166-
.setAttribute(AttributesConstants.AWS_LAMBDA_FUNCTION_ARN, LambdaHandlerProcessor.isColdStart())
167-
.setAttribute(AttributesConstants.FAAS_INVOCATION_ID, lambdaContext.getAwsRequestId())
168-
.startSpan();
169-
170-
try (SpanScope scope = new SpanScope(span)) {
153+
try (SpanScope scope = addSpan(name, kind, attributes)) {
171154
try {
172-
T result = operation.execute(span);
173-
174-
LambdaHandlerProcessor.coldStartDone();
175-
176-
return result;
155+
return operation.execute(scope.span());
177156
} catch (Exception exception) {
178157
scope.recordException(exception);
179158
throw exception;
@@ -186,25 +165,24 @@ public <T> Context extractContext(T carrier, TextMapGetter<T> getter) {
186165
return extractContext(Context.current(), carrier, getter);
187166
}
188167

189-
190168
public <T> Context extractContext(Context context, T carrier, TextMapGetter<T> getter) {
191169

192170
Objects.requireNonNull(context, "context must not be null");
171+
Objects.requireNonNull(carrier, "carrier must not be null");
193172
Objects.requireNonNull(getter, "getter must not be null");
194173

195174
return propagator.extract(context, carrier, getter);
196175
}
197176

198-
199177
public <T> void injectContext(T carrier, TextMapSetter<T> setter) {
200178

201179
injectContext(Context.current(), carrier, setter);
202180
}
203181

204-
205182
public <T> void injectContext(Context context, T carrier, TextMapSetter<T> setter) {
206183

207184
Objects.requireNonNull(context, "context must not be null");
185+
Objects.requireNonNull(carrier, "carrier must not be null");
208186
Objects.requireNonNull(setter, "setter must not be null");
209187

210188
propagator.inject(context, carrier, setter);
@@ -218,12 +196,10 @@ private static LambdaEventContextExtractorResolver createDefaultEventContextExtr
218196
return LambdaEventContextExtractorResolver.create();
219197
}
220198

221-
222199
public static TracingOpenTelemetry create() {
223200
return new TracingOpenTelemetry();
224201
}
225202

226-
227203
public static Builder builder() {
228204
return new Builder();
229205
}

powertools-tracing-opentelemetry/src/main/java/software/amazon/lambda/powertools/tracing/opentelemetry/provider/OpenTelemetryProvider.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator;
1212
import io.opentelemetry.context.propagation.TextMapGetter;
1313
import io.opentelemetry.context.propagation.TextMapPropagator;
14+
import io.opentelemetry.contrib.awsxray.propagator.AwsXrayPropagator;
1415
import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter;
1516
import io.opentelemetry.sdk.trace.SdkTracerProvider;
1617
import io.opentelemetry.sdk.trace.export.BatchSpanProcessor;
@@ -33,6 +34,7 @@ public final class OpenTelemetryProvider {
3334
private static final SdkTracerProvider TRACER_PROVIDER = createTracerProvider();
3435
private static final TraceContextPropagationMode TRACE_CONTEXT_PROPAGATION_MODE = retrieveTraceContextMode();
3536
private static final TextMapGetter<Map<String, String>> TEXT_MAP_GETTER = createTextMapGetter();
37+
private static final TextMapPropagator PROPAGATOR = createPropagator();
3638
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
3739

3840
private OpenTelemetryProvider() {
@@ -55,7 +57,7 @@ public static SdkTracerProvider tracerProvider() {
5557
}
5658

5759
public static TextMapPropagator propagator() {
58-
return createPropagator();
60+
return PROPAGATOR;
5961
}
6062

6163
public static TextMapGetter<Map<String, String>> textMapGetter() {
@@ -127,9 +129,11 @@ private static SdkTracerProvider createTracerProvider() {
127129
.addSpanProcessor(processor)
128130
.build();
129131
}
130-
131-
//TODO Pending adding AWS X-RAY propagation, the library opentelemetry-aws-xray-propagator is still in alpha
132+
132133
private static TextMapPropagator createPropagator() {
133-
return W3CTraceContextPropagator.getInstance();
134+
return TextMapPropagator.composite(
135+
W3CTraceContextPropagator.getInstance(),
136+
AwsXrayPropagator.getInstance()
137+
);
134138
}
135139
}

powertools-tracing-opentelemetry/src/test/java/software/amazon/lambda/powertools/tracing/opentelemetry/TracingOpenTelemetryTest.java

Lines changed: 0 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,15 @@
1919

2020
import io.opentelemetry.api.trace.Span;
2121
import io.opentelemetry.api.trace.SpanContext;
22-
import io.opentelemetry.api.trace.SpanKind;
2322
import io.opentelemetry.api.trace.Tracer;
2423
import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator;
2524
import io.opentelemetry.context.Context;
2625
import io.opentelemetry.context.propagation.TextMapGetter;
2726
import io.opentelemetry.context.propagation.TextMapPropagator;
2827
import io.opentelemetry.sdk.testing.exporter.InMemorySpanExporter;
2928
import io.opentelemetry.sdk.trace.SdkTracerProvider;
30-
import io.opentelemetry.sdk.trace.data.SpanData;
3129
import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor;
3230
import java.util.HashMap;
33-
import java.util.List;
3431
import java.util.Map;
3532
import org.junit.jupiter.api.Test;
3633
import software.amazon.lambda.powertools.tracing.opentelemetry.internal.SpanScope;
@@ -249,78 +246,5 @@ void shouldReturnInvalidContextWhenTraceparentIsMissing() {
249246
.isFalse();
250247
}
251248

252-
@Test
253-
void shouldCreateServerSpanWithParentContext() throws Exception {
254-
255-
String traceId = "4bf92f3577b34da6a3ce929d0e0e4736";
256-
String parentSpanId = "00f067aa0ba902b7";
257-
258-
Map<String, String> headers = new HashMap<>();
259-
headers.put(
260-
"traceparent",
261-
"00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01"
262-
);
263-
264-
TextMapPropagator propagator =
265-
W3CTraceContextPropagator.getInstance();
266-
267-
InMemorySpanExporter exporter =
268-
InMemorySpanExporter.create();
269-
270-
SdkTracerProvider tracerProvider =
271-
SdkTracerProvider.builder()
272-
.addSpanProcessor(
273-
SimpleSpanProcessor.create(exporter)
274-
)
275-
.build();
276-
277-
Tracer tracer = tracerProvider.get("test-tracer");
278-
279-
TracingOpenTelemetry tracing =
280-
TracingOpenTelemetry.builder()
281-
.tracer(tracer)
282-
.propagator(propagator)
283-
.build();
284-
285-
Context parentContext = tracing.extractContext(
286-
headers,
287-
MAP_GETTER
288-
);
289-
290-
291-
tracing.captureLambdaHandler(
292-
"lambda-handler",
293-
null,
294-
parentContext,
295-
span -> "result"
296-
);
297-
298-
299-
List<SpanData> spans = exporter.getFinishedSpanItems();
300-
301-
assertThat(spans)
302-
.hasSize(1);
303-
304-
SpanData span = spans.get(0);
305-
306-
assertThat(span.getName())
307-
.isEqualTo("lambda-handler");
308-
309-
assertThat(span.getKind())
310-
.isEqualTo(SpanKind.SERVER);
311-
312-
assertThat(span.getSpanContext().isValid())
313-
.isTrue();
314-
315-
assertThat(span.getSpanContext().getTraceId())
316-
.isEqualTo(traceId);
317-
318-
assertThat(span.getParentSpanId())
319-
.isEqualTo(parentSpanId);
320-
321-
assertThat(span.getSpanId())
322-
.isNotEqualTo(parentSpanId);
323-
}
324-
325249

326250
}

0 commit comments

Comments
 (0)