SigNoz
Docs
PricingCustomers
Get Started - Free
Docs
IntroductionContributingMigrate from DatadogSigNoz API
OpenTelemetry
What is OpenTelemetryOpenTelemetry Collector GuideOpenTelemetry Demo
Community
Support
Slack
X
Launch Week
Changelog
Dashboard Templates
DevOps Wordle
Newsletter
KubeCon, Atlanta 2025
More
SigNoz vs DatadogSigNoz vs New RelicSigNoz vs GrafanaSigNoz vs Dynatrace
Careers
AboutTermsPrivacySecurity & Compliance
SigNoz Logo
SigNoz
All systems operational
HIPAASOC-2
SigNoz Cloud - This page applies to SigNoz Cloud editions.
Self-Host - This page applies to self-hosted SigNoz editions.

Node.js OpenTelemetry Instrumentation Guide

This guide shows you how to instrument your Node.js or NestJS application with OpenTelemetry and send traces to SigNoz. You can use either zero-code automatic instrumentation or code-level setup depending on your needs.

Most steps are identical. To adapt this guide, update the endpoint and remove the ingestion key header as shown in Cloud to Self-Hosted.

Prerequisites

  • Node.js 20.6.0+
  • If you're on Node 18, use 18.19.0+. Node 18 reached end of life on March 27, 2025.
  • A SigNoz Cloud account or self-hosted SigNoz instance

Send traces to SigNoz

A VM is a virtual computer that runs on physical hardware. This includes:

  • Cloud VMs: AWS EC2, Google Compute Engine, Azure VMs, DigitalOcean Droplets
  • On-premise VMs: VMware, VirtualBox, Hyper-V, KVM
  • Bare metal servers: Physical servers running Linux/Unix directly

Use this section if you're deploying your Node.js application directly on a server or VM without containerization.

Step 1. Set environment variables

export OTEL_TRACES_EXPORTER="otlp"
export OTEL_EXPORTER_OTLP_ENDPOINT="https://ingest.<region>.signoz.cloud:443"
export OTEL_NODE_RESOURCE_DETECTORS="env,host,os"
export OTEL_SERVICE_NAME="<service-name>"
export OTEL_RESOURCE_ATTRIBUTES="service.version=<service-version>"
export OTEL_EXPORTER_OTLP_HEADERS="signoz-ingestion-key=<your-ingestion-key>"
export NODE_OPTIONS="--require @opentelemetry/auto-instrumentations-node/register"

Verify these values:

  • <region>: Your SigNoz Cloud region
  • <your-ingestion-key>: Your SigNoz ingestion key.
  • <service-name>: Name of your service (e.g., payment-service).
  • <service-version> (optional): Your release version, image tag, or git SHA (e.g., 1.4.2, a01dbef8).

Set service.version to a per-build value, not a static string. SigNoz detects a deployment each time this value changes. Common sources:

  • Bash / shell: service.version=$(git rev-parse --short HEAD)
  • GitHub Actions: service.version=${{ github.sha }}
  • GitLab CI: service.version=$CI_COMMIT_SHORT_SHA
  • Kubernetes: inject from your Helm chart image tag or CI variable

Step 2. Install OpenTelemetry packages

npm install --save @opentelemetry/api @opentelemetry/auto-instrumentations-node

Step 3. Run the application

node app.js

Need to enable or disable instrumentation for specific libraries? Check out our guide on selective instrumentation.

Consider using the OTel Operator for centralized instrumentation management across your cluster.

Step 1. Set environment variables

Add OpenTelemetry environment variables to your Kubernetes deployment manifest:

env:
- name: OTEL_TRACES_EXPORTER
  value: 'otlp'
- name: OTEL_EXPORTER_OTLP_ENDPOINT
  value: 'https://ingest.<region>.signoz.cloud:443'
- name: OTEL_NODE_RESOURCE_DETECTORS
  value: 'env,host,os'
- name: OTEL_SERVICE_NAME
  value: '<service-name>'
- name: OTEL_RESOURCE_ATTRIBUTES
  value: 'service.version=<service-version>'
- name: OTEL_EXPORTER_OTLP_HEADERS
  value: 'signoz-ingestion-key=<your-ingestion-key>'
- name: NODE_OPTIONS
  value: '--require @opentelemetry/auto-instrumentations-node/register'

Verify these values:

  • <region>: Your SigNoz Cloud region
  • <your-ingestion-key>: Your SigNoz ingestion key.
  • <service-name>: Name of your service (e.g., payment-service).
  • <service-version> (optional): Your release version, image tag, or git SHA (e.g., 1.4.2, a01dbef8).

Set service.version to a per-build value, not a static string. SigNoz detects a deployment each time this value changes. Common sources:

  • Bash / shell: service.version=$(git rev-parse --short HEAD)
  • GitHub Actions: service.version=${{ github.sha }}
  • GitLab CI: service.version=$CI_COMMIT_SHORT_SHA
  • Kubernetes: inject from your Helm chart image tag or CI variable

Step 2. Install OpenTelemetry packages

Ensure your application image includes the OpenTelemetry packages:

npm install --save @opentelemetry/api @opentelemetry/auto-instrumentations-node

Step 3. Deploy and run

Apply your deployment to the cluster. The environment variables will configure OpenTelemetry automatically when your application starts.

Need to enable or disable instrumentation for specific libraries? Check out our guide on selective instrumentation.

The OpenTelemetry Operator auto-injects instrumentation into your Node.js pods without modifying your application image.

Step 1. Set up the OpenTelemetry Operator

Install the Operator and Collector following the K8s OTel Operator installation guide.

Step 2. Create the Instrumentation resource

Create instrumentation.yaml to configure Node.js auto-instrumentation:

instrumentation.yaml
apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
metadata:
  name: nodejs-instrumentation
spec:
  exporter:
    endpoint: http://otel-collector-collector:4318
  propagators:
    - tracecontext
    - baggage
  nodejs:
    image: ghcr.io/open-telemetry/opentelemetry-operator/autoinstrumentation-nodejs:latest

Deploy this resource to your cluster.

Step 3. Add annotations to your deployment

Add these annotations to your pod template's metadata.annotations:

instrumentation.opentelemetry.io/inject-nodejs: "true"
resource.opentelemetry.io/service.name: "<service-name>"
resource.opentelemetry.io/service.version: "<service-version>"

Verify these values:

  • <service-name>: A descriptive name for your service (e.g., my-node-app).
  • <service-version> (optional): Your release version, image tag, or git SHA (e.g., 1.4.2, a01dbef8).

Set service.version to a per-build value, not a static string. SigNoz detects a deployment each time this value changes. Common sources:

  • Bash / shell: service.version=$(git rev-parse --short HEAD)
  • GitHub Actions: service.version=${{ github.sha }}
  • GitLab CI: service.version=$CI_COMMIT_SHORT_SHA
  • Kubernetes: inject from your Helm chart image tag or CI variable

Step 1. Set environment variables (PowerShell)

$env:OTEL_TRACES_EXPORTER = "otlp"
$env:OTEL_EXPORTER_OTLP_ENDPOINT = "https://ingest.<region>.signoz.cloud:443"
$env:OTEL_NODE_RESOURCE_DETECTORS = "env,host,os"
$env:OTEL_SERVICE_NAME = "<service-name>"
$env:OTEL_RESOURCE_ATTRIBUTES = "service.version=<service-version>"
$env:OTEL_EXPORTER_OTLP_HEADERS = "signoz-ingestion-key=<your-ingestion-key>"
$env:NODE_OPTIONS = "--require @opentelemetry/auto-instrumentations-node/register"

Verify these values:

  • <region>: Your SigNoz Cloud region.
  • <your-ingestion-key>: Your SigNoz ingestion key.
  • <service-name>: Name of your service.
  • <service-version> (optional): Your release version, image tag, or git SHA (e.g., 1.4.2, a01dbef8).

Set service.version to a per-build value, not a static string. SigNoz detects a deployment each time this value changes. Common sources:

  • Bash / shell: service.version=$(git rev-parse --short HEAD)
  • GitHub Actions: service.version=${{ github.sha }}
  • GitLab CI: service.version=$CI_COMMIT_SHORT_SHA
  • Kubernetes: inject from your Helm chart image tag or CI variable

Step 2. Install OpenTelemetry packages

npm install --save @opentelemetry/api @opentelemetry/auto-instrumentations-node

Step 3. Run the application

node app.js

Need to enable or disable instrumentation for specific libraries? Check out our guide on selective instrumentation.

Step 1. Add OpenTelemetry to your Dockerfile

Dockerfile
# ... your existing build steps ...

# Install OpenTelemetry packages
RUN npm install @opentelemetry/api@^1.9.0 @opentelemetry/auto-instrumentations-node@^0.67.0

# Set OpenTelemetry environment variables
ENV OTEL_TRACES_EXPORTER="otlp"
ENV OTEL_EXPORTER_OTLP_ENDPOINT="https://ingest.<region>.signoz.cloud:443"
ENV OTEL_NODE_RESOURCE_DETECTORS="env,host,os"
ENV OTEL_SERVICE_NAME="<service-name>"
ENV OTEL_RESOURCE_ATTRIBUTES="service.version=<service-version>"
ENV OTEL_EXPORTER_OTLP_HEADERS="signoz-ingestion-key=<your-ingestion-key>"
ENV NODE_OPTIONS="--require @opentelemetry/auto-instrumentations-node/register"

# ... your CMD or ENTRYPOINT ...

Or pass them at runtime:

docker run \
  -e OTEL_TRACES_EXPORTER="otlp" \
  -e OTEL_EXPORTER_OTLP_ENDPOINT="https://ingest.<region>.signoz.cloud:443" \
  -e OTEL_NODE_RESOURCE_DETECTORS="env,host,os" \
  -e OTEL_SERVICE_NAME="<service-name>" \
  -e OTEL_RESOURCE_ATTRIBUTES="service.version=<service-version>" \
  -e OTEL_EXPORTER_OTLP_HEADERS="signoz-ingestion-key=<your-ingestion-key>" \
  -e NODE_OPTIONS="--require @opentelemetry/auto-instrumentations-node/register" \
  your-image:latest

Verify these values:

  • <region>: Your SigNoz Cloud region
  • <your-ingestion-key>: Your SigNoz ingestion key.
  • <service-name>: Name of your service (e.g., payment-service).
  • <service-version> (optional): Your release version, image tag, or git SHA (e.g., 1.4.2, a01dbef8).

Set service.version to a per-build value, not a static string. SigNoz detects a deployment each time this value changes. Common sources:

  • Bash / shell: service.version=$(git rev-parse --short HEAD)
  • GitHub Actions: service.version=${{ github.sha }}
  • GitLab CI: service.version=$CI_COMMIT_SHORT_SHA
  • Kubernetes: inject from your Helm chart image tag or CI variable

Step 2. Build and run

docker build -t my-nodejs-app . && docker run -d -p 8080:8080 my-nodejs-app

Need to enable or disable instrumentation for specific libraries? Check out our guide on selective instrumentation.

Validate

After running your instrumented application, verify traces appear in SigNoz:

  1. Generate traffic by making requests to your application.
  2. Open SigNoz and navigate to Services. Click Refresh and look for your service.
  3. Go to Traces and apply filters to see your application's traces.

Troubleshooting

Enable debug logging

Set the log level to see detailed configuration and span information:

export OTEL_LOG_LEVEL=debug

Look for span output like this in your console:

{
  "traceId": "985b66d592a1299f7d12ebca56ca1fe3",
  "parentId": "8d62a70aa335a227",
  "name": "bar",
  "id": "17ada85c3d55376a",
  "kind": 0,
  "timestamp": 1685674607399000,
  "duration": 299,
  "attributes": {},
  "status": { "code": 0 },
  "events": []
}

Short-lived applications (Lambda/Serverless)

If your application exits quickly, explicitly shutdown the SDK to flush all spans:

// Assumes 'sdk' is your NodeSDK instance from the setup
await sdk.shutdown();

Service not appearing in SigNoz

  • Verify your OTEL_EXPORTER_OTLP_ENDPOINT and OTEL_EXPORTER_OTLP_HEADERS are set correctly
  • Check network connectivity to the SigNoz endpoint
  • Ensure your application is receiving traffic (OpenTelemetry buffers data before sending)

Code-Based Setup (Optional)

Unlike env vars, code-based setup gives you full control over SDK initialization, like custom processors, advanced sampling, or pulling config from your app. This replaces the env var setup above. If switching from env vars, remove the NODE_OPTIONS line to avoid duplicate instrumentation.

Step 1. Install OpenTelemetry packages

npm install --save @opentelemetry/api@^1.9.0 \
  @opentelemetry/sdk-node@^0.208.0 \
  @opentelemetry/auto-instrumentations-node@^0.67.0 \
  @opentelemetry/exporter-trace-otlp-http@^0.208.0

Step 2. Create the tracing file

tracing.js
'use strict'
const process = require('process');
const opentelemetry = require('@opentelemetry/sdk-node');
const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node');
const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-http');
const { resourceFromAttributes } = require('@opentelemetry/resources');
const { ATTR_SERVICE_NAME } = require('@opentelemetry/semantic-conventions');

const exporterOptions = {
  url: 'https://ingest.<region>.signoz.cloud:443/v1/traces',
  headers: { 'signoz-ingestion-key': '<your-ingestion-key>' }
}

const traceExporter = new OTLPTraceExporter(exporterOptions);
const sdk = new opentelemetry.NodeSDK({
  traceExporter,
  instrumentations: [getNodeAutoInstrumentations()],
  resource: resourceFromAttributes({
    [ATTR_SERVICE_NAME]: '<service-name>'
  })
});

sdk.start();

process.on('SIGTERM', () => {
  sdk.shutdown()
    .then(() => console.log('Tracing terminated'))
    .catch((error) => console.log('Error terminating tracing', error))
    .finally(() => process.exit(0));
});
tracing.ts
import process from 'process';
import * as opentelemetry from '@opentelemetry/sdk-node';
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
import { resourceFromAttributes } from '@opentelemetry/resources';
import { ATTR_SERVICE_NAME } from '@opentelemetry/semantic-conventions';

const exporterOptions = {
  url: 'https://ingest.<region>.signoz.cloud:443/v1/traces',
  headers: { 'signoz-ingestion-key': '<your-ingestion-key>' }
}

const traceExporter = new OTLPTraceExporter(exporterOptions);
const sdk = new opentelemetry.NodeSDK({
  traceExporter,
  instrumentations: [getNodeAutoInstrumentations()],
  resource: resourceFromAttributes({
    [ATTR_SERVICE_NAME]: '<service-name>'
  })
});

sdk.start();

process.on('SIGTERM', () => {
  sdk.shutdown()
    .then(() => console.log('Tracing terminated'))
    .catch((error) => console.log('Error terminating tracing', error))
    .finally(() => process.exit(0));
});

Verify these values:

  • <region>: Your SigNoz Cloud region
  • <your-ingestion-key>: Your SigNoz ingestion key.
  • <service-name>: Name of your service (e.g., payment-service).

Step 3. Load the tracing file before your app

node -r ./tracing.js app.js

Import the tracing file at the top of your entry point:

// index.ts or main.ts
import './tracing';

Then run:

npx ts-node src/index.ts

Need to enable or disable instrumentation for specific libraries? Check out our guide on selective instrumentation.

Setup OpenTelemetry Collector (Optional)

What is the OpenTelemetry Collector?

The OTel Collector acts as a middleman between your app and SigNoz. Instead of sending data directly, your application sends everything to the Collector first, which then forwards it along.

Why use it?

  • Cleaning up data — Filter out noisy traces you don't care about, or remove sensitive info before it leaves your servers.
  • Keeping your app lightweight — Let the Collector handle batching, retries, and compression instead of your application code.
  • Adding context automatically — The Collector can tag your data with useful info like which Kubernetes pod or cloud region it came from.
  • Future flexibility — Want to send data to multiple backends later? The Collector makes that easy without changing your app.

See Switch from direct export to Collector for step-by-step instructions.

Sample applications

  • Sample Node.js App
  • Sample NestJS App

Next steps

  • Complete your observability setup by sending metrics and logs from your Node.js application.
  • Instrument the client-side of your app for traces
  • Capture frontend metrics, logs, and vitals
  • Exclude HTTP Endpoints
  • Selective Instrumentation
  • Manual Instrumentation

Last updated: May 18, 2026

Edit on GitHub

Was this page helpful?

Your response helps us improve this page.

Prev
Javascript
Next
Next.js
On this page
Prerequisites
Send traces to SigNoz
Step 1. Set environment variables
Step 2. Install OpenTelemetry packages
Step 3. Run the application
Step 1. Set environment variables
Step 2. Install OpenTelemetry packages
Step 3. Deploy and run
Step 1. Set up the OpenTelemetry Operator
Step 2. Create the Instrumentation resource
Step 3. Add annotations to your deployment
Step 1. Set environment variables (PowerShell)
Step 2. Install OpenTelemetry packages
Step 3. Run the application
Step 1. Add OpenTelemetry to your Dockerfile
Step 2. Build and run
Validate
Troubleshooting
Enable debug logging
Short-lived applications (Lambda/Serverless)
Service not appearing in SigNoz
Code-Based Setup (Optional)
Step 1. Install OpenTelemetry packages
Step 2. Create the tracing file
Step 3. Load the tracing file before your app
Setup OpenTelemetry Collector (Optional)
What is the OpenTelemetry Collector?
Why use it?
Sample applications
Next steps

Is this page helpful?

Your response helps us improve this page.