Executor mode is the default mode for instrumenting the asynchronous tasks beginning with the Java Agent 20.11 release.

When the agent is in Executor mode, transaction activity is tracked from thread to thread by instrumenting Executor.exeute()and similar method(s) such that the agent can identify application work to track as that work is being scheduled.

Benefits of Executor Mode

  • Reduces the agent's resource consumption for most use cases
  • Enables tracking thread hand-offs using the new agent API
  • Improves reliability of last thread on tier asynchronous transaction demarcation
  • Allows Service Endpoints to measure the response time of services implemented using asynchronous frameworks

Behavior of Service Endpoints in Executor Mode

The behavior of Service Endpoints differs between the Constructor and Executor modes. In Constructor mode, each asynchronous transaction segment is represented by its own Service Endpoint, and the Service Endpoint corresponding to the transaction entry point shows the execution time of the initiating thread as shown:

Service Endpoint

With the Executor instrumentation strategy, metrics for a single Service Endpoint are reported, with a response time corresponding to the execution time of the entire asynchronous transaction as shown below. 

Executor Instrumentation

Currently, each service entry point must match a transaction entry point. Configuration of Service Endpoints at other points within the execution of asynchronous transactions is not supported in the Executor mode. Additionally, Service Endpoints only report if placed within the context of executing a Business Transaction when the agent is in Executor mode.

Raw Threads Support

Support for raw threads differs between the Executor and Constructor modes. While Constructor mode supports tracking of all threads created in the context of a transaction, the Executor mode supports only non-daemon threads that are started in the context of a transaction. The daemon status is inherited from the parent thread which can cause unexpected results. For example, the worker threads in an application server are often daemon threads, so any thread started directly within servlet code is not tracked in the Executor mode unless the application explicitly unsets its daemon status.

Node Properties

This table presents the node properties which are specific for the executor-based instrumentation strategy, or which work differently than for the constructor-based instrumentation strategy (default).

Property

Default value

Description

Property

Default value

Description

thread-correlation-classes


none

These properties have the same effect in the Executor mode as in Constructor mode, however, their use is discouraged in Executor mode, especially when used to limit the costs of thread tracking. Due to the differences in implementation of the async hand-offs, any performance gains achieved using these settings in constructor mode are likely to be available using the out of the box settings in Executor mode.
thread-correlation-classes-exclude
min-transaction-stall-threshold-in-seconds60For Executor mode only, the transactions will not get checked for stall unless they run at least the specified number of seconds

Exclude Selected Activities from Transactions

Asynchronous frameworks use lower-level asynchronous mechanisms that are not related to the processing of user transactions (for example, a thread pool might grow and shrink automatically, depending on the load or a framework might initialize its thread pool upon the first use). You must ignore threads used in these contexts since their lifecycle is not bound to any individual application transaction.

To facilitate the exclusion of such asynchronous components (usually Threads and other Runnables), the Executor mode offers a mechanism called capture suppression. The suppression is tied to a specific method by a suppression rule in the async-config section of app-agent-config.xml. Consider the following example of such a rule provided by default:

<job>
  <match-class type="matches-class"><name filter-type="EQUALS" filter-value="java.util.concurrent.ThreadPoolExecutor"/></match-class>
  <match-method><name filter-type="EQUALS" filter-value="addWorker"/></match-method>
  <action type="suppression"/>
</job>

The addWorker method on the  java.util.concurrent.ThreadPoolExecutor class is a private method invoked by ThreadPoolExecutor whenever a new worker thread is to be created, started and added to the pool. Since such threads are not directly associated with any individual transaction at the point of creation, a suppression rule is used in order that any asynchronous task hands offs occurring within this method will not get associated with the transaction. Any asynchronous tasks subsequently executed by these threads will be associated with the transaction that created the task.