Node.js Collector Installation
- Installing the Node.js Collector Package
- Common Pitfalls
- Advanced Deployment Scenarios
- Advanced Build Scenarios
- Native Add-ons
- Disabling The Node.js Collector During Development
- Change of Package Name
- Updating the @instana/collector Package
- See Also
Installing the Node.js Collector Package
Note: If your applications are run exclusively on Kubernetes, consider using the Instana AutoTrace WebHook method instead.
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
CommonJS
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.
ECMAScript modules
When @instana/collector
is installed as a dependency, you need to activate the collector for the application by loading the Instana Node.js collector through the --experimental-loaders
argument.
For more information, see ECMAScript Modules.
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 parentheses 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');
...
When you use ECMAScript modules (ESM), do not import or require the collector in the code as follows:
import instana from '@instana/collector'
instana()
import { something, else } from 'some-module';
Instead, load the collector by using the experimental loaders flag.
Opentelemetry
Using both the OpenTelemetry SDK and the Instana collector in the same Node.js application is not supported. It might cause the following problems:
- Missing call in Instana
- Duplicated data in Instana
- Broken instrumentations
You are not recommended to use both the OpenTelemetry SDK and the Instana collector in the same Node.js application. If you want to use the Opentelemetry SDK, see Node.js OpenTelemetry integration.
Advanced Deployment Scenarios
Kubernetes & OpenShift
Instana AutoTrace WebHook
Note: This installation method is currently in Technical Preview.
The Instana AutoTrace WebHook is an implementation of a Kubernetes Mutating WebHook Admission Controller that automatically configures all the requirements to run Node.js applications across an entire Kubernetes cluster.
If you elect to install the Instana AutoTrace WebHook on your Kubernetes clusters, you have no need to perform any manual step to trace any of your Node.js applications running in those clusters.
Note: If you use the Instana AutoTrace webhook and you want to use the Instana Node.js SDK, review the using the API together with the AutoTrace WebHook section.
Manual installation
If your Node.js application and the Instana agent run in a Kubernetes cluster, check the documentation on Kubernetes 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
).
Next.js
For Next.js applications, we recommend to use the the approach described in Installation Without Modifying the Source Code.
Installation Without Modifying the Source Code
There are situations where you cannot (or do not want to) modify the source code of the monitored application. For these scenarios, the following approach can be used. This is also the preferred approach for applications built with Webpack, Babel or any other kind of bundler or transpiler. Last but not least, it is the recommended approach for Next.js applications.
There are two flavors of this method:
- Installing
@instana/collector
as a local dependency of your project, or - installing
@instana/collector
globally on the target system.
Both flavors are described in detail as follows.
Local Installation As A Dependency
Add the package @instana/collector
to your project's dependencies by running the command npm install --save @instana/collector or yarn add @instana/collector. Do not add the statement
require('@instana/collector')();
to your code. In fact, none of your JavaScript or TypeScript files needs to mention any @instana
package.
CommonJS
Either set the environment variable NODE_OPTIONS or add an additional --require
parameter when you start the node
executable.
Complete either of the following steps: - Set the NODE_OPTIONS variable before starting the Node.js process:
``` {: codeblock}
NODE_OPTIONS="--require ./node_modules/@instana/collector/src/immediate"
```
If you build the application with Docker, you need to do this by adding the following line to your `Dockerfile` (after the last `FROM` statement and before the final `CMD` or `ENTRYPOINT` that starts the `node` process):
``` {: codeblock}
ENV NODE_OPTIONS="--require ./node_modules/@instana/collector/src/immediate"
```
**Note:** The `src/immediate` part is important, so make sure you do not accidentally omit it. The path needs to start with `./` so Node.js knows that it is a relative path and not a module identifier. The path is evaluated based on the current working directory.
- Instead of setting the **NODE_OPTIONS** variable, you can also add the `--require` parameter to the command that starts Node.js. If you normally start the application by doing something like `node app/index.js`, add an additional `--require` command line argument (see <https://nodejs.org/api/cli.html#cli_r_require_module>). For example, change the command **node app/index.js** to **node --require ./node_modules/@instana/collector/src/immediate app/index.js**.
**Note:** The `src/immediate` part is important, so make sure that you do not accidentally omit it. The path needs to start with `./`, so Node.js knows that it is a relative path and not a module identifier. The path is evaluated based on the current working directory. If this is application is built and run by using Docker, you need to modify the final `CMD` or the `ENTRYPOINT` in your `Dockerfile` accordingly.
This will load and initialize the Node.js collector before the application code is loaded.
It is important that @instana/collector
is installed on the target system by a package manager, so all its dependencies are also correctly installed. Running the npm install
or yarn
/yarn install
somewhere else (on a build system, for example) and then copying the resulting node_modules
folder to the target system is not recommended. The package installation step includes compilation of the native add-ons,
which needs to happen on the target architecture and for the correct Node.js version.
ECMAScript modules
Follow the steps from the previous section, but use the following argument instead of --require
:
--experimental-loader /path/to/instana/node_modules/@instana/collector/esm-loader.mjs
Notes:
- ECMAScript support is added from Node.js collector 2.14.0.
- Experimental loaders are available from Node v16.
- The Instana Node.js collector will be initialized automatically by the loader.
Global Installation
Make the package @instana/collector
with all its dependencies that are available on the target system in a well-known location, such as /path/to/instana/node_modules/@instana/collector
.
For example, you can run the command npm install -g @instana/collector on the target system. If you use yarn instead of npm, run the command yarn global add instead of npm install -g. If
this is a containerized application, this statement can easily be added to the Dockerfile
. You need to know where the command npm install -g will actually put the package. This depends on the operating system.
For more information, see folders.
CommonJS
Either set the environment variable NODE_OPTIONS
or add an additional --require
parameter when you start the node
executable.
Complete either of the following steps: - Set the NODE_OPTIONS variable before you start the Node.js process:
``` {: codeblock}
NODE_OPTIONS="--require /path/to/instana/node_modules/@instana/collector/src/immediate"
```
You need to replace `/path/to/instana` with the actual path. If you build the application with Docker, you need to do this by adding the following line to your `Dockerfile` (somewhere after the last `FROM` statement and before the final `CMD` or `ENTRYPOINT` that starts the `node` process):
``` {: codeblock}
ENV NODE_OPTIONS="--require /path/to/instana/node_modules/@instana/collector/src/immediate"
```
**Note:** The `src/immediate` part is important, so make sure that you do not accidentally omit it. The path needs to start either with `/` or `./` to tell Node.js that it is an absolute or relative path, and not a module identifier.
- *Instead of* setting the `NODE_OPTIONS` variable, you can also add the `--require` parameter to the command that starts Node.js. If you normally start the application by doing something like `node /path/to/app/`, add an additional `--require` command line argument (see <https://nodejs.org/api/cli.html#cli_r_require_module>). For example, change the command **node /path/to/app** to **node --require /path/to/instana/node_modules/@instana/collector/src/immediate /path/to/app**.
**Note:** The `src/immediate` part is important, so make sure that you do not accidentally omit it. The path needs to start either with `/` or `./` to tell Node.js that it is an absolute or relative path, and not a module identifier. If this is application is built and run by using Docker, you need to modify the final `CMD` or the `ENTRYPOINT` in your `Dockerfile` accordingly.
This will load and initialize the Node.js collector before the application code is loaded.
It is important that @instana/collector
is installed on the target system by a package manager, so all its dependencies are also correctly installed. Installing @instana/collector
somewhere else (on a build system,
for example) and then copying the package to the target system is not recommended. The npm install
step includes compilation of the native add-ons, which needs to happen on the target architecture and for the correct
Node.js version.
ECMAScript modules
Follow the steps from the previous section, but use the following argument instead of --require
:
--experimental-loader /path/to/instana/node_modules/@instana/collector/esm-loader.mjs
Notes:
- ECMAScript support is added from Node.js collector 2.14.0.
- Experimental loaders are available from Node v16.
Advanced Build Scenarios
Bundlers (Webpack and Similar)
The preferred installation method when you pre-process your Node.js server application with a bundler like Webpack or Rollup is described in Installation Without Modifying the Source Code.
Alternatively, if you can also install @instana/collector
as a normal dependency.
In both cases you need to make sure to only bundle your own code, not the code of your dependencies from the node_modules
folder. There are two reasons for this:
- The module
@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. - To instrument third party libraries,
@instana/collector
hooks into Node.js'require
process. But if those libraries are not loaded at runtime and instead are bundled with your own code at build time, no actualrequire
is executed and the instrumentation is not applied. Tracing will not work or only work partially in such a setup. (To be precise, tracing will probably only work for Node.js core modules likehttp
because those are usually excluded from bundling by default.)
Thus, we strongly recommend 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()],
...
};
In case you are using Angular CLI, in particular with Angular Universal/SSR, you should add "externalDependencies": ["@instana/collector"]
(and possibly other
libraries that @instana/collector
instruments) to your angular.json
file to exclude it/them from bundling (see here).
Transpilers (Babel etc.)
The preferred installation method when using a transpiler (like Babel, Traceur, or the TypeScript compiler tsc
) is described in Installation Without Modifying the Source Code.
Alternatively, you could als install @instana/collector
as a normal dependency but we do not recommend this approach. It requires you to pay close attention to how import
and require
statements are treated
by your transpiler. That is particular import if your transpiler processes 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://www.instana.com/docs/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
.
Some information is not available to Node.js programs without the help of native add-ons. Specifically, the Instana Node.js collector uses these add-ons:
- To retrieve information about garbage collection
- To retrieve information about event loop activity
- For profiling
All native add-ons are optional dependencies. The collector will work fine without these native add-ons, but the features mentioned above will be disabled. If any of these dependencies are missing, a log message will be printed to the application log at startup which reads like this:
Could not load @instana/autoprofile. You will not get profiling information for this Node.js app in Instana, although
autoprofiling has been enabled. This typically occurs when native add-ons could not be built during module installation
(npm install/yarn) or when npm install --no-optional or yarn --ignore-optional have been used to install dependencies.
See the instructions to learn more about the requirements of the collector:
https://www.ibm.com/docs/de/obi/current?topic=nodejs-collector-installation#native-add-ons
Note: You can safely ignore these message if the additional garbage collection and event loop metrics are not relevant for you and if you do not plan to use the Instana AutoProfile feature on Node.js.
There are two possible reasons for missing native add-ons:
- Installing dependencies with
npm install --no-optional
oryarn --ignore-optional
. If that flag is present, npm/yarn will not even attempt to install these dependencies. To fix that, either remove the--no-optional/--ignore-optional
flag from the install step, or add explicit install steps for the dependencies in question after thenpm install --no-optional
/yarn --ignore-optional
step:npm install @instana/autoprofile
/yarn add @instana/autoprofile
npm install event-loop-stats
/yarn add event-loop-stats
npm install gcstats.js
/yarn add gcstats.js
- Add-on compilation has failed during the
npm install
/yarn
step. The remainder of this section explains why this might happen and how to fix it.
Native add-ons 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
or yarn
step). To make the compilation work, the
system needs to have tools like make
, g++
and python
installed. These tools can often be installed by using a bundle called build-essential
or similar (depending on your operating system's
package manager and registry). The following examples shows how to do this for popular Linux distributions:
# for Debian-based distributions (including Ubuntu)
apt-get install build-essential
# or, for Fedora-based distributions (CentOS, Red Hat, etc.)
yum groupinstall "Development Tools"
# or, for Alpine Linux
apk add build-base python
Important: The installation of the dependencies needs to happen on the machine that will run the application. Otherwise native add-ons might be incompatible with the target machine's system architecture or the Node.js version
in use. Therefore it is a bad practice to install the dependencies by running the command npm install
/yarn
on a build server and then copy the application (including the dependencies) to the target machine.
If you run your Node.js application in a container, 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.
If the native add-on dependencies like gcstats.js
and event-loop-stats
were not installed successfully when running npm install
, the package @instana/collector
will automatically try to use
pre-built binaries that match the operating system, Node.js version and libc
variant. This feature is only available on x64 Linux. It can be disabled by setting INSTANA_COPY_PRECOMPILED_NATIVE_ADDONS=false
.
Disabling The Node.js Collector During Development
The easiest way to disable the Node.js collector for (local) 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
instana-nodejs-sensor package is no longer updated.
Note: Still using package name instana-nodejs-sensor
? Switch to @instana/collector
.
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
every time 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.
Specifying 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 yourpackage.json
file. It will also update the version range string inpackage.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 yourpackage.json
file, but only if- the
node_modules
folder does not already contain a version of@instana/collector
that matches the version range, and - no
package-lock.json
file is present that locks the version of the package.
- the
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
, refer to the yarn documentation, in particular yarn update
for details, but basically the recommendations
and procedures are the same.