Docs
DocumentationQuery ReferenceAPI Reference
Open Console→→
DocumentationQuery ReferenceAPI Reference

Platform overview

What is Axiom?QuickstartArchitectureFeatures
Fundamentals
Datasets
Edge deployments
Limits
Performance
Optimize usage
Requirements
Semantic conventions
Glossary
Tour
SecurityRoadmap

Send data

Reference architecturesMethods

Understand data

Console
Query
Builder
Editor
Query results
Visualize
Traces
Metrics
Correlations
Save queries
Stream
Dashboard
Create
Elements
Create
Configure
Element types
Gauge
Heatmap
Log stream
Monitor list
Note
Pie chart
Scatter plot
Statistic
Table
Time series
Sections
Configure
Filter
Annotate
Monitor
Overview
View status
Configure
Examples
Monitor types
Anomaly
Match
Threshold
Alerting
Overview
Configure
Notifier types
Custom Webhook
Discord
Email
Microsoft Teams
Opsgenie
PagerDuty
Slack
Manage
Datasets
Overview
Views
Virtual fields
Access
RBAC
Tokens
CLI
Organization
Audit log
Settings
Usage and billing
Profile
Extend
Overview
AWS Lambda
AWS PrivateLink
Cloudflare Workers
Cloudflare Logpush
Convex
Grafana
Hex
Netlify
Supabase
Tailscale
Terraform
Vercel
Intelligence
Overview
Spotlight
AI agents
Overview
MCP Server
Query cost limits
Agent-created orgs
Skills
Overview
Axiom alerting
Build dashboards
Control costs
Query metrics
SRE
Translate SPL to APL
Splunk
Overview
Splunk app
Install and configure
Commands
Examples
Portal
How it works
Set up standard mode
Set up transparent mode
Observability Cloud
SPL command support
Examples
Monitor and troubleshoot

Use cases

ObservabilityProduct analytics
LLM observability
Overview
Use Axiom AI SDK
Manual instrumentation
GenAI attributes
Redaction policies

Miscellaneous

LLMs
Overview
List of docs pages
Full docs
Query reference
FAQs
Legal
Acceptable use policy
Cookies
Data processing
HIPAA
Partner agreement
Partner program guide
Privacy policy
SLA
Terms of service
Terms of use

OpenTelemetry using Node.js

This guide demonstrates how to configure OpenTelemetry in a Node.js app to send telemetry data to Axiom.

OpenTelemetry provides a unified approach to collecting telemetry data from your Node.js and TypeScript apps. This guide demonstrates how to configure OpenTelemetry in a Node.js app to send telemetry data to Axiom using OpenTelemetry SDK.

Prerequisites

To configure OpenTelemetry in a Node.js app for sending telemetry data to Axiom, certain prerequisites are necessary. These include:

  • Node:js: Node.js version 14 or newer.
  • Node.js app: Use your own app written in Node.js, or you can start with the provided app.ts sample.
  • Create an Axiom account.
  • Create a dataset in Axiom where you send your data.
  • Create an API token in Axiom with permissions to create, read, update, and delete datasets.

Core Application (app.ts)

app.ts is the core of the app. It uses Express.js to create a simple web server. The server has an endpoint /rolldice that returns a random number, simulating a basic API. It also demonstrates the usage of span links to establish relationships between spans across different traces.

javascript
/*app.ts*/

// Importing OpenTelemetry instrumentation for tracing
import './instrumentation';
import { trace, context } from '@opentelemetry/api';

// Importing Express.js: A minimal and flexible Node.js web app framework
import express from 'express';

// Setting up the server port: Use the PORT environment variable or default to 8080
const PORT = parseInt(process.env.PORT || '8080');
const app = express();

// Get the tracer from the global tracer provider
const tracer = trace.getTracer('node-traces');

/**
 * Function to generate a random number between min and max (inclusive).
 * @param min - The minimum number (inclusive).
 * @param max - The maximum number (exclusive).
 * @returns A random number between min and max.
 */
function getRandomNumber(min: number, max: number): number {
  return Math.floor(Math.random() * (max - min) + min);
}

// Defining a route handler for '/rolldice' that returns a random dice roll
app.get('/rolldice', (req, res) => {
  const span = trace.getSpan(context.active());
  /**
   * Spans can be created with zero or more Links to other Spans that are related.
   * Links allow creating connections between different traces
   */
  const rollDiceSpan = tracer.startSpan('roll_dice_span', {
    links: span ? [{ context: span.spanContext() }] : [],
  });

  // Set the rollDiceSpan as the currently active span
  context.with(trace.setSpan(context.active(), rollDiceSpan), () => {
    const diceRoll = getRandomNumber(1, 6).toString();
    res.send(diceRoll);
    rollDiceSpan.end();
  });
});

// Defining a route handler for '/roll_with_link' that creates a parent span and calls '/rolldice'
app.get('/roll_with_link', (req, res) => {
  /**
   * A common scenario is to correlate one or more traces with the current span.
   * This can help in tracing and debugging complex interactions across different parts of the app.
   */
  const parentSpan = tracer.startSpan('parent_span');

  // Set the parentSpan as the currently active span
  context.with(trace.setSpan(context.active(), parentSpan), () => {
    const diceRoll = getRandomNumber(1, 6).toString();
    res.send(`Dice roll result (with link): ${diceRoll}`);
    parentSpan.end();
  });
});

// Starting the server on the specified PORT and logging the listening message
app.listen(PORT, () => {
  console.log(`Listening for requests on http://localhost:${PORT}`);
});

Exporter (instrumentation.ts)

instrumentation.ts sets up the OpenTelemetry instrumentation. It configures the OTLP (OpenTelemetry Protocol) exporters for traces and initializes the Node SDK with automatic instrumentation capabilities.

javascript
/*instrumentation.ts*/

// Importing necessary OpenTelemetry packages including the core SDK, auto-instrumentations, OTLP trace exporter, and batch span processor
import { NodeSDK } from '@opentelemetry/sdk-node';
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-proto';
import { BatchSpanProcessor } from '@opentelemetry/sdk-trace-base';
import { Resource } from '@opentelemetry/resources';
import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions';

// Initialize OTLP trace exporter with the endpoint URL and headers
const traceExporter = new OTLPTraceExporter({
  url: 'https://AXIOM_DOMAIN/v1/traces',
  headers: {
    'Authorization': 'Bearer API_TOKEN',
    'X-Axiom-Dataset': 'DATASET_NAME'
  },
});

// Creating a resource to identify your service in traces
const resource = new Resource({
  [SemanticResourceAttributes.SERVICE_NAME]: 'node traces',
});

// Configuring the OpenTelemetry Node SDK
const sdk = new NodeSDK({
  // Adding a BatchSpanProcessor to batch and send traces
  spanProcessor: new BatchSpanProcessor(traceExporter),

  // Registering the resource to the SDK
  resource: resource,

  // Adding auto-instrumentations to automatically collect trace data
  instrumentations: [getNodeAutoInstrumentations()],
});

// Starting the OpenTelemetry SDK to begin collecting telemetry data
sdk.start();
Info

Replace API_TOKEN with the Axiom API token you have generated. For added security, store the API token in an environment variable.

Replace DATASET_NAME with the name of the Axiom dataset where you send your data.

Replace AXIOM_DOMAIN with the base domain of your edge deployment. For more information, see Edge deployments.

Installing the Dependencies

Navigate to the root directory of your project and run the following command to install the required dependencies:

shell
npm install

This command will install all the necessary packages listed in your package.json below

Setting Up TypeScript Development Environment

To run the TypeScript app, you need to set up a TypeScript development environment. This includes adding a package.json file to manage your project’s dependencies and scripts, and a tsconfig.json file to manage TypeScript compiler options.

Add package.json

Create a package.json file in the root of your project with the following content:

JSON
{
    "name": "typescript-traces",
    "version": "1.0.0",
    "description": "",
    "main": "app.js",
    "scripts": {
        "build": "tsc",
        "start": "ts-node app.ts",
        "dev": "ts-node-dev --respawn app.ts"
    },
    "keywords": [],
    "author": "",
    "license": "ISC",
    "dependencies": {
        "@opentelemetry/api": "^1.6.0",
        "@opentelemetry/api-logs": "^0.46.0",
        "@opentelemetry/auto-instrumentations-node": "^0.39.4",
        "@opentelemetry/exporter-metrics-otlp-http": "^0.45.0",
        "@opentelemetry/exporter-metrics-otlp-proto": "^0.45.1",
        "@opentelemetry/exporter-trace-otlp-http": "^0.45.0",
        "@opentelemetry/sdk-logs": "^0.46.0",
        "@opentelemetry/sdk-metrics": "^1.20.0",
        "@opentelemetry/sdk-node": "^0.45.1",
        "express": "^4.18.2"
    },
    "devDependencies": {
        "@types/express": "^4.17.21",
        "@types/node": "^16.18.71",
        "ts-node": "^10.9.2",
        "ts-node-dev": "^2.0.0",
        "tsc-watch": "^4.6.2",
        "typescript": "^4.9.5"
    }
}

Add tsconfig.json

Create a tsconfig.json file in the root of your project with the following content:

JSON
{
  "compilerOptions": {
    "target": "es2016",
    "module": "commonjs",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true
  }
}

This configuration file specifies how the TypeScript compiler should transpile TypeScript files into JavaScript.

Running the Instrumented Application

To run your Node.js app with OpenTelemetry instrumentation, make sure your API token, and dataset is set in the instrumentation.ts file.

In Development Mode

For development purposes, especially when you need automatic restarts upon file changes, use:

shell
npm run dev

This command will start the OpenTelemetry instrumentation in development mode using ts-node-dev. It sets up the exporter for tracing and restarts the server automatically whenever you make changes to the files.

In Production Mode

To run the app in production mode, you need to first build the TypeScript files into JavaScript. Run the following command to build your app:

shell
npm run build

This command compiles the TypeScript files to JavaScript based on the settings specified in tsconfig.json. Once the build process is complete, you can start your app in production mode with:

shell
npm start

The server will start on the specified port, and you can interact with it by sending requests to the /rolldice endpoint.

Observe the telemetry data in Axiom

As you interact with your app, traces will be collected and exported to Axiom, where you can monitor and analyze your app’s performance and behavior.

Observing the telemetry data in Axiom
└Observing the telemetry data in Axiom

Dynamic OpenTelemetry traces dashboard

This data can then be further viewed and analyzed in Axiom’s dashboard, providing insights into the performance and behaviour of your app.

Dynamic OpenTelemetry traces dashboard
└Dynamic OpenTelemetry traces dashboard

Send data from an existing Node project

Manual Instrumentation

Manual instrumentation in Node.js requires adding code to create and manage spans around the code blocks you want to trace.

  1. Initialize Tracer:

Import and configure a tracer in your Node.js app. Use the tracer configured in your instrumentation setup (instrumentation.ts).

javascript
// Assuming OpenTelemetry SDK is already configured
const { trace } = require('@opentelemetry/api');
const tracer = trace.getTracer('example-tracer');
  1. Create Spans:

Wrap the code blocks that you want to trace with spans. Start and end these spans within your code.

javascript
const span = tracer.startSpan('operation_name');
try {
  // Your code here
  span.end();
} catch (error) {
  span.recordException(error);
  span.end();
}
  1. Annotate Spans:

Add metadata and logs to your spans for the trace data.

javascript
span.setAttribute('key', 'value');
span.addEvent('event name', { eventKey: 'eventValue' });

Automatic Instrumentation

Automatic instrumentation in Node.js simplifies adding telemetry data to your app. It uses pre-built libraries to automatically instrument common frameworks and libraries.

  1. Install Instrumentation Libraries:

Use OpenTelemetry packages that automatically instrument common Node.js frameworks and libraries.

shell
npm install @opentelemetry/auto-instrumentations-node
  1. Instrument Application: Configure your app to use these libraries, which will automatically generate spans for standard operations.
javascript
// In your instrumentation setup (instrumentation.ts)
const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node');

const sdk = new NodeSDK({
  // ... other configurations ...
  instrumentations: [getNodeAutoInstrumentations()]
});

After you set them up, these libraries automatically trace relevant operations without additional code changes in your app.

Reference

List of OpenTelemetry trace fields

Field CategoryField NameDescription
Unique Identifiers
_rowidUnique identifier for each row in the trace data.
span_idUnique identifier for the span within the trace.
trace_idUnique identifier for the entire trace.
Timestamps
_systimeSystem timestamp when the trace data was recorded.
_timeTimestamp when the actual event being traced occurred.
HTTP Attributes
attributes.custom["http.host"]Host information where the HTTP request was sent.
attributes.custom["http.server_name"]Server name for the HTTP request.
attributes.http.flavorHTTP protocol version used.
attributes.http.methodHTTP method used for the request.
attributes.http.routeRoute accessed during the HTTP request.
attributes.http.schemeProtocol scheme (HTTP/HTTPS).
attributes.http.status_codeHTTP response status code.
attributes.http.targetSpecific target of the HTTP request.
attributes.http.user_agentUser agent string of the client.
Network Attributes
attributes.net.host.portPort number on the host receiving the request.
attributes.net.peer.portPort number on the peer (client) side.
attributes.custom["net.peer.ip"]IP address of the peer in the network interaction.
Operational Details
durationTime taken for the operation.
kindType of span (for example,, server, client).
nameName of the span.
scopeInstrumentation scope.
service.nameName of the service generating the trace.
Resource Process Attributes
resource.process.commandCommand line string used to start the process.
resource.process.command_argsList of command line arguments used in starting the process.
resource.process.executable.nameName of the executable running the process.
resource.process.executable.pathPath to the executable running the process.
resource.process.ownerOwner of the process.
resource.process.pidProcess ID.
resource.process.runtime.descriptionDescription of the runtime environment.
resource.process.runtime.nameName of the runtime environment.
resource.process.runtime.versionVersion of the runtime environment.
Telemetry SDK Attributes
telemetry.sdk.languageLanguage of the telemetry SDK.
telemetry.sdk.nameName of the telemetry SDK.
telemetry.sdk.versionVersion of the telemetry SDK.

List of imported libraries

The instrumentation.ts file imports the following libraries:

@opentelemetry/sdk-node

This package is the core SDK for OpenTelemetry in Node.js. It provides the primary interface for configuring and initializing OpenTelemetry in a Node.js app. It includes functionalities for managing traces and context propagation. The SDK is designed to be extensible, allowing for custom configurations and integration with different telemetry backends like Axiom.

@opentelemetry/auto-instrumentations-node

This package offers automatic instrumentation for Node.js apps. It simplifies the process of instrumenting various common Node.js libraries and frameworks. By using this package, developers can automatically collect telemetry data (such as traces) from their apps without needing to manually instrument each library or API call. This is important for apps with complex dependencies, as it ensures comprehensive and consistent telemetry collection across the app.

@opentelemetry/exporter-trace-otlp-proto

The @opentelemetry/exporter-trace-otlp-proto package provides an exporter that sends trace data using the OpenTelemetry Protocol (OTLP). OTLP is the standard protocol for transmitting telemetry data in the OpenTelemetry ecosystem. This exporter allows Node.js apps to send their collected traces to any backend that supports OTLP, such as Axiom. The use of OTLP ensures broad compatibility and a standardized way of transmitting telemetry data.

@opentelemetry/sdk-trace-base

Contained within this package is the BatchSpanProcessor, among other foundational elements for tracing in OpenTelemetry. The BatchSpanProcessor is a component that collects and processes spans (individual units of trace data). As the name suggests, it batches these spans before sending them to the configured exporter (in this case, the OTLPTraceExporter). This batching mechanism is efficient as it reduces the number of outbound requests by aggregating multiple spans into fewer batches. It helps in the performance and scalability of trace data export in an OpenTelemetry-instrumented app.

Was this page helpful?
Suggest edits on GitHub
On this page
PrerequisitesCore Application (app.ts)Exporter (instrumentation.ts)Installing the DependenciesSetting Up TypeScript Development EnvironmentAdd package.jsonAdd tsconfig.jsonRunning the Instrumented ApplicationIn Development ModeIn Production ModeObserve the telemetry data in AxiomDynamic OpenTelemetry traces dashboardSend data from an existing Node projectManual InstrumentationAutomatic InstrumentationReferenceList of OpenTelemetry trace fieldsList of imported libraries@opentelemetry/sdk-node@opentelemetry/auto-instrumentations-node@opentelemetry/exporter-trace-otlp-proto@opentelemetry/sdk-trace-base