1+ < ?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> < html xmlns ="http://www.w3.org/1999/xhtml " lang ="en "> < head > < meta http-equiv ="Content-Type " content ="text/html;charset=UTF-8 "/> < link rel ="stylesheet " href ="../../jacoco-resources/report.css " type ="text/css "/> < link rel ="shortcut icon " href ="../../jacoco-resources/report.gif " type ="image/gif "/> < title > OtelXRayWaitExample.java</ title > < link rel ="stylesheet " href ="../../jacoco-resources/prettify.css " type ="text/css "/> < script type ="text/javascript " src ="../../jacoco-resources/prettify.js "> </ script > </ head > < body onload ="window['PR_TAB_WIDTH']=4;prettyPrint() "> < div class ="breadcrumb " id ="breadcrumb "> < span class ="info "> < a href ="../../jacoco-sessions.html " class ="el_session "> Sessions</ a > </ span > < a href ="../../index.html " class ="el_report "> AWS Lambda Durable Execution SDK Coverage Report</ a > > < a href ="../index.html " class ="el_bundle "> aws-durable-execution-sdk-java-examples</ a > > < a href ="index.source.html " class ="el_package "> software.amazon.lambda.durable.examples.otel</ a > > < span class ="el_source "> OtelXRayWaitExample.java</ span > </ div > < h1 > OtelXRayWaitExample.java</ h1 > < pre class ="source lang-java linenums "> // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+ // SPDX-License-Identifier: Apache-2.0
3+ package software.amazon.lambda.durable.examples.otel;
4+
5+ import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter;
6+ import io.opentelemetry.sdk.trace.SdkTracerProvider;
7+ import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor;
8+ import java.time.Duration;
9+ import software.amazon.lambda.durable.DurableConfig;
10+ import software.amazon.lambda.durable.DurableContext;
11+ import software.amazon.lambda.durable.DurableHandler;
12+ import software.amazon.lambda.durable.examples.types.GreetingRequest;
13+ import software.amazon.lambda.durable.otel.OpenTelemetryDurablePlugin;
14+
15+ /**
16+ * OTel + X-Ray example: step → wait → step pattern that forces multiple Lambda invocations.
17+ *
18+ * <p>This handler exercises the critical multi-invocation tracing scenario:
19+ *
20+ * <ol>
21+ * <li>Invocation 1: "before-wait" step completes → wait suspends execution
22+ * <li>Invocation 2: replays "before-wait" (no-op) → wait completes → "after-wait" step runs
23+ * </ol>
24+ *
25+ * <p>Exports spans via OTLP to the ADOT Lambda Layer collector. Requires:
26+ *
27+ * <ul>
28+ * <li>{@code Tracing: Active} on the Lambda function
29+ * <li>ADOT Lambda Layer added to the function
30+ * <li>{@code AWS_LAMBDA_EXEC_WRAPPER=/opt/otel-handler} environment variable
31+ * </ul>
32+ *
33+ * <p>Expected trace structure in X-Ray (all under one trace ID — backend propagates same Root):
34+ *
35+ * <pre>
36+ * Trace (single trace ID across both invocations)
37+ * ├── durable.invocation (invocation 1)
38+ * │ ├── durable.step:before-wait
39+ * │ │ └── durable.step:before-wait [attempt 1]
40+ * │ └── durable.wait:pause (ended as PENDING)
41+ * └── durable.invocation (invocation 2)
42+ * ├── durable.wait:pause (completed)
43+ * └── durable.step:after-wait
44+ * └── durable.step:after-wait [attempt 1]
45+ * </pre>
46+ */
47+ < span class ="fc " id ="L47 "> public class OtelXRayWaitExample extends DurableHandler<GreetingRequest, String> {</ span >
48+
49+ @Override
50+ protected DurableConfig createConfiguration() {
51+ // OTLP exporter sends spans to the ADOT collector (localhost:4317 by default)
52+ < span class ="fc " id ="L52 "> var otlpExporter = OtlpGrpcSpanExporter.getDefault();</ span >
53+
54+ < span class ="fc " id ="L54 "> var otelPlugin = new OpenTelemetryDurablePlugin(</ span >
55+ < span class ="fc " id ="L55 "> SdkTracerProvider.builder().addSpanProcessor(SimpleSpanProcessor.create(otlpExporter)));</ span >
56+
57+ < span class ="fc " id ="L57 "> return DurableConfig.builder().withPlugins(otelPlugin).build();</ span >
58+ }
59+
60+ @Override
61+ public String handleRequest(GreetingRequest input, DurableContext context) {
62+ < span class ="fc " id ="L62 "> context.getLogger().info("Starting OTel X-Ray wait example for {}", input.getName());</ span >
63+
64+ < span class ="fc " id ="L64 "> var before = context.step("before-wait", String.class, stepCtx -> "Prepared: " + input.getName());</ span >
65+
66+ // This wait forces Lambda to suspend and re-invoke after the duration
67+ < span class ="fc " id ="L67 "> context.wait("pause", Duration.ofSeconds(5));</ span >
68+
69+ < span class ="fc " id ="L69 "> var after = context.step("after-wait", String.class, stepCtx -> before + " | Resumed and completed");</ span >
70+
71+ < span class ="fc " id ="L71 "> context.getLogger().info("OTel X-Ray wait example complete: {}", after);</ span >
72+ < span class ="fc " id ="L72 "> return after;</ span >
73+ }
74+ }
75+ </ pre > < div class ="footer "> < span class ="right "> Created with < a href ="http://www.jacoco.org/jacoco "> JaCoCo</ a > 0.8.15.202606040825</ span > </ div > </ body > </ html >
0 commit comments