Giter Club home page Giter Club logo

aws-xray-sdk-java's Introduction

Build Status

📣 OpenTelemetry Java with AWS X-Ray

AWS X-Ray supports using OpenTelemetry Java and the AWS Distro for OpenTelemetry (ADOT) Collector to instrument your application and send trace data to X-Ray. The OpenTelemetry SDKs are an industry-wide standard for tracing instrumentation. They provide more instrumentations and have a larger community for support, but may not have complete feature parity with the X-Ray SDKs. See choosing between the ADOT and X-Ray SDKs for more help with choosing between the two.

If you want additional features when tracing your Java applications, please open an issue on the OpenTelemetry Java Instrumentation repository.

AWS X-Ray SDK for Java

Screenshot of the AWS X-Ray console

Installing

The AWS X-Ray SDK for Java is compatible with Java 8 and 11.

Add the AWS X-Ray SDK dependencies to your pom.xml:

<dependency>
  <groupId>com.amazonaws</groupId>
  <artifactId>aws-xray-recorder-sdk-core</artifactId>
  <version>2.16.0</version>
</dependency>
<dependency>
  <groupId>com.amazonaws</groupId>
  <artifactId>aws-xray-recorder-sdk-apache-http</artifactId>
  <version>2.16.0</version>
</dependency>
<dependency>
  <groupId>com.amazonaws</groupId>
  <artifactId>aws-xray-recorder-sdk-aws-sdk</artifactId>
  <version>2.16.0</version>
</dependency>
<dependency>
  <groupId>com.amazonaws</groupId>
  <artifactId>aws-xray-recorder-sdk-aws-sdk-v2</artifactId>
  <version>2.16.0</version>
</dependency>
<dependency>
  <groupId>com.amazonaws</groupId>
  <artifactId>aws-xray-recorder-sdk-aws-sdk-instrumentor</artifactId>
  <version>2.16.0</version>
</dependency>
<dependency>
  <groupId>com.amazonaws</groupId>
  <artifactId>aws-xray-recorder-sdk-aws-sdk-v2-instrumentor</artifactId>
  <version>2.16.0</version>
</dependency>
<dependency>
  <groupId>com.amazonaws</groupId>
  <artifactId>aws-xray-recorder-sdk-sql</artifactId>
  <version>2.16.0</version>
</dependency>
<dependency>
  <groupId>com.amazonaws</groupId>
  <artifactId>aws-xray-recorder-sdk-sql-mysql</artifactId>
  <version>2.16.0</version>
</dependency>
<dependency>
  <groupId>com.amazonaws</groupId>
  <artifactId>aws-xray-recorder-sdk-sql-postgres</artifactId>
  <version>2.16.0</version>
</dependency>
<dependency>
  <groupId>com.amazonaws</groupId>
  <artifactId>aws-xray-recorder-sdk-spring</artifactId>
  <version>2.16.0</version>
</dependency>
<dependency>
  <groupId>com.amazonaws</groupId>
  <artifactId>aws-xray-recorder-sdk-log4j</artifactId>
  <version>2.16.0</version>
</dependency>
<dependency>
  <groupId>com.amazonaws</groupId>
  <artifactId>aws-xray-recorder-sdk-slf4j</artifactId>
  <version>2.16.0</version>
</dependency>
<dependency>
  <groupId>com.amazonaws</groupId>
  <artifactId>aws-xray-recorder-sdk-metrics</artifactId>
  <version>2.16.0</version>
</dependency>

Getting Help

Please use these community resources for getting help. We use the GitHub issues for tracking bugs and feature requests.

Opening Issues

If you encounter a bug with the AWS X-Ray SDK for Java we would like to hear about it. Search the existing issues and see if others are also experiencing the issue before opening a new issue. Please include the version of AWS X-Ray SDK for Java, AWS SDK for Java, JDK, and OS you’re using. Please also include repro case when appropriate.

The GitHub issues are intended for bug reports and feature requests. For help and questions with using AWS X-Ray SDK for Java please make use of the resources listed in the Getting Help section. Keeping the list of open issues lean will help us respond in a timely manner.

Documentation

The developer guide provides in-depth guidance on using the AWS X-Ray service and the AWS X-Ray SDK for Java.

See awslabs/eb-java-scorekeep for a sample application that uses this SDK.

Quick Start

Intercept incoming HTTP requests

For many applications, work on a task begins with an incoming HTTP request.

There are a few different options for intercepting this incoming HTTP request.

Applications using javax.servlet may utilize the AWSXRayServletFilter

Add the filter in Tomcat's web.xml:

  <filter>
     <filter-name>AWSXRayServletFilter</filter-name>
     <filter-class>com.amazonaws.xray.javax.servlet.AWSXRayServletFilter</filter-class>
     <init-param>
        <param-name>fixedName</param-name>
        <param-value>defaultSegmentName</param-value>
     </init-param>
  </filter>
  <filter-mapping>
     <filter-name>AWSXRayServletFilter</filter-name>
     <url-pattern>*</url-pattern>
  </filter-mapping>

Alternatively, Spring users may add the AWSXRayServletFilter to their WebConfig:

@Configuration
public class WebConfig {

    ...

    @Bean
    public Filter TracingFilter() {
        return new AWSXRayServletFilter(new FixedSegmentNamingStrategy("defaultSegmentName"));
    }
}

The servlet filter will fail to serve incoming requests if a SegmentNamingStrategy is not supplied, either through web.xml init-params or through the constructor.

Applications using jakarta.servlet or Spring 6

Include from the Jakarta namespace. Example: com.amazonaws.xray.javax.servlet.AWSXRayServletFilter

Applications not using javax.servlet may include custom interceptors to begin and end trace segments

Directly call beginSegment and endSegment as necessary. Note: this method requires additional work to ensure that the X-Amzn-Trace-Id header is properly propogated and sufficient information about the request and response is captured with the segment.

Intercept AWS requests

Applications may make calls to Amazon Web Services. Included in the X-Ray SDK is an extension of the AWS SDK's RequestHandler2.

To instrument an example instance of AmazonWebServiceClient:

AmazonDynamoDBClient tracedDynamoClient = 
    new AmazonDynamoDBClient().standard().withRequestHandlers(new TracingHandler()).withRegion(Regions.US_EAST_1).build();

Intercept outgoing HTTP requests

Applications may make downstream HTTP calls to communicate with other applications. If these downstream applications are also traced, trace context information will need to be passed so that the trace segments may be properly grouped into a single trace.

The following options are available for ensuring these downstream calls include trace context information as well as locally generate the appropriate trace subsegments.

Applications using Apache's HttpClient library may utilize proxy classes included in com.amazonaws.xray.proxies.apache.http

Change the import line for your DefaultHttpClient or HttpClientBuilder to the appropriate proxy import. Continue to use the class as normal; method signatures do not change.

// Change the import
import com.amazonaws.xray.proxies.apache.http.DefaultHttpClient;
...
// Keep the invocation
HttpClient httpClient = new DefaultHttpClient();
httpClient.execute(request);

Intercept JDBC-Based SQL Queries

In addition to our Postgres and MySQL patchers documented in the official docs, this SDK also includes the aws-xray-recorder-sdk-sql library. This library can instrument any JDBC data source, connection, or statement so that its queries are recorded by AWS X-Ray.

import com.amazonaws.xray.sql.TracingConnection;
import com.amazonaws.xray.sql.TracingDataSource;
import com.amazonaws.xray.sql.TracingStatement;
import java.sql.*;

// Choose the one that you'd like to trace
String sql = "SELECT * FROM MYTABLE";
DataSource dataSource = TracingDataSource.decorate(dataSource);
Connection connection = TracingConnection.decorate(connection);
Statement statement = TracingStatement.decorateStatement(statement);
PreparedStatement preparedStatement = TracingStatement.decoratePreparedStatement(preparedStatement, sql);
CallableStatement callableStatement = TracingStatement.decorateCallableStatement(callableStatement, sql);

For security reasons, the SQL query is not recorded by default. However, you can opt-in to SQL query recording by setting the AWS_XRAY_COLLECT_SQL_QUERIES environment variable or the com.amazonaws.xray.collectSqlQueries system property to true.

Intercept custom methods

It may be useful to further decorate portions of an application for which performance is critical. Generating subsegments around these hot spots will help in understanding their impact on application performance. There are a few different styles available for tracing custom methods.

Using traced closures
import com.amazonaws.xray.AWSXRayRecorder;
import com.amazonaws.xray.AWSXRayRecorderBuilder;
...
AWSXRayRecorder xrayRecorder = AWSXRayRecorderBuilder.defaultRecorder();
...
xrayRecorder.createSubsegment("getMovies" (subsegment) -> {
    doSomething();
});
Using explicit calls to begin and end subsegments.
Subsegment subsegment = xrayRecorder.beginSubsegment("providedMovie");
try {
    doSomething();
    throw new RuntimeException("user error");
} catch (RuntimeException e) {
    subsegment.addException(e);
    subsegment.setError(true);
} finally {
    xrayRecorder.endSubsegment();
}

Note that in the closure-based example above, exceptions are intercepted automatically.

Oversampling Mitigation

Oversampling mitigation allows you to ignore a parent segment/subsegment's sampled flag and instead sets the subsegment's sampled flag to false. This ensures that downstream calls are not sampled and this subsegment is not emitted.

public class Handler implements RequestHandler<SQSEvent, String> {
    public Handler() {
    }

    @Override
    public String handleRequest(SQSEvent event, Context context) {
        AWSXRay.beginSubsegmentWithoutSampling("Processing Event");

        AmazonSQS sqs = AmazonSQSClientBuilder.defaultClient();

        ListQueuesResult lq_result = sqs.listQueues();
      
        System.out.println("Your SQS Queue URLs:");

        for (String url : lq_result.getQueueUrls()) {
            System.out.println(url);
        }

        AWSXRay.endSubsegment();

        return "Success";
    }
}

The code below demonstrates overriding the sampled flag based on the SQS message.

public class Handler implements RequestHandler<SQSEvent, String> {
    public Handler() {
    }

    @Override
    public String handleRequest(SQSEvent event, Context context) {

        int i = 1;

        for (SQSMessage message: event.getRecords()) {

            // Check if the message is sampled
            if (SQSMessageHelper.isSampled(message)) {
                AWSXRay.beginSubsegment("Processing Message - " + i);
            } else {
                AWSXRay.beginSubsegmentWithoutSampling("Processing Message - " + i);
            }

            i++;

            // Do your procesing work here
            System.out.println("Doing processing work");

            // End your subsegment
            AWSXRay.endSubsegment();
        }
        
        return "Success";
    }
}

Integration with ServiceLens

As of version 2.4.0, the X-Ray SDK for Java is integrated with CloudWatch ServiceLens. This allows you to use a wide range of new observability features which connect your traces, logs, and metrics in one place.

Trace ID Injection into Logs

You can automatically inject your current Trace ID into logging statements if you use the Log4J or SLF4J logging frontends. To learn more and enable this feature on your instrumented project, see the developer guide.

Vended Segment-Level Metrics

The X-Ray SDK can now automatically vend metrics that aggregate information about the segments your application sends as a custom CloudWatch metric. To learn more and enable this feature on your instrumented project, see the developer guide.

Log Group Correlation

If you are working in an environment with a supported plugin enabled and you use CloudWatch logs, the X-Ray SDK will automatically record the log group(s) you are using in that environment in the segment document. To learn more and see which plugins are supported, see the developer guide.

Alternatively, you can manually configure a log group to be associated with your application's segment data by setting the AWS_LOG_GROUP environment variable to the name of your application's log group. Note this setting makes the assumption the log group is in the same AWS account and region as the application.

Snapshots

Snapshots are published for each commit to AWS Sonatype snapshots repository at https://aws.oss.sonatype.org/content/repositories/snapshots

Building From Source

Once you check out the code from GitHub, you can build it using Maven. To disable the GPG-signing in the build, use:

./gradlew build

License

The AWS X-Ray SDK for Java is licensed under the Apache 2.0 License. See LICENSE and NOTICE.txt for more information.

aws-xray-sdk-java's People

Contributors

andrewpowell avatar atshaw43 avatar bhautikpip avatar brcolow avatar c1tadel avatar chamsco-aws avatar chanchiem avatar chrisradek avatar dekelpilli avatar friscomad avatar haotianw465 avatar jamesdbowman avatar jj22ee avatar kurru avatar luluzhao avatar lupengamzn avatar majanjua-amzn avatar mfriesen avatar msailes avatar nathanielrn avatar rhernandez35 avatar rohitnair avatar rudygt avatar shengxil avatar srprash avatar ss2305 avatar steven-aerts avatar wangzlei avatar willarmiros avatar zhengyal avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

aws-xray-sdk-java's Issues

Wrong inheritance of XRayInspector - does not compile

In the Spring example https://aws.amazon.com/blogs/devops/aspect-oriented-programming-for-aws-x-ray-using-spring/ public class XRayInspector extends AbstractXRayInterceptor and @Override method protected Map<String, Map<String, Object>> generateMetadata but there is no generateMetadata in the parent class.

Full code from link above:

@Aspect
@Component
public class XRayInspector extends AbstractXRayInterceptor {    
    @Override    
    protected Map<String, Map<String, Object>> generateMetadata(ProceedingJoinPoint proceedingJoinPoint, Subsegment subsegment) throws Exception {      
        return super.generateMetadata(proceedingJoinPoint, subsegment);    
    }    
  
  @Override    
  @Pointcut("@within(com.amazonaws.xray.spring.aop.XRayEnabled) && bean(*Controller)")    
  public void xrayEnabledClasses() {}
  
}

ClassCastException when invoking beginSubsegment

I experience following exception when try to invoke lambda directly with X-Ray tracing feature

java.lang.ClassCastException: com.amazonaws.xray.entities.SegmentImpl cannot be cast to com.amazonaws.xray.entities.Subsegment
at com.amazonaws.xray.contexts.LambdaSegmentContext.beginSubsegment(LambdaSegmentContext.java:53) ~[task/:?]
at com.amazonaws.xray.AWSXRayRecorder.beginSubsegment(AWSXRayRecorder.java:410) ~[task/:?]
at com.amazonaws.xray.handlers.TracingHandler.beforeRequest(TracingHandler.java:152) ~[task/:?]
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.runBeforeRequestHandlers(AmazonHttpClient.java:770) ~[task/:?]
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.doExecute(AmazonHttpClient.java:724) ~[task/:?]
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeWithTimer(AmazonHttpClient.java:717) ~[task/:?]
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.execute(AmazonHttpClient.java:699) ~[task/:?]
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.access$500(AmazonHttpClient.java:667) ~[task/:?]
at com.amazonaws.http.AmazonHttpClient$RequestExecutionBuilderImpl.execute(AmazonHttpClient.java:649) ~[task/:?]
at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:513) ~[task/:?]
at com.amazonaws.services.lambda.AWSLambdaClient.doInvoke(AWSLambdaClient.java:2654) ~[task/:?]
at com.amazonaws.services.lambda.AWSLambdaClient.invoke(AWSLambdaClient.java:2630) ~[task/:?]
at com.amazonaws.services.lambda.AWSLambdaClient.executeInvoke(AWSLambdaClient.java:1497) ~[task/:?]
at com.amazonaws.services.lambda.AWSLambdaClient.invoke(AWSLambdaClient.java:1473) ~[task/:?]
*** omitted handler code ***
at lambdainternal.EventHandlerLoader$PojoHandlerAsStreamHandler.handleRequest(EventHandlerLoader.java:178) [LambdaSandboxJava-1.0.jar:?]
at lambdainternal.EventHandlerLoader$2.call(EventHandlerLoader.java:888) [LambdaSandboxJava-1.0.jar:?]
at lambdainternal.AWSLambda.startRuntime(AWSLambda.java:292) [LambdaSandboxJava-1.0.jar:?]
at lambdainternal.AWSLambda.<clinit>(AWSLambda.java:64) [LambdaSandboxJava-1.0.jar:?]
at java.lang.Class.forName0(Native Method) ~[?:1.8.0_141]
at java.lang.Class.forName(Class.java:348) [?:1.8.0_141]
at lambdainternal.LambdaRTEntry.main(LambdaRTEntry.java:94) [LambdaJavaRTEntry-1.0.jar:?]

As I see in LambdaSegmentContext.beginSubsegment we do not check type of trace entity and consider it is instance of Subsegment class, but in my case it's Segment entity.

SQL query is not traced

https://docs.aws.amazon.com/xray/latest/devguide/xray-api-segmentdocuments.html#api-segmentdocuments-sql mentioned that the subsegment can/should contain sanitized_query, however TracingInterceptor never sends it:

if (process && null != subsegment) {
subsegment.putAllSql(additionalParams);
subsegment.setNamespace(Namespace.REMOTE.toString());
}

@jamesdbowman Is this a bug or is it intentional?

If it's indeed intentional, then please add a way to enable/disable this, most likely through environment variable or system property or AWSXRayRecorderBuilder. (since in Spring Boot, we simply use spring.datasource.tomcat.jdbc-interceptors=com.amazonaws.xray.sql.postgres.TracingInterceptor which means no direct bean property configuration)

I'm thinking that SQL statement should be included in the trace by default (but can be disabled for those who want it), because as it stands, TracingInterceptor is almost useless. I know each request performs a bunch of queries, and a few are slow, but which ones?

Misleading Documentation Comments for overloaded methods: "createSegment" and "createSubsegment"

The following methods contain comments that don't specify that the segment/subsegment entities are ended automatically and can be confusing because the other overloaded methods do specify it.


//  Begins a segment and passes it to the supplied consumer. 
// Intercepts exceptions, adds them to the segment, and re-throws them.
public void createSegment(String name, Consumer<Segment> consumer)

...

// Begins a subsegment and passes it to the supplied consumer. 
// Intercepts exceptions, adds them to the subsegment, and re-throws them.
public void createSubsegment(String name, Consumer<Subsegment> consumer)

For reference:

// Begins a segment, passes it to the supplied function, 
// **and ends the segment before returning the supplied function's result.** 
// Intercepts exceptions, adds them to the segment, and re-throws them.
public <R> R createSegment(String name, Function<Segment, R> function) {

A better solution would be to rename the methods to make it more clear, but this would cause issues to existing customers.

UnsupportedOperationException - FacadeSegments cannot be mutated

Occasionally the following exception thrown from a Lambda:

java.lang.UnsupportedOperationException: FacadeSegments cannot be mutated. at com.amazonaws.xray.entities.FacadeSegment.addException(FacadeSegment.java:341) at com.amazonaws.xray.spring.aop.AbstractXRayInterceptor.processXRayTrace(AbstractXRayInterceptor.java:53) at com.amazonaws.xray.spring.aop.AbstractXRayInterceptor.traceAroundMethods(AbstractXRayInterceptor.java:44) at sun.reflect.GeneratedMethodAccessor58.invoke at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:643) at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:632) at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:174) at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:689) at com.umusic.work.generator.WorkRecordGeneratorImpl$$EnhancerBySpringCGLIB$$cc14bb97.processWork(<generated>) at com.umusic.work.generator.WorkRecordGeneratorHandler.handleRequest(WorkRecordGeneratorHandler.java:51) at com.umusic.work.generator.WorkRecordGeneratorHandler.handleRequest(WorkRecordGeneratorHandler.java:21) at lambdainternal.EventHandlerLoader$PojoHandlerAsStreamHandler.handleRequest(EventHandlerLoader.java:178) at lambdainternal.EventHandlerLoader$2.call(EventHandlerLoader.java:888) at lambdainternal.AWSLambda.startRuntime(AWSLambda.java:283) at lambdainternal.AWSLambda.<clinit>(AWSLambda.java:64) at java.lang.Class.forName0(Class.java) at java.lang.Class.forName(Class.java:348) at lambdainternal.LambdaRTEntry.main(LambdaRTEntry.java:94)

Apart from that the instrumentation appears to be working fine - I'm using the latest version 1.3.1 - of aws-xray-record-sdk-spring, and have tried 1.1.0 and 1.2.0 of aws-lambda-java-core

What does this exception mean?

Using com.amazonaws.xray.emitters.daemonAddress doesn't set TCPAddress and UDPAddress

Setting com.amazonaws.xray.emitters.daemonAddress doesn't set TCPAddress and UDPAddress properties in code here:

and that causes null pointer exception here:

AwsClientBuilder.EndpointConfiguration endpointConfig = new AwsClientBuilder.EndpointConfiguration(

Now, I might be doing something wrong but it seems TCPAddress and UDPAddress are not set when property is set. They are, however, set when environment variable is used or when there is no property or env variable.

thanks,
gorazd

Perform out of band sampling rule polling when sampling rules are updated in the X-Ray console

Background

For centralized sampling strategy (default), rule poller and target poller threads are asynchronously spawned in the background to fetch sampling rules from the X-Ray console using X-Ray daemon.

  1. Rule poller makes call to GetSamplingRules X-Ray API every 5 min with jitter to fetch sampling rules from the X-Ray console.
  2. Target poller makes call to GetSamplingTargets X-Ray API every 10 sec with jitter. This reports rule matched statistics within the interval to X-Ray service.

Issue

After rule poller fetches sampling rules, if a sampling rule is created/updated/deleted, the X-Ray instrumented application will get the updated sampling rules list in the next iteration of the rule poller fetch call. In the worst case it will take 5 min for the application to start using updated list of sampling rules fetched from the X-Ray console.

Expected Behavior

Ideally, if the sampling rules are updated from the X-Ray console, target poller should perform out of band polling of waking up rule poller to fetch updated sampling rules. In this case, the application will start using updated sampling rules in the following iteration of target poller. The worst case will be 10 seconds.

In order to do this, leverage GetsamplingTargets API response instance - GetSamplingTargetsResult. It has method getLastRuleModification() method that returns the last time a user changed the sampling rule configuration from the X-Ray console.

Reference

AWS X-Ray SDK for .NET/Core has necessary logic : code

Workarounds and visibility on IOException: Message too long

We are running into the well known (#4) problem that sometimes a segment is too big to fit in a UDP message (65,507 bytes). For example because it contains a big sql statement or an exception.

The problem is however that if these issues happen sporadically they are very difficult to debug as there is almost no visibility.

We see a few possible improvements which can be made easily:

  • Enhance visibility: For example by logging the segment when it is too big.
    It could be as easy as doing something like this:
     }
 
-    private boolean sendData(byte[] data) {
+    private boolean sendData(byte[] data, Entity entity) {
+        if (data.length > 65_527) {
+            logger.warn("(sub)segment is too big to send: " + entity.prettySerialize());
+            return false;
+        }
         DatagramPacket packet = new DatagramPacket(sendBuffer, DAEMON_BUF_RECEIVE_SIZE, config.address);

(Btw: it also puzzles us why DAEMON_BUF_RECEIVE_SIZE is a lot bigger then 65_527)

  • Add retry behavior which tries to send the completed subsegments (so if one is too big, it does not break the others). We for example currently quickly implemented a RetryingEmitter which works like this:
public class RetryingEmitter extends UDPEmitter {
    private static final Log logger = LogFactory.getLog(MethodHandles.lookup().lookupClass());
    private final StreamingStrategy streamingStrategy;
    public RetryingEmitter(StreamingStrategy streamingStrategy) throws SocketException {
        super();
        this.streamingStrategy = streamingStrategy;
    }
    public boolean sendSegment(Segment segment) {return trySplitOnFailure(segment, super::sendSegment);}
    public boolean sendSubsegment(Subsegment subsegment) {return trySplitOnFailure(subsegment, super::sendSubsegment);}
    <T extends Entity> boolean trySplitOnFailure(T entity, Predicate<T> send) {
        boolean ok = send.test(entity);
        if (!ok) {
            logger.info("send of entity " + entity.getId() + " failed, retrying.");
            streamingStrategy.streamSome(entity, this);
            ok = send.test(entity);
            if (!ok) {
                logger.warn("Unable to send entity " +  entity.getId() + " after split. size: " +
                        entity.serialize().length() + ", content: " + entity.prettySerialize());
            }
        }
        return ok;
    }
}

This is of course rather naive, as a lot of errors are still send. But it helps us to debug these kinds of issues.

What do you think about these proposals?

Thanks,

Steven

Upgrade `com.fasterxml.jackson.core:jackson-databind` version

Hi team,

Please, would it be possible to upgrade this dependency: com.fasterxml.jackson.core:jackson-databind?

The latest version of the Jackson Databind library is 2.9.8. Our vulnerability bot spotted that there was a high vulnerability with this library.

I would be more than happy to help upgrading this dependency via a pull request, but it looks like the dependencies are fetched remotely (I might be wrong).

Many thanks

Remove unnecessary Guava dependency

In commit Support CS in Java com.google.guava:guava:25.1-jre was added as a dependency to aws-xray-recorder-sdk-core/pom.xml. To the best of my knowledge this is not used anywhere (all tests pass without it) and unnecessarily bloats up modules that depend on aws-xray-recorder-sdk-core. This can have adverse performance impacts in places like lambda deployments.

For the time being, I've manually excluded the dependency like so:

        <dependency>
            <groupId>com.amazonaws</groupId>
            <artifactId>aws-xray-recorder-sdk-aws-sdk</artifactId>
            <version>2.0.1</version>
            <exclusions>
                <exclusion>
                    <groupId>com.google.guava</groupId>
                    <artifactId>guava</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.amazonaws</groupId>
            <artifactId>aws-xray-recorder-sdk-aws-sdk-instrumentor</artifactId>
            <version>2.0.1</version>
        </dependency>

X-Ray instrumentation seems to work as expected even without guava. Please let me know if excluding this dependency might lead into some unwanted results.

Trace entity is initially null in lambda functions

Java version: 1.8.0_141
SDK version: 1.11.259

Not sure if this is a bug or more an "undocumented behaviour": when invoking a Java lambda function, it looks like the lambda infrastructure creates a top-level Segment (in fact, it creates two: one with resource type AWS::Lamda to track the whole invocation, and another of type AWS::Lambda::Function, to cover the time spent in user code). This is all expected according to e.g. the examples in the documentation.

However, I was surprised that neither trace entity is set on the global recorder. This is surprising since I'd expect to find the AWS::Lambda::Function entity there, since it's really the "current" trace entity at this point.

public class EntityCheck {
  public void checkEntity(Context context) {
    // This returns null
    Entity traceEntity = AWSXRay.getTraceEntity()
  }
}

LambdaSegmentContext works around this by explicitly checking for null, and the Java tracing documentation gives an example which directly uses subsegments - but the documentation doesn't state that using Segments is forbidden, or explain why this works as it does.

At the very least, might it be worth adding something to the documentation like "only ever use subsegments in lambda functions"?

AWSXRay Config not respecting AWS_XRAY_DAEMON_ADDRESS or system property (Springboot)

I am trying to get Xray setup in a springboot project of mine and no matter how I try to set the Daemon address, it always give this error:

Encountered error polling GetSamplingRules: 
com.amazonaws.SdkClientException: Unable to execute HTTP request: Connect to 127.0.0.1:2000 [/127.0.0.1] failed: Connection refused (Connection refused)

Im running the Springboot service on EKS, I have set the Enviroment variable in the deployment.yaml:

env:
- name: AWS_XRAY_DAEMON_ADDRESS 
  value: xray-service.default

I have also tried setting that enviroment variable when the docker image is built with ENV in the Dockerfile

I also tried setting

com:
  amazonaws:
    xray:
      emitters:
        daemonAddress: xray-service.default

in the application.yml as well as setting a <systemPropertyVariables> in the pom.xml.

Is there another configuration I need to set somewhere?

UPDATE:
Turns out I was missing the port for the kubernetes service (2000), now its sending traces to the daemon, however I still get an error:

Encountered error polling GetSamplingRules: 
com.amazonaws.SdkClientException: Unable to execute HTTP request: Connect to xray-service:2000 [xray-service/HIDDEN-IP, xray-service/HIDDEN-IP] failed: Connection refused (Connection refused) 

Unable to see all SQL properties added to subsegment

I'm running the X-Ray for Java SDK 2.1.0 .

I'm having an issue with the subsegment sql in that, in the AWS console, I am seeing only one of four properties that I've added to the underlying concurrent hash map.

I've debugged the code and inspected the map as part of the segment.end() method and I can see that all four properties are included in the associated subsegment.sql.

Does the AWS console and specifically, the SQL tab, hide certain properties?

The one property I see: url. The three properties I don't see: username, driverClassName, databaseId.

Thanks, Tom

Works with webflux?

Are there any limitations for using aws-xray-recorder-sdk-spring on a webflux project?

Instrumenting JDBC connections independently from Tomcat

Hi, partially a question, partially feature request: whats currently the recommended way to instrument JDBC connections not running on Tomcat? Custom segments?

Any thoughts on if it's possible to provide this functionality in the SDK without depending on Tomcat?

Add testing for JDK 11

In pursuit of adding X-Ray support for JDK 11, we need to add JDK 11 in the testing suite.

LogContextMissingStrategy with customizable logging level

Currently LogErrorContextMissingStrategy uses commons-logging and always logs error:

logger.error("Suppressing AWS X-Ray context missing exception (" + exceptionClass.getSimpleName() + "): " + message);

My suggestion:

  1. Use slf4j-api instead, which is de facto standard for modern Java apps and also more performant
  2. Add LogContextMissingStrategy which can be used to log to user-specified level. LogErrorContextMissingStrategy will just become a very thin subclass (for backwards compatbility) that uses Level.ERROR

What I use:

public static class LogContextMissingStrategy implements ContextMissingStrategy {
    private static final Logger logger = LoggerFactory.getLogger(LogContextMissingStrategy.class);
    private final Level level;
    private static final Map<Level, LoggingFunction> map;

    static {
        map = new HashMap<>();
        map.put(Level.TRACE, (logger, format, params) -> logger.trace(format, params));
        map.put(Level.DEBUG, (logger, format, params) -> logger.debug(format, params));
        map.put(Level.INFO, (logger, format, params) -> logger.info(format, params));
        map.put(Level.WARN, (logger, format, params) -> logger.warn(format, params));
        map.put(Level.ERROR, (logger, format, params) -> logger.error(format, params));
    }

    @FunctionalInterface
    private interface LoggingFunction {
        void log(Logger logger, String format, Object... params);
    }

    public LogContextMissingStrategy(Level level) {
        this.level = level;
    }

    /**
     * Logs {@code message} on the specified level.
     * @param message the message to log
     * @param exceptionClass the type of exception suppressed in favor of logging {@code message}
     */
    @Override
    public void contextMissing(String message, Class<? extends RuntimeException> exceptionClass) {
        map.get(level).log(logger, "Suppressing AWS X-Ray context missing exception ({}): {}",
                exceptionClass.getSimpleName(), message);
    }

}

Instruction to instrument non-Spring applications using the SDKs.

@zhengyal There are currently no instruction on how to implement tracing for non spring java applications. There is simply one line in the instructions that specifies https://github.com/aws/aws-xray-sdk-java#applications-not-using-javaxservlet-may-include-custom-interceptors-to-begin-and-end-trace-segments that * Applications not using javax.servlet may include custom interceptors to begin and end trace segments
Directly call beginSegment and endSegment as necessary. Note: this method requires additional work to ensure that the X-Amzn-Trace-Id header is properly propogated and sufficient information about the request and response is captured with the segment.* .

This seems like a very convenient way to leave the most important intricacies of tracing to the developer. Are there any guidelines on how we can implement this in our Java Play applications ?

Spring: Failed to end subsegment: subsegment cannot be found.

Hello,

I'm using X-Ray in a Spring application. I have followed the instruction and have:

  • Added all dependencies
  • Added a filter identical to the example (except the name)
  • Created XRayInterceptorConfig identical to the example

I'm getting an error on the instrumentation. I have read the troubleshooting guide and I believe this seems to be due to You're using instrumented clients in worker threads. However, I cannot really use the suggested workarounds and solutions since this is a Spring app.

Thanks!

2019-02-05 21:29:21.974 WARN  c.a.a.security.AuthenticateUserService : Internal problem during authentication
com.amazonaws.xray.exceptions.SubsegmentNotFoundException: Failed to end subsegment: subsegment cannot be found.
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:1.8.0_40]
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[na:1.8.0_40]
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:1.8.0_40]
	at java.lang.reflect.Constructor.newInstance(Constructor.java:422) ~[na:1.8.0_40]
	at com.amazonaws.xray.strategy.RuntimeErrorContextMissingStrategy.contextMissing(RuntimeErrorContextMissingStrategy.java:17) ~[aws-xray-recorder-sdk-core-2.1.0.jar:na]
	at com.amazonaws.xray.contexts.ThreadLocalSegmentContext.endSubsegment(ThreadLocalSegmentContext.java:54) ~[aws-xray-recorder-sdk-core-2.1.0.jar:na]
	at com.amazonaws.xray.AWSXRayRecorder.endSubsegment(AWSXRayRecorder.java:434) ~[aws-xray-recorder-sdk-core-2.1.0.jar:na]
	at com.amazonaws.xray.AWSXRay.endSubsegment(AWSXRay.java:96) ~[aws-xray-recorder-sdk-core-2.1.0.jar:na]
	at com.amazonaws.xray.spring.aop.AbstractXRayInterceptor.processXRayTrace(AbstractXRayInterceptor.java:59) ~[aws-xray-recorder-sdk-spring-2.1.0.jar:na]
	at com.amazonaws.xray.spring.aop.AbstractXRayInterceptor.traceAroundMethods(AbstractXRayInterceptor.java:44) ~[aws-xray-recorder-sdk-spring-2.1.0.jar:na]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_40]
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_40]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_40]
	at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_40]
	at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:644) ~[spring-aop-5.0.10.RELEASE.jar:5.0.10.RELEASE]
	at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:633) ~[spring-aop-5.0.10.RELEASE.jar:5.0.10.RELEASE]
	at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70) ~[spring-aop-5.0.10.RELEASE.jar:5.0.10.RELEASE]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:174) ~[spring-aop-5.0.10.RELEASE.jar:5.0.10.RELEASE]
	at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) ~[spring-aop-5.0.10.RELEASE.jar:5.0.10.RELEASE]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.10.RELEASE.jar:5.0.10.RELEASE]
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688) ~[spring-aop-5.0.10.RELEASE.jar:5.0.10.RELEASE]
	at com.adirit.alfredpad.service.impl.DefaultUserService$$EnhancerBySpringCGLIB$$2d62c02d.getUserByEmail(<generated>) ~[classes/:na]
	at com.adirit.alfredpad.security.AuthenticateUserService.loadUserByUsername(AuthenticateUserService.java:33) ~[classes/:na]
	at org.springframework.security.authentication.dao.DaoAuthenticationProvider.retrieveUser(DaoAuthenticationProvider.java:104) [spring-security-core-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider.authenticate(AbstractUserDetailsAuthenticationProvider.java:144) [spring-security-core-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:174) [spring-security-core-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:199) [spring-security-core-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilterInternal(BasicAuthenticationFilter.java:180) [spring-security-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.0.10.RELEASE.jar:5.0.10.RELEASE]
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116) [spring-security-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:66) [spring-security-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.0.10.RELEASE.jar:5.0.10.RELEASE]
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) [spring-security-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) [spring-security-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.0.10.RELEASE.jar:5.0.10.RELEASE]
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215) [spring-security-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178) [spring-security-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:357) [spring-web-5.0.10.RELEASE.jar:5.0.10.RELEASE]
	at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:270) [spring-web-5.0.10.RELEASE.jar:5.0.10.RELEASE]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) [spring-web-5.0.10.RELEASE.jar:5.0.10.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.0.10.RELEASE.jar:5.0.10.RELEASE]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:109) [spring-web-5.0.10.RELEASE.jar:5.0.10.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.0.10.RELEASE.jar:5.0.10.RELEASE]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93) [spring-web-5.0.10.RELEASE.jar:5.0.10.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.0.10.RELEASE.jar:5.0.10.RELEASE]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:155) [spring-boot-actuator-2.0.6.RELEASE.jar:2.0.6.RELEASE]
	at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:123) [spring-boot-actuator-2.0.6.RELEASE.jar:2.0.6.RELEASE]
	at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:108) [spring-boot-actuator-2.0.6.RELEASE.jar:2.0.6.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.0.10.RELEASE.jar:5.0.10.RELEASE]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200) [spring-web-5.0.10.RELEASE.jar:5.0.10.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.0.10.RELEASE.jar:5.0.10.RELEASE]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:493) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:800) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:806) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1498) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_40]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_40]
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at java.lang.Thread.run(Thread.java:745) [na:1.8.0_40]

Make TraceInterceptor.entityKey public

See aws/aws-sdk-java-v2#1277 for an explanation of the underlying problem: ExecutionAttribute keys are deliberately compared / hashed by reference and not by name.

I'd like to write some code which augments TracingInterceptor (e.g. by subclassing it) but I can't currently get hold of the trace entity from ExecutionAttributes.

One solution would be to make entityKey public so that other code could make use of it.

How to add X-Amzn-Trace-Id in logger log4j. #Spring #microservice

Like Spring sleuth trace id (X-B3-TraceId), i want to put inside the logger format.
How to add X-Amzn-Trace-Id into logger?
This will enable to watch the request related logs in cloudwatch as in xray, we dont see logs information when we search for trace id.

`beginSegment()` should perform sampling if the caller haven't done any sampling decision

Problem

The beginSegment() method doesn't perform sampling if the caller of this method hasn't done any sampling decision.

Background

Currently sampling for a given incoming request is performed by shouldTrace(). By default, this method starts pollers in the background to fetch sampling rules from the X-Ray console and sampling is performed based on fetched sampling rules.

Usecase

Currently, shouldTrace() is only called by AWSXRayServerFilter middleware. In the scenario where a user doesn't want to use AWSXRayServletFilter middleware and instrument application using just beginSegment() and endSegment(), no sampling would be performed. This is due to limitation of beginSegment not performing sampling, if the caller of this method has not performed sampling decision. As a result, all the segments are sampled and sampling rules configured through X-Ray console doesn't have any effect.

Proposed solution

beginSegment should do sampling if the caller hasn't done any sampling.

Reference

AWS X-Ray SDK for .NET/Core has necessary implementation.

Note :

  1. This should be backwards compatible change.

CentralizedSamplingStrategy constructs a new recorder at each invocation when no service type in sampling request

When an AWSXRayRecorder is built without plugins and without explicitly setting the origin, CentralizedSamplingStrategy#shouldTrace will be called with a sampling request that doesn't have a service type. It has the following fallback:

if (!samplingRequest.getServiceType().isPresent()) {
samplingRequest.setServiceType(AWSXRayRecorderBuilder.defaultRecorder().getOrigin());
}

Not only does the fallback construct a new recorder at each invocation, but it also ends up being wasted work because the result of defaultRecorder() won't have any plugins either.

I'd be happy to submit a fix, but don't know what would be your preferred approach:

  1. Just remove the fallback since it isn't working anyway?
  2. Make CentralizedSamplingStrategy or AWSXRayRecorderBuilder have a list of default plugins that will be queried for origin when the recorder doesn't have an origin? (Though it looks like only EC2Plugin could be on the list since ECSPlugin always "matches" and ElasticBeanstalkPlugin is too noisy when it doesn't.)
  3. Something else?

NoClassDefFoundError - DatatypeConverter - java 11

When using opendjk 11, the usage of AWSXRay.beginDummySegment() method throws:
java.lang.ClassNotFoundException: javax.xml.bind.DatatypeConverter.

Caused by: java.lang.NoClassDefFoundError: javax/xml/bind/DatatypeConverter
	at com.amazonaws.xray.strategy.sampling.CentralizedSamplingStrategy.<clinit>(CentralizedSamplingStrategy.java:27)
	at com.amazonaws.xray.AWSXRayRecorder.<init>(AWSXRayRecorder.java:87)
	at com.amazonaws.xray.AWSXRayRecorderBuilder.build(AWSXRayRecorderBuilder.java:145)
	at com.amazonaws.xray.AWSXRayRecorderBuilder.defaultRecorder(AWSXRayRecorderBuilder.java:78)
	at com.amazonaws.xray.AWSXRay.<clinit>(AWSXRay.java:18)

Version: 2.0.1

Flexible configuration of AWSServiceHandlerManifest

The AWSServiceHandlerManifest class configures which values from an SDK request are logged by the TracingInterceptor. However, there are only two ways to configure this:

  • supply a URL to a single JSON file, which gets parsed by TracingInterceptor, or
  • fall back to the default configuration (bundled with this library)

For example, currently there's no way to "append" configuration: if I want to modify the parameters logged for, say, calls to Lambda then I have to take a copy of the default file, modify it and bundle it myself. If the defaults change for other services at any point, my custom file will now be out of sync and the burden is on me to keep my config up to date.

It would be extremely useful to have more flexible configuration options for this. One possible design would be to:

  • provide a flexible builder for AWSServiceHandlerManifest
    • move the logic to load the default configuration into here
    • add methods to load additional / custom JSON files
    • add methods to explicitly override parts of the configuration
  • construct TracingInterceptor by passing an instance of AWSServiceHandlerManifest directly

I'm happy to have a stab at a PR for this if you think the design is reasonable?

ClassCastException in Xray Java SDK when used with Lambda in Java Container using SpringBoot

Scenario:

  1. Create a RESTful API using Java Spring Boot in Lambda using
com.amazonaws.serverless aws-serverless-java-container-spring 1.3 as per the instructions given in https://github.com/awslabs/aws-serverless-java-container
  1. Add XRay Java SDK in Dependency as below
com.amazonaws aws-xray-recorder-sdk-core 1.2.1 com.amazonaws aws-xray-recorder-sdk-apache-http 2.1.0
  1. Use com.amazonaws.xray.proxies.apache.http.HttpClientBuilder class to create an httpClient to call external REST calls from this lambda so that Xray can intercept and add Subsegment ID to this outgoing call for overall tracing.

  2. Expose the Lambda function using Lambda Proxy INtegration using API Gateway

  3. Test it using API Gateway Test Console

  4. Get below error

2019-01-19T07:03:03.055Z java.lang.ClassCastException: com.amazonaws.xray.entities.SegmentImpl cannot be cast to com.amazonaws.xray.entities.Subsegment

2019-01-19T07:03:03.055Z at com.amazonaws.xray.contexts.LambdaSegmentContext.beginSubsegment(LambdaSegmentContext.java:53)

2019-01-19T07:03:03.055Z at com.amazonaws.xray.AWSXRayRecorder.beginSubsegment(AWSXRayRecorder.java:423)

2019-01-19T07:03:03.055Z at com.amazonaws.xray.proxies.apache.http.TracedHttpClient.execute(TracedHttpClient.java:171)

2019-01-19T07:03:03.055Z at com.amazon.sa.USCISCaseStatusController.caseStatus(USCISCaseStatusController.java:81)

2019-01-19T07:03:03.055Z at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

2019-01-19T07:03:03.055Z at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)

2019-01-19T07:03:03.055Z at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

2019-01-19T07:03:03.055Z at java.lang.reflect.Method.invoke(Method.java:498)

2019-01-19T07:03:03.055Z at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:209)

2019-01-19T07:03:03.055Z at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136)

2019-01-19T07:03:03.055Z at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)

2019-01-19T07:03:03.055Z at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:891)

2019-01-19T07:03:03.055Z at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797)

2019-01-19T07:03:03.056Z at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)

2019-01-19T07:03:03.056Z at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:991)

2019-01-19T07:03:03.056Z at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925)

2019-01-19T07:03:03.056Z at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:974)

2019-01-19T07:03:03.056Z at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:866)

2019-01-19T07:03:03.056Z at javax.servlet.http.HttpServlet.service(HttpServlet.java:687)

2019-01-19T07:03:03.056Z at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:851)

SQL tracing: Support safely capturing parameterized SQL queries

I am running a Spring webapp with this configuration:

dataSource.setJdbcInterceptors("com.amazonaws.xray.sql.mysql.TracingInterceptor;");

Debugging confirms I am running into the TracingInterceptor and inside that, I can even see the sql inside the TracingInterceptor.

However, in the AWS XRay Console I cannot see the SQL commandos fired, just some meta data (like connection information).

Am I supposed to see the raw SQL running against a database? If yes, is there any additional step I missed?

Race Condition on configuring custom recorder for X-Ray servlet filter

The AWSXRayServletFilter has multiple constructors that don't take a recorder as an input:https://github.com/aws/aws-xray-sdk-java/blob/master/aws-xray-recorder-sdk-core/src/main/java/com/amazonaws/xray/javax/servlet/AWSXRayServletFilter.java#L50-L60. In that case it will use the default global recorder initialized statically.

If the user create a custom recorder and set it to be the global one using AWSXRay.setGlobalRecorder after filter construction, this global recorder will not be used.

The servlet filter should not use any recorder if not passed during construction. It should lazy fetch the global recorder when the recorder is actually needed.

CentralizedSampling will not work with instrumentor

When using XRay SDK 2.0.1, we see every 5 seconds:

java.lang.NullPointerException: null
	at com.amazonaws.xray.handlers.TracingHandler.beforeExecution(TracingHandler.java:138) ~[aws-xray-recorder-sdk-aws-sdk-2.0.1.jar:?]
	at com.amazonaws.AmazonWebServiceClient.beforeClientExecution(AmazonWebServiceClient.java:723) ~[aws-java-sdk-core-1.11.398.jar:?]
	at com.amazonaws.services.xray.AWSXRayClient.getSamplingRules(AWSXRayClient.java:538) ~[aws-java-sdk-xray-1.11.398.jar:?]
	at com.amazonaws.xray.strategy.sampling.pollers.RulePoller.pollRule(RulePoller.java:53) ~[aws-xray-recorder-sdk-core-2.0.1.jar:?]
	at com.amazonaws.xray.strategy.sampling.pollers.RulePoller.lambda$start$0(RulePoller.java:41) ~[aws-xray-recorder-sdk-core-2.0.1.jar:?]
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [?:1.8.0_152]
	at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308) [?:1.8.0_152]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180) [?:1.8.0_152]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294) [?:1.8.0_152]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:1.8.0_152]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:1.8.0_152]

This is caused by the TracingHandler being created when the globalrecorder has not yet finished initialization. Then the recorder of the TracingHandler will be null. See stacktrace below. The globalrecorder is in the process of being created but AWSXray.globalRecorder has not been assigned yet.

When just getting the globalRecorder, you will trigger this problem:

  at com.amazonaws.xray.AWSXRay.getGlobalRecorder(AWSXRay.java:28)
	  at com.amazonaws.xray.handlers.TracingHandler.<init>(TracingHandler.java:94)
	  at sun.reflect.NativeConstructorAccessorImpl.newInstance0(NativeConstructorAccessorImpl.java:-1)
	  at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	  at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	  at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
	  at java.lang.Class.newInstance(Class.java:442)
	  at com.amazonaws.handlers.HandlerChainFactory.createRequestHandler(HandlerChainFactory.java:113)
	  at com.amazonaws.handlers.HandlerChainFactory.getGlobalHandlers(HandlerChainFactory.java:74)
	  at com.amazonaws.services.xray.AWSXRayClient.init(AWSXRayClient.java:283)
	  at com.amazonaws.services.xray.AWSXRayClient.<init>(AWSXRayClient.java:256)
	  at com.amazonaws.services.xray.AWSXRayClientBuilder.build(AWSXRayClientBuilder.java:61)
	  at com.amazonaws.services.xray.AWSXRayClientBuilder.build(AWSXRayClientBuilder.java:27)
	  at com.amazonaws.client.builder.AwsSyncClientBuilder.build(AwsSyncClientBuilder.java:46)
	  at com.amazonaws.xray.strategy.sampling.XRayClient.newClient(XRayClient.java:31)
	  at com.amazonaws.xray.strategy.sampling.CentralizedSamplingStrategy.<init>(CentralizedSamplingStrategy.java:40)
	  at com.amazonaws.xray.strategy.sampling.DefaultSamplingStrategy.<init>(DefaultSamplingStrategy.java:5)
	  at com.amazonaws.xray.AWSXRayRecorder.<init>(AWSXRayRecorder.java:87)
	  at com.amazonaws.xray.AWSXRayRecorderBuilder.build(AWSXRayRecorderBuilder.java:145)
	  at com.amazonaws.xray.AWSXRayRecorderBuilder.defaultRecorder(AWSXRayRecorderBuilder.java:78)
	  at com.amazonaws.xray.AWSXRay.<clinit>(AWSXRay.java:18)

Setting the samplingStrategy to CentralizedSampling again later, is a workaround.

        AWSXRay.getGlobalRecorder().setSamplingStrategy(new DefaultSamplingStrategy());

"Segment has already been emitted" when streaming

SDK version: 2.2.1
Java version: 1.8.0_202

We've run into the known issue of large traces not sending correctly over UDP so had enabled streaming with the DefaultStreamingStrategy, and configured it to stream in chunks of 10. However, we see a large number of errors in the logs like this:

com.amazonaws.xray.exceptions.AlreadyEmittedException: Segment foo has already been emitted.

It looks like DefaultStreamingStrategy is careful to lock and unlock access to the list of subsegments in a trace, to avoid synchronization issues. However, this lock is not checked (as far as I can see) when the whole trace is finished - meaning it's possible that X-Ray attempts to stream the same segments twice.

Failed to begin subsegment named 'AWSXRay'

When you use the CentralizedSamplingStrategy it will create a java sdk AWSXRay client which uses the XRay http api to communicate with the local xray daemon.
This client is used from a polling threads which typically do not have any context set.

When you have enabled the aws-xray-recorder-sdk-aws-sdk-instrumentor it will trigger the currently configured ContextMissingStrategy (throwing a runtime exception or logging an error).

We think this is rather ugly.

We are wondering if this is the designed behaviour.

Wouldn't it be better to run these pollers within a dummy segment or disable the xray request handlers for the AWSXRay client?

AWSXRayServletFilterTest flaky caused random CI build failures

An example failed build: https://travis-ci.org/aws/aws-xray-sdk-java/jobs/457711364

[ERROR]   AWSXRayServletFilterTest.testNameOverrideSystemProperty:145 
emitter.sendSegment(<Capturing argument>);
Wanted 1 time:
-> at com.amazonaws.xray.javax.servlet.AWSXRayServletFilterTest.testNameOverrideSystemProperty(AWSXRayServletFilterTest.java:145)
But was 707 times. Undesired invocation:
-> at com.amazonaws.xray.AWSXRayRecorder.sendSegment(AWSXRayRecorder.java:132)
[INFO] 
[ERROR] Tests run: 144, Failures: 1, Errors: 0, Skipped: 0

getUrl in TracedHttpClient generates invalid Url

public static String getUrl(HttpHost target, HttpRequest request) { return target.getHostName() + request.getRequestLine().getUri(); }

This method is generating a value of (hostname + absolute url). I believe this method should check to see if the request line url is absolute before doing this concatenation. If this is indeed the case, I'm happy to make the change and submit a pull request. I wanted to make sure it wasn't intentional first.

Thanks,
Brandon

No op implementation

It would be great to have "no op" implementation for at least the AWSXRayServletFilter. So far it is impossible (or I didn't see how to do it yet) to disable XRay for local development without touching the web.xml or Spring boot filter code. Having an environment flag would be helpful.

UDP Emitter should refresh daemon address periodically and should not throw communication errors

We have the XRay daemon running in an ECS container with awsvpc network mode and Route53 Auto Naming Service Discovery enabled. The XRay address is set via the AWS_XRAY_DAEMON_ADDRESS system property as fqdn. Due to some shortcomings in the UDPEmitter, this causes some problems.

  1. Sometimes the XRay container is not started at the moment the UDPEmitter on the 'to be traced' server is constructed. The java InetAddress could not resolve the hostname and sets a flag 'unknown host'. This flag will never be reset.
  2. The IP address of the XRay container could change when it is restarted. The UDPEmitter keeps throwing its data to the first found IP.
  3. The communication errors which occurs as result of cause 1, is not catched.

I think it will be easy to implement a polling thread which periodically re-resolves the daemon address and pass the new InetAddress to the UDPEmitter.
And add some try/catch wrappers around the UDPEmitter data transfer methods.

aws-xray-recorder-sdk-aws-sdk-instrumentor does not support SDKv2 clients

Hello,

Including aws-xray-recorder-sdk-aws-sdk-instrumentor adds the AWS SDK v1 global interceptor which activates Xray for all AWS SDKv1 clients.

I believe the counterpart to SDKv2 clients is missing. If I understand correctly, /software/amazon/awssdk/global/handlers/execution.interceptors should be included and list the required interceptor from aws-xray-recorder-sdk-aws-sdk-v2

Periodically conection errors on ElasticBeanstalk

I receive segments in my dashboard, but sometimes I have errors like:

com.amazonaws.SdkClientException: Unable to execute HTTP request: Connect to 127.0.0.1:2000 [/127.0.0.1] failed: Connection refused (Connection refused)

Sometimes I get things like this:

2018-12-05 17:20:17,963 [http-nio-8080-exec-9] ERROR [anonymous] LogErrorContextMissingStrategy - Suppressing AWS X-Ray context missing exception (SegmentNotFoundException): Failed to begin subsegment named 'XXXX': segment cannot be found.

which is very annoying. The daemon itself appears to be running fine, but sometimes it looks like connectivity is not really good.

Report aws region

Hi,

I am testing out xray with Java on Lambda and I don't see the region being reported for sub-segments generated for calls to aws services. I've tested out S3 and DynamoDB.

I've noticed that with nodejs xray sdk, the region is being reported fine. This feature seems to be missing from the Java xray sdk.

Is there anyway to get the sdk to report the aws region being accessed for sub-segment calls to aws services?

Much thanks,

Guy

Add and document X-Ray tracing for AWS SDK v2

Expected Behavior

The AWS SDK team has now released version 2 of the Java SDK. Previously it was possible to write:

AWSLambda lambda = AWSLambdaClientBuilder
      .standard()
      .withRequestHandlers(new TracingHandler(recorder))
      .build()

but the RequestHandler API has been replaced in v2 with a new ExecutionInterceptor API for wrapping client requests:

https://github.com/aws/aws-sdk-java-v2/blob/master/core/sdk-core/src/main/java/software/amazon/awssdk/core/interceptor/ExecutionInterceptor.java

This means that, as far as I can see, it's currently not possible to add X-Ray traces to AWS calls using the v2 SDK.

Current Behavior

I can't see an equivalent implementation in the v2 SDK anywhere - assuming it would use the new ExecutionInterceptor API - or if there is one, I can't see it documented in the developer guide.

Possible Solution

Add and document an implementation of ExecutionInterceptor that traces AWS client requests.

Steps to Reproduce (for bugs)

N/A

Context

Required for parity with the 1.11 SDK.

Your Environment

  • AWS Java SDK version used: 2.1.0
  • JDK version used: 8

Unable to fetch SamplingRules configured in AWS console

Hi,

With X-ray 2.0, I wanted to try out the option to manage sampling rules within the console itself. However the rules are not being applied/fetched from the console. In the stacktrace, I can see that it fails in the RulePoller trying to fetch the sampling rules.

We use a config equivalent to the following to initialize the global recorder:

            AWSXRayRecorderBuilder builder = AWSXRayRecorderBuilder.standard()
                .withPlugin(new EC2Plugin()).withPlugin(new ElasticBeanstalkPlugin())
                .withSamplingStrategy(new CentralizedSamplingStrategy(MyConfig.class.getResource("/xray/rules.json")))
                .withContextMissingStrategy(new NoOpXrayContextMissingStratergy()); //skips logging
            AWSXRay.setGlobalRecorder(builder.build());

Stacktrace:

2018-09-04 11:27:41,312 ERROR [pool-5-thread-1] c.a.x.s.sampling.pollers.RulePoller  Encountered error polling GetSamplingRules:
com.amazonaws.xray.exceptions.SegmentNotFoundException: Failed to begin subsegment named 'AWSXRay': segment cannot be found.
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
        at org.springsource.loaded.ri.ReflectiveInterceptor.jlrConstructorNewInstance(ReflectiveInterceptor.java:1002)
        at com.amazonaws.xray.strategy.RuntimeErrorContextMissingStrategy.contextMissing(RuntimeErrorContextMissingStrategy.java:17)
        at com.amazonaws.xray.contexts.ThreadLocalSegmentContext.beginSubsegment(ThreadLocalSegmentContext.java:23)
        at com.amazonaws.xray.AWSXRayRecorder.beginSubsegment(AWSXRayRecorder.java:418)
        at com.amazonaws.xray.handlers.TracingHandler.beforeRequest(TracingHandler.java:152)
        at com.amazonaws.http.AmazonHttpClient$RequestExecutor.runBeforeRequestHandlers(AmazonHttpClient.java:782)
        at com.amazonaws.http.AmazonHttpClient$RequestExecutor.doExecute(AmazonHttpClient.java:726)
        at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeWithTimer(AmazonHttpClient.java:719)
        at com.amazonaws.http.AmazonHttpClient$RequestExecutor.execute(AmazonHttpClient.java:701)
        at com.amazonaws.http.AmazonHttpClient$RequestExecutor.access$500(AmazonHttpClient.java:669)
        at com.amazonaws.http.AmazonHttpClient$RequestExecutionBuilderImpl.execute(AmazonHttpClient.java:651)
        at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:515)
        at com.amazonaws.services.xray.AWSXRayClient.doInvoke(AWSXRayClient.java:1257)
        at com.amazonaws.services.xray.AWSXRayClient.invoke(AWSXRayClient.java:1226)
        at com.amazonaws.services.xray.AWSXRayClient.invoke(AWSXRayClient.java:1215)
        at com.amazonaws.services.xray.AWSXRayClient.executeGetSamplingRules(AWSXRayClient.java:568)
        at com.amazonaws.services.xray.AWSXRayClient.getSamplingRules(AWSXRayClient.java:539)
        at com.amazonaws.xray.strategy.sampling.pollers.RulePoller.pollRule(RulePoller.java:53)
        at com.amazonaws.xray.strategy.sampling.pollers.RulePoller.lambda$start$0(RulePoller.java:41)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
        at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)

Few details:

Versions:
com.amazonaws:aws-xray-recorder-sdk-core:2.0.0
com.amazonaws:aws-xray-recorder-sdk-aws-sdk:2.0.0
com.amazonaws:aws-xray-recorder-sdk-aws-sdk-instrumentor:2.0.0
com.amazonaws:aws-xray-recorder-sdk-apache-http:2.0.0
com.amazonaws:aws-java-sdk-xray:1.11.400

Deployed on:
ElasticBeanstalk Java 8 running on 64bit Amazon Linux/2.7.4

Should Entity#close throw Exception?

Entity extends Autoclosable allowing Entity#close to throw any Exception. However both Segment and Subsegment interfaces override close to ditch the Exception. This discrepancy causes me troubles as it means that (Subs|S)egment can be easily wrapped in a try-with-resource statement but doing the same with Entity requires an explicit error path.

Why would Entity#close throw a checked Exception? As AWSXrayRecorder#end(Subs|S)egment only raise (Subs|S)egementNotFoundException and close seems an alternative way to end an entity, I wouldn't expect it to throw any exception. What is the caller expected to do when a such exception is thrown?

My current understanding of the API is that Entity#close should not throw and this is an oversight but please correct me if I am wrong.

New release

Hi,

I've been really looking forward to the changes done to DefaultOperationParameterWhitelist.json as part of #9 which is currently in master but not part of a release. I didn't want to manage this file in my repository and hence was wondering when we could see a new release.

Thanks,
Anay

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.