How to Use Node.js diagnostics_channel

This article provides a practical guide on how to use the node:diagnostics_channel module in Node.js to publish and subscribe to internal diagnostic events. You will learn how to create channels, publish telemetry data, and consume those events to monitor application performance and behavior without tightly coupling your business logic to your observability tools.

The node:diagnostics_channel module is a built-in Node.js API designed to facilitate the flow of diagnostic data. It allows libraries and application code to publish data points—such as database query times, HTTP request details, or custom application states—that monitoring tools, loggers, and APM (Application Performance Monitoring) agents can subscribe to.

Why Use diagnostics_channel?

Historically, integrating APM tools required monkey-patching core modules or third-party libraries. This module solves that problem by introducing a publish-subscribe (pub/sub) pattern directly into the Node.js runtime.

Key benefits include: * Decoupling: Publishers do not need to know who is subscribing to their data. * Performance: Channels are designed to be extremely lightweight when there are no active subscribers. * Standardization: It provides a unified way for library maintainers to expose diagnostic hooks.

Subscribing to a Channel

To consume diagnostic data, you subscribe to a specific named channel using the diagnostics_channel module.

import diagnostics_channel from 'node:diagnostics_channel';

// Subscribe to a specific channel
diagnostics_channel.subscribe('my-app.database.query', (message, name) => {
  console.log(`Received event from ${name}:`, message);
});

The callback function receives two arguments: the message object published by the channel, and the name of the channel.

Publishing to a Channel

To publish data, you first need to acquire a channel by its unique name, and then call the publish() method.

import diagnostics_channel from 'node:diagnostics_channel';

// Acquire the channel
const queryChannel = diagnostics_channel.channel('my-app.database.query');

// Publish data to the channel
if (queryChannel.hasSubscribers) {
  queryChannel.publish({
    query: 'SELECT * FROM users',
    durationMs: 12,
    timestamp: Date.now()
  });
}

Note: Checking channel.hasSubscribers before publishing is a best practice. It prevents the unnecessary creation of message objects and execution of measurement logic when no active listeners exist, keeping overhead to a minimum.

Unsubscribing from a Channel

If you no longer need to listen to events, you should unsubscribe to prevent memory leaks.

import diagnostics_channel from 'node:diagnostics_channel';

function onMessage(message, name) {
  console.log('Event received:', message);
}

// Subscribe
diagnostics_channel.subscribe('my-app.database.query', onMessage);

// Unsubscribe when done
diagnostics_channel.unsubscribe('my-app.database.query', onMessage);

Channel Naming Best Practices

When creating channel names, use a namespace prefix (e.g., app.database.query or library.http.request) to avoid name collisions with other packages or Node.js internal channels.