Node.js
Before using OTEL to send Trace / Metric data to DataKit, make sure you have configured the collector.
OpenTelemetry Node.js collects Trace and Metric data from Node.js applications and reports it to DataKit through OTLP for unified display in Guance.
In addition to standard OpenTelemetry capabilities, Guance provides a Profile extension for Node.js. Based on @cloudcare/profiler-nodejs and @datadog/pprof, which are maintained and released by Guance, it collects wall / heap profiles and reports them to Guance through DataKit's /profiling/v1/input endpoint.
Version Support¶
- Node.js:
^18.19.0or>=20.6.0 - OpenTelemetry: the current stable version is recommended
- Profile extension package:
@cloudcare/profiler-nodejs - Default Profiling endpoint:
http://127.0.0.1:9529/profiling/v1/input
Automatic Instrumentation¶
Automatic instrumentation is the most common way to quickly integrate Node.js applications.
1) Install Dependencies¶
npm install \
@opentelemetry/api \
@opentelemetry/sdk-node \
@opentelemetry/auto-instrumentations-node \
@opentelemetry/exporter-trace-otlp-proto \
@opentelemetry/exporter-metrics-otlp-proto
2) Configure with Environment Variables¶
export OTEL_SERVICE_NAME="nodejs-demo"
export OTEL_TRACES_EXPORTER="otlp"
export OTEL_METRICS_EXPORTER="otlp"
export OTEL_LOGS_EXPORTER="none"
export OTEL_EXPORTER_OTLP_PROTOCOL="http/protobuf"
export OTEL_EXPORTER_OTLP_ENDPOINT="http://127.0.0.1:9529/otel"
export NODE_OPTIONS="--require @opentelemetry/auto-instrumentations-node/register"
Then start your application directly:
When the default HTTP paths are used, the actual Trace and Metric endpoints are:
- Trace:
http://127.0.0.1:9529/otel/v1/traces - Metric:
http://127.0.0.1:9529/otel/v1/metrics
3) Start from the Command Line¶
If you do not want to inject the configuration through the environment, set it directly in the startup command:
OTEL_SERVICE_NAME=nodejs-demo \
OTEL_TRACES_EXPORTER=otlp \
OTEL_METRICS_EXPORTER=otlp \
OTEL_LOGS_EXPORTER=none \
OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf \
OTEL_EXPORTER_OTLP_ENDPOINT=http://127.0.0.1:9529/otel \
NODE_OPTIONS="--require @opentelemetry/auto-instrumentations-node/register" \
node app.js
4) PM2 / Systemd¶
If the application is started by PM2, Systemd, or another process manager, add the preceding OTEL_* environment variables and NODE_OPTIONS to its startup configuration.
The two essential settings are usually:
OTEL_SERVICE_NAMENODE_OPTIONS=--require @opentelemetry/auto-instrumentations-node/register
Add the remaining OTLP parameters based on the actual DataKit address.
Programmatic Integration¶
If automatic instrumentation is unsuitable, integrate the OpenTelemetry SDK programmatically.
Install Dependencies¶
npm install \
@opentelemetry/api \
@opentelemetry/sdk-node \
@opentelemetry/resources \
@opentelemetry/semantic-conventions \
@opentelemetry/exporter-trace-otlp-proto \
@opentelemetry/exporter-metrics-otlp-proto \
@opentelemetry/instrumentation-http
Example¶
const { NodeSDK } = require('@opentelemetry/sdk-node');
const { resourceFromAttributes } = require('@opentelemetry/resources');
const {
ATTR_SERVICE_NAME,
ATTR_SERVICE_VERSION,
SEMRESATTRS_DEPLOYMENT_ENVIRONMENT,
} = require('@opentelemetry/semantic-conventions');
const { HttpInstrumentation } = require('@opentelemetry/instrumentation-http');
const {
OTLPTraceExporter,
} = require('@opentelemetry/exporter-trace-otlp-proto');
const resource = resourceFromAttributes({
[ATTR_SERVICE_NAME]: 'orders-api',
[ATTR_SERVICE_VERSION]: '1.0.0',
[SEMRESATTRS_DEPLOYMENT_ENVIRONMENT]: 'prod',
});
const sdk = new NodeSDK({
resource,
traceExporter: new OTLPTraceExporter({
url: 'http://127.0.0.1:9529/otel/v1/traces',
}),
instrumentations: [new HttpInstrumentation()],
});
async function main() {
await sdk.start();
console.log('OpenTelemetry Node.js started');
}
main().catch(err => {
console.error(err);
process.exit(1);
});
Node.js Profile Extension¶
Node.js Profile is an extension provided by Guance for Node.js. It supplements standard OTel Trace / Metric collection with profile data.
This feature is not part of the official OpenTelemetry npm packages. It is extended from OpenTelemetry Node.js and released by Guance.
Supported profile types:
wallheap
For an initial integration, enable wall first, verify that the data path is stable, and then enable heap as needed.
Obtain @cloudcare/profiler-nodejs¶
The Node.js Profile extension package is:
If the public npm registry is directly accessible, run:
Install Dependencies¶
npm install \
@cloudcare/profiler-nodejs \
@datadog/pprof \
@opentelemetry/resources \
@opentelemetry/semantic-conventions
Minimal Example¶
const { resourceFromAttributes } = require('@opentelemetry/resources');
const {
ATTR_SERVICE_NAME,
ATTR_SERVICE_VERSION,
SEMRESATTRS_DEPLOYMENT_ENVIRONMENT,
} = require('@opentelemetry/semantic-conventions');
const {
DatakitProfilingExporter,
NodeProfiling,
} = require('@cloudcare/profiler-nodejs');
const profiler = new NodeProfiling({
resource: resourceFromAttributes({
[ATTR_SERVICE_NAME]: 'orders-api',
[ATTR_SERVICE_VERSION]: '1.2.3',
[SEMRESATTRS_DEPLOYMENT_ENVIRONMENT]: 'prod',
}),
exporter: new DatakitProfilingExporter({
endpoint: 'http://127.0.0.1:9529/profiling/v1/input',
}),
profileTypes: ['wall'],
cpuProfilingEnabled: true,
});
async function main() {
await profiler.start();
}
main().catch(err => {
console.error(err);
process.exit(1);
});
Use with the OpenTelemetry SDK¶
If the application already uses the OpenTelemetry SDK, initialize the profiler alongside it:
const { NodeSDK } = require('@opentelemetry/sdk-node');
const { resourceFromAttributes } = require('@opentelemetry/resources');
const {
ATTR_SERVICE_NAME,
ATTR_SERVICE_VERSION,
SEMRESATTRS_DEPLOYMENT_ENVIRONMENT,
} = require('@opentelemetry/semantic-conventions');
const {
DatakitProfilingExporter,
NodeProfiling,
} = require('@cloudcare/profiler-nodejs');
const resource = resourceFromAttributes({
[ATTR_SERVICE_NAME]: 'orders-api',
[ATTR_SERVICE_VERSION]: '1.2.3',
[SEMRESATTRS_DEPLOYMENT_ENVIRONMENT]: 'prod',
});
const sdk = new NodeSDK({
resource,
});
const profiling = new NodeProfiling({
resource,
exporter: new DatakitProfilingExporter({
endpoint: 'http://127.0.0.1:9529/profiling/v1/input',
}),
});
async function main() {
await sdk.start();
await profiling.start();
}
process.on('SIGTERM', async () => {
await profiling.shutdown();
await sdk.shutdown();
process.exit(0);
});
main().catch(err => {
console.error(err);
process.exit(1);
});
Trigger a Collection Manually¶
To verify the data path, run:
This is useful for:
- Verifying the reachability of the Profiling endpoint during initial setup;
- Checking whether a profile is generated and sent successfully;
- Collecting a profile at a specific point during a load-test window.
Recommended Profile Configuration¶
In most cases, only the following key parameters need attention:
| Parameter | Default | Description |
|---|---|---|
endpoint |
http://127.0.0.1:9529/profiling/v1/input |
Profile upload endpoint |
profileTypes |
['wall', 'heap'] |
Profile types to collect; start with ['wall'] |
intervalMillis |
60000 |
Collection interval |
wallDurationMillis |
10000 |
Duration of each wall profile |
Keep the default values unless specific performance tuning is required.
Default Behavior¶
By default, the Node.js Profile extension:
- Collects once every
60seconds; - Collects both
wallandheapprofiles in each cycle; - Collects each
wallprofile for10seconds; - Enables
cpuProfilingEnabled; - Sends profiles to
http://127.0.0.1:9529/profiling/v1/input.
The exporter sends two pprof attachments:
wall.pprofspace.pprof
They contain:
wall.pprof:sample/count, optionalcpu/nanoseconds, andwall/nanosecondsspace.pprof:objects/countandspace/bytes
An event.json attachment is also included, where:
profileris fixed toddtracefamilyis fixed tonodejsformatis fixed topprof
This layout is compatible with the current Node.js Profile processing pipeline in Guance.
Verification¶
Verify Trace / Metric Reporting¶
Confirm that the application can reach the DataKit OTLP HTTP endpoints:
Verify Profile Reporting¶
Confirm that the application can reach the Profiling endpoint:
Verify Logs¶
When a profile is reported successfully, the debug log usually contains a message similar to:
Verify Data in Guance¶
After integration, check the following in Guance:
- Traces are reported successfully by service;
- Metrics are available in the corresponding measurement;
- Node.js Profiles are displayed by service.
Notes¶
- Node.js Profile is a Guance extension, not an official OpenTelemetry capability;
- Only
wallandheapprofiles are currently supported; - If the runtime does not provide
globalThis.fetch, explicitly pass afetchimplementation; - To avoid losing profiles before the process exits, call
shutdown()during process termination; - If only Trace / Metric data is needed,
@cloudcare/profiler-nodejsis not required.