-
Notifications
You must be signed in to change notification settings - Fork 64
Commit d96644e
authored
Enable OTel API instrumentation for generating custom spans (#1058)
### Problem
When using the Application Signals lambda layer for auto-instrumenting a
lambda function, we found that if we want to generate custom spans using
the OTel APIs, then these spans are generated with no-op context and are
not available in Application Signals.
### Steps to reproduce
- Create a Java lambda function (can use [this pre-build
app](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/blank-java))
with the following code
```java
package example;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.LambdaLogger;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import java.util.Map;
import software.amazon.awssdk.services.lambda.LambdaClient;
import software.amazon.awssdk.services.lambda.model.GetAccountSettingsResponse;
import software.amazon.awssdk.services.lambda.model.LambdaException;
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.api.trace.SpanKind;
// Handler value: example.Handler
public class Handler implements RequestHandler<Map<String,String>, String> {
private static final LambdaClient lambdaClient = LambdaClient.builder().build();
@OverRide
public String handleRequest(Map<String,String> event, Context context) {
LambdaLogger logger = context.getLogger();
logger.log("Handler invoked");
GetAccountSettingsResponse response = null;
try {
response = lambdaClient.getAccountSettings();
} catch(LambdaException e) {
logger.log(e.getMessage());
}
logger.log("=====1.");
Span parentSpan = Span.current();
logger.log(parentSpan.toString());
if (GlobalOpenTelemetry.get() == null) {
logger.log("----- GlobalOTelTracer is null");
} else {
logger.log("----- GlobalOTelTracer is initialized");
}
Tracer tracer = GlobalOpenTelemetry.getTracer("my-app");
Span span = tracer.spanBuilder("rollTheDice")
.setSpanKind(SpanKind.SERVER)
.setParent(io.opentelemetry.context.Context.current().with(parentSpan))
.startSpan();
span.end();
logger.log(span.toString());
logger.log("=====2.");
return response != null ? "Total code size for your account is " + response.accountLimit().totalCodeSize() + " bytes" : "Error";
}
}
```
- Enable Application Signals from the Lambda function console.
- Invoke the function and observe the CW logs. You should see the
following lines where the two spans are both no-op
```
Handler invoked
--
=====1.
PropagatedSpan{ImmutableSpanContext{traceId=00000000000000000000000000000000, spanId=0000000000000000, traceFlags=00, traceState=ArrayBasedTraceState{entries=[]}, remote=false, valid=false}}
----- GlobalOTelTracer is initialized
PropagatedSpan{ImmutableSpanContext{traceId=00000000000000000000000000000000, spanId=0000000000000000, traceFlags=00, traceState=ArrayBasedTraceState{entries=[]}, remote=false, valid=false}}
=====2.
```
### Solution
- OpenTelemetry treats the [`opentelemetry-api` just like any other
library
instrumentation](https://github.com/open-telemetry/opentelemetry-java-instrumentation/tree/main/instrumentation/opentelemetry-api).
When instrumented, the methods (like `startSpan`) from the OpenTelemetry
API will produce spans that have proper context.
- In the Application Lambda layer, [only a handful of library
instrumentations are enabled by
default](https://github.com/aws-observability/aws-otel-java-instrumentation/blob/43bc6bcc795749e043aee5c64f794a525139d975/lambda-layer/otel-instrument#L38-L44).
This does not include the `opentelemetry-api` instrumentation.
- Adding the `OTEL_INSTRUMENTATION_OPENTELEMETRY_API_ENABLED=true`
environment variable will enable this instrumentation.
### Testing
- Once the `OTEL_INSTRUMENTATION_OPENTELEMETRY_API_ENABLED=true` was
set, the same code produced correct spans
```
Handler invoked
--
=====1.
ApplicationSpan{agentSpan=SdkSpan{traceId=67dc8edd575d3de05e89c56b19240ffd, spanId=d9039dec8378a88c, parentSpanContext=ImmutableSpanContext{traceId=67dc8edd575d3de05e89c56b19240ffd, spanId=796364ca3c8551b1, traceFlags=01, traceState=ArrayBasedTraceState{entries=[]}, remote=true, valid=true}, name=blank-java-function-Hs0Awjtfeqgx, kind=SERVER, attributes=AttributesMap{data={thread.name=main, cloud.resource_id=arn:aws:lambda:us-west-2:702258172533:function:blank-java-function-Hs0Awjtfeqgx, thread.id=1, cloud.account.id=702258172533, faas.invocation_id=4ca9914c-ba2b-4236-ba0d-8bc176593816}, capacity=128, totalAddedValues=5}, status=ImmutableStatusData{statusCode=UNSET, description=}, totalRecordedEvents=0, totalRecordedLinks=0, startEpochNanos=1742507745533600918, endEpochNanos=0}}
----- GlobalOTelTracer is initialized
ApplicationSpan{agentSpan=SdkSpan{traceId=67dc8edd575d3de05e89c56b19240ffd, spanId=62d682028539df0b, parentSpanContext=ImmutableSpanContext{traceId=67dc8edd575d3de05e89c56b19240ffd, spanId=d9039dec8378a88c, traceFlags=01, traceState=ArrayBasedTraceState{entries=[]}, remote=false, valid=true}, name=rollTheDice, kind=SERVER, attributes=AttributesMap{data={thread.name=main, thread.id=1, aws.local.operation=blank-java-function-Hs0Awjtfeqgx/FunctionHandler}, capacity=128, totalAddedValues=3}, status=ImmutableStatusData{statusCode=UNSET, description=}, totalRecordedEvents=0, totalRecordedLinks=0, startEpochNanos=1742507746224698439, endEpochNanos=1742507746224823765}}
=====2.
```
By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 license.1 parent 43bc6bc commit d96644eCopy full SHA for d96644e
File tree
Expand file treeCollapse file tree
1 file changed
+1
-0
lines changedFilter options
- lambda-layer
Expand file treeCollapse file tree
1 file changed
+1
-0
lines changedlambda-layer/otel-instrument
Copy file name to clipboardExpand all lines: lambda-layer/otel-instrument+1Lines changed: 1 addition & 0 deletions
Original file line number | Diff line number | Diff line change | |
---|---|---|---|
| |||
37 | 37 |
| |
38 | 38 |
| |
39 | 39 |
| |
| 40 | + | |
40 | 41 |
| |
41 | 42 |
| |
42 | 43 |
| |
|
0 commit comments