Lambda context cannot create an initial subsegment and causes a ClassCastException
- 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
Assessment
This issue has not been assessed yet.