Dec 17th, ‘24/12 min read

Introduction to OpenTelemetry Express for Node.js Applications

OpenTelemetry Express simplifies trace collection for Node.js apps, helping you monitor performance and diagnose issues across distributed systems.

Introduction to OpenTelemetry Express for Node.js Applications

When it comes to monitoring and troubleshooting applications, observability is key. As applications grow in complexity, especially with microservices and distributed systems, tracking their performance becomes a challenge.

This is where OpenTelemetry Express comes in, offering an easy-to-integrate observability framework for Node.js applications.

In this blog, we’ll walk through everything you need to know about OpenTelemetry Express: what it is, why it’s useful, and how you can use it to improve your Node.js apps' performance and reliability.

What is OpenTelemetry Express?

OpenTelemetry Express is an open-source library built to work with OpenTelemetry in Node.js applications, specifically targeting the popular Express framework.

If you’re familiar with OpenTelemetry, you know that it’s a powerful observability toolkit that helps collect, process, and export telemetry data—metrics, traces, and logs—from your applications.

By integrating OpenTelemetry Express, you can easily add observability features to your Express-based web services, improving monitoring, error tracking, and performance analysis.

Think of it as a bridge that connects the power of OpenTelemetry to your Express app, without much hassle.

What are OpenTelemetry Metrics? A Comprehensive Guide | Last9
Learn about OpenTelemetry Metrics, types of instruments, and best practices for effective application performance monitoring and observability.

Why Should You Use OpenTelemetry Express?

The short answer? It makes your life easier. Here's why you should consider using OpenTelemetry Express:

Effortless Integration

OpenTelemetry Express is built to be simple to set up with minimal changes to your existing code. If you’re already using Express, adding observability to your app is just a few lines of code away.

Deep Insights into Your Application

With OpenTelemetry Express, you can track distributed traces (like how requests flow across services), gather metrics (like response times and error rates), and even capture logs. This gives you a comprehensive view of your app’s performance and health.

Distributed Tracing

In a microservices architecture, understanding how a request flows through various services is crucial. OpenTelemetry Express supports distributed tracing, which helps you trace requests from the front end to the back end, and even across different services.

Customizable

It’s highly customizable, allowing you to fine-tune which data you collect. Whether you want to track every request or only specific ones, OpenTelemetry Express gives you full control.

Seamless Export to Various Backends

Whether you're using Prometheus, Jaeger, or any other observability tool, OpenTelemetry Express can export your telemetry data to your backend of choice.

Getting Started with OpenTelemetry in Rust | Last9
Learn how to implement OpenTelemetry in Rust for effective observability, including tracing, metrics, and debugging in your applications.

Setting Up OpenTelemetry Express in Your Application

Getting started with OpenTelemetry Express is straightforward. Let’s break it down into simple steps.

1. Install OpenTelemetry Packages

To get started, you'll need to install the OpenTelemetry SDK and the Express plugin. Run the following command:

npm install @opentelemetry/api @opentelemetry/sdk-node @opentelemetry/instrumentation-express

This will install the core OpenTelemetry API, the Node.js SDK, and the Express instrumentation library.

2. Set Up OpenTelemetry in Your App

In your application’s entry file (usually index.js or app.js), initialize OpenTelemetry:

const { NodeTracerProvider } = require('@opentelemetry/sdk-node');
const { SimpleSpanProcessor } = require('@opentelemetry/sdk-trace-base');
const { ConsoleSpanExporter } = require('@opentelemetry/tracing');
const express = require('express');
const { ExpressInstrumentation } = require('@opentelemetry/instrumentation-express');
// Initialize the tracer provider
const provider = new NodeTracerProvider();
provider.addSpanProcessor(new SimpleSpanProcessor(new ConsoleSpanExporter()));
provider.register();
// Initialize Express
const app = express();
// Enable Express instrumentation
const expressInstrumentation = new ExpressInstrumentation();
expressInstrumentation.setTracerProvider(provider);
// Define your routes
app.get('/', (req, res) => {
  res.send('Hello World!');
});
// Start the server
app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

3. Choose Your Exporter

In this example, we’re exporting traces to the console for simplicity. However, you can configure the exporter to send data to backends like Jaeger, Prometheus, or any other observability platform that OpenTelemetry supports.

To use Jaeger as an exporter, you would install the Jaeger exporter package:

npm install @opentelemetry/exporter-jaeger
Then modify the span processor to use the Jaeger exporter:
javascript
Copy code
const { JaegerExporter } = require('@opentelemetry/exporter-jaeger');
const jaegerExporter = new JaegerExporter({
  serviceName: 'my-express-app',
  host: 'localhost',
  port: 5775,
});
provider.addSpanProcessor(new SimpleSpanProcessor(jaegerExporter));

4. Run Your Application

Now, start your application:

node app.js

Your Express application is now instrumented with OpenTelemetry. You’ll see trace data either in the console or in your configured observability backend.

Getting Started with Host Metrics Using OpenTelemetry | Last9
Learn to monitor host metrics with OpenTelemetry. Discover setup tips, common pitfalls, and best practices for effective observability.

Common Use Cases for OpenTelemetry Express

Once you’ve set up OpenTelemetry Express, you’ll want to track some common performance metrics and traces. Here are a few examples:

  • Request Latency: Track the time taken by each request. This helps you understand which endpoints are slow and need optimization.
  • Error Handling: Track failed requests and the errors that occur, enabling faster debugging and resolution.
  • User Journey: Trace how a request flows through multiple services. This is particularly useful for microservices applications where a single user action might involve several services.
  • Resource Usage: Measure the resource consumption of your Express app, like CPU usage, memory, and request load.

Best Practices for Using OpenTelemetry Express

To get the most out of OpenTelemetry Express, keep these best practices in mind:

Filter What You Capture

Only capture what’s necessary for your application. Too much telemetry data can overwhelm your system and make troubleshooting harder.

Use Correlation IDs

Use correlation IDs to trace requests through multiple services. This is especially useful when dealing with distributed systems.

Monitor Key Metrics

Focus on the most relevant metrics (like response times and error rates) that give you an actionable view of your app’s health.

Keep Your Dependencies Updated

The OpenTelemetry ecosystem evolves rapidly, so be sure to keep your dependencies up to date to get the latest features and bug fixes.

Identify Root Spans in Otel Collector | Last9
How to identify root spans in OpenTelemetry Collector using filter and transform processors

What is Auto-Instrumentation?

Auto-instrumentation refers to the automatic process of adding telemetry tracking—like traces and metrics—without the need to manually add code for each part of the application.

In the context of Node.js and Express.js, auto-instrumentation can automatically detect and capture data about HTTP requests, database queries, and other interactions within the app.

With OpenTelemetry’s auto-instrumentation, libraries and frameworks are detected automatically, and relevant telemetry data is captured, processed, and sent to your observability backend (e.g., Jaeger, Prometheus, etc.).

How Auto-Instrumentation Works in Node.js with Express.js

Auto-instrumentation simplifies adding tracing to your Express.js application. Here’s how it works:

Installation:

First, you’ll need to install the OpenTelemetry SDK and the necessary auto-instrumentation libraries for Node.js.

npm install @opentelemetry/api @opentelemetry/sdk-node @opentelemetry/instrumentation-express

Automatic Detection:

After installation, the auto-instrumentation library detects Express automatically when your app starts. It hooks into Express.js to track HTTP requests and related aspects.

Tracing:

OpenTelemetry automatically creates traces for incoming HTTP requests, capturing details such as:

    • Request URL
    • HTTP method (GET, POST, etc.)
    • Response status code
    • Request duration (latency)

Metrics:

Performance metrics are automatically captured, including:

    • Response times
    • Request counts
    • Error rates

This data helps you monitor your app’s health and performance.

Logging:

If configured, logs (like errors or warnings) from Express can also be captured, making it easier to correlate logs with traces and metrics.

How to Use Jaeger with OpenTelemetry | Last9
This guide shows you how to easily use Jaeger with OpenTelemetry for improved tracing and application monitoring.

Benefits of Auto-Instrumentation for Express.js

Auto-instrumentation offers several benefits for Express.js applications:

  • Less Effort, More Insights: Auto-instrumentation captures all the important metrics and traces without requiring you to manually add tracking to each route or service call.
  • Comprehensive Observability: It tracks not just HTTP requests, but also interactions with other libraries and services, like databases (e.g., MongoDB or MySQL).
  • Faster Troubleshooting: By generating distributed traces, auto-instrumentation helps you visualize the flow of requests across services, making it easier to find bottlenecks or failures.
  • Consistency: It ensures that all HTTP requests are captured consistently across the app, even in large or complex systems.
  • Customizability: While auto-instrumentation works out of the box, you can customize it to fit your specific needs (e.g., filtering which routes to trace or adjusting data exports).

How to Enable Auto-Instrumentation in Express.js

To set up auto-instrumentation for Express.js, follow these steps:

1. Install Dependencies

Run this command to install the necessary packages:

npm install @opentelemetry/api @opentelemetry/sdk-node @opentelemetry/instrumentation-express

2. Set Up OpenTelemetry SDK

In your Express.js app, initialize OpenTelemetry and enable auto-instrumentation for Express:

const { NodeTracerProvider } = require('@opentelemetry/sdk-node');
const { SimpleSpanProcessor } = require('@opentelemetry/sdk-trace-base');
const { ConsoleSpanExporter } = require('@opentelemetry/tracing');
const { ExpressInstrumentation } = require('@opentelemetry/instrumentation-express');
const express = require('express');
// Initialize the tracer provider
const provider = new NodeTracerProvider();
provider.addSpanProcessor(new SimpleSpanProcessor(new ConsoleSpanExporter()));
provider.register();
// Initialize Express
const app = express();
// Enable auto-instrumentation for Express
const expressInstrumentation = new ExpressInstrumentation();
expressInstrumentation.setTracerProvider(provider);
// Define your routes
app.get('/', (req, res) => {
  res.send('Hello, OpenTelemetry with Express!');
});
// Start the server
app.listen(3000, () => {
  console.log('Server running on port 3000');
});

3. Start Your App

Now, when you run your app, it will automatically track HTTP requests, capturing telemetry data and sending it to your configured exporter (e.g., Jaeger or Prometheus).

Instrumenting fasthttp with OpenTelemetry: A Complete Guide | Last9
We cover everything from initial setup to practical tips for monitoring and improving your fasthttp applications. Follow along to enhance your observability and get a clearer view of your app’s performance.

Troubleshooting Common Issues with OpenTelemetry in Express.js

Here are some common issues you may encounter when using OpenTelemetry with Express.js and how to resolve them:

1. No Telemetry Data Captured

Possible Causes:

  • OpenTelemetry SDK not initialized correctly.
  • Misconfigured tracing exporter (e.g., Jaeger, Prometheus).
  • Express instrumentation not applied.

Solutions:

Check SDK Initialization: Make sure OpenTelemetry is initialized before any other modules.

const { NodeTracerProvider } = require('@opentelemetry/sdk-node');
const { SimpleSpanProcessor } = require('@opentelemetry/sdk-trace-base');
const { ConsoleSpanExporter } = require('@opentelemetry/tracing');
const provider = new NodeTracerProvider();
provider.addSpanProcessor(new SimpleSpanProcessor(new ConsoleSpanExporter()));
provider.register();
  • Ensure Correct Exporter Configuration: Double-check your backend configurations, like Jaeger’s host and port.
  • Verify Express Instrumentation: Ensure that Express instrumentation is set up after the SDK initialization.

2. High Latency or Performance Degradation

Possible Causes:

  • Excessive telemetry data.
  • Unoptimized exporter or slow network connection.
  • Incorrect sampling configuration.

Solutions:

Optimize Sampling Rate: Adjust the sampling rate to capture only relevant traces (e.g., 10% of traces).

const { TraceIdRatioBasedSampler } = require('@opentelemetry/core');
provider.register({ sampler: new TraceIdRatioBasedSampler(0.1) });
  • Use Asynchronous Exporters: Ensure telemetry data is exported asynchronously to avoid blocking the main thread.
  • Monitor Exporter Performance: If exporting to a backend like Jaeger, check the speed and reliability of the connection.

3. Incomplete or Missing Trace Data

Possible Causes:

  • Some parts of the app might not be automatically instrumented.
  • Trace context not propagating correctly across services.

Solutions:

Manually Instrument Custom Code: Add spans for custom routes or middleware that aren’t automatically instrumented.

const { trace } = require('@opentelemetry/api');
const tracer = trace.getTracer('custom-tracer');
app.use((req, res, next) => {
  const span = tracer.startSpan('custom-middleware');
  res.on('finish', () => {
    span.end();
  });
  next();
});
  • Ensure Proper Trace Context Propagation: If using microservices, make sure to pass trace context (e.g., traceparent header) across service boundaries.

4. Spans Not Closing Properly

Possible Causes:

  • Spans not ending at the correct time.
  • Asynchronous code (e.g., callbacks or promises) not handling spans correctly.

Solutions:

Ensure Span Closure: Always close spans when the operation is complete.

app.get('/some-path', async (req, res) => {
  const span = tracer.startSpan('some-span');
  try {
    const result = await someAsyncFunction();
    res.send(result);
  } finally {
    span.end();  // Close the span when done
  }
});
  • Check Middleware Behavior: Ensure middleware doesn’t interfere with the span’s lifecycle.
OpenTelemetry Filelog Receiver: Collecting Kubernetes Logs | Last9
Learn to configure, optimize, and troubleshoot log collection from various sources including syslog and application logs. Discover advanced parser operator techniques for robust observability.

Send Distributed Traces from Express.js to Last9 with OpenTelemetry

Prerequisites:

Before you start, ensure the following:

  • You have an Express.js application.
  • You’ve signed up for Last9, created a cluster, and obtained the following OTLP credentials from the Integrations page:
    • endpoint
    • auth_header

Setting Up Distributed Tracing with OpenTelemetry in Express.js for Last9

1. Install OpenTelemetry Packages

To start instrumentation, install the following OpenTelemetry packages using npm:

npm install --save @opentelemetry/api \
  @opentelemetry/instrumentation \
  @opentelemetry/tracing \
  @opentelemetry/exporter-trace-otlp-http \
  @opentelemetry/resources \
  @opentelemetry/semantic-conventions \
  @opentelemetry/auto-instrumentations-node \
  @opentelemetry/sdk-node

For detailed information on each package, check the OpenTelemetry documentation.

2. Configure Auto-Instrumentation with OpenTelemetry

Step 1: Set Environment Variables
Add the required environment variables to your application. You can find these values on the Integrations page:

Set Environment Variables
Set Environment Variables
OTLP_ENDPOINT=<ENDPOINT>
OTLP_AUTH_HEADER="Basic <BASIC_AUTH_HEADER>"

Step 2: Create instrumentation.ts
Create a file named instrumentation.ts and include the following code:

import { NodeTracerProvider, TracerConfig } from "@opentelemetry/sdk-trace-node";
import { BatchSpanProcessor } from "@opentelemetry/sdk-trace-base"; // Improved performance with BatchSpanProcessor
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http"; // OTLP exporter
import { registerInstrumentations } from "@opentelemetry/instrumentation";
import { getNodeAutoInstrumentations } from "@opentelemetry/auto-instrumentations-node";
import { SEMRESATTRS_SERVICE_NAME, SEMRESATTRS_DEPLOYMENT_ENVIRONMENT } from "@opentelemetry/semantic-conventions";
import { Resource } from "@opentelemetry/resources";

const providerConfig: TracerConfig = {
  resource: new Resource({
    [SEMRESATTRS_SERVICE_NAME]: "<your-service-name>",
    [SEMRESATTRS_DEPLOYMENT_ENVIRONMENT]: process.env.NODE_ENV,
  }),
};

// Set up and register the tracer provider
const provider = new NodeTracerProvider(providerConfig);
const otlp = new OTLPTraceExporter({
  url: process.env.OTLP_ENDPOINT,
  headers: {
    Authorization: process.env.OTLP_AUTH_HEADER,
  },
}); // Configure OTLP exporter
provider.addSpanProcessor(new BatchSpanProcessor(otlp));
provider.register();

// Auto-instrument HTTP and Express (optional: exclude file system instrumentation for better performance)
registerInstrumentations({
  instrumentations: [
    getNodeAutoInstrumentations({
      "@opentelemetry/instrumentation-fs": {
        enabled: false, // Disable file system instrumentation
      },
    }),
  ],
});

What This Code Does:

  • Trace Provider Configuration: Sets up the trace provider with your app’s service name.
  • OTLP Exporter: Configures the exporter to send traces to Last9.
  • Auto Instrumentation: Automatically instruments HTTP and Express, while excluding unnecessary file system spans for improved performance.

Step 3: Import Instrumentation in Your App
In your main application file (e.g., server.ts), import instrumentation.ts at the beginning of the file:

// server.ts
import "./instrumentation.ts";
// Your application code...

If you’re not using TypeScript, you can use instrumentation.js.

3. View Traces in Last9

Once your app is running, it will begin sending traces to Last9. You can view them in the APM dashboard of Last9.

View Traces in Last9
View Traces in Last9

Conclusion

OpenTelemetry Express provides a simple and efficient way to add observability to your Node.js applications using the Express framework.

With just a few lines of code, you can:

  • Improve troubleshooting
  • Monitor key metrics
  • Optimize user experience

Whether you're running a small app or managing a complex microservices architecture, OpenTelemetry Express can help you stay on top of your app’s performance and ensure it runs smoothly.

🤝
Have more questions? Join us on Discord! Our dedicated channel lets you connect with fellow developers and share your use case.

FAQs: OpenTelemetry Express in Node.js

What is OpenTelemetry?

OpenTelemetry is a set of APIs, libraries, and agents designed to collect and export telemetry data like traces, metrics, and logs for observability.

How does OpenTelemetry help with Express.js applications?

OpenTelemetry automatically instruments Express.js to capture HTTP request traces, metrics, and logs, helping you monitor and troubleshoot your app’s performance.

Do I need to modify my Express.js code to use OpenTelemetry?

No, OpenTelemetry can automatically instrument your Express.js app with minimal setup. You can further customize it if needed.

How do I install OpenTelemetry for Express.js?

Install OpenTelemetry in your Node.js app using npm:

bash

Copy code

npm install @opentelemetry/api @opentelemetry/sdk-node @opentelemetry/instrumentation-express

What telemetry data does OpenTelemetry collect for Express.js?

OpenTelemetry collects:

  • Traces: Request/response data
  • Metrics: Response times, request counts
  • Logs: To give insights into app performance

How do I export OpenTelemetry data to a backend?

You can configure OpenTelemetry to export data to services like Jaeger, Prometheus, or a local console exporter by setting up the appropriate exporter in your code.

Can I use OpenTelemetry with other Node.js frameworks?

Yes, OpenTelemetry supports various Node.js frameworks like Koa, Hapi, and Fastify, in addition to Express.js.

How do I troubleshoot missing traces or performance issues with OpenTelemetry?

Common troubleshooting steps include:

  • Verifying SDK initialization
  • Checking exporter configuration
  • Optimizing sampling
  • Ensuring proper span closure in asynchronous code

Contents


Newsletter

Stay updated on the latest from Last9.

Handcrafted Related Posts