• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Diagnostics Channel
2
3<!-- YAML
4added:
5  - v15.1.0
6  - v14.17.0
7changes:
8  - version: v18.13.0
9    pr-url: https://github.com/nodejs/node/pull/45290
10    description: diagnostics_channel is now Stable.
11-->
12
13<!--introduced_in=v15.1.0-->
14
15> Stability: 2 - Stable
16
17<!-- source_link=lib/diagnostics_channel.js -->
18
19The `node:diagnostics_channel` module provides an API to create named channels
20to report arbitrary message data for diagnostics purposes.
21
22It can be accessed using:
23
24```mjs
25import diagnostics_channel from 'node:diagnostics_channel';
26```
27
28```cjs
29const diagnostics_channel = require('node:diagnostics_channel');
30```
31
32It is intended that a module writer wanting to report diagnostics messages
33will create one or many top-level channels to report messages through.
34Channels may also be acquired at runtime but it is not encouraged
35due to the additional overhead of doing so. Channels may be exported for
36convenience, but as long as the name is known it can be acquired anywhere.
37
38If you intend for your module to produce diagnostics data for others to
39consume it is recommended that you include documentation of what named
40channels are used along with the shape of the message data. Channel names
41should generally include the module name to avoid collisions with data from
42other modules.
43
44## Public API
45
46### Overview
47
48Following is a simple overview of the public API.
49
50```mjs
51import diagnostics_channel from 'node:diagnostics_channel';
52
53// Get a reusable channel object
54const channel = diagnostics_channel.channel('my-channel');
55
56function onMessage(message, name) {
57  // Received data
58}
59
60// Subscribe to the channel
61diagnostics_channel.subscribe('my-channel', onMessage);
62
63// Check if the channel has an active subscriber
64if (channel.hasSubscribers) {
65  // Publish data to the channel
66  channel.publish({
67    some: 'data',
68  });
69}
70
71// Unsubscribe from the channel
72diagnostics_channel.unsubscribe('my-channel', onMessage);
73```
74
75```cjs
76const diagnostics_channel = require('node:diagnostics_channel');
77
78// Get a reusable channel object
79const channel = diagnostics_channel.channel('my-channel');
80
81function onMessage(message, name) {
82  // Received data
83}
84
85// Subscribe to the channel
86diagnostics_channel.subscribe('my-channel', onMessage);
87
88// Check if the channel has an active subscriber
89if (channel.hasSubscribers) {
90  // Publish data to the channel
91  channel.publish({
92    some: 'data',
93  });
94}
95
96// Unsubscribe from the channel
97diagnostics_channel.unsubscribe('my-channel', onMessage);
98```
99
100#### `diagnostics_channel.hasSubscribers(name)`
101
102<!-- YAML
103added:
104 - v15.1.0
105 - v14.17.0
106-->
107
108* `name` {string|symbol} The channel name
109* Returns: {boolean} If there are active subscribers
110
111Check if there are active subscribers to the named channel. This is helpful if
112the message you want to send might be expensive to prepare.
113
114This API is optional but helpful when trying to publish messages from very
115performance-sensitive code.
116
117```mjs
118import diagnostics_channel from 'node:diagnostics_channel';
119
120if (diagnostics_channel.hasSubscribers('my-channel')) {
121  // There are subscribers, prepare and publish message
122}
123```
124
125```cjs
126const diagnostics_channel = require('node:diagnostics_channel');
127
128if (diagnostics_channel.hasSubscribers('my-channel')) {
129  // There are subscribers, prepare and publish message
130}
131```
132
133#### `diagnostics_channel.channel(name)`
134
135<!-- YAML
136added:
137 - v15.1.0
138 - v14.17.0
139-->
140
141* `name` {string|symbol} The channel name
142* Returns: {Channel} The named channel object
143
144This is the primary entry-point for anyone wanting to publish to a named
145channel. It produces a channel object which is optimized to reduce overhead at
146publish time as much as possible.
147
148```mjs
149import diagnostics_channel from 'node:diagnostics_channel';
150
151const channel = diagnostics_channel.channel('my-channel');
152```
153
154```cjs
155const diagnostics_channel = require('node:diagnostics_channel');
156
157const channel = diagnostics_channel.channel('my-channel');
158```
159
160#### `diagnostics_channel.subscribe(name, onMessage)`
161
162<!-- YAML
163added:
164 - v18.7.0
165-->
166
167* `name` {string|symbol} The channel name
168* `onMessage` {Function} The handler to receive channel messages
169  * `message` {any} The message data
170  * `name` {string|symbol} The name of the channel
171
172Register a message handler to subscribe to this channel. This message handler
173will be run synchronously whenever a message is published to the channel. Any
174errors thrown in the message handler will trigger an [`'uncaughtException'`][].
175
176```mjs
177import diagnostics_channel from 'node:diagnostics_channel';
178
179diagnostics_channel.subscribe('my-channel', (message, name) => {
180  // Received data
181});
182```
183
184```cjs
185const diagnostics_channel = require('node:diagnostics_channel');
186
187diagnostics_channel.subscribe('my-channel', (message, name) => {
188  // Received data
189});
190```
191
192#### `diagnostics_channel.unsubscribe(name, onMessage)`
193
194<!-- YAML
195added:
196 - v18.7.0
197-->
198
199* `name` {string|symbol} The channel name
200* `onMessage` {Function} The previous subscribed handler to remove
201* Returns: {boolean} `true` if the handler was found, `false` otherwise.
202
203Remove a message handler previously registered to this channel with
204[`diagnostics_channel.subscribe(name, onMessage)`][].
205
206```mjs
207import diagnostics_channel from 'node:diagnostics_channel';
208
209function onMessage(message, name) {
210  // Received data
211}
212
213diagnostics_channel.subscribe('my-channel', onMessage);
214
215diagnostics_channel.unsubscribe('my-channel', onMessage);
216```
217
218```cjs
219const diagnostics_channel = require('node:diagnostics_channel');
220
221function onMessage(message, name) {
222  // Received data
223}
224
225diagnostics_channel.subscribe('my-channel', onMessage);
226
227diagnostics_channel.unsubscribe('my-channel', onMessage);
228```
229
230### Class: `Channel`
231
232<!-- YAML
233added:
234 - v15.1.0
235 - v14.17.0
236-->
237
238The class `Channel` represents an individual named channel within the data
239pipeline. It is used to track subscribers and to publish messages when there
240are subscribers present. It exists as a separate object to avoid channel
241lookups at publish time, enabling very fast publish speeds and allowing
242for heavy use while incurring very minimal cost. Channels are created with
243[`diagnostics_channel.channel(name)`][], constructing a channel directly
244with `new Channel(name)` is not supported.
245
246#### `channel.hasSubscribers`
247
248<!-- YAML
249added:
250 - v15.1.0
251 - v14.17.0
252-->
253
254* Returns: {boolean} If there are active subscribers
255
256Check if there are active subscribers to this channel. This is helpful if
257the message you want to send might be expensive to prepare.
258
259This API is optional but helpful when trying to publish messages from very
260performance-sensitive code.
261
262```mjs
263import diagnostics_channel from 'node:diagnostics_channel';
264
265const channel = diagnostics_channel.channel('my-channel');
266
267if (channel.hasSubscribers) {
268  // There are subscribers, prepare and publish message
269}
270```
271
272```cjs
273const diagnostics_channel = require('node:diagnostics_channel');
274
275const channel = diagnostics_channel.channel('my-channel');
276
277if (channel.hasSubscribers) {
278  // There are subscribers, prepare and publish message
279}
280```
281
282#### `channel.publish(message)`
283
284<!-- YAML
285added:
286 - v15.1.0
287 - v14.17.0
288-->
289
290* `message` {any} The message to send to the channel subscribers
291
292Publish a message to any subscribers to the channel. This will trigger
293message handlers synchronously so they will execute within the same context.
294
295```mjs
296import diagnostics_channel from 'node:diagnostics_channel';
297
298const channel = diagnostics_channel.channel('my-channel');
299
300channel.publish({
301  some: 'message',
302});
303```
304
305```cjs
306const diagnostics_channel = require('node:diagnostics_channel');
307
308const channel = diagnostics_channel.channel('my-channel');
309
310channel.publish({
311  some: 'message',
312});
313```
314
315#### `channel.subscribe(onMessage)`
316
317<!-- YAML
318added:
319 - v15.1.0
320 - v14.17.0
321deprecated: v18.7.0
322-->
323
324> Stability: 0 - Deprecated: Use [`diagnostics_channel.subscribe(name, onMessage)`][]
325
326* `onMessage` {Function} The handler to receive channel messages
327  * `message` {any} The message data
328  * `name` {string|symbol} The name of the channel
329
330Register a message handler to subscribe to this channel. This message handler
331will be run synchronously whenever a message is published to the channel. Any
332errors thrown in the message handler will trigger an [`'uncaughtException'`][].
333
334```mjs
335import diagnostics_channel from 'node:diagnostics_channel';
336
337const channel = diagnostics_channel.channel('my-channel');
338
339channel.subscribe((message, name) => {
340  // Received data
341});
342```
343
344```cjs
345const diagnostics_channel = require('node:diagnostics_channel');
346
347const channel = diagnostics_channel.channel('my-channel');
348
349channel.subscribe((message, name) => {
350  // Received data
351});
352```
353
354#### `channel.unsubscribe(onMessage)`
355
356<!-- YAML
357added:
358 - v15.1.0
359 - v14.17.0
360deprecated: v18.7.0
361changes:
362  - version:
363    - v17.1.0
364    - v16.14.0
365    - v14.19.0
366    pr-url: https://github.com/nodejs/node/pull/40433
367    description: Added return value. Added to channels without subscribers.
368-->
369
370> Stability: 0 - Deprecated: Use [`diagnostics_channel.unsubscribe(name, onMessage)`][]
371
372* `onMessage` {Function} The previous subscribed handler to remove
373* Returns: {boolean} `true` if the handler was found, `false` otherwise.
374
375Remove a message handler previously registered to this channel with
376[`channel.subscribe(onMessage)`][].
377
378```mjs
379import diagnostics_channel from 'node:diagnostics_channel';
380
381const channel = diagnostics_channel.channel('my-channel');
382
383function onMessage(message, name) {
384  // Received data
385}
386
387channel.subscribe(onMessage);
388
389channel.unsubscribe(onMessage);
390```
391
392```cjs
393const diagnostics_channel = require('node:diagnostics_channel');
394
395const channel = diagnostics_channel.channel('my-channel');
396
397function onMessage(message, name) {
398  // Received data
399}
400
401channel.subscribe(onMessage);
402
403channel.unsubscribe(onMessage);
404```
405
406### Built-in Channels
407
408> Stability: 1 - Experimental
409
410While the diagnostics\_channel API is now considered stable, the built-in
411channels currently available are not. Each channel must be declared stable
412independently.
413
414#### HTTP
415
416`http.client.request.start`
417
418* `request` {http.ClientRequest}
419
420Emitted when client starts a request.
421
422`http.client.response.finish`
423
424* `request` {http.ClientRequest}
425* `response` {http.IncomingMessage}
426
427Emitted when client receives a response.
428
429`http.server.request.start`
430
431* `request` {http.IncomingMessage}
432* `response` {http.ServerResponse}
433* `socket` {net.Socket}
434* `server` {http.Server}
435
436Emitted when server receives a request.
437
438`http.server.response.finish`
439
440* `request` {http.IncomingMessage}
441* `response` {http.ServerResponse}
442* `socket` {net.Socket}
443* `server` {http.Server}
444
445Emitted when server sends a response.
446
447`net.client.socket`
448
449* `socket` {net.Socket}
450
451Emitted when a new TCP or pipe client socket is created.
452
453`net.server.socket`
454
455* `socket` {net.Socket}
456
457Emitted when a new TCP or pipe connection is received.
458
459`udp.socket`
460
461* `socket` {dgram.Socket}
462
463Emitted when a new UDP socket is created.
464
465[`'uncaughtException'`]: process.md#event-uncaughtexception
466[`channel.subscribe(onMessage)`]: #channelsubscribeonmessage
467[`diagnostics_channel.channel(name)`]: #diagnostics_channelchannelname
468[`diagnostics_channel.subscribe(name, onMessage)`]: #diagnostics_channelsubscribename-onmessage
469[`diagnostics_channel.unsubscribe(name, onMessage)`]: #diagnostics_channelunsubscribename-onmessage
470