aws / aws/aws-xray-sdk-java

Lambda context cannot create an initial subsegment and causes a ClassCastException

Open
#245 9 comments 3 reactions 1 assignee Claimed by @willarmiros View on GitHub
bug
Dominant language
Java
Stars
100
Forks
100
PR merge metrics
No merged PRs in 30d

Description

I'm using aws-xray-recorder-sdk-core version 2.8.0

Exception message and partial trace:
```
class com.amazonaws.xray.entities.SegmentImpl cannot be cast to class com.amazonaws.xray.entities.Subsegment (com.amazonaws.xray.entities.SegmentImpl and com.amazonaws.xray.entities.Subsegment are in unnamed module of loader lambdainternal.CustomerClassLoader @5f184fc6): java.lang.ClassCastException
java.lang.ClassCastException: class com.amazonaws.xray.entities.SegmentImpl cannot be cast to class com.amazonaws.xray.entities.Subsegment (com.amazonaws.xray.entities.SegmentImpl and com.amazonaws.xray.entities.Subsegment are in unnamed module of loader lambdainternal.CustomerClassLoader @5f184fc6)
at com.amazonaws.xray.contexts.LambdaSegmentContext.beginSubsegment(LambdaSegmentContext.java:74)
at com.amazonaws.xray.AWSXRayRecorder.beginSubsegment(AWSXRayRecorder.java:613)
at com.id.cloud.runtime.compose.helpers.TraceHelper.lambda$beginSubsegment$7(TraceHelper.java:168)
at java.base/java.util.Optional.ifPresent(Unknown Source)
at com.id.cloud.runtime.compose.helpers.TraceHelper.beginSubsegment(TraceHelper.java:165)
```
Invocation that led to the exception:
```java
AWSXRay.beginSegment("my segment", getRootTraceID(), getParentID());
//...
AWSXRay.getCurrentSegmentOptional().ifPresent(segment -> AWSXRay.beginSubsegment("my new subsegment"));
```
The code works correctly when running local JUnit tests, because then `com.amazonaws.xray.contexts.ThreadLocalSegmentContext` is used as context. However, when deploying the code in an AWS Lambda, `com.amazonaws.xray.contexts.LambdaSegmentContext` is used, which has a rather different implementation for `beginSubsegment`: both the ThreadLocal and the Lambda implementation obtain the current trace entity via a call to `getTraceEntity()` and both perform a nullcheck on the result. However, the ThreadLocal implementation then creates a new subsegment using the current entity as parent, while the Lambda implementation blandly assumes that the current entity must already be a Subsegment and downcasts it immediately, leading to a CCE when no subsegment was previously started (which, given the code, seems to be impossible from within the deployed lambda).

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.