Node.js Collector Installation

Installing the Node.js Collector Package

The installation of the Instana Node.js collector is a simple two step process. First, install the npm package @instana/collector in your application via:

npm install --save @instana/collector

Now that the collector is installed, it needs to be activated from within the application. Do this by requiring and initializing it as the first statement in your application. Please take care that this is the first statement as the collector will otherwise not be able to access certain information.

require('@instana/collector')();

// All other require statements must be done after the collector is initialized.
// Note the () after the require statement of the collector which initializes it.


// const express = require('express');

The code shown above initializes the collector with default configuration options. You can also pass in a configuration object when initializing the Instana Node.js collector. Refer to the the configuration page for a list of valid configuration options, and in particular to the section agent communication for details about configuring connectivity between your monitored application and the Instana agent.

Kubernetes & OpenShift

If your Node.js application and the Instana agent run in a Kubernetes cluster, please check the documentation on Kubernets network access for information about the required configuration in this setup.

Cloud Foundry

Note: This section assumes that the Instana agent is currently running on the Diego cells of the Cloud Foundry foundation. Without an agent running on the underpinning Diego cell, monitoring Cloud Foundry applications is not supported.

For information on how to setup Instana agents and the related Cloud Foundry or Pivotal Platform functionality, see our Cloud Foundry and Pivotal Platform documentation.

On Cloud Foundry, a configuration is not required at the level of cf push and the application manifest. The only necessary step is to add the @instana/collector package to the Cloud Foundry Node.js application as described above.

Apigee Microgateway

Please refer to the Apigee Microgateway page for information on how to use the Instana Node.js collector package with Apigee Microgateway (also known as edgemicro).

Common Pitfalls

Incorrectly integrating the collector will usually lead to a loss of observability. Your Node.js application will still be shown in Instana but tracing will only work partially. Some calls will be traced but others will be missing.

Important: It is not enough to only have the require statement as the first statement in your application and calling the function exported by require('@instana/collector') later. That is, the following is not supported:

// WRONG!
require('@instana/collector'); // @instana/collector is not initialized

require('something');
require('another-thing');

...

and neither is this:

// WRONG!
const instana = require('@instana/collector');

require('something');
require('another-thing');

instana(); // TOO LATE!
...

Instead, the function exported by require('@instana/collector') must be called right away, before any other require or import statements. This can either be done in one statement as shown above (note the second pair of parantheses in require('@instana/collector')()) or in two consecutive statements:

// Correct:
const instana = require('@instana/collector');
instana(); // this is fine

// Now all other modules can be required:
require('something');
require('another-thing');
...

The same constraint applies if you are using ES6 module syntax. The following is not supported:

// WRONG!
import instana from '@instana/collector';

import { something, else } from 'some-module';
import anotherThing from 'another-module';

instana(); // TOO LATE!
...

Instead, do this:

import instana from '@instana/collector';
// You need to call the exported function *immediately*, before importing anything else.
instana();

// Now all other modules can be imported:
import { something, else } from 'some-module';
import anotherThing from 'another-module';
...

Native Addons

Some information is not available to Node.js programs without the help of native addons. Specifically, the Instana Node.js collector uses these addons

  • to retrieve information about garbage collection,
  • to retrieve information about event loop activity,
  • for CPU profiling, and
  • to report uncaught exceptions (if enabled).

While the collector works fine without these native addons (technically, they are marked as optional dependencies), we strongly recommend you to support native addon compilation.

Native addons are compiled automatically for your system and Node.js version when the Instana Node.js collector dependency is installed (as part of the npm install step). In order for the compilation to work, the system needs to have tools like make, g++ and python installed. These tools can often be installed via a bundle called build-essential or similar (depending on your package manager and registry). The following example shows how to do this for a typical Ubuntu setup.

apt-get install build-essential
# -or-
yum groupinstall "Development Tools"

It is important that the installation of the dependencies is happening on the machine which will run the application. This needs to be ensured, because otherwise native addons may be incompatible with the target machine’s system architecture or the Node.js version in use. It is therefore a bad practice to npm install dependencies on a build server and to copy the application (including the dependencies) to the target machine.

If you run your Node.js application dockerized, this aspect deserves extra attention. You might want to check the output of your Docker build for node-gyp errors (look for gyp ERR! and node-pre-gyp ERR!). If these are present, you should inspect and evaluate them. Some of them can be safely ignored. For example, some packages might try to download precompiled binaries, if this fails, they fall back to compilation via node-gyp that is, the download error can be ignored, if the compilation step worked. Other packages emit a lot of notes and warnings during compilation, which can also be ignored.

If the installation of an optional dependency ends with gyp ERR! not ok, you might want to look into it. While Instana can unfortunately not provide support for fixing your particular Dockerfile, we do provide some example Dockerfiles.

Transpilers (Babel etc.)

This section is relevant if you transpile your code with a transpiler like Babel, Traceur, Rollup, Webpack or the TypeScript compiler (tsc), and in particular if you use it to transpile ES6 import statements. Just putting something like this at the top of your main file will not work in such a setup:

import instana from '@instana/collector';

// THIS WILL NOT WORK because transpilers change the order of imports and statements.
instana();

import express from 'express';

Why not? According to the ES6 spec, all imports are evaluated before the body of the module is executed. Babel and other transpilers comply with this rule and move all imports to the top when transpiling source files. All actual statments will be put after the imports. As a consequence, the import for express in this example will be placed before the instana(); call. You will end up with something like this in your transpiled file:

var _instana = _interopRequireDefault(require("@instana/collector"));

var _express = _interopRequireDefault(require("express"));

var _morgan = _interopRequireDefault(require("morgan"));

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

(0, _instana.default)(); // <- This is too late, since all other modules will already have been required.

...

As you can see, the actual call to the @instana/collector’s init function comes after all require statements in the transpiled file.

Instead, you can do something like this:

// Put this import at the top of your main file. Only the import here,
// don't change this to "import instana from './instanaInit'"!
import './instanaInit';

// Now all the other imports can follow:
import express from 'express';
import morgan from 'morgan';

// The following statement is optional; it is only required if you want to use
// Instana's Node.js API (https://docs.instana.io/ecosystem/node-js/api/):
// @ts-ignore (in case you are using TypeScript, to avoid 'Could not find a declaration file for '@instana/collector')
import instana from '@instana/collector';

The file instanaInit.js (or instanaInit.ts if you use TypeScript) should just have this one statement:

require('@instana/collector')();

This way, the init function is called right away when the process starts.

In general, when using any transpiler, it is a good idea to inspect the transpiler’s output files when integrating @instana/collector.

Bundlers (Webpack and Similar)

If you pre-process your Node.js server application with a bundler like webpack before deploying it, you need to make sure to only bundle your own code, not the code of your dependencies from the node_modules folder. In particular, @instana/collector does not support being pre-processed with webpack. Among other problems, dynamic require statements used in our code will not be resolved correctly. You need to configure your bundler so that everything in in node_modules is excluded from all code transformations.

You can use the module webpack-node-externals to achieve that:

// your webpack.config.js:

const nodeExternals = require('webpack-node-externals');

module.exports = {
  ...
  // externals: nodeModules,
  externals: [nodeExternals()],
  ...
};

How Can The Node.js Collector Be Disabled For (Local) Development?

The easiest way to disable the Node.js collector for development is to use environment variables. The Express framework popularized the environment variable NODE_ENV for this purpose, which we recommend to use for this purpose. Load the Node.js collector in the following way:

if (process.env.NODE_ENV !== 'development') {
  require('@instana/collector')();
}

Next, start your application locally with the NODE_ENV variable set to development. Example:

export NODE_ENV=development
# -or-
NODE_ENV=development node myApp.js

Change of Package Name

Up to release 1.64.0, our npm package was called instana-nodejs-sensor. Starting with version 1.65.0 the name has changed to @instana/collector. To prevent breaking changes, we are keeping instana-nodejs-sensor as an alias for @instana/collector for the foreseeable future.

Please refer to our migration guide below to update applications that still use the instana-nodejs-sensor package:

  1. Update the package name in the dependencies section in your package.json file from instana-nodejs-sensor to @instana/collector.
  2. Run npm install/yarn install afterwards (to update package-lock.json/yarn.lock).
  3. Double check that all references to instana-nodejs-sensor have been removed from package-lock.json/yarn.lock and that the collector package has been isntalled to node_modules/@instana/collector.
  4. In your source code, you need to replace all occurrences of

    • require('instana-nodejs-sensor') with require('@instana/collector'), and
    • import instana from 'instana-nodejs-sensor' with import instana from '@instana/collector'.
    • Most applications will only have one such require/import statement.

Note: To help users that cannot migrate immediately, we will keep publishing new versions of @instana/collector additionally under the name instana-nodejs-sensor.

Updating the @instana/collector Package

We continuously improve Instana’s Node.js support and recommend to always use the latest available version of the @instana/collector package to benefit from the these improvements. Updating the package to its latest version everytime you build/roll out your app is a good practice. Updating works just like with any other npm package.

After the initial npm install --save @instana/collector (see above), your package.json will contain a dependency declaration like "@instana/collector": "^1.68.2". The caret (^) denotes a SemVer version range (in this example ^1.68.2 stands for >= 1.68.2 && < 2.0.0). The version ranges dictates the behaviour of the npm install and npm update commands.

Specifiying the version as "@instana/collector": "1.68.2" (without the caret or more generally, without using a version range) would pin that exact version, that is, npm install and npm update would always use version 1.68.2. This is not recommended. Check out the npm docs on version ranges for more details.

  • Executing npm update @instana/collector in your project will install the latest version that matches the version range in your package.json file. It will also update the version range string in package.json. If a lockfile (package-lock.json) is present, it too will be updated accordingly. See the docs for npm update.
  • Executing npm install in your project will also install the latest version that matches the version range in your package.json file, but only if

    1. the node_modules folder does not already contain a version of @instana/collector that matches the version range, and
    2. no package-lock.json file is present that locks the version of the package.

In conclusion, if you build your app on CI and do a fresh npm install every time (you don’t keep the node_modules folder between builds), and if you do not commit package-lock.json to version control, running npm install as a build step is sufficient to get the latest version. In all other cases (keeping node_modules between builds and/or having package-lock.json in version control), it is recommended to run npm update @instana/collector as part of your build.

If you use yarn instead of npm, please refer to the yarn documentation, in particular yarn update for details, but basically the recommendations and procedures are the same.

See Also