Node.js v20.11.0 文档


诊断通道#

Diagnostics Channel

稳定性: 2 - 稳定的

Stability: 2 - Stable

源代码: lib/diagnostics_channel.js

node:diagnostics_channel 模块提供了一个 API 来创建命名通道来报告任意消息数据以用于诊断目的。

The node:diagnostics_channel module provides an API to create named channels to report arbitrary message data for diagnostics purposes.

可以使用以下方式访问它:

It can be accessed using:

import diagnostics_channel from 'node:diagnostics_channel';const diagnostics_channel = require('node:diagnostics_channel');

希望报告诊断消息的模块编写者将创建一个或多个顶层通道来报告消息。也可以在运行时获取通道,但由于这样做会产生额外的开销,因此不鼓励这样做。为方便起见,可以导出通道,但只要知道名称,就可以在任何地方获取。

It is intended that a module writer wanting to report diagnostics messages will create one or many top-level channels to report messages through. Channels may also be acquired at runtime but it is not encouraged due to the additional overhead of doing so. Channels may be exported for convenience, but as long as the name is known it can be acquired anywhere.

如果你打算让你的模块生成诊断数据以供其他人使用,建议你包含使用哪些命名通道的文档以及消息数据的形状。通道名称通常应包括模块名称,以避免与其他模块的数据发生冲突。

If you intend for your module to produce diagnostics data for others to consume it is recommended that you include documentation of what named channels are used along with the shape of the message data. Channel names should generally include the module name to avoid collisions with data from other modules.

公共接口#

Public API

概述#

Overview

以下是公共 API 的简单概述。

Following is a simple overview of the public API.

import diagnostics_channel from 'node:diagnostics_channel';

// Get a reusable channel object
const channel = diagnostics_channel.channel('my-channel');

function onMessage(message, name) {
  // Received data
}

// Subscribe to the channel
diagnostics_channel.subscribe('my-channel', onMessage);

// Check if the channel has an active subscriber
if (channel.hasSubscribers) {
  // Publish data to the channel
  channel.publish({
    some: 'data',
  });
}

// Unsubscribe from the channel
diagnostics_channel.unsubscribe('my-channel', onMessage);const diagnostics_channel = require('node:diagnostics_channel');

// Get a reusable channel object
const channel = diagnostics_channel.channel('my-channel');

function onMessage(message, name) {
  // Received data
}

// Subscribe to the channel
diagnostics_channel.subscribe('my-channel', onMessage);

// Check if the channel has an active subscriber
if (channel.hasSubscribers) {
  // Publish data to the channel
  channel.publish({
    some: 'data',
  });
}

// Unsubscribe from the channel
diagnostics_channel.unsubscribe('my-channel', onMessage);

diagnostics_channel.hasSubscribers(name)#

检查指定通道是否有活跃订阅者。如果你要发送的消息的准备成本可能很高,这将很有帮助。

Check if there are active subscribers to the named channel. This is helpful if the message you want to send might be expensive to prepare.

此 API 是可选的,但在尝试从对性能非常敏感的代码发布消息时很有用。

This API is optional but helpful when trying to publish messages from very performance-sensitive code.

import diagnostics_channel from 'node:diagnostics_channel';

if (diagnostics_channel.hasSubscribers('my-channel')) {
  // There are subscribers, prepare and publish message
}const diagnostics_channel = require('node:diagnostics_channel');

if (diagnostics_channel.hasSubscribers('my-channel')) {
  // There are subscribers, prepare and publish message
}

diagnostics_channel.channel(name)#

这是任何想要发布到命名通道的人的主要入口点。它生成一个通道对象,该对象经过优化以尽可能减少发布时的开销。

This is the primary entry-point for anyone wanting to publish to a named channel. It produces a channel object which is optimized to reduce overhead at publish time as much as possible.

import diagnostics_channel from 'node:diagnostics_channel';

const channel = diagnostics_channel.channel('my-channel');const diagnostics_channel = require('node:diagnostics_channel');

const channel = diagnostics_channel.channel('my-channel');

diagnostics_channel.subscribe(name, onMessage)#

注册消息处理程序以订阅此通道。每当消息发布到通道时,此消息处理程序将同步运行。消息处理程序中抛出的任何错误都将触发 'uncaughtException'

Register a message handler to subscribe to this channel. This message handler will be run synchronously whenever a message is published to the channel. Any errors thrown in the message handler will trigger an 'uncaughtException'.

import diagnostics_channel from 'node:diagnostics_channel';

diagnostics_channel.subscribe('my-channel', (message, name) => {
  // Received data
});const diagnostics_channel = require('node:diagnostics_channel');

diagnostics_channel.subscribe('my-channel', (message, name) => {
  // Received data
});

diagnostics_channel.unsubscribe(name, onMessage)#
  • name <string> | <symbol> 通道名称

    name <string> | <symbol> The channel name

  • onMessage <Function> 要删除的先前订阅的处理程序

    onMessage <Function> The previous subscribed handler to remove

  • 返回:<boolean> 如果找到处理程序则为 true,否则为 false

    Returns: <boolean> true if the handler was found, false otherwise.

删除以前使用 diagnostics_channel.subscribe(name, onMessage) 注册到此通道的消息处理程序。

Remove a message handler previously registered to this channel with diagnostics_channel.subscribe(name, onMessage).

import diagnostics_channel from 'node:diagnostics_channel';

function onMessage(message, name) {
  // Received data
}

diagnostics_channel.subscribe('my-channel', onMessage);

diagnostics_channel.unsubscribe('my-channel', onMessage);const diagnostics_channel = require('node:diagnostics_channel');

function onMessage(message, name) {
  // Received data
}

diagnostics_channel.subscribe('my-channel', onMessage);

diagnostics_channel.unsubscribe('my-channel', onMessage);

diagnostics_channel.tracingChannel(nameOrChannels)#

稳定性: 1 - 实验性的

Stability: 1 - Experimental

为给定的 TracingChannel 通道 创建一个 TracingChannel 封装器。如果给定名称,将以 tracing:${name}:${eventType} 的形式创建相应的跟踪通道,其中 eventType 对应于 TracingChannel 通道 的类型。

Creates a TracingChannel wrapper for the given TracingChannel Channels. If a name is given, the corresponding tracing channels will be created in the form of tracing:${name}:${eventType} where eventType corresponds to the types of TracingChannel Channels.

import diagnostics_channel from 'node:diagnostics_channel';

const channelsByName = diagnostics_channel.tracingChannel('my-channel');

// or...

const channelsByCollection = diagnostics_channel.tracingChannel({
  start: diagnostics_channel.channel('tracing:my-channel:start'),
  end: diagnostics_channel.channel('tracing:my-channel:end'),
  asyncStart: diagnostics_channel.channel('tracing:my-channel:asyncStart'),
  asyncEnd: diagnostics_channel.channel('tracing:my-channel:asyncEnd'),
  error: diagnostics_channel.channel('tracing:my-channel:error'),
});const diagnostics_channel = require('node:diagnostics_channel');

const channelsByName = diagnostics_channel.tracingChannel('my-channel');

// or...

const channelsByCollection = diagnostics_channel.tracingChannel({
  start: diagnostics_channel.channel('tracing:my-channel:start'),
  end: diagnostics_channel.channel('tracing:my-channel:end'),
  asyncStart: diagnostics_channel.channel('tracing:my-channel:asyncStart'),
  asyncEnd: diagnostics_channel.channel('tracing:my-channel:asyncEnd'),
  error: diagnostics_channel.channel('tracing:my-channel:error'),
});

类:Channel#

Class: Channel

Channel 类代表数据管道中的一个单独的命名通道。它用于跟踪订阅者并在有订阅者时发布消息。它作为一个单独的对象存在,以避免在发布时进行通道查找,从而实现非常快的发布速度并允许大量使用,同时产生非常低的成本。通道是用 diagnostics_channel.channel(name) 创建的,不支持直接用 new Channel(name) 构建通道。

The class Channel represents an individual named channel within the data pipeline. It is used to track subscribers and to publish messages when there are subscribers present. It exists as a separate object to avoid channel lookups at publish time, enabling very fast publish speeds and allowing for heavy use while incurring very minimal cost. Channels are created with diagnostics_channel.channel(name), constructing a channel directly with new Channel(name) is not supported.

channel.hasSubscribers#
  • 返回:<boolean> 如果有活跃订阅者

    Returns: <boolean> If there are active subscribers

检查此通道是否有活跃订阅者。如果你要发送的消息的准备成本可能很高,这将很有帮助。

Check if there are active subscribers to this channel. This is helpful if the message you want to send might be expensive to prepare.

此 API 是可选的,但在尝试从对性能非常敏感的代码发布消息时很有用。

This API is optional but helpful when trying to publish messages from very performance-sensitive code.

import diagnostics_channel from 'node:diagnostics_channel';

const channel = diagnostics_channel.channel('my-channel');

if (channel.hasSubscribers) {
  // There are subscribers, prepare and publish message
}const diagnostics_channel = require('node:diagnostics_channel');

const channel = diagnostics_channel.channel('my-channel');

if (channel.hasSubscribers) {
  // There are subscribers, prepare and publish message
}

channel.publish(message)#
  • message <any> 要发送给通道订阅者的消息

    message <any> The message to send to the channel subscribers

向通道的任何订阅者发布消息。这将同步触发消息处理程序,因此它们将在同一上下文中执行。

Publish a message to any subscribers to the channel. This will trigger message handlers synchronously so they will execute within the same context.

import diagnostics_channel from 'node:diagnostics_channel';

const channel = diagnostics_channel.channel('my-channel');

channel.publish({
  some: 'message',
});const diagnostics_channel = require('node:diagnostics_channel');

const channel = diagnostics_channel.channel('my-channel');

channel.publish({
  some: 'message',
});

channel.subscribe(onMessage)#

注册消息处理程序以订阅此通道。每当消息发布到通道时,此消息处理程序将同步运行。消息处理程序中抛出的任何错误都将触发 'uncaughtException'

Register a message handler to subscribe to this channel. This message handler will be run synchronously whenever a message is published to the channel. Any errors thrown in the message handler will trigger an 'uncaughtException'.

import diagnostics_channel from 'node:diagnostics_channel';

const channel = diagnostics_channel.channel('my-channel');

channel.subscribe((message, name) => {
  // Received data
});const diagnostics_channel = require('node:diagnostics_channel');

const channel = diagnostics_channel.channel('my-channel');

channel.subscribe((message, name) => {
  // Received data
});

channel.unsubscribe(onMessage)#

  • onMessage <Function> 要删除的先前订阅的处理程序

    onMessage <Function> The previous subscribed handler to remove

  • 返回:<boolean> 如果找到处理程序则为 true,否则为 false

    Returns: <boolean> true if the handler was found, false otherwise.

删除以前使用 channel.subscribe(onMessage) 注册到此通道的消息处理程序。

Remove a message handler previously registered to this channel with channel.subscribe(onMessage).

import diagnostics_channel from 'node:diagnostics_channel';

const channel = diagnostics_channel.channel('my-channel');

function onMessage(message, name) {
  // Received data
}

channel.subscribe(onMessage);

channel.unsubscribe(onMessage);const diagnostics_channel = require('node:diagnostics_channel');

const channel = diagnostics_channel.channel('my-channel');

function onMessage(message, name) {
  // Received data
}

channel.subscribe(onMessage);

channel.unsubscribe(onMessage);

channel.bindStore(store[, transform])#

稳定性: 1 - 实验性的

Stability: 1 - Experimental

  • store <AsyncLocalStorage> 将上下文数据绑定到的存储

    store <AsyncLocalStorage> The store to which to bind the context data

  • transform <Function> 在设置存储上下文之前转换上下文数据

    transform <Function> Transform context data before setting the store context

调用 channel.runStores(context, ...) 时,给定的上下文数据将应用于绑定到通道的任何存储。如果存储已经绑定,则之前的 transform 功能将被替换为新功能。可以省略 transform 函数以将给定的上下文数据直接设置为上下文。

When channel.runStores(context, ...) is called, the given context data will be applied to any store bound to the channel. If the store has already been bound the previous transform function will be replaced with the new one. The transform function may be omitted to set the given context data as the context directly.

import diagnostics_channel from 'node:diagnostics_channel';
import { AsyncLocalStorage } from 'node:async_hooks';

const store = new AsyncLocalStorage();

const channel = diagnostics_channel.channel('my-channel');

channel.bindStore(store, (data) => {
  return { data };
});const diagnostics_channel = require('node:diagnostics_channel');
const { AsyncLocalStorage } = require('node:async_hooks');

const store = new AsyncLocalStorage();

const channel = diagnostics_channel.channel('my-channel');

channel.bindStore(store, (data) => {
  return { data };
});

channel.unbindStore(store)#

稳定性: 1 - 实验性的

Stability: 1 - Experimental

删除以前使用 channel.bindStore(store) 注册到此通道的消息处理程序。

Remove a message handler previously registered to this channel with channel.bindStore(store).

import diagnostics_channel from 'node:diagnostics_channel';
import { AsyncLocalStorage } from 'node:async_hooks';

const store = new AsyncLocalStorage();

const channel = diagnostics_channel.channel('my-channel');

channel.bindStore(store);
channel.unbindStore(store);const diagnostics_channel = require('node:diagnostics_channel');
const { AsyncLocalStorage } = require('node:async_hooks');

const store = new AsyncLocalStorage();

const channel = diagnostics_channel.channel('my-channel');

channel.bindStore(store);
channel.unbindStore(store);

channel.runStores(context, fn[, thisArg[, ...args]])#

稳定性: 1 - 实验性的

Stability: 1 - Experimental

  • context <any> 发送给订阅者并绑定到存储的消息

    context <any> Message to send to subscribers and bind to stores

  • fn <Function> 在输入的存储上下文中运行的处理程序

    fn <Function> Handler to run within the entered storage context

  • thisArg <any> 用于函数调用的接收器。

    thisArg <any> The receiver to be used for the function call.

  • ...args <any> 传递给函数的可选参数。

    ...args <any> Optional arguments to pass to the function.

在给定函数的持续时间内将给定数据应用于绑定到通道的任何 AsyncLocalStorage 实例,然后在该数据应用于存储的范围内发布到通道。

Applies the given data to any AsyncLocalStorage instances bound to the channel for the duration of the given function, then publishes to the channel within the scope of that data is applied to the stores.

如果为 channel.bindStore(store) 提供了转换函数,它将在消息数据成为存储的上下文值之前应用于转换消息数据。在需要上下文链接的情况下,可以从转换函数中访问先前的存储上下文。

If a transform function was given to channel.bindStore(store) it will be applied to transform the message data before it becomes the context value for the store. The prior storage context is accessible from within the transform function in cases where context linking is required.

应用到存储的上下文应该可以在任何异步代码中访问,这些代码从给定函数期间开始的执行继续,但是在某些情况下可能会出现 上下文丢失

The context applied to the store should be accessible in any async code which continues from execution which began during the given function, however there are some situations in which context loss may occur.

import diagnostics_channel from 'node:diagnostics_channel';
import { AsyncLocalStorage } from 'node:async_hooks';

const store = new AsyncLocalStorage();

const channel = diagnostics_channel.channel('my-channel');

channel.bindStore(store, (message) => {
  const parent = store.getStore();
  return new Span(message, parent);
});
channel.runStores({ some: 'message' }, () => {
  store.getStore(); // Span({ some: 'message' })
});const diagnostics_channel = require('node:diagnostics_channel');
const { AsyncLocalStorage } = require('node:async_hooks');

const store = new AsyncLocalStorage();

const channel = diagnostics_channel.channel('my-channel');

channel.bindStore(store, (message) => {
  const parent = store.getStore();
  return new Span(message, parent);
});
channel.runStores({ some: 'message' }, () => {
  store.getStore(); // Span({ some: 'message' })
});

类:TracingChannel#

Class: TracingChannel

稳定性: 1 - 实验性的

Stability: 1 - Experimental

TracingChannelTracingChannel 通道 的集合,它们一起表示单个可追踪的动作。它用于形式化和简化生成事件以跟踪应用流的过程。diagnostics_channel.tracingChannel() 用于构建 TracingChannel。与 Channel 一样,建议在文件的顶层创建和重用单个 TracingChannel,而不是动态创建它们。

The class TracingChannel is a collection of TracingChannel Channels which together express a single traceable action. It is used to formalize and simplify the process of producing events for tracing application flow. diagnostics_channel.tracingChannel() is used to construct a TracingChannel. As with Channel it is recommended to create and reuse a single TracingChannel at the top-level of the file rather than creating them dynamically.

tracingChannel.subscribe(subscribers)#

稳定性: 1 - 实验性的

Stability: 1 - Experimental

订阅函数集合到相应通道的助手。这与在每个通道上单独调用 channel.subscribe(onMessage) 相同。

Helper to subscribe a collection of functions to the corresponding channels. This is the same as calling channel.subscribe(onMessage) on each channel individually.

import diagnostics_channel from 'node:diagnostics_channel';

const channels = diagnostics_channel.tracingChannel('my-channel');

channels.subscribe({
  start(message) {
    // Handle start message
  },
  end(message) {
    // Handle end message
  },
  asyncStart(message) {
    // Handle asyncStart message
  },
  asyncEnd(message) {
    // Handle asyncEnd message
  },
  error(message) {
    // Handle error message
  },
});const diagnostics_channel = require('node:diagnostics_channel');

const channels = diagnostics_channel.tracingChannel('my-channel');

channels.subscribe({
  start(message) {
    // Handle start message
  },
  end(message) {
    // Handle end message
  },
  asyncStart(message) {
    // Handle asyncStart message
  },
  asyncEnd(message) {
    // Handle asyncEnd message
  },
  error(message) {
    // Handle error message
  },
});

tracingChannel.unsubscribe(subscribers)#

稳定性: 1 - 实验性的

Stability: 1 - Experimental

从相应通道取消订阅功能集合的助手。这与在每个通道上单独调用 channel.unsubscribe(onMessage) 相同。

Helper to unsubscribe a collection of functions from the corresponding channels. This is the same as calling channel.unsubscribe(onMessage) on each channel individually.

import diagnostics_channel from 'node:diagnostics_channel';

const channels = diagnostics_channel.tracingChannel('my-channel');

channels.unsubscribe({
  start(message) {
    // Handle start message
  },
  end(message) {
    // Handle end message
  },
  asyncStart(message) {
    // Handle asyncStart message
  },
  asyncEnd(message) {
    // Handle asyncEnd message
  },
  error(message) {
    // Handle error message
  },
});const diagnostics_channel = require('node:diagnostics_channel');

const channels = diagnostics_channel.tracingChannel('my-channel');

channels.unsubscribe({
  start(message) {
    // Handle start message
  },
  end(message) {
    // Handle end message
  },
  asyncStart(message) {
    // Handle asyncStart message
  },
  asyncEnd(message) {
    // Handle asyncEnd message
  },
  error(message) {
    // Handle error message
  },
});

tracingChannel.traceSync(fn[, context[, thisArg[, ...args]]])#

稳定性: 1 - 实验性的

Stability: 1 - Experimental

  • fn <Function> 环绕轨迹的函数

    fn <Function> Function to wrap a trace around

  • context <Object> 通过共享对象关联事件

    context <Object> Shared object to correlate events through

  • thisArg <any> 用于函数调用的接收器

    thisArg <any> The receiver to be used for the function call

  • ...args <any> 传递给函数的可选参数

    ...args <any> Optional arguments to pass to the function

  • 返回:<any> 给定函数的返回值

    Returns: <any> The return value of the given function

跟踪同步函数调用。这将始终在执行过程中产生 start 事件end 事件,如果给定的函数抛出错误,则可能会产生 error 事件。这将在 start 通道上使用 channel.runStores(context, ...) 运行给定函数,确保所有事件都应设置任何绑定存储以匹配此跟踪上下文。

Trace a synchronous function call. This will always produce a start event and end event around the execution and may produce an error event if the given function throws an error. This will run the given function using channel.runStores(context, ...) on the start channel which ensures all events should have any bound stores set to match this trace context.

import diagnostics_channel from 'node:diagnostics_channel';

const channels = diagnostics_channel.tracingChannel('my-channel');

channels.traceSync(() => {
  // Do something
}, {
  some: 'thing',
});const diagnostics_channel = require('node:diagnostics_channel');

const channels = diagnostics_channel.tracingChannel('my-channel');

channels.traceSync(() => {
  // Do something
}, {
  some: 'thing',
});

tracingChannel.tracePromise(fn[, context[, thisArg[, ...args]]])#

稳定性: 1 - 实验性的

Stability: 1 - Experimental

  • fn <Function> promise 返回函数来环绕跟踪

    fn <Function> Promise-returning function to wrap a trace around

  • context <Object> 用于关联跟踪事件的共享对象

    context <Object> Shared object to correlate trace events through

  • thisArg <any> 用于函数调用的接收器

    thisArg <any> The receiver to be used for the function call

  • ...args <any> 传递给函数的可选参数

    ...args <any> Optional arguments to pass to the function

  • 返回:<Promise> 从给定函数返回的 promise 链接

    Returns: <Promise> Chained from promise returned by the given function

跟踪 promise 返回函数调用。这将始终围绕函数执行的同步部分生成 start 事件end 事件,并在达到 promise 继续时生成 asyncStart 事件asyncEnd 事件。如果给定的函数抛出错误或返回的 promise 被拒绝,它也可能产生一个 error 事件。这将在 start 通道上使用 channel.runStores(context, ...) 运行给定函数,确保所有事件都应设置任何绑定存储以匹配此跟踪上下文。

Trace a promise-returning function call. This will always produce a start event and end event around the synchronous portion of the function execution, and will produce an asyncStart event and asyncEnd event when a promise continuation is reached. It may also produce an error event if the given function throws an error or the returned promise rejects. This will run the given function using channel.runStores(context, ...) on the start channel which ensures all events should have any bound stores set to match this trace context.

import diagnostics_channel from 'node:diagnostics_channel';

const channels = diagnostics_channel.tracingChannel('my-channel');

channels.tracePromise(async () => {
  // Do something
}, {
  some: 'thing',
});const diagnostics_channel = require('node:diagnostics_channel');

const channels = diagnostics_channel.tracingChannel('my-channel');

channels.tracePromise(async () => {
  // Do something
}, {
  some: 'thing',
});

tracingChannel.traceCallback(fn[, position[, context[, thisArg[, ...args]]]])#

稳定性: 1 - 实验性的

Stability: 1 - Experimental

  • fn <Function> 使用函数来封装跟踪的回调

    fn <Function> callback using function to wrap a trace around

  • position <number> 预期回调的零索引参数位置

    position <number> Zero-indexed argument position of expected callback

  • context <Object> 用于关联跟踪事件的共享对象

    context <Object> Shared object to correlate trace events through

  • thisArg <any> 用于函数调用的接收器

    thisArg <any> The receiver to be used for the function call

  • ...args <any> 传递给函数的可选参数

    ...args <any> Optional arguments to pass to the function

  • 返回:<any> 给定函数的返回值

    Returns: <any> The return value of the given function

跟踪回调接收函数调用。这将始终围绕函数执行的同步部分生成 start 事件end 事件,并将围绕回调执行生成 asyncStart 事件asyncEnd 事件。如果给定的函数抛出错误或返回的 promise 被拒绝,它也可能产生一个 error 事件。这将在 start 通道上使用 channel.runStores(context, ...) 运行给定函数,确保所有事件都应设置任何绑定存储以匹配此跟踪上下文。

Trace a callback-receiving function call. This will always produce a start event and end event around the synchronous portion of the function execution, and will produce a asyncStart event and asyncEnd event around the callback execution. It may also produce an error event if the given function throws an error or the returned promise rejects. This will run the given function using channel.runStores(context, ...) on the start channel which ensures all events should have any bound stores set to match this trace context.

默认情况下,position 将为 -1 以指示应将最终参数用作回调。

The position will be -1 by default to indicate the final argument should be used as the callback.

import diagnostics_channel from 'node:diagnostics_channel';

const channels = diagnostics_channel.tracingChannel('my-channel');

channels.traceCallback((arg1, callback) => {
  // Do something
  callback(null, 'result');
}, 1, {
  some: 'thing',
}, thisArg, arg1, callback);const diagnostics_channel = require('node:diagnostics_channel');

const channels = diagnostics_channel.tracingChannel('my-channel');

channels.traceCallback((arg1, callback) => {
  // Do something
  callback(null, 'result');
}, {
  some: 'thing',
}, thisArg, arg1, callback);

回调也将与 channel.runStores(context, ...) 一起运行,在某些情况下启用上下文丢失恢复。

The callback will also be run with channel.runStores(context, ...) which enables context loss recovery in some cases.

import diagnostics_channel from 'node:diagnostics_channel';
import { AsyncLocalStorage } from 'node:async_hooks';

const channels = diagnostics_channel.tracingChannel('my-channel');
const myStore = new AsyncLocalStorage();

// The start channel sets the initial store data to something
// and stores that store data value on the trace context object
channels.start.bindStore(myStore, (data) => {
  const span = new Span(data);
  data.span = span;
  return span;
});

// Then asyncStart can restore from that data it stored previously
channels.asyncStart.bindStore(myStore, (data) => {
  return data.span;
});const diagnostics_channel = require('node:diagnostics_channel');
const { AsyncLocalStorage } = require('node:async_hooks');

const channels = diagnostics_channel.tracingChannel('my-channel');
const myStore = new AsyncLocalStorage();

// The start channel sets the initial store data to something
// and stores that store data value on the trace context object
channels.start.bindStore(myStore, (data) => {
  const span = new Span(data);
  data.span = span;
  return span;
});

// Then asyncStart can restore from that data it stored previously
channels.asyncStart.bindStore(myStore, (data) => {
  return data.span;
});

TracingChannel 通道#

TracingChannel Channels

TracingChannel 是多个 diagnostics_channels 的集合,表示单个可跟踪操作的执行生命周期中的特定点。该行为分为五个 diagnostics_channels,包括 startendasyncStartasyncEnderror。单个可跟踪操作将在所有事件之间共享相同的事件对象,这有助于通过 weakmap 管理相关性。

A TracingChannel is a collection of several diagnostics_channels representing specific points in the execution lifecycle of a single traceable action. The behavior is split into five diagnostics_channels consisting of start, end, asyncStart, asyncEnd, and error. A single traceable action will share the same event object between all events, this can be helpful for managing correlation through a weakmap.

当任务 "completes" 时,这些事件对象将使用 resulterror 值进行扩展。在同步任务的情况下,result 将是返回值,error 将是函数抛出的任何值。对于基于回调的异步函数,result 将是回调的第二个参数,而 error 将是 end 事件中可见的抛出错误或 asyncStartasyncEnd 事件中的第一个回调参数。

These event objects will be extended with result or error values when the task "completes". In the case of a synchronous task the result will be the return value and the error will be anything thrown from the function. With callback-based async functions the result will be the second argument of the callback while the error will either be a thrown error visible in the end event or the first callback argument in either of the asyncStart or asyncEnd events.

跟踪通道应遵循以下命名模式:

Tracing channels should follow a naming pattern of:

  • tracing:module.class.method:starttracing:module.function:start

    tracing:module.class.method:start or tracing:module.function:start

  • tracing:module.class.method:endtracing:module.function:end

    tracing:module.class.method:end or tracing:module.function:end

  • tracing:module.class.method:asyncStarttracing:module.function:asyncStart

    tracing:module.class.method:asyncStart or tracing:module.function:asyncStart

  • tracing:module.class.method:asyncEndtracing:module.function:asyncEnd

    tracing:module.class.method:asyncEnd or tracing:module.function:asyncEnd

  • tracing:module.class.method:errortracing:module.function:error

    tracing:module.class.method:error or tracing:module.function:error

start(event)#
  • 名称:tracing:${name}:start

    Name: tracing:${name}:start

start 事件表示函数被调用的时间点。此时,事件数据可能包含函数参数或函数执行开始时可用的任何其他内容。

The start event represents the point at which a function is called. At this point the event data may contain function arguments or anything else available at the very start of the execution of the function.

end(event)#
  • 名称:tracing:${name}:end

    Name: tracing:${name}:end

end 事件表示函数调用返回值的时间点。在异步函数的情况下,这是当 promise 返回时,而不是当函数本身在内部进行 return 语句时。此时,如果跟踪函数是同步的,result 字段将设置为函数的返回值。或者,可能会出现 error 字段以表示任何抛出的错误。

The end event represents the point at which a function call returns a value. In the case of an async function this is when the promise returned not when the function itself makes a return statement internally. At this point, if the traced function was synchronous the result field will be set to the return value of the function. Alternatively, the error field may be present to represent any thrown errors.

建议专门监听 error 事件以跟踪错误,因为可跟踪的操作可能会产生多个错误。例如,失败的异步任务可能会在任务的同步部分抛出错误之前在内部启动。

It is recommended to listen specifically to the error event to track errors as it may be possible for a traceable action to produce multiple errors. For example, an async task which fails may be started internally before the sync part of the task then throws an error.

asyncStart(event)#
  • 名称:tracing:${name}:asyncStart

    Name: tracing:${name}:asyncStart

asyncStart 事件表示正在到达的可跟踪函数的回调或继续。此时回调参数之类的东西可能可用,或者任何其他表达操作的 "result" 的东西。

The asyncStart event represents the callback or continuation of a traceable function being reached. At this point things like callback arguments may be available, or anything else expressing the "result" of the action.

对于基于回调的函数,回调的第一个参数将分配给 error 字段,如果不是 undefinednull,第二个参数将分配给 result 字段。

For callbacks-based functions, the first argument of the callback will be assigned to the error field, if not undefined or null, and the second argument will be assigned to the result field.

对于 promises,resolve 路径的参数将分配给 result,或者 reject 路径的参数将分配给 error

For promises, the argument to the resolve path will be assigned to result or the argument to the reject path will be assign to error.

建议专门监听 error 事件以跟踪错误,因为可跟踪的操作可能会产生多个错误。例如,失败的异步任务可能会在任务的同步部分抛出错误之前在内部启动。

It is recommended to listen specifically to the error event to track errors as it may be possible for a traceable action to produce multiple errors. For example, an async task which fails may be started internally before the sync part of the task then throws an error.

asyncEnd(event)#
  • 名称:tracing:${name}:asyncEnd

    Name: tracing:${name}:asyncEnd

asyncEnd 事件表示异步函数返回的回调。在 asyncStart 事件之后事件数据不太可能发生变化,但是查看回调完成的时间点可能很有用。

The asyncEnd event represents the callback of an asynchronous function returning. It's not likely event data will change after the asyncStart event, however it may be useful to see the point where the callback completes.

error(event)#
  • 名称:tracing:${name}:error

    Name: tracing:${name}:error

error 事件表示可跟踪函数同步或异步产生的任何错误。如果在跟踪函数的同步部分抛出错误,错误将分配给事件的 error 字段,并触发 error 事件。如果通过回调或 promise 拒绝异步接收到错误,它也将分配给事件的 error 字段并触发 error 事件。

The error event represents any error produced by the traceable function either synchronously or asynchronously. If an error is thrown in the synchronous portion of the traced function the error will be assigned to the error field of the event and the error event will be triggered. If an error is received asynchronously through a callback or promise rejection it will also be assigned to the error field of the event and trigger the error event.

单个可跟踪函数调用可能会多次产生错误,因此在使用此事件时应考虑到这一点。例如,如果另一个异步任务在内部触发失败,然后函数的同步部分抛出错误,将触发两个 error 事件,一个用于同步错误,一个用于异步错误。

It is possible for a single traceable function call to produce errors multiple times so this should be considered when consuming this event. For example, if another async task is triggered internally which fails and then the sync part of the function then throws and error two error events will be emitted, one for the sync error and one for the async error.

内置通道#

Built-in Channels

稳定性: 1 - 实验性的

Stability: 1 - Experimental

虽然 diagnostics_channel API 现在被认为是稳定的,但当前可用的内置通道却不稳定。每个通道都必须独立声明为稳定的。

While the diagnostics_channel API is now considered stable, the built-in channels currently available are not. Each channel must be declared stable independently.

HTTP#

http.client.request.start

当客户端开始请求时触发。

Emitted when client starts a request.

http.client.response.finish

当客户端收到响应时触发。

Emitted when client receives a response.

http.server.request.start

当服务器收到请求时触发。

Emitted when server receives a request.

http.server.response.finish

服务器发送响应时触发。

Emitted when server sends a response.

NET#

net.client.socket

创建新的 TCP 或管道客户端套接字时触发。

Emitted when a new TCP or pipe client socket is created.

net.server.socket

当接收到新的 TCP 或管道连接时触发。

Emitted when a new TCP or pipe connection is received.

UDP#

udp.socket

创建新的 UDP 套接字时触发。

Emitted when a new UDP socket is created.

进程#

Process

child_process

创建新进程时触发。

Emitted when a new process is created.

工作线程#

Worker Thread

worker_threads

创建新线程时触发。

Emitted when a new thread is created.