New Relic for Java includes a set of API methods for custom instrumentation of asynchronous activity. This is most useful to instrument asynchronous activity in unsupported frameworks, but you can also use the API to add additional instrumentation to supported frameworks. This document explains how asynchronous activity occurs, and how New Relic monitors async work.
Asynchronous operations
With a synchronous programming model, programming tasks are usually executed in a specific order. One task must complete before the next task begins, and each task blocks the next task from completing.
Asynchronous programming uses a non-blocking model, so that tasks can be run in parallel. Tasks executed asynchronously are completely independent of each other in their execution and initialization. Because asynchronous code doesn't execute in a specific order, the server's full processing power can be used more efficiently, and the app's throughput increases.
Async and thread-switching
For applications that use asynchronous processing, thread-switching is when a program or task switches from one thread to another. Understanding these asynchronous interleavings can help you decide which methods should be instrumented.
Here is an example method with a controller that makes external requests in parallel. These requests execute asynchronously, so each request executes independently of each other and getScoreAsync()
returns immediately after being called. This allows the requesting thread to continue making requests while getScoreAsync()
makes an external call and sends a reply.
@ResponseBody@RequestMapping("getScores", method = RequestMethod.Get produces = “text/plain”)public String getCreditScores(@RequestParam(name = "uids") uids) { return Arrays.stream(uids.split(",")) .parallel() .map(Integer::valueOf) .map(uid -> getScoreAsync(uid)) .collect(Collectors.toList());}
Some of these requests will finish before others. Some might even finish after the requesting thread has moved on to other tasks:
With New Relic's asynchronous instrumentation, the APM UI flags the work as Async. For example, if the above method were instrumented by New Relic (either automatically or via custom instrumentation), this is what the APM UI would show on the Trace details page:
one.newrelic.com > APM > (select an app) > Transactions > Transaction trace > Trace details: When asynchronous activity in a Java application is detected by APM, it is indicated with the Async flag in the Drilldown column.
Async and response time
Response time is defined as the duration of a transaction from the perspective of the requester. For asynchronous applications, the response time is often less than the total transaction time. This is because the methods don't have to wait for all preceding methods to complete before returning. Because tasks can be deferred, the application can take advantage of its limited resources and process things more quickly.
The chart's response time line gives you more insight into the perceived behavior and speed of your application than does the total web transaction time:
one.newrelic.com > APM > (select an app) > Summary: On the APM Summary page, asynchronous activity in a Java app can result in the response time (the blue line) being less than the total transaction time. This is because the methods don't have to wait for all preceding methods to complete before returning.
Custom instrumentation with the async API
To implement custom instrumentation of async work, see the Java agent async API guide. For general information on how to use the Java agent API, see Java agent API guide.
For more help
If you need more help, check out these support and learning resources:
- Browse the Explorers Hub to get help from the community and join in discussions.
- Find answers on our sites and learn how to use our support portal.
- Run New Relic Diagnostics, our troubleshooting tool for Linux, Windows, and macOS.
- Review New Relic's and and documentation.