The AppDynamics Node.js Agent APIs enable the Node.js Agent to monitor business transactions that a web application performs outside the context of an HTTP request or an application that is not web-based.

Business Transaction Definition

You define a custom business transaction using appd.startTransaction() and end().

If the custom transaction runs for a long time or if it crosses an asynchronous boundary, you can use resume() to rejoin the running transaction.

A downstream transaction in a distributed transaction cannot start until its upstream transaction has made its exit call.

The order of transactions respects the nonlinear nature of Node.js applications. An upstream transaction might end immediately after its exit call completes or sometime later. It is not necessary for an upstream transaction to end before or after its downstream transaction starts or ends. It is possible for a downstream transaction to end before its upstream transactions have ended.

Marking a Transaction as an Error Transaction

An error transaction is one in which an exception occurred. It is reported as an error transaction and not as a slow, very slow or stalled transaction, even if the transaction in which the error occurred was also slow or stalled.

To attach a JavaScript error object to a transaction using the Node.js APIs do one of the following:

  • Use trx.markError() passing in the JavaScript error object.
  • Attach the error object to the HTTP response associated with the transaction as response.error.

When an error is marked, the status code defaults to 500, unless you set it using one of the following techniques:

  • Use trx.markError() passing in the JavaScript error object and the optional status code.
  • Set the statusCode property in the error object passed to trx.markError() as error.StatusCode.
  • Set the statusCode property on the response.error object as response.error.StatusCode.

Transaction Correlation Management

Transaction correlation is the functionality that maintains the business transaction context across all tiers—servers—traversed by a distributed transaction. The tiers may be built on platforms other than Node.js. For example, Java, .NET, and PHP tiers may participate in a distributed business transaction in which a Node.js tier participates, as originating, continuing or terminating tiers in the transaction.

The Node.js Agent APIs provide facilities for managing transaction correlation among various transactions, which may be custom or automatically-detected.

While the AppDynamics default auto-detection mechanism obtains transaction correlation information from an incoming HTTP request, the Node.js Agent APIs allow you to obtain this information from other sources, such as a custom field in a Redis cache entry, and to supply it to your custom transactions. You can use the APIs to support forward correlation by supplying transaction correlation information on exit calls that you make to downstream transactions.

A downstream transaction starts after its immediate upstream transaction makes its exit call. That call could be a direct exit call to the next tier or a call to a backend service that does some processing, such as publishing a message onto a queue.

.Transaction Correlation

Exit Call Management

An exit call is either a custom exit call or an automatically-detected exit call. A transaction needs its exit call object to create correlation information to provide to a downstream transaction that needs to correlate with it.

Custom Exit Calls

If you want an exit call to be reported to the controller, and it is not automatically detected by the agent, create a custom exit call with startExitCall() and end it with endExitCall().

See Node.js Supported Environments for the list of backends that are automatically detected by the Node.js Agent. If the exit call invokes a backend not listed on this page, you probably need to create a custom exit call.

You can also use a beforeExitCall() callback function to check for the existence of an automatically-detected exit call.

Processing a custom exit call is straightforward. First, create the exit call and then pass its returned ExitCall object to createCorrelationInfo() to create a string-encoded correlation information object that a downstream transaction can fetch later.

Workflow for a custom exit call

// start a custom transaction
var trx = appd.startTransaction(. . . )
. . . 

// start a custom exit call
exit = trx.startExitCall(. . .);

// create correlation information
cinfo = trx.createCorrelationInfo(exit)
//store cinfo where it can be made available to a downstream transaction

// make the exit call
. . . 
trx.endExitCall(. . .)
CODE

Automatically Detected Exit Calls

The code executing in your custom transaction might make an exit call that is automatically detected by the Node.js Agent.

In this case, you can provide a beforeExitCall() callback function to process that exit call. When your code makes an automatically-detected exit call, the agent intercepts the exit call request and invokes the callback, if you have provided one. Then it allows the application to proceed with the exit call request.

You would install a beforeExitCall() callback function for the following purposes:

  • To test for the existence of an automatically-detected exit call
    If you are uncertain that the exit call will be automatically detected, you can install a callback function to test for the exit call. If the callback is not invoked, the exit call is not automatically detected.

    // start a custom transaction
    var trx = appd.startTransaction(. . . )
    . . . 
    
    var detected = false;
    trx.beforeExitCall = function(call) { detected = true; return call; };
    
    // make the exit call
    . . . 
    
    // test whether the exit call was automatically detected
    if (detected == false)
    . . . 
    CODE


    If detected is false after the exit call, you need to create a custom exit call to report the exit call to the Controller. If detected is true, you can capture the exit call and create the correlation information with the callback.

  • To capture the ExitCall object to create correlation information

    // start a custom transaction
    var trx = appd.startTransaction(. . . )
    . . . 
    
    trx.beforeExitCall = function getExitInfo(exitCall) { 
        // create the correlation header from the captured exit call 
        var c = trx.createCorrelationInfo(exitCall); 
        // store c somewhere
        // … (c)  
        return exitCall; 
    } 
    // make the exit call
    CODE
  • To modify the exit call that is reported to the Controller

    // start a custom transaction
    var trx = appd.startTransaction(. . . )
    . . . 
    
    trx.beforeExitCall = function customExitCallHandler(exitCall) {
        // don't report database access for this transaction
        if (exitCall.isSql) return; 
        // customize label for all other exit calls in this transaction
        exitCall.label += " (my custom transaction)";
        return exitCall;
    }
    // make the exit call
    JS

Workflow: Create Originating Transaction with Correlation Information

In this scenario, you create a custom originating transaction and the correlation header that a downstream transaction will need to correlate with it.

  1. Start a custom transaction: var trx=appd.startTransaction(...).
  2. Either start a custom exit call using e=trx.startExitCall(einfo) or capture a detected exit call by installing a callback function to e=trx.beforeExitCall(e).
  3. Create correlation information from the exit call: c=trx.createCorrelationInfo(e).
  4. Store the correlation information.
  5. Make the exit call.
  6. Optionally provide a trx.exitCallCompleted(e) callback function, if you want to modify what is reported to the controller based on information obtained from the execution of the exit call.
  7. If you created a custom exit call, end the exit call after you have processed the exit call response: trx.endExitCall(e).
  8. End the transaction: trx.end().

Workflow: Create Terminating Transaction Correlated with Upstream Transaction

In this scenario, you create a custom transaction, which needs to correlate with an upstream transaction but not with another downstream transaction.

  1. Retrieve the correlation information stored by the previous transaction.
  2. Parse the retrieved correlation information into a correlation header: ch=appd.parseCorrelationInfo(c).
  3. Start a custom transaction using the correlation header: trx=appd.startTransaction(ch).
  4. Optionally make an exit call.
  5. End the transaction: trx.end().

Workflow: Create Continuing Transaction Correlated with Upstream and Downstream Transactions

In this scenario, you create a continuing transaction that needs to correlate both with an upstream originating transaction and a downstream transaction. It uses the correlation techniques described in both of the previous workflows.

  1. Retrieve correlation information stored by the previous transaction.
  2. Parse the retrieved correlation information into a correlation header: ch=appd.parseCorrelationInfo(c1).
  3. Start a custom transaction using the correlation header: trx=appd.startTransaction(ch).
  4. Either start a custom exit call using e=trx.startExitCall(einfo), or capture a detected exit call by installing a callback function to e=trx.beforeExitCall(e).
  5. Create correlation information from the exit call in this transaction: c2=trx.createCorrelationInfo(e).
  6. Store the correlation information for the next downstream transaction.
  7. Make the exit call.
  8. Optionally provide a trx.exitCallCompleted(e) callback function, if you want to modify what is reported to the controller based on information obtained from the execution of the exit call.
  9. If you created a custom exit call, end the exit call after you have processed the exit call response: trx.endExitCall(e).
  10. End the transaction: trx.end().