{
  "type": "module",
  "source": "doc/api/api-diagnosticschannel.md",
  "introduced_in": "v6.3.0",
  "stability": 1,
  "stabilityText": "Experimental",
  "miscs": [
    {
      "textRaw": "Diagnostics Channel Support",
      "name": "Diagnostics Channel Support",
      "introduced_in": "v6.3.0",
      "type": "misc",
      "stability": 1,
      "stabilityText": "Experimental",
      "desc": "<p>Undici is instrumented with Node.js' built-in <a href=\"https://nodejs.org/api/diagnostics_channel.html\"><code>diagnostics_channel</code></a> module.\nIt is the preferred way to observe undici's internal behaviour without patching\nthe library, and it backs the human-readable <a href=\"Debug.html\">debug logs</a>.</p>\n<p>Each integration point is exposed as a named channel. To observe an event,\nobtain the channel by name and subscribe to it:</p>\n<pre><code class=\"language-mjs\">import diagnosticsChannel from 'node:diagnostics_channel'\n\ndiagnosticsChannel.channel('undici:request:create').subscribe(({ request }) => {\n  console.log(request.method, request.origin, request.path)\n})\n</code></pre>\n<pre><code class=\"language-cjs\">const diagnosticsChannel = require('node:diagnostics_channel')\n\ndiagnosticsChannel.channel('undici:request:create').subscribe(({ request }) => {\n  console.log(request.method, request.origin, request.path)\n})\n</code></pre>\n<p>The message published to a channel is always a single object whose shape depends\non the channel. The sections below describe every channel and the object it\npublishes. Subscriber callbacks run synchronously inside undici, so they should\nbe fast and must not throw.</p>\n<p>The same <code>request</code> object is shared across all <code>undici:request:*</code> channels for a\ngiven request, so a subscriber may correlate the lifecycle of one request by\nidentity.</p>",
      "events": [
        {
          "textRaw": "Event: `'undici:request:create'`",
          "name": "undici:request:create",
          "type": "event",
          "meta": {
            "added": [
              "v6.3.0"
            ],
            "changes": []
          },
          "params": [
            {
              "textRaw": "`message` {Object}",
              "name": "message",
              "type": "Object",
              "options": [
                {
                  "textRaw": "`request` {Object} The request being created.",
                  "name": "request",
                  "type": "Object",
                  "desc": "The request being created.",
                  "options": [
                    {
                      "textRaw": "`origin` {string|URL} The origin the request is sent to.",
                      "name": "origin",
                      "type": "string|URL",
                      "desc": "The origin the request is sent to."
                    },
                    {
                      "textRaw": "`completed` {boolean} Whether the request has completed. `false` at this point.",
                      "name": "completed",
                      "type": "boolean",
                      "desc": "Whether the request has completed. `false` at this point."
                    },
                    {
                      "textRaw": "`method` {string} The HTTP method, e.g. `'GET'`.",
                      "name": "method",
                      "type": "string",
                      "desc": "The HTTP method, e.g. `'GET'`."
                    },
                    {
                      "textRaw": "`path` {string} The request path, including any query string.",
                      "name": "path",
                      "type": "string",
                      "desc": "The request path, including any query string."
                    },
                    {
                      "textRaw": "`headers` {string}[] The request headers as a flat array of strings, alternating between header name and value.",
                      "name": "headers",
                      "type": "string",
                      "desc": "[] The request headers as a flat array of strings, alternating between header name and value."
                    }
                  ]
                }
              ]
            }
          ],
          "desc": "<p>Published when a new outgoing request is created, before it is dispatched.</p>\n<p>The <code>request</code> object also exposes an <code>addHeader(name, value)</code> method that\nappends a header before the request is sent.</p>\n<pre><code class=\"language-mjs\">import diagnosticsChannel from 'node:diagnostics_channel'\n\ndiagnosticsChannel.channel('undici:request:create').subscribe(({ request }) => {\n  console.log('origin', request.origin)\n  console.log('completed', request.completed)\n  console.log('method', request.method)\n  console.log('path', request.path)\n  console.log('headers', request.headers)\n  request.addHeader('hello', 'world')\n})\n</code></pre>\n<p>A request is only loosely bound to a given socket at this stage.</p>"
        },
        {
          "textRaw": "Event: `'undici:request:bodyChunkSent'`",
          "name": "undici:request:bodyChunkSent",
          "type": "event",
          "meta": {
            "added": [
              "v7.11.0"
            ],
            "changes": []
          },
          "params": [
            {
              "textRaw": "`message` {Object}",
              "name": "message",
              "type": "Object",
              "options": [
                {
                  "textRaw": "`request` {Object} The same object published by `'undici:request:create'`.",
                  "name": "request",
                  "type": "Object",
                  "desc": "The same object published by `'undici:request:create'`."
                },
                {
                  "textRaw": "`chunk` {Uint8Array|string} The body chunk being sent.",
                  "name": "chunk",
                  "type": "Uint8Array|string",
                  "desc": "The body chunk being sent."
                }
              ]
            }
          ],
          "desc": "<p>Published each time a chunk of the request body is written to the socket.</p>\n<pre><code class=\"language-mjs\">import diagnosticsChannel from 'node:diagnostics_channel'\n\ndiagnosticsChannel.channel('undici:request:bodyChunkSent').subscribe(({ request, chunk }) => {\n  console.log('sent', chunk.length, 'bytes')\n})\n</code></pre>"
        },
        {
          "textRaw": "Event: `'undici:request:bodySent'`",
          "name": "undici:request:bodySent",
          "type": "event",
          "meta": {
            "added": [
              "v6.3.0"
            ],
            "changes": []
          },
          "params": [
            {
              "textRaw": "`message` {Object}",
              "name": "message",
              "type": "Object",
              "options": [
                {
                  "textRaw": "`request` {Object} The same object published by `'undici:request:create'`.",
                  "name": "request",
                  "type": "Object",
                  "desc": "The same object published by `'undici:request:create'`."
                }
              ]
            }
          ],
          "desc": "<p>Published after the request body has been fully sent.</p>\n<pre><code class=\"language-mjs\">import diagnosticsChannel from 'node:diagnostics_channel'\n\ndiagnosticsChannel.channel('undici:request:bodySent').subscribe(({ request }) => {\n  // request is the same object as in 'undici:request:create'\n})\n</code></pre>"
        },
        {
          "textRaw": "Event: `'undici:request:headers'`",
          "name": "undici:request:headers",
          "type": "event",
          "meta": {
            "added": [
              "v6.3.0"
            ],
            "changes": []
          },
          "params": [
            {
              "textRaw": "`message` {Object}",
              "name": "message",
              "type": "Object",
              "options": [
                {
                  "textRaw": "`request` {Object} The same object published by `'undici:request:create'`.",
                  "name": "request",
                  "type": "Object",
                  "desc": "The same object published by `'undici:request:create'`."
                },
                {
                  "textRaw": "`response` {Object} The response being received.",
                  "name": "response",
                  "type": "Object",
                  "desc": "The response being received.",
                  "options": [
                    {
                      "textRaw": "`statusCode` {number} The HTTP status code.",
                      "name": "statusCode",
                      "type": "number",
                      "desc": "The HTTP status code."
                    },
                    {
                      "textRaw": "`statusText` {string} The HTTP status message.",
                      "name": "statusText",
                      "type": "string",
                      "desc": "The HTTP status message."
                    },
                    {
                      "textRaw": "`headers` {Buffer}[] The raw response headers as an array of buffers, alternating between header name and value.",
                      "name": "headers",
                      "type": "Buffer",
                      "desc": "[] The raw response headers as an array of buffers, alternating between header name and value."
                    }
                  ]
                }
              ]
            }
          ],
          "desc": "<p>Published after the response headers have been received.</p>\n<pre><code class=\"language-mjs\">import diagnosticsChannel from 'node:diagnostics_channel'\n\ndiagnosticsChannel.channel('undici:request:headers').subscribe(({ request, response }) => {\n  console.log('statusCode', response.statusCode)\n  console.log(response.statusText)\n  console.log(response.headers.map((x) => x.toString()))\n})\n</code></pre>"
        },
        {
          "textRaw": "Event: `'undici:request:bodyChunkReceived'`",
          "name": "undici:request:bodyChunkReceived",
          "type": "event",
          "meta": {
            "added": [
              "v7.11.0"
            ],
            "changes": []
          },
          "params": [
            {
              "textRaw": "`message` {Object}",
              "name": "message",
              "type": "Object",
              "options": [
                {
                  "textRaw": "`request` {Object} The same object published by `'undici:request:create'`.",
                  "name": "request",
                  "type": "Object",
                  "desc": "The same object published by `'undici:request:create'`."
                },
                {
                  "textRaw": "`chunk` {Buffer} The body chunk that was received.",
                  "name": "chunk",
                  "type": "Buffer",
                  "desc": "The body chunk that was received."
                }
              ]
            }
          ],
          "desc": "<p>Published each time a chunk of the response body is received.</p>\n<pre><code class=\"language-mjs\">import diagnosticsChannel from 'node:diagnostics_channel'\n\ndiagnosticsChannel.channel('undici:request:bodyChunkReceived').subscribe(({ request, chunk }) => {\n  console.log('received', chunk.length, 'bytes')\n})\n</code></pre>"
        },
        {
          "textRaw": "Event: `'undici:request:trailers'`",
          "name": "undici:request:trailers",
          "type": "event",
          "meta": {
            "added": [
              "v6.3.0"
            ],
            "changes": []
          },
          "params": [
            {
              "textRaw": "`message` {Object}",
              "name": "message",
              "type": "Object",
              "options": [
                {
                  "textRaw": "`request` {Object} The same object published by `'undici:request:create'`. `request.completed` is now `true`.",
                  "name": "request",
                  "type": "Object",
                  "desc": "The same object published by `'undici:request:create'`. `request.completed` is now `true`."
                },
                {
                  "textRaw": "`trailers` {Buffer}[] The raw response trailers as an array of buffers, alternating between header name and value.",
                  "name": "trailers",
                  "type": "Buffer",
                  "desc": "[] The raw response trailers as an array of buffers, alternating between header name and value."
                }
              ]
            }
          ],
          "desc": "<p>Published after the response body and trailers have been received, that is, once\nthe response has fully completed.</p>\n<pre><code class=\"language-mjs\">import diagnosticsChannel from 'node:diagnostics_channel'\n\ndiagnosticsChannel.channel('undici:request:trailers').subscribe(({ request, trailers }) => {\n  console.log('completed', request.completed)\n  console.log(trailers.map((x) => x.toString()))\n})\n</code></pre>"
        },
        {
          "textRaw": "Event: `'undici:request:error'`",
          "name": "undici:request:error",
          "type": "event",
          "meta": {
            "added": [
              "v6.3.0"
            ],
            "changes": []
          },
          "params": [
            {
              "textRaw": "`message` {Object}",
              "name": "message",
              "type": "Object",
              "options": [
                {
                  "textRaw": "`request` {Object} The same object published by `'undici:request:create'`.",
                  "name": "request",
                  "type": "Object",
                  "desc": "The same object published by `'undici:request:create'`."
                },
                {
                  "textRaw": "`error` {Error} The error the request is about to fail with.",
                  "name": "error",
                  "type": "Error",
                  "desc": "The error the request is about to fail with."
                }
              ]
            }
          ],
          "desc": "<p>Published when the request is about to error, before the error is surfaced to\nthe caller.</p>\n<pre><code class=\"language-mjs\">import diagnosticsChannel from 'node:diagnostics_channel'\n\ndiagnosticsChannel.channel('undici:request:error').subscribe(({ request, error }) => {\n  console.error(error)\n})\n</code></pre>"
        },
        {
          "textRaw": "Event: `'undici:client:sendHeaders'`",
          "name": "undici:client:sendHeaders",
          "type": "event",
          "meta": {
            "added": [
              "v6.3.0"
            ],
            "changes": [
              {
                "version": "v7.0.0",
                "pr-url": "https://github.com/nodejs/undici/pull/3585",
                "description": "Refactor the diagnostics channel internals."
              }
            ]
          },
          "params": [
            {
              "textRaw": "`message` {Object}",
              "name": "message",
              "type": "Object",
              "options": [
                {
                  "textRaw": "`request` {Object} The same object published by `'undici:request:create'`.",
                  "name": "request",
                  "type": "Object",
                  "desc": "The same object published by `'undici:request:create'`."
                },
                {
                  "textRaw": "`headers` {string} The request headers as a single raw string, with lines separated by `\\r\\n`.",
                  "name": "headers",
                  "type": "string",
                  "desc": "The request headers as a single raw string, with lines separated by `\\r\\n`."
                },
                {
                  "textRaw": "`socket` {net.Socket} The socket the request is written to.",
                  "name": "socket",
                  "type": "net.Socket",
                  "desc": "The socket the request is written to."
                }
              ]
            }
          ],
          "desc": "<p>Published immediately before the first byte of the request is written to the\nsocket. The headers are published exactly as they will be sent to the server, in\nraw form.</p>\n<pre><code class=\"language-mjs\">import diagnosticsChannel from 'node:diagnostics_channel'\n\ndiagnosticsChannel.channel('undici:client:sendHeaders').subscribe(({ request, headers, socket }) => {\n  console.log(`Full headers list: ${headers.split('\\r\\n')}`)\n})\n</code></pre>"
        },
        {
          "textRaw": "Event: `'undici:client:beforeConnect'`",
          "name": "undici:client:beforeConnect",
          "type": "event",
          "meta": {
            "added": [
              "v6.3.0"
            ],
            "changes": [
              {
                "version": "v7.0.0",
                "pr-url": "https://github.com/nodejs/undici/pull/3585",
                "description": "Refactor the diagnostics channel internals."
              }
            ]
          },
          "params": [
            {
              "textRaw": "`message` {Object}",
              "name": "message",
              "type": "Object",
              "options": [
                {
                  "textRaw": "`connectParams` {Object} The parameters used to open the connection.",
                  "name": "connectParams",
                  "type": "Object",
                  "desc": "The parameters used to open the connection.",
                  "options": [
                    {
                      "textRaw": "`host` {string} The connection host, including the port if present.",
                      "name": "host",
                      "type": "string",
                      "desc": "The connection host, including the port if present."
                    },
                    {
                      "textRaw": "`hostname` {string} The connection hostname.",
                      "name": "hostname",
                      "type": "string",
                      "desc": "The connection hostname."
                    },
                    {
                      "textRaw": "`protocol` {string} The protocol, e.g. `'https:'`.",
                      "name": "protocol",
                      "type": "string",
                      "desc": "The protocol, e.g. `'https:'`."
                    },
                    {
                      "textRaw": "`port` {string} The connection port.",
                      "name": "port",
                      "type": "string",
                      "desc": "The connection port."
                    },
                    {
                      "textRaw": "`servername` {string|null} The TLS server name, or `null`.",
                      "name": "servername",
                      "type": "string|null",
                      "desc": "The TLS server name, or `null`."
                    }
                  ]
                },
                {
                  "textRaw": "`connector` {Function} The function that creates the socket.",
                  "name": "connector",
                  "type": "Function",
                  "desc": "The function that creates the socket."
                }
              ]
            }
          ],
          "desc": "<p>Published before a new connection is opened for any request. This event cannot be\nattributed to a specific request, because connections are pooled and shared.</p>\n<pre><code class=\"language-mjs\">import diagnosticsChannel from 'node:diagnostics_channel'\n\ndiagnosticsChannel.channel('undici:client:beforeConnect').subscribe(({ connectParams, connector }) => {\n  const { host, hostname, protocol, port, servername } = connectParams\n  // connector is the function that creates the socket\n})\n</code></pre>"
        },
        {
          "textRaw": "Event: `'undici:client:connected'`",
          "name": "undici:client:connected",
          "type": "event",
          "meta": {
            "added": [
              "v6.3.0"
            ],
            "changes": [
              {
                "version": "v7.0.0",
                "pr-url": "https://github.com/nodejs/undici/pull/3585",
                "description": "Refactor the diagnostics channel internals."
              }
            ]
          },
          "params": [
            {
              "textRaw": "`message` {Object}",
              "name": "message",
              "type": "Object",
              "options": [
                {
                  "textRaw": "`socket` {net.Socket} The newly connected socket.",
                  "name": "socket",
                  "type": "net.Socket",
                  "desc": "The newly connected socket."
                },
                {
                  "textRaw": "`connectParams` {Object} The parameters used to open the connection. See `'undici:client:beforeConnect'` for the field descriptions.",
                  "name": "connectParams",
                  "type": "Object",
                  "desc": "The parameters used to open the connection. See `'undici:client:beforeConnect'` for the field descriptions."
                },
                {
                  "textRaw": "`connector` {Function} The function that created the socket.",
                  "name": "connector",
                  "type": "Function",
                  "desc": "The function that created the socket."
                }
              ]
            }
          ],
          "desc": "<p>Published after a connection has been successfully established.</p>\n<pre><code class=\"language-mjs\">import diagnosticsChannel from 'node:diagnostics_channel'\n\ndiagnosticsChannel.channel('undici:client:connected').subscribe(({ socket, connectParams, connector }) => {\n  const { host, hostname, protocol, port, servername } = connectParams\n})\n</code></pre>"
        },
        {
          "textRaw": "Event: `'undici:client:connectError'`",
          "name": "undici:client:connectError",
          "type": "event",
          "meta": {
            "added": [
              "v6.3.0"
            ],
            "changes": [
              {
                "version": "v7.0.0",
                "pr-url": "https://github.com/nodejs/undici/pull/3585",
                "description": "Refactor the diagnostics channel internals."
              }
            ]
          },
          "params": [
            {
              "textRaw": "`message` {Object}",
              "name": "message",
              "type": "Object",
              "options": [
                {
                  "textRaw": "`error` {Error} The error that prevented the connection.",
                  "name": "error",
                  "type": "Error",
                  "desc": "The error that prevented the connection."
                },
                {
                  "textRaw": "`socket` {net.Socket} The socket associated with the failed attempt.",
                  "name": "socket",
                  "type": "net.Socket",
                  "desc": "The socket associated with the failed attempt."
                },
                {
                  "textRaw": "`connectParams` {Object} The parameters used to open the connection. See `'undici:client:beforeConnect'` for the field descriptions.",
                  "name": "connectParams",
                  "type": "Object",
                  "desc": "The parameters used to open the connection. See `'undici:client:beforeConnect'` for the field descriptions."
                },
                {
                  "textRaw": "`connector` {Function} The function that created the socket.",
                  "name": "connector",
                  "type": "Function",
                  "desc": "The function that created the socket."
                }
              ]
            }
          ],
          "desc": "<p>Published when a connection could not be established.</p>\n<pre><code class=\"language-mjs\">import diagnosticsChannel from 'node:diagnostics_channel'\n\ndiagnosticsChannel.channel('undici:client:connectError').subscribe(({ error, socket, connectParams, connector }) => {\n  console.error(`Connect failed with ${error.message}`)\n})\n</code></pre>"
        },
        {
          "textRaw": "Event: `'undici:websocket:open'`",
          "name": "undici:websocket:open",
          "type": "event",
          "meta": {
            "added": [
              "v6.3.0"
            ],
            "changes": []
          },
          "params": [
            {
              "textRaw": "`message` {Object}",
              "name": "message",
              "type": "Object",
              "options": [
                {
                  "textRaw": "`address` {Object|null} The remote socket address, as returned by `socket.address()`, or `null` if it cannot be determined. When present, it contains `address`, `family`, and `port`.",
                  "name": "address",
                  "type": "Object|null",
                  "desc": "The remote socket address, as returned by `socket.address()`, or `null` if it cannot be determined. When present, it contains `address`, `family`, and `port`."
                },
                {
                  "textRaw": "`protocol` {string} The negotiated subprotocol.",
                  "name": "protocol",
                  "type": "string",
                  "desc": "The negotiated subprotocol."
                },
                {
                  "textRaw": "`extensions` {string} The negotiated extensions.",
                  "name": "extensions",
                  "type": "string",
                  "desc": "The negotiated extensions."
                },
                {
                  "textRaw": "`websocket` {WebSocket} The `WebSocket` instance.",
                  "name": "websocket",
                  "type": "WebSocket",
                  "desc": "The `WebSocket` instance."
                },
                {
                  "textRaw": "`handshakeResponse` {Object} The HTTP response that upgraded the connection.",
                  "name": "handshakeResponse",
                  "type": "Object",
                  "desc": "The HTTP response that upgraded the connection.",
                  "options": [
                    {
                      "textRaw": "`status` {number} The HTTP status code: `101` for an HTTP/1.1 upgrade, or `200` for an HTTP/2 extended `CONNECT`.",
                      "name": "status",
                      "type": "number",
                      "desc": "The HTTP status code: `101` for an HTTP/1.1 upgrade, or `200` for an HTTP/2 extended `CONNECT`."
                    },
                    {
                      "textRaw": "`statusText` {string} The HTTP status message: `'Switching Protocols'` for HTTP/1.1, and commonly `'OK'` for HTTP/2.",
                      "name": "statusText",
                      "type": "string",
                      "desc": "The HTTP status message: `'Switching Protocols'` for HTTP/1.1, and commonly `'OK'` for HTTP/2."
                    },
                    {
                      "textRaw": "`headers` {Object} The response headers from the server. The `upgrade` and `connection` headers are only present for HTTP/1.1 handshakes.",
                      "name": "headers",
                      "type": "Object",
                      "desc": "The response headers from the server. The `upgrade` and `connection` headers are only present for HTTP/1.1 handshakes."
                    }
                  ]
                }
              ]
            }
          ],
          "desc": "<p>Published after a <a href=\"WebSocket.html#class-websocket\"><code>WebSocket</code></a> has successfully connected to a server.</p>\n<pre><code class=\"language-mjs\">import diagnosticsChannel from 'node:diagnostics_channel'\n\ndiagnosticsChannel.channel('undici:websocket:open').subscribe(({\n  address,\n  protocol,\n  extensions,\n  websocket,\n  handshakeResponse\n}) => {\n  console.log(address)\n  console.log(protocol)\n  console.log(extensions)\n  console.log(handshakeResponse.status)\n  console.log(handshakeResponse.headers)\n})\n</code></pre>"
        },
        {
          "textRaw": "Event: `'undici:websocket:close'`",
          "name": "undici:websocket:close",
          "type": "event",
          "meta": {
            "added": [
              "v6.3.0"
            ],
            "changes": []
          },
          "params": [
            {
              "textRaw": "`message` {Object}",
              "name": "message",
              "type": "Object",
              "options": [
                {
                  "textRaw": "`websocket` {WebSocket} The `WebSocket` instance.",
                  "name": "websocket",
                  "type": "WebSocket",
                  "desc": "The `WebSocket` instance."
                },
                {
                  "textRaw": "`code` {number} The closing status code.",
                  "name": "code",
                  "type": "number",
                  "desc": "The closing status code."
                },
                {
                  "textRaw": "`reason` {string} The closing reason.",
                  "name": "reason",
                  "type": "string",
                  "desc": "The closing reason."
                }
              ]
            }
          ],
          "desc": "<p>Published after the <a href=\"WebSocket.html#class-websocket\"><code>WebSocket</code></a> connection has closed.</p>\n<pre><code class=\"language-mjs\">import diagnosticsChannel from 'node:diagnostics_channel'\n\ndiagnosticsChannel.channel('undici:websocket:close').subscribe(({ websocket, code, reason }) => {\n  console.log(code, reason)\n})\n</code></pre>"
        },
        {
          "textRaw": "Event: `'undici:websocket:socket_error'`",
          "name": "undici:websocket:socket_error",
          "type": "event",
          "meta": {
            "added": [
              "v6.3.0"
            ],
            "changes": []
          },
          "params": [
            {
              "textRaw": "`error` {Error} The socket error.",
              "name": "error",
              "type": "Error",
              "desc": "The socket error."
            }
          ],
          "desc": "<p>Published when the underlying WebSocket socket experiences an error. Unlike the\nother WebSocket channels, the published message is the error itself.</p>\n<pre><code class=\"language-mjs\">import diagnosticsChannel from 'node:diagnostics_channel'\n\ndiagnosticsChannel.channel('undici:websocket:socket_error').subscribe((error) => {\n  console.error(error)\n})\n</code></pre>"
        },
        {
          "textRaw": "Event: `'undici:websocket:ping'`",
          "name": "undici:websocket:ping",
          "type": "event",
          "meta": {
            "added": [
              "v6.3.0"
            ],
            "changes": []
          },
          "params": [
            {
              "textRaw": "`message` {Object}",
              "name": "message",
              "type": "Object",
              "options": [
                {
                  "textRaw": "`payload` {Buffer|undefined} The optional application data carried by the frame.",
                  "name": "payload",
                  "type": "Buffer|undefined",
                  "desc": "The optional application data carried by the frame."
                },
                {
                  "textRaw": "`websocket` {WebSocket} The `WebSocket` instance.",
                  "name": "websocket",
                  "type": "WebSocket",
                  "desc": "The `WebSocket` instance."
                }
              ]
            }
          ],
          "desc": "<p>Published after the client receives a ping frame.</p>\n<pre><code class=\"language-mjs\">import diagnosticsChannel from 'node:diagnostics_channel'\n\ndiagnosticsChannel.channel('undici:websocket:ping').subscribe(({ payload, websocket }) => {\n  console.log(payload)\n})\n</code></pre>"
        },
        {
          "textRaw": "Event: `'undici:websocket:pong'`",
          "name": "undici:websocket:pong",
          "type": "event",
          "meta": {
            "added": [
              "v6.3.0"
            ],
            "changes": []
          },
          "params": [
            {
              "textRaw": "`message` {Object}",
              "name": "message",
              "type": "Object",
              "options": [
                {
                  "textRaw": "`payload` {Buffer|undefined} The optional application data carried by the frame.",
                  "name": "payload",
                  "type": "Buffer|undefined",
                  "desc": "The optional application data carried by the frame."
                },
                {
                  "textRaw": "`websocket` {WebSocket} The `WebSocket` instance.",
                  "name": "websocket",
                  "type": "WebSocket",
                  "desc": "The `WebSocket` instance."
                }
              ]
            }
          ],
          "desc": "<p>Published after the client receives a pong frame.</p>\n<pre><code class=\"language-mjs\">import diagnosticsChannel from 'node:diagnostics_channel'\n\ndiagnosticsChannel.channel('undici:websocket:pong').subscribe(({ payload, websocket }) => {\n  console.log(payload)\n})\n</code></pre>"
        },
        {
          "textRaw": "Event: `'undici:proxy:connected'`",
          "name": "undici:proxy:connected",
          "type": "event",
          "meta": {
            "added": [
              "v7.17.0"
            ],
            "changes": []
          },
          "params": [
            {
              "textRaw": "`message` {Object}",
              "name": "message",
              "type": "Object",
              "options": [
                {
                  "textRaw": "`socket` {net.Socket} The socket connected to the proxy.",
                  "name": "socket",
                  "type": "net.Socket",
                  "desc": "The socket connected to the proxy."
                },
                {
                  "textRaw": "`connectParams` {Object} The parameters used to establish the tunnel.",
                  "name": "connectParams",
                  "type": "Object",
                  "desc": "The parameters used to establish the tunnel.",
                  "options": [
                    {
                      "textRaw": "`origin` {string|URL} The proxy origin.",
                      "name": "origin",
                      "type": "string|URL",
                      "desc": "The proxy origin."
                    },
                    {
                      "textRaw": "`port` {string} The proxy port.",
                      "name": "port",
                      "type": "string",
                      "desc": "The proxy port."
                    },
                    {
                      "textRaw": "`path` {string} The requested tunnel target, e.g. `'example.com:443'`.",
                      "name": "path",
                      "type": "string",
                      "desc": "The requested tunnel target, e.g. `'example.com:443'`."
                    },
                    {
                      "textRaw": "`signal` {AbortSignal|undefined} The signal associated with the request.",
                      "name": "signal",
                      "type": "AbortSignal|undefined",
                      "desc": "The signal associated with the request."
                    },
                    {
                      "textRaw": "`headers` {Object} The headers sent in the `CONNECT` request.",
                      "name": "headers",
                      "type": "Object",
                      "desc": "The headers sent in the `CONNECT` request."
                    },
                    {
                      "textRaw": "`servername` {string|undefined} The TLS server name used for the proxy.",
                      "name": "servername",
                      "type": "string|undefined",
                      "desc": "The TLS server name used for the proxy."
                    }
                  ]
                }
              ]
            }
          ],
          "desc": "<p>Published after a <a href=\"ProxyAgent.html#class-proxyagent\"><code>ProxyAgent</code></a> has established a tunnel to the proxy server.</p>\n<pre><code class=\"language-mjs\">import diagnosticsChannel from 'node:diagnostics_channel'\n\ndiagnosticsChannel.channel('undici:proxy:connected').subscribe(({ socket, connectParams }) => {\n  const { origin, port, path, signal, headers, servername } = connectParams\n})\n</code></pre>"
        },
        {
          "textRaw": "Event: `'undici:request:pending-requests'`",
          "name": "undici:request:pending-requests",
          "type": "event",
          "meta": {
            "added": [
              "v6.3.0"
            ],
            "changes": []
          },
          "params": [
            {
              "textRaw": "`message` {Object}",
              "name": "message",
              "type": "Object",
              "options": [
                {
                  "textRaw": "`type` {string} Either `'added'` when a new pending request is registered, or `'removed'` when a pending request completes, whether successfully or with an error.",
                  "name": "type",
                  "type": "string",
                  "desc": "Either `'added'` when a new pending request is registered, or `'removed'` when a pending request completes, whether successfully or with an error."
                },
                {
                  "textRaw": "`size` {number} The number of pending requests after the change.",
                  "name": "size",
                  "type": "number",
                  "desc": "The number of pending requests after the change."
                },
                {
                  "textRaw": "`key` {string} The deduplication key for the request, composed of the origin, method, path, and request headers.",
                  "name": "key",
                  "type": "string",
                  "desc": "The deduplication key for the request, composed of the origin, method, path, and request headers."
                }
              ]
            }
          ],
          "desc": "<p>Published when the <a href=\"Dispatcher.html#dedupe\"><code>dedupe</code></a> interceptor's set of pending requests changes.\nThe interceptor coalesces concurrent identical requests so that only one reaches\nthe origin; this channel exposes that bookkeeping for monitoring and debugging.</p>\n<pre><code class=\"language-mjs\">import diagnosticsChannel from 'node:diagnostics_channel'\n\ndiagnosticsChannel.channel('undici:request:pending-requests').subscribe(({ type, size, key }) => {\n  if (type === 'added') {\n    console.log(`New pending request: ${key} (${size} total pending)`)\n  } else {\n    console.log(`Request completed: ${key} (${size} remaining)`)\n  }\n})\n</code></pre>\n<p>This is useful for verifying that deduplication is working, monitoring the number\nof concurrent in-flight requests, and debugging deduplication behaviour in\nproduction.</p>"
        }
      ]
    }
  ]
}