/** * 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: * * ```js * import diagnostics_channel from '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. * @since v15.1.0, v14.17.0 * @see [source](https://github.com/nodejs/node/blob/v20.2.0/lib/diagnostics_channel.js) */ declare module "diagnostics_channel" { import { AsyncLocalStorage } from "node:async_hooks"; /** * 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. * * This API is optional but helpful when trying to publish messages from very * performance-sensitive code. * * ```js * import diagnostics_channel from 'node:diagnostics_channel'; * * if (diagnostics_channel.hasSubscribers('my-channel')) { * // There are subscribers, prepare and publish message * } * ``` * @since v15.1.0, v14.17.0 * @param name The channel name * @return If there are active subscribers */ function hasSubscribers(name: string | symbol): boolean; /** * 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. * * ```js * import diagnostics_channel from 'node:diagnostics_channel'; * * const channel = diagnostics_channel.channel('my-channel'); * ``` * @since v15.1.0, v14.17.0 * @param name The channel name * @return The named channel object */ function channel(name: string | symbol): Channel; type ChannelListener = (message: unknown, name: string | symbol) => void; /** * 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'`. * * ```js * import diagnostics_channel from 'node:diagnostics_channel'; * * diagnostics_channel.subscribe('my-channel', (message, name) => { * // Received data * }); * ``` * @since v18.7.0, v16.17.0 * @param name The channel name * @param onMessage The handler to receive channel messages */ function subscribe(name: string | symbol, onMessage: ChannelListener): void; /** * Remove a message handler previously registered to this channel with {@link subscribe}. * * ```js * 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); * ``` * @since v18.7.0, v16.17.0 * @param name The channel name * @param onMessage The previous subscribed handler to remove * @return `true` if the handler was found, `false` otherwise. */ function unsubscribe(name: string | symbol, onMessage: ChannelListener): boolean; /** * 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`. * * ```js * 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'), * }); * ``` * @since v19.9.0 * @experimental * @param nameOrChannels Channel name or object containing all the `TracingChannel Channels` * @return Collection of channels to trace with */ function tracingChannel< StoreType = unknown, ContextType extends object = StoreType extends object ? StoreType : object, >( nameOrChannels: string | TracingChannelCollection, ): TracingChannel; /** * 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 {@link channel}, constructing a channel directly * with `new Channel(name)` is not supported. * @since v15.1.0, v14.17.0 */ class Channel { readonly name: string | symbol; /** * Check if there are active subscribers to this channel. This is helpful if * the message you want to send might be expensive to prepare. * * This API is optional but helpful when trying to publish messages from very * performance-sensitive code. * * ```js * import diagnostics_channel from 'node:diagnostics_channel'; * * const channel = diagnostics_channel.channel('my-channel'); * * if (channel.hasSubscribers) { * // There are subscribers, prepare and publish message * } * ``` * @since v15.1.0, v14.17.0 */ readonly hasSubscribers: boolean; private constructor(name: string | symbol); /** * Publish a message to any subscribers to the channel. This will trigger * message handlers synchronously so they will execute within the same context. * * ```js * import diagnostics_channel from 'node:diagnostics_channel'; * * const channel = diagnostics_channel.channel('my-channel'); * * channel.publish({ * some: 'message', * }); * ``` * @since v15.1.0, v14.17.0 * @param message The message to send to the channel subscribers */ publish(message: unknown): void; /** * 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'`. * * ```js * import diagnostics_channel from 'node:diagnostics_channel'; * * const channel = diagnostics_channel.channel('my-channel'); * * channel.subscribe((message, name) => { * // Received data * }); * ``` * @since v15.1.0, v14.17.0 * @deprecated Since v18.7.0,v16.17.0 - Use {@link subscribe(name, onMessage)} * @param onMessage The handler to receive channel messages */ subscribe(onMessage: ChannelListener): void; /** * Remove a message handler previously registered to this channel with `channel.subscribe(onMessage)`. * * ```js * 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); * ``` * @since v15.1.0, v14.17.0 * @deprecated Since v18.7.0,v16.17.0 - Use {@link unsubscribe(name, onMessage)} * @param onMessage The previous subscribed handler to remove * @return `true` if the handler was found, `false` otherwise. */ unsubscribe(onMessage: ChannelListener): void; /** * 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. * * ```js * 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 }; * }); * ``` * @since v19.9.0 * @experimental * @param store The store to which to bind the context data * @param transform Transform context data before setting the store context */ bindStore(store: AsyncLocalStorage, transform?: (context: ContextType) => StoreType): void; /** * Remove a message handler previously registered to this channel with `channel.bindStore(store)`. * * ```js * 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); * ``` * @since v19.9.0 * @experimental * @param store The store to unbind from the channel. * @return `true` if the store was found, `false` otherwise. */ unbindStore(store: any): void; /** * 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. * * 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. * * ```js * 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' }) * }); * ``` * @since v19.9.0 * @experimental * @param context Message to send to subscribers and bind to stores * @param fn Handler to run within the entered storage context * @param thisArg The receiver to be used for the function call. * @param args Optional arguments to pass to the function. */ runStores(): void; } interface TracingChannelSubscribers { start: (message: ContextType) => void; end: ( message: ContextType & { error?: unknown; result?: unknown; }, ) => void; asyncStart: ( message: ContextType & { error?: unknown; result?: unknown; }, ) => void; asyncEnd: ( message: ContextType & { error?: unknown; result?: unknown; }, ) => void; error: ( message: ContextType & { error: unknown; }, ) => void; } interface TracingChannelCollection { start: Channel; end: Channel; asyncStart: Channel; asyncEnd: Channel; error: Channel; } /** * 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.{@link 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. * @since v19.9.0 * @experimental */ class TracingChannel implements TracingChannelCollection { start: Channel; end: Channel; asyncStart: Channel; asyncEnd: Channel; error: Channel; /** * Helper to subscribe a collection of functions to the corresponding channels. * This is the same as calling `channel.subscribe(onMessage)` on each channel * individually. * * ```js * 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 * }, * }); * ``` * @since v19.9.0 * @experimental * @param subscribers Set of `TracingChannel Channels` subscribers */ subscribe(subscribers: TracingChannelSubscribers): void; /** * Helper to unsubscribe a collection of functions from the corresponding channels. * This is the same as calling `channel.unsubscribe(onMessage)` on each channel * individually. * * ```js * 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 * }, * }); * ``` * @since v19.9.0 * @experimental * @param subscribers Set of `TracingChannel Channels` subscribers * @return `true` if all handlers were successfully unsubscribed, and `false` otherwise. */ unsubscribe(subscribers: TracingChannelSubscribers): void; /** * 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. * * ```js * import diagnostics_channel from 'node:diagnostics_channel'; * * const channels = diagnostics_channel.tracingChannel('my-channel'); * * channels.traceSync(() => { * // Do something * }, { * some: 'thing', * }); * ``` * @since v19.9.0 * @experimental * @param fn Function to wrap a trace around * @param context Shared object to correlate events through * @param thisArg The receiver to be used for the function call * @param args Optional arguments to pass to the function * @return The return value of the given function */ traceSync( fn: (this: ThisArg, ...args: Args) => any, context?: ContextType, thisArg?: ThisArg, ...args: Args ): void; /** * 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. * * ```js * import diagnostics_channel from 'node:diagnostics_channel'; * * const channels = diagnostics_channel.tracingChannel('my-channel'); * * channels.tracePromise(async () => { * // Do something * }, { * some: 'thing', * }); * ``` * @since v19.9.0 * @experimental * @param fn Promise-returning function to wrap a trace around * @param context Shared object to correlate trace events through * @param thisArg The receiver to be used for the function call * @param args Optional arguments to pass to the function * @return Chained from promise returned by the given function */ tracePromise( fn: (this: ThisArg, ...args: Args) => Promise, context?: ContextType, thisArg?: ThisArg, ...args: Args ): void; /** * 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. * * The `position` will be -1 by default to indicate the final argument should * be used as the callback. * * ```js * 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); * ``` * * The callback will also be run with `channel.runStores(context, ...)` which * enables context loss recovery in some cases. * * ```js * 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; * }); * ``` * @since v19.9.0 * @experimental * @param fn callback using function to wrap a trace around * @param position Zero-indexed argument position of expected callback * @param context Shared object to correlate trace events through * @param thisArg The receiver to be used for the function call * @param args Optional arguments to pass to the function * @return The return value of the given function */ traceCallback any>( fn: Fn, position: number | undefined, context: ContextType | undefined, thisArg: any, ...args: Parameters ): void; } } declare module "node:diagnostics_channel" { export * from "diagnostics_channel"; }