The New Relic Node.js agent provides first-class, out-of-the-box visibility into many of the most popular Node.js modules and frameworks. It also provides open APIs for custom instrumentation that can be used to augment that visibility in your own application code.

And now we’re excited to announce the release of the New Relic Agent for Node.js v2.0. The 2.0 release expands our existing API and instrumentation support by adding a new plugin-style API designed specifically to make it easier to add new instrumentation for modules that are not instrumented out-of-the-box. It can even replace or disable our existing instrumentations based on the particular monitoring needs of your specific applications.

The Node agent includes instrumentation for all asynchronous functions from the Node core, as well as many popular modules (Express.js, MongoDB, Redis, etc.). But suppose you want to see additional timing information for a library that New Relic doesn’t instrument out-of-the-box. Up until now your only options were to either use our existing createTracer API inside your application code, or submit a PR to our agent.

With the new 2.0 API, we have added an additional mechanism designed to address those challenges. Instrumentation can now be written as an isolated, separate module, and registered with the agent as a kind of plugin. This means that the application code itself does not have to be modified, and the custom instrumentation can be reused as its own module, distributed independently from the agent across different projects.

We’ve also added new helper methods to the API that are designed to make the task of writing instrumentation for the most common types of libraries even simpler. They now do much of the heavy lifting for you. Essentially, you tell us the name of the module and provide some information about the interesting methods to instrument—and we do the rest.

How the Node Agent 2.0 API works

The agent provides a high-level API to register different kinds of instrumentations—instrument(), instrumentDatastore(), instrumentWebframework(), and instrumentMessages(). By calling one of these methods, you are telling the agent: when a module with this name is imported in code (using require), execute this instrumentation function.

Here is an example of registering a custom datastore instrumentation:

var newrelic = require('newrelic')
var instrument = require('myCustomInstrumentation')

newrelic.instrumentDatastore('myDbDriver', instrument)

The agent then passes the following parameters to the instrumentation function when it is executed:

  • a shim object
  • the module to be instrumented
  • the name of the module

The shim object contains API methods for performing the instrumentation on the provided module. Here is an example of instrumenting a datastore query call:

function instrumentMyDbDriver(shim, myDbDriverModule, name) {
   // set the name of the datastore
   shim.setDatastore(‘myDatastore’);

   // assuming the datastore module exports a Client class with query method
   shim.recordQuery(myDbDriverModule.Client.prototype, ‘query’, {
      query: shim.FIRST,
      callback: shim.LAST
   });
}

Here we are telling the agent: when the Client.query() method is called, record the query from the first argument, and stop timing when the callback is called, which is the last argument. For all possible methods and parameters, see our API documentation at https://newrelic.github.io/node-newrelic/docs/.

Types of instrumentation

There are a few different types of instrumentation: generic, datastore, web framework, and message broker. Each type is registered using a different function and receives a different type of shim object.

The shim object will in all cases contain generic methods applicable for all types of instrumentation, and it will also contain methods specific to the type of instrumentation.

For example, the datastore instrumentation shim provides methods for recording database operations (recordQuery and recordOperation). Internally, the shim creates the correct metrics, which are then displayed in the Databases view in the New Relic APM UI.

new relic apm ui

Similarly, the web framework instrumentation has methods for recording middleware functions, which are then displayed in transaction breakdown and transaction traces, as shown below:

transaction breakdown

breakdown table

Lastly, the message broker instrumentation has methods for recording message broker operations (producing and consuming messages). The API ensures that the correct transaction segments and metrics are created. In addition to the breakdown table, the generated metrics are also used in the Messages tab in the Transactions view:

messages transaction view

The message broker API is also responsible for automatically creating transactions when using a subscription model with a message broker. In this case, each created transaction corresponds to a single consumed message:

transactions

The messaging API also has support for cross-application tracing, when messages are used to communicate between two different (instrumented) apps.

For more information on writing different types of instrumentation, see the following documentation and tutorials:

Documentation: https://docs.newrelic.com/docs/agents/nodejs-agent/installation-configuration/upgrade-nodejs-agent

Datastore: https://newrelic.github.io/node-newrelic/docs/tutorial-Datastore-Simple.html

Web framework: https://newrelic.github.io/node-newrelic/docs/tutorial-Webframework-Simple.html

Message broker: https://newrelic.github.io/node-newrelic/docs/tutorial-Messaging-Simple.html

Generic: https://newrelic.github.io/node-newrelic/docs/tutorial-Instrumentation-Basics.html

Overview: https://newrelic.github.io/node-newrelic/docs/

All of our datastore and web framework instrumentations now use the new Node Agent 2.0 API. We have also added instrumentation of the amqplib module (client for the RabbitMQ message broker) using the new API. All of these can be used as a reference.

Better understanding of your applications

The New Relic Node Agent 2.0 expands our API and instrumentation support with a plug-in-style API designed to make it easier to add new instrumentation for modules, without having to add custom code. Using the 2.0 release to instrument your custom framework will lead to deeper insights and enhanced understanding of the behavior of your application.

If you have feedback or suggestions on these improvements, please get in touch at the New Relic forum. We would love to hear from you!

 

James is a product manager in New Relic's APM organization with responsibility for the Node, Ruby, and Python agents. He has been a technology startup entrepreneur for an accelerator-backed startup and held senior engineering and engineering management positions at IBM. James has a passion for creating tools and services that make the lives of software developers and IT professionals better. View posts by .

Interested in writing for New Relic Blog? Send us a pitch!