诊断通道
History
diagnostics_channel 现在是稳定的。
稳定性:2 - 稳定
node:diagnostics_channel 模块提供了一个 API,用于创建命名通道,以便出于诊断目的报告任意消息数据。
可以通过以下方式访问它:
import diagnostics_channel from 'node:diagnostics_channel';
const diagnostics_channel = require('node:diagnostics_channel');
希望报告诊断消息的模块作者应该创建一个或多个顶层通道来报告消息。通道也可以在运行时获取,但由于这样做的额外开销,不建议这样做。通道可以为了方便而导出,但只要知道名称,就可以在任何地方获取。
如果你打算让你的模块生成供他人使用的诊断数据,建议你包含所使用的命名通道以及消息数据形状的文档。通道名称通常应包括模块名称,以避免与其他模块的数据冲突。
以下是公共 API 的简要概述。
import diagnostics_channel from 'node:diagnostics_channel'; // 获取可重用的通道对象 const channel = diagnostics_channel.channel('my-channel'); function onMessage(message, name) { // 接收到的数据 } // 订阅通道 diagnostics_channel.subscribe('my-channel', onMessage); // 检查通道是否有活跃订阅者 if (channel.hasSubscribers) { // 向通道发布数据 channel.publish({ some: 'data', }); } // 取消订阅通道 diagnostics_channel.unsubscribe('my-channel', onMessage);
const diagnostics_channel = require('node:diagnostics_channel'); // 获取可重用的通道对象 const channel = diagnostics_channel.channel('my-channel'); function onMessage(message, name) { // 接收到的数据 } // 订阅通道 diagnostics_channel.subscribe('my-channel', onMessage); // 检查通道是否有活跃订阅者 if (channel.hasSubscribers) { // 向通道发布数据 channel.publish({ some: 'data', }); } // 取消订阅通道 diagnostics_channel.unsubscribe('my-channel', onMessage);
diagnostics_channel.hasSubscribers(name): void
检查命名通道是否有活跃订阅者。如果你要发送的消息准备开销可能很大,这很有帮助。
此 API 是可选的,但在尝试从对性能非常敏感的代码发布消息时很有帮助。
import diagnostics_channel from 'node:diagnostics_channel'; if (diagnostics_channel.hasSubscribers('my-channel')) { // 存在订阅者,准备并发布消息 }
const diagnostics_channel = require('node:diagnostics_channel'); if (diagnostics_channel.hasSubscribers('my-channel')) { // 存在订阅者,准备并发布消息 }
diagnostics_channel(name): void
这是任何想要发布到命名通道的人的主要入口点。它会生成一个通道对象,并尽可能优化,以减少发布时的开销。
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): void
注册消息处理函数以订阅此通道。每当消息发布到通道时,此消息处理函数将同步运行。消息处理函数中抛出的任何错误都将触发一个 'uncaughtException'.
import diagnostics_channel from 'node:diagnostics_channel'; diagnostics_channel.subscribe('my-channel', (message, name) => { // 接收到的数据 });
const diagnostics_channel = require('node:diagnostics_channel'); diagnostics_channel.subscribe('my-channel', (message, name) => { // 接收到的数据 });
diagnostics_channel.unsubscribe(name, onMessage): void
移除之前使用 diagnostics_channel.subscribe(name, onMessage) 注册到此通道的消息处理函数。
import diagnostics_channel from 'node:diagnostics_channel'; function onMessage(message, name) { // 接收到的数据 } diagnostics_channel.subscribe('my-channel', onMessage); diagnostics_channel.unsubscribe('my-channel', onMessage);
const diagnostics_channel = require('node:diagnostics_channel'); function onMessage(message, name) { // 接收到的数据 } diagnostics_channel.subscribe('my-channel', onMessage); diagnostics_channel.unsubscribe('my-channel', onMessage);
diagnostics_channel.tracingChannel
History
Marked as stable.
diagnostics_channel.tracingChannel(nameOrChannels): void
稳定性:2 - 稳定
- 创建:
string | TracingChannel通道名称或包含所有 TracingChannel 通道 的对象 - 返回:
TracingChannel用于追踪的通道集合
为给定的 TracingChannel 通道 创建一个 TracingChannel 包装器。如果给定名称,将以 tracing:${name}:${eventType} 的形式创建相应的追踪通道,其中 eventType 对应于 TracingChannel 通道 的类型。
import diagnostics_channel from 'node:diagnostics_channel'; const channelsByName = diagnostics_channel.tracingChannel('my-channel'); // 或... 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'); // 或... 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'), });
diagnostics_channel.boundedChannel(nameOrChannels): void
稳定性:1 - 实验性
string | BoundedChannel为给定的通道创建一个 BoundedChannel 包装器。如果给定名称,将以 tracing:${name}:${eventType} 的形式创建相应的通道,其中 eventType 为 start 或 end。
BoundedChannel 是 TracingChannel 的简化版本,仅追踪同步操作。它只有 start 和 end 事件,没有 asyncStart、asyncEnd 或 error 事件,使其适合追踪不涉及异步延续或错误处理的操作。
import { boundedChannel, channel } from 'node:diagnostics_channel'; const wc = boundedChannel('my-operation'); // 或... const wc2 = boundedChannel({ start: channel('tracing:my-operation:start'), end: channel('tracing:my-operation:end'), });
const { boundedChannel, channel } = require('node:diagnostics_channel'); const wc = boundedChannel('my-operation'); // 或... const wc2 = boundedChannel({ start: channel('tracing:my-operation:start'), end: channel('tracing:my-operation:end'), });
类:Channel
History
Channel 类表示数据管道中的一个独立命名通道。它用于跟踪订阅者,并在存在订阅者时发布消息。它作为一个单独的对象存在,以避免在发布时进行通道查找,从而实现非常快的发布速度,并允许大量使用而产生极小的开销。通道是使用 diagnostics_channel.channel(name) 创建的,不支持直接使用 new Channel(name) 构造通道。
- 返回:
boolean如果存在活跃订阅者
检查此通道是否有活跃订阅者。如果你要发送的消息准备开销可能很大,这会很有帮助。
此 API 是可选的,但在尝试从对性能非常敏感的代码发布消息时很有帮助。
import diagnostics_channel from 'node:diagnostics_channel'; const channel = diagnostics_channel.channel('my-channel'); if (channel.hasSubscribers) { // 存在订阅者,准备并发布消息 }
const diagnostics_channel = require('node:diagnostics_channel'); const channel = diagnostics_channel.channel('my-channel'); if (channel.hasSubscribers) { // 存在订阅者,准备并发布消息 }
channel.publish(message): void
任意向通道的任何订阅者发布消息。这将同步触发消息处理函数,因此它们将在同一上下文中执行。
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): void
注册消息处理函数以订阅此通道。每当消息发布到通道时,此消息处理函数将同步运行。消息处理函数中抛出的任何错误都将触发一个 'uncaughtException'。
import diagnostics_channel from 'node:diagnostics_channel'; const channel = diagnostics_channel.channel('my-channel'); channel.subscribe((message, name) => { // 接收到的数据 });
const diagnostics_channel = require('node:diagnostics_channel'); const channel = diagnostics_channel.channel('my-channel'); channel.subscribe((message, name) => { // 接收到的数据 });
channel.unsubscribe
History
弃用已撤销。
仅文档弃用。
添加了返回值。添加到没有订阅者的通道。
channel.unsubscribe(onMessage): void
Function移除之前使用 channel.subscribe(onMessage) 注册到此通道的消息处理函数。
import diagnostics_channel from 'node:diagnostics_channel'; const channel = diagnostics_channel.channel('my-channel'); function onMessage(message, name) { // 接收到的数据 } channel.subscribe(onMessage); channel.unsubscribe(onMessage);
const diagnostics_channel = require('node:diagnostics_channel'); const channel = diagnostics_channel.channel('my-channel'); function onMessage(message, name) { // 接收到的数据 } channel.subscribe(onMessage); channel.unsubscribe(onMessage);
channel.bindStore(store, transform?): void
稳定性:1 - 实验性
AsyncLocalStorageFunction当调用 channel.runStores(context, ...) 时,给定的上下文数据将应用于绑定到通道的任何存储。如果存储已经绑定,之前的 transform 函数将被新的替换。可以省略 transform 函数以直接将给定的上下文数据设置为上下文。
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): void
稳定性:1 - 实验性
AsyncLocalStorage移除之前使用 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?): void
稳定性:1 - 实验性
将给定数据应用于绑定到通道的任何 AsyncLocalStorage 实例,持续给定函数的执行期间,然后在数据应用于存储的范围内发布到通道。
如果给 channel.bindStore(store) 提供了 transform 函数,它将在消息数据成为存储的上下文值之前应用于转换消息数据。在需要上下文链接的情况下,先前的存储上下文可在 transform 函数内访问。
应用于存储的上下文应在从给定函数开始执行的任何异步代码中可访问,但在某些情况下可能会发生 上下文丢失。
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' }) });
channel.withStoreScope(data): void
稳定性:1 - 实验性
any创建一个可处置的作用域,将给定数据绑定到绑定到通道的任何 AsyncLocalStorage 实例,并发布给订阅者。处置时,作用域自动恢复先前的存储上下文。
此方法启用使用 JavaScript 的显式资源管理(using 语法与 Symbol.dispose)来管理存储上下文而无需闭包包装。
import { channel } from 'node:diagnostics_channel'; import { AsyncLocalStorage } from 'node:async_hooks'; const store = new AsyncLocalStorage(); const ch = channel('my-channel'); ch.bindStore(store, (message) => { return { ...message, timestamp: Date.now() }; }); { using scope = ch.withStoreScope({ request: 'data' }); // 存储已进入,数据已发布 console.log(store.getStore()); // { request: 'data', timestamp: ... } } // 存储已在作用域退出时自动恢复
const { channel } = require('node:diagnostics_channel'); const { AsyncLocalStorage } = require('node:async_hooks'); const store = new AsyncLocalStorage(); const ch = channel('my-channel'); ch.bindStore(store, (message) => { return { ...message, timestamp: Date.now() }; }); { using scope = ch.withStoreScope({ request: 'data' }); // 存储已进入,数据已发布 console.log(store.getStore()); // { request: 'data', timestamp: ... } } // 存储已在作用域退出时自动恢复
类:RunStoresScope
History
稳定性:1 - 实验性
RunStoresScope 类代表由 channel.withStoreScope(data) 创建的可处置作用域。它管理存储上下文的生命周期,并确保它们在作用域退出时被正确恢复。
必须与 using 语法一起使用作用域以确保正确处置。
类:TracingChannel
History
Marked as stable.
稳定性:2 - 稳定
TracingChannel 类是 [TracingChannel Channels][] 的集合,这些通道共同表示单个可追踪操作。它用于规范化并简化生成用于追踪应用程序流程的事件的过程。
使用 diagnostics_channel.tracingChannel() 构造 TracingChannel。与 Channel 一样,建议在文件顶层创建并复用单个 TracingChannel,而不是动态创建它们。
tracingChannel.subscribe(subscribers): void
ObjectFunctionasyncStart 事件
订阅者FunctionasyncEnd 事件
订阅者用于将函数集合订阅到相应通道的辅助函数。这与在每个通道上单独调用 channel.subscribe(onMessage) 相同。
import diagnostics_channel from 'node:diagnostics_channel'; const channels = diagnostics_channel.tracingChannel('my-channel'); channels.subscribe({ start(message) { // 处理 start 消息 }, end(message) { // 处理 end 消息 }, asyncStart(message) { // 处理 asyncStart 消息 }, asyncEnd(message) { // 处理 asyncEnd 消息 }, error(message) { // 处理 error 消息 }, });
const diagnostics_channel = require('node:diagnostics_channel'); const channels = diagnostics_channel.tracingChannel('my-channel'); channels.subscribe({ start(message) { // 处理 start 消息 }, end(message) { // 处理 end 消息 }, asyncStart(message) { // 处理 asyncStart 消息 }, asyncEnd(message) { // 处理 asyncEnd 消息 }, error(message) { // 处理 error 消息 }, });
tracingChannel.unsubscribe(subscribers): void
ObjectFunctionasyncStart 事件
订阅者FunctionasyncEnd 事件
订阅者用于从相应通道取消订阅函数集合的辅助函数。这与在每个通道上单独调用 channel.unsubscribe(onMessage) 相同。
import diagnostics_channel from 'node:diagnostics_channel'; const channels = diagnostics_channel.tracingChannel('my-channel'); channels.unsubscribe({ start(message) { // 处理 start 消息 }, end(message) { // 处理 end 消息 }, asyncStart(message) { // 处理 asyncStart 消息 }, asyncEnd(message) { // 处理 asyncEnd 消息 }, error(message) { // 处理 error 消息 }, });
const diagnostics_channel = require('node:diagnostics_channel'); const channels = diagnostics_channel.tracingChannel('my-channel'); channels.unsubscribe({ start(message) { // 处理 start 消息 }, end(message) { // 处理 end 消息 }, asyncStart(message) { // 处理 asyncStart 消息 }, asyncEnd(message) { // 处理 asyncEnd 消息 }, error(message) { // 处理 error 消息 }, });
tracingChannel.traceSync(fn, context?, thisArg?, ...args?): void
追踪同步函数调用。这将始终在执行周围产生 start 事件 和 end 事件,如果给定函数抛出错误,可能会产生 error 事件。这将在 start 通道上使用 channel.runStores(context, ...) 运行给定函数,确保所有事件都将任何绑定的存储设置为与此追踪上下文匹配。
为确保只形成正确的追踪图,只有在开始追踪之前存在订阅者时才会发布事件。在追踪开始后添加的订阅将不会接收来自该追踪的未来事件,只会看到未来的追踪。
import diagnostics_channel from 'node:diagnostics_channel'; const channels = diagnostics_channel.tracingChannel('my-channel'); channels.traceSync(() => { // 做点什么 }, { some: 'thing', });
const diagnostics_channel = require('node:diagnostics_channel'); const channels = diagnostics_channel.tracingChannel('my-channel'); channels.traceSync(() => { // 做点什么 }, { some: 'thing', });
tracingChannel.tracePromise
History
非原生 Promise 的 thenable 现在会按原样返回, 保留其原始类型和方法。
非 thenable 将在返回时发出警告。
tracingChannel.tracePromise(fn, context?, thisArg?, ...args?): void
追踪返回 Promise 或 thenable 对象 的异步函数调用。这将始终在函数执行的同步部分周围产生 start 事件 和 end 事件,并在返回的 promise 被解决或拒绝时产生 asyncStart 事件 和 asyncEnd 事件。如果给定函数抛出错误或返回的 promise 被拒绝,也可能产生 error 事件。这将在 start 通道上使用 channel.runStores(context, ...) 运行给定函数,确保所有事件都将任何绑定的存储设置为匹配此追踪上下文。
如果 fn 返回的值不是 Promise 或 thenable,则将其返回并带有警告,并且不会产生 asyncStart 或 asyncEnd 事件。
为确保只形成正确的追踪图,只有在开始追踪之前存在订阅者时才会发布事件。在追踪开始后添加的订阅将不会接收来自该追踪的未来事件,只会看到未来的追踪。
import diagnostics_channel from 'node:diagnostics_channel'; const channels = diagnostics_channel.tracingChannel('my-channel'); channels.tracePromise(async () => { // 做点什么 }, { some: 'thing', });
const diagnostics_channel = require('node:diagnostics_channel'); const channels = diagnostics_channel.tracingChannel('my-channel'); channels.tracePromise(async () => { // 做点什么 }, { some: 'thing', });
tracingChannel.traceCallback(fn, position?, context?, thisArg?, ...args?): void
追踪接收回调的函数调用。预期回调遵循错误作为第一个参数的约定。这将始终在函数执行的同步部分周围产生 start 事件 和 end 事件,并在回调执行周围产生 asyncStart 事件 和 asyncEnd 事件。如果给定函数抛出或传递给回调的第一个参数被设置,也可能产生 error 事件。这将在 start 通道上使用 channel.runStores(context, ...) 运行给定函数,确保所有事件都将任何绑定的存储设置为与此追踪上下文匹配。
为确保只形成正确的追踪图,只有在开始追踪之前存在订阅者时才会发布事件。在追踪开始后添加的订阅将不会接收来自该追踪的未来事件,只会看到未来的追踪。
import diagnostics_channel from 'node:diagnostics_channel'; const channels = diagnostics_channel.tracingChannel('my-channel'); channels.traceCallback((arg1, callback) => { // 做点什么 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) => { // 做点什么 callback(null, 'result'); }, 1, { some: 'thing', }, thisArg, arg1, callback);
回调也将使用 channel.runStores(context, ...) 运行,这在某些情况下启用上下文丢失恢复。
import diagnostics_channel from 'node:diagnostics_channel'; import { AsyncLocalStorage } from 'node:async_hooks'; const channels = diagnostics_channel.tracingChannel('my-channel'); const myStore = new AsyncLocalStorage(); // start 通道将初始存储数据设置为某物 // 并将该存储数据值存储在追踪上下文对象上 channels.start.bindStore(myStore, (data) => { const span = new Span(data); data.span = span; return span; }); // 然后 asyncStart 可以从之前存储的数据中恢复 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(); // start 通道将初始存储数据设置为某物 // 并将该存储数据值存储在追踪上下文对象上 channels.start.bindStore(myStore, (data) => { const span = new Span(data); data.span = span; return span; }); // 然后 asyncStart 可以从之前存储的数据中恢复 channels.asyncStart.bindStore(myStore, (data) => { return data.span; });
- 返回:
boolean如果任何独立通道有订阅者则为true,否则为false。
这是 TracingChannel 实例上可用的辅助方法,用于检查是否有任何 TracingChannel 通道 有订阅者。如果其中任何一个至少有一个订阅者则返回 true,否则返回 false。
import diagnostics_channel from 'node:diagnostics_channel'; const channels = diagnostics_channel.tracingChannel('my-channel'); if (channels.hasSubscribers) { // 做点什么 }
const diagnostics_channel = require('node:diagnostics_channel'); const channels = diagnostics_channel.tracingChannel('my-channel'); if (channels.hasSubscribers) { // 做点什么 }
类:BoundedChannel
History
稳定性:1 - 实验性
BoundedChannel 类是 TracingChannel 的简化版本,仅追踪同步操作。它由两个通道(start 和 end)组成,而不是五个,省略了 asyncStart、asyncEnd 和 error 事件。这使其适合追踪不涉及异步延续或错误处理的操作。
与 TracingChannel 一样,建议在文件顶层创建并重用单个 BoundedChannel,而不是动态创建它们。
- 返回:
boolean如果任何独立通道有订阅者则为true,否则为false。
检查任何 start 或 end 通道是否有订阅者。
import { boundedChannel } from 'node:diagnostics_channel'; const wc = boundedChannel('my-operation'); if (wc.hasSubscribers) { // 存在订阅者,执行追踪操作 }
const { boundedChannel } = require('node:diagnostics_channel'); const wc = boundedChannel('my-operation'); if (wc.hasSubscribers) { // 存在订阅者,执行追踪操作 }
boundedChannel.subscribe(handlers): void
订阅有界通道事件。这与在每个通道上单独调用 channel.subscribe(onMessage) 等效。
import { boundedChannel } from 'node:diagnostics_channel'; const wc = boundedChannel('my-operation'); wc.subscribe({ start(message) { // 处理 start }, end(message) { // 处理 end }, });
const { boundedChannel } = require('node:diagnostics_channel'); const wc = boundedChannel('my-operation'); wc.subscribe({ start(message) { // 处理 start }, end(message) { // 处理 end }, });
boundedChannel.unsubscribe(handlers): void
取消订阅有界通道事件。这与在每个通道上单独调用 channel.unsubscribe(onMessage) 等效。
import { boundedChannel } from 'node:diagnostics_channel'; const wc = boundedChannel('my-operation'); const handlers = { start(message) {}, end(message) {}, }; wc.subscribe(handlers); wc.unsubscribe(handlers);
const { boundedChannel } = require('node:diagnostics_channel'); const wc = boundedChannel('my-operation'); const handlers = { start(message) {}, end(message) {}, }; wc.subscribe(handlers); wc.unsubscribe(handlers);
boundedChannel.run(context, fn, thisArg?, ...args?): void
追踪同步函数调用。这将在执行周围产生 start 事件和 end 事件。这将在 start 通道上使用 channel.runStores(context, ...) 运行给定函数,确保所有事件都将任何绑定的存储设置为匹配此追踪上下文。
import { boundedChannel } from 'node:diagnostics_channel'; const wc = boundedChannel('my-operation'); const result = wc.run({ operationId: '123' }, () => { // 执行操作 return 42; });
const { boundedChannel } = require('node:diagnostics_channel'); const wc = boundedChannel('my-operation'); const result = wc.run({ operationId: '123' }, () => { // 执行操作 return 42; });
boundedChannel.withScope(context?): void
Object创建一个可处置的作用域,用于使用 JavaScript 的显式资源管理(using 语法)追踪同步操作。作用域自动发布 start 和 end 事件,进入绑定的存储,并在处置时处理清理。
import { boundedChannel } from 'node:diagnostics_channel'; const wc = boundedChannel('my-operation'); const context = { operationId: '123' }; { using scope = wc.withScope(context); // 存储已进入,start 事件已发布 // 执行工作并在上下文上设置结果 context.result = 42; } // End 事件已发布,存储已自动恢复
const { boundedChannel } = require('node:diagnostics_channel'); const wc = boundedChannel('my-operation'); const context = { operationId: '123' }; { using scope = wc.withScope(context); // 存储已进入,start 事件已发布 // 执行工作并在上下文上设置结果 context.result = 42; } // End 事件已发布,存储已自动恢复
类:BoundedChannelScope
History
稳定性:1 - 实验性
BoundedChannelScope 类代表由 boundedChannel.withScope(context) 创建的可处置作用域。它管理追踪操作的生命周期,自动发布事件和管理存储上下文。
必须与 using 语法一起使用作用域以确保正确处置。
import { boundedChannel } from 'node:diagnostics_channel'; const wc = boundedChannel('my-operation'); const context = {}; { using scope = wc.withScope(context); // Start 事件已发布,存储已进入 context.result = performOperation(); // End 事件在块结束时自动发布 }
const { boundedChannel } = require('node:diagnostics_channel'); const wc = boundedChannel('my-operation'); const context = {}; { using scope = wc.withScope(context); // Start 事件已发布,存储已进入 context.result = performOperation(); // End 事件在块结束时自动发布 }
BoundedChannel 由两个诊断通道组成,表示使用 using 语法创建的作用域的生命周期:
tracing:${name}:start- 当using语句执行时发布(作用域创建)tracing:${name}:end- 当退出块时发布(作用域处置)
当使用 using 语法与 [boundedChannel.withScope([context])][] 时,start 事件在语句执行时立即发布,end 事件在块结束时发生处置时自动发布。所有事件共享相同的上下文对象,可以在作用域执行期间用附加属性如 result 扩展。
TracingChannel 是若干 diagnostics_channels 的集合,表示单个可跟踪操作的执行生命周期中的特定点。行为分为五个 diagnostics_channels,由 start、end、asyncStart、asyncEnd 和 error 组成。单个可跟踪操作将在所有事件之间共享相同的事件对象,这对于通过 weakmap 管理关联可能很有帮助。
当任务“完成”时,这些事件对象将扩展 result 或 error 值。对于同步任务,result 将是返回值,error 将是函数抛出的任何内容。对于基于回调的异步函数,result 将是回调的第二个参数,而 error 将是 end 事件中可见的抛出错误,或 asyncStart 或 asyncEnd 事件中的第一个回调参数。
为确保只形成正确的跟踪图,只有在开始跟踪之前存在订阅者时才应发布事件。在跟踪开始后添加的订阅不应接收来自该跟踪的未来事件,只会看到未来的跟踪。
跟踪通道应遵循以下命名模式:
tracing:module.class.method:start或tracing:module.function:starttracing:module.class.method:end或tracing:module.function:endtracing:module.class.method:asyncStart或tracing:module.function:asyncStarttracing:module.class.method:asyncEnd或tracing:module.function:asyncEndtracing:module.class.method:error或tracing:module.function:error
start(event): void
- 名称:
tracing:${name}:start
start 事件表示函数被调用的点。此时事件数据可能包含函数参数或函数执行开始时可用的任何其他内容。
end
end(event): void
- 名称:
tracing:${name}:end
end 事件表示函数调用返回值的点。对于异步函数,这是当 promise 返回时,而不是函数内部执行 return 语句时。此时,如果跟踪的函数是同步的,result 字段将设置为函数的返回值。或者,error 字段可能存在以表示任何抛出的错误。
建议专门监听 error 事件以跟踪错误,因为可跟踪的操作可能会产生多个错误。例如,失败的异步任务可能在任务的同步部分抛出错误之前就在内部启动了。
asyncStart(event): void
- 名称:
tracing:${name}:asyncStart
asyncStart 事件表示到达可跟踪函数的回调或延续。此时回调参数等内容可能可用,或表达操作“结果”的任何其他内容。
对于基于回调的函数,回调的第一个参数将分配给 error 字段(如果不是 undefined 或 null),第二个参数将分配给 result 字段。
对于 promises,resolve 路径的参数将分配给 result,或 reject 路径的参数将分配给 error。
建议专门监听 error 事件以跟踪错误,因为可跟踪的操作可能会产生多个错误。例如,失败的异步任务可能在任务的同步部分抛出错误之前就在内部启动了。
asyncEnd(event): void
- 名称:
tracing:${name}:asyncEnd
asyncEnd 事件表示异步函数的回调返回。asyncStart 事件后事件数据不太可能更改,但查看回调完成的点可能很有用。
error(event): void
- 名称:
tracing:${name}:error
error 事件表示可跟踪函数同步或异步产生的任何错误。如果在跟踪函数的同步部分抛出错误,错误将分配给事件的 error 字段,并且将触发 error 事件。如果通过回调或 promise 拒绝异步接收错误,它也将分配给事件的 error 字段,并触发 error 事件。
单个可跟踪函数调用可能多次产生错误,因此在消费此事件时应考虑这一点。例如,如果内部触发了另一个失败的异步任务,然后函数的同步部分抛出错误,将发出两个 error 事件,一个用于同步错误,一个用于异步错误。
稳定性:1 - 实验性
any[]当调用 console.log() 时发出。接收传递给 console.log() 的参数数组。
any[]当调用 console.info() 时发出。接收传递给 console.info() 的参数数组。
any[]当调用 console.debug() 时发出。接收传递给 console.debug() 的参数数组。
any[]当调用 console.warn() 时发出。接收传递给 console.warn() 的参数数组。
any[]当调用 console.error() 时发出。接收传递给 console.error() 的参数数组。
稳定性:1 - 实验性
http.ClientRequest当客户端创建请求对象时发出。
与 http.client.request.start 不同,此事件在请求发送之前发出。
http.ClientRequest当客户端启动请求时发出。
http.ClientRequestError当客户端请求期间发生错误时发出。
http.ClientRequesthttp.IncomingMessage当客户端接收响应时发出。
当服务器接收请求时发出。
http.IncomingMessagehttp.ServerResponse当服务器创建响应时发出。 该事件在响应发送之前发出。
当服务器发送响应时发出。
稳定性:1 - 实验性
ClientHttp2StreamHTTP/2 Headers Object当客户端创建流时发出。
ClientHttp2StreamHTTP/2 Headers Object当客户端启动流时发出。
ClientHttp2StreamError当客户端处理流期间发生错误时发出。
当客户端接收流时发出。
当发送客户端流主体的一块时发出。
ClientHttp2Stream在客户端流主体完全发送后发出。
ClientHttp2Stream当客户端关闭流时发出。关闭流时使用的 HTTP/2 错误代码可以使用 stream.rstCode 属性检索。
ServerHttp2StreamHTTP/2 Headers Object当服务器创建流时发出。
ServerHttp2StreamHTTP/2 Headers Object当服务器启动流时发出。
ServerHttp2StreamError当服务器处理流期间发生错误时发出。
当服务器发送流时发出。
ServerHttp2Stream当服务器关闭流时发出。关闭流时使用的 HTTP/2 错误代码可以使用 stream.rstCode 属性检索。
稳定性:1 - 实验性
当执行 require() 时发出。参见 start 事件。
当 require() 调用返回时发出。参见 end 事件。
当 require() 抛出错误时发出。参见 error 事件。
当调用 import() 时发出。参见 asyncStart 事件。
当 import() 完成时发出。参见 asyncEnd 事件。
当 import() 抛出错误时发出。参见 error 事件。
稳定性:1 - 实验性
net.Socket | tls.TLSSocket当创建新的 TCP 或管道客户端套接字连接时发出。
net.Socket当接收新的 TCP 或管道连接时发出。
net.ServerObject当调用 net.Server.listen() 时发出,在端口或管道实际设置之前。
net.Server当 net.Server.listen() 完成时发出,因此服务器准备好接受连接。
net.ServerError当 net.Server.listen() 返回错误时发出。
稳定性:1 - 实验性
dgram.Socket当创建新的 UDP 套接字时发出。
进程
History
稳定性:1 - 实验性
ChildProcess当创建新进程时发出。
tracing:child_process.spawn:start
ChildProcessObject当调用 child_process.spawn() 时发出,在实际生成进程之前。
tracing:child_process.spawn:end
ChildProcess当 child_process.spawn() 成功完成且进程已创建时发出。
tracing:child_process.spawn:error
ChildProcessError当 child_process.spawn() 遇到错误时发出。
当调用 process.execve() 时发出。
Web 锁
History
稳定性:1 - 实验性
每次调用 locks.request() 时都会发出这些通道。有关 Web 锁的详细信息,请参阅 worker_threads.locks。
当启动锁请求时发出,在授予锁之前。
当成功授予锁且回调即将运行时发出。
当 ifAvailable 为 true 且锁不可立即使用时发出,此时请求回调被调用时传入 null 而不是 Lock 对象。
当锁请求完成时发出,无论回调成功、抛出错误还是锁被窃取。
工作线程
History
稳定性:1 - 实验性
Worker当创建新线程时发出。