Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using X-Ray throws ClassCastExceptions for Subsegments, documentation unclear #326

Open
shearn89 opened this issue Mar 2, 2022 · 1 comment

Comments

@shearn89
Copy link

shearn89 commented Mar 2, 2022

The documentation around using X-Ray in Java with Lambda is (IMO) very unclear. I keep getting a ClassCastException when trying to do what I think should be a simple task: instrument my code with segments/subsegments.

I've created a very simple example repo to demonstrate the issue. If you build and invoke locally, you get the same exception as deploying and calling via the CLI:

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 @433c675d)
	at com.amazonaws.xray.contexts.LambdaSegmentContext.beginSubsegment(LambdaSegmentContext.java:80)
	at com.amazonaws.xray.AWSXRayRecorder.beginSubsegment(AWSXRayRecorder.java:616)
	at com.amazonaws.xray.AWSXRay.beginSubsegment(AWSXRay.java:121)
	at helloworld.App.doSomething(App.java:31)
	at helloworld.App.handleRequest(App.java:25)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.base/java.lang.reflect.Method.invoke(Unknown Source)

The lambda is trivial:

package helloworld;

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.xray.AWSXRay;
import com.amazonaws.xray.AWSXRayRecorderBuilder;
import com.amazonaws.xray.entities.Subsegment;
import com.amazonaws.xray.strategy.sampling.NoSamplingStrategy;

import java.util.Map;

/**
 * Handler for requests to Lambda function.
 */
public class App implements RequestHandler<Map<String,Object>, String> {

    public App() {
        AWSXRayRecorderBuilder builder = AWSXRayRecorderBuilder.standard();
        builder.withSamplingStrategy(new NoSamplingStrategy());
        AWSXRay.setGlobalRecorder(builder.build());
    }

    public String handleRequest(Map<String,Object> input, final Context context) {
        AWSXRay.beginSegment("simpleJavaXrayTest");
        String output = doSomething();
        AWSXRay.endSegment();
        return output;
    }

    private String doSomething() {
        Subsegment subsegment = AWSXRay.beginSubsegment("doSomething");
        try {
            thrower();
        } catch (Exception e) {
            subsegment.addException(e);
        }
        AWSXRay.endSubsegment();
        return "here we are";
    }

    private void thrower() throws Exception {
        throw new Exception("oops");
    }
}

As per this page, first paragraph (emphasis mine):

The X-Ray SDK for Java is a set of libraries for Java web applications that provide classes and methods for generating and sending trace data to the X-Ray daemon. Trace data includes information about incoming HTTP requests served by the application, and calls that the application makes to downstream services using the AWS SDK, HTTP clients, or an SQL database connector. You can also create segments manually and add debug information in annotations and metadata.

There's also a whole page on custom subsegments in Java, but I'm still stumped.

I had to come to GitHub to find this message which seems to say that I can't use Segments in my Lambda. The actual code I'm working on does a couple of different things with binary data, so I'd like to add segments/subsegments to time and trace the various sections of the code (read/store/process). It's a little frustrating that there doesn't seem to be a simple example of doing this, and lots of the java docs reference Servlets which are irrelevant to my application!

TL;DR - the exception thrown is unclear and unhelpful to the uninitiated. It doesn't tell you what you're doing wrong, and the documentation doesn't seem to say I'm doing something incorrect. The troubleshooting page has nothing that would tell me what to do next.

@willarmiros
Copy link
Contributor

Hi @shearn89,

As you pointed out, the problem in the code that raises the confusing CCE is already raised in #245. For the documentation, Lambda is a special use case for the X-Ray SDKs and we document the behavior that customers are unable to manually create segments here: https://docs.aws.amazon.com/lambda/latest/dg/services-xray.html

We also mention the difference in SDK usage on our Lambda integration page: https://docs.aws.amazon.com/xray/latest/devguide/xray-services-lambda.html

I agree that it would be ideal if it were mentioned on each of the language's documentation page, but really the root cause here is the same as #245 which is we should throw a more descriptive exception or at least error message.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants