Files
projektuebersicht/node_modules/undici/docs/docs/api/DiagnosticsChannel.md
T
erikandClaude Sonnet 5 6ba93b2a92 Plan Checker, Wochenbericht-Fokus-Modus und Wandtafel-Dashboard-Feinschliff
Plan Checker (neues Studenten-Werkzeug, Seitenleiste + Admin → Plan-Checker-
Merkmale): lädt einen Bauplan als PDF hoch und lässt ChatGPT oder Claude ihn
gegen eine gepflegte Merkmalsliste prüfen. PDF-Rendering (pdf.js +
@napi-rs/canvas) berücksichtigt jetzt Ebenen (Optional Content Groups) und
WASM-Decoder korrekt, sendet eine Übersicht plus mehrere hochaufgelöste
Kachel-Ausschnitte statt eines einzelnen, zu groben Bilds, und beide Anbieter
bekommen dasselbe Bildmaterial. Jedes Prüfergebnis kann auf eines der
gesendeten Bilder als Beleg verweisen (bildIndex) — als Screenshot im
Ergebnis anklickbar, öffnet vergrößert in einem Modal statt eines von Chrome
blockierten target=_blank-Links auf eine data:-URL. KI-Modellname ist jetzt
pro Konto überschreibbar (Einstellungen → Mein Konto) für Drittanbieter mit
abweichendem Modell-Katalog.

Wochenbericht: dichte Kartenansicht bekommt einen Fokus-Modus — nur der
Kommentar liegt offen, Leistungsphasen und Beteiligte stecken in
aufklappbaren Abschnitten statt dauerhaft nebeneinander zu stehen.

Projektbereich: Terminplan-Auslastung rechnet jetzt exakt wie der
Auslastungs-Tab/die Wandtafel (statt einer unabhängigen, tageweisen
Schätzung); die LPH-Fortschrittsliste im Dashboard zeigt nur noch die
beauftragten Leistungsphasen.

Wandtafel: Dashboard-Kopf mit Kennzahlen-Reihe und Panel-Reihe neu
strukturiert, in den Blautönen des Firmenlogos; dieselbe Palette wurde
anschließend auf den gesamten App-weiten Dark Mode übernommen.

Dateibereinigung: nicht mehr benötigte Test-Uploads/Backups entfernt.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-05 14:01:41 +02:00

15 KiB

Diagnostics Channel Support

Stability: 1 - Experimental

Undici is instrumented with Node.js' built-in diagnostics_channel module. It is the preferred way to observe undici's internal behaviour without patching the library, and it backs the human-readable debug logs.

Each integration point is exposed as a named channel. To observe an event, obtain the channel by name and subscribe to it:

import diagnosticsChannel from 'node:diagnostics_channel'

diagnosticsChannel.channel('undici:request:create').subscribe(({ request }) => {
  console.log(request.method, request.origin, request.path)
})
const diagnosticsChannel = require('node:diagnostics_channel')

diagnosticsChannel.channel('undici:request:create').subscribe(({ request }) => {
  console.log(request.method, request.origin, request.path)
})

The message published to a channel is always a single object whose shape depends on the channel. The sections below describe every channel and the object it publishes. Subscriber callbacks run synchronously inside undici, so they should be fast and must not throw.

The same request object is shared across all undici:request:* channels for a given request, so a subscriber may correlate the lifecycle of one request by identity.

Event: 'undici:request:create'

Published when a new outgoing request is created, before it is dispatched.

  • message {Object}
    • request {Object} The request being created.
      • origin {string|URL} The origin the request is sent to.
      • completed {boolean} Whether the request has completed. false at this point.
      • method {string} The HTTP method, e.g. 'GET'.
      • path {string} The request path, including any query string.
      • headers {string[]} The request headers as a flat array of strings, alternating between header name and value.

The request object also exposes an addHeader(name, value) method that appends a header before the request is sent.

import diagnosticsChannel from 'node:diagnostics_channel'

diagnosticsChannel.channel('undici:request:create').subscribe(({ request }) => {
  console.log('origin', request.origin)
  console.log('completed', request.completed)
  console.log('method', request.method)
  console.log('path', request.path)
  console.log('headers', request.headers)
  request.addHeader('hello', 'world')
})

A request is only loosely bound to a given socket at this stage.

Event: 'undici:request:bodyChunkSent'

Published each time a chunk of the request body is written to the socket.

  • message {Object}
    • request {Object} The same object published by 'undici:request:create'.
    • chunk {Uint8Array|string} The body chunk being sent.
import diagnosticsChannel from 'node:diagnostics_channel'

diagnosticsChannel.channel('undici:request:bodyChunkSent').subscribe(({ request, chunk }) => {
  console.log('sent', chunk.length, 'bytes')
})

Event: 'undici:request:bodySent'

Published after the request body has been fully sent.

import diagnosticsChannel from 'node:diagnostics_channel'

diagnosticsChannel.channel('undici:request:bodySent').subscribe(({ request }) => {
  // request is the same object as in 'undici:request:create'
})

Event: 'undici:request:headers'

Published after the response headers have been received. This includes a successful CONNECT or protocol upgrade response.

  • message {Object}
    • request {Object} The same object published by 'undici:request:create'.
    • response {Object} The response being received.
      • statusCode {number} The HTTP status code.
      • statusText {string} The HTTP status message.
      • headers {Buffer[]|Object} HTTP/1.1 response headers are an array of buffers alternating between header name and value. HTTP/2 response headers are an object.
import diagnosticsChannel from 'node:diagnostics_channel'

diagnosticsChannel.channel('undici:request:headers').subscribe(({ request, response }) => {
  console.log('statusCode', response.statusCode)
  console.log(response.statusText)
  console.log(response.headers)
})

Event: 'undici:request:bodyChunkReceived'

Published each time a chunk of the response body is received.

  • message {Object}
    • request {Object} The same object published by 'undici:request:create'.
    • chunk {Buffer} The body chunk that was received.
import diagnosticsChannel from 'node:diagnostics_channel'

diagnosticsChannel.channel('undici:request:bodyChunkReceived').subscribe(({ request, chunk }) => {
  console.log('received', chunk.length, 'bytes')
})

Event: 'undici:request:trailers'

Published once the response has fully completed. After an upgraded socket has been passed to the request handler, this event is published with an empty trailers array.

  • message {Object}
    • request {Object} The same object published by 'undici:request:create'. request.completed is now true.
    • trailers {Buffer[]} The raw response trailers as an array of buffers, alternating between header name and value.
import diagnosticsChannel from 'node:diagnostics_channel'

diagnosticsChannel.channel('undici:request:trailers').subscribe(({ request, trailers }) => {
  console.log('completed', request.completed)
  console.log(trailers.map((x) => x.toString()))
})

Event: 'undici:request:error'

Published when the request is about to error, before the error is surfaced to the caller.

  • message {Object}
    • request {Object} The same object published by 'undici:request:create'.
    • error {Error} The error the request is about to fail with.
import diagnosticsChannel from 'node:diagnostics_channel'

diagnosticsChannel.channel('undici:request:error').subscribe(({ request, error }) => {
  console.error(error)
})

Event: 'undici:client:sendHeaders'

Published immediately before the first byte of the request is written to the socket. The headers are published exactly as they will be sent to the server, in raw form.

  • message {Object}
    • request {Object} The same object published by 'undici:request:create'.
    • headers {string} The request headers as a single raw string, with lines separated by \r\n.
    • socket {net.Socket} The socket the request is written to.
import diagnosticsChannel from 'node:diagnostics_channel'

diagnosticsChannel.channel('undici:client:sendHeaders').subscribe(({ request, headers, socket }) => {
  console.log(`Full headers list: ${headers.split('\r\n')}`)
})

Event: 'undici:client:beforeConnect'

Published before a new connection is opened for any request. This event cannot be attributed to a specific request, because connections are pooled and shared.

  • message {Object}
    • connectParams {Object} The parameters used to open the connection.
      • host {string} The connection host, including the port if present.
      • hostname {string} The connection hostname.
      • protocol {string} The protocol, e.g. 'https:'.
      • port {string} The connection port.
      • servername {string|null} The TLS server name, or null.
    • connector {Function} The function that creates the socket.
import diagnosticsChannel from 'node:diagnostics_channel'

diagnosticsChannel.channel('undici:client:beforeConnect').subscribe(({ connectParams, connector }) => {
  const { host, hostname, protocol, port, servername } = connectParams
  // connector is the function that creates the socket
})

Event: 'undici:client:connected'

Published after a connection has been successfully established.

  • message {Object}
    • socket {net.Socket} The newly connected socket.
    • connectParams {Object} The parameters used to open the connection. See 'undici:client:beforeConnect' for the field descriptions.
    • connector {Function} The function that created the socket.
import diagnosticsChannel from 'node:diagnostics_channel'

diagnosticsChannel.channel('undici:client:connected').subscribe(({ socket, connectParams, connector }) => {
  const { host, hostname, protocol, port, servername } = connectParams
})

Event: 'undici:client:connectError'

Published when a connection could not be established.

  • message {Object}
    • error {Error} The error that prevented the connection.
    • socket {net.Socket} The socket associated with the failed attempt.
    • connectParams {Object} The parameters used to open the connection. See 'undici:client:beforeConnect' for the field descriptions.
    • connector {Function} The function that created the socket.
import diagnosticsChannel from 'node:diagnostics_channel'

diagnosticsChannel.channel('undici:client:connectError').subscribe(({ error, socket, connectParams, connector }) => {
  console.error(`Connect failed with ${error.message}`)
})

Event: 'undici:websocket:open'

Published after a WebSocket has successfully connected to a server.

  • message {Object}
    • 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.
    • protocol {string} The negotiated subprotocol.
    • extensions {string} The negotiated extensions.
    • websocket {WebSocket} The WebSocket instance.
    • handshakeResponse {Object} The HTTP response that upgraded the connection.
      • status {number} The HTTP status code: 101 for an HTTP/1.1 upgrade, or 200 for an HTTP/2 extended CONNECT.
      • statusText {string} The HTTP status message: 'Switching Protocols' for HTTP/1.1, and commonly 'OK' for HTTP/2.
      • headers {Object} The response headers from the server. The upgrade and connection headers are only present for HTTP/1.1 handshakes.
import diagnosticsChannel from 'node:diagnostics_channel'

diagnosticsChannel.channel('undici:websocket:open').subscribe(({
  address,
  protocol,
  extensions,
  websocket,
  handshakeResponse
}) => {
  console.log(address)
  console.log(protocol)
  console.log(extensions)
  console.log(handshakeResponse.status)
  console.log(handshakeResponse.headers)
})

Event: 'undici:websocket:close'

Published after the WebSocket connection has closed.

  • message {Object}
    • websocket {WebSocket} The WebSocket instance.
    • code {number} The closing status code.
    • reason {string} The closing reason.
import diagnosticsChannel from 'node:diagnostics_channel'

diagnosticsChannel.channel('undici:websocket:close').subscribe(({ websocket, code, reason }) => {
  console.log(code, reason)
})

Event: 'undici:websocket:socket_error'

Published when the underlying WebSocket socket experiences an error. Unlike the other WebSocket channels, the published message is the error itself.

  • error {Error} The socket error.
import diagnosticsChannel from 'node:diagnostics_channel'

diagnosticsChannel.channel('undici:websocket:socket_error').subscribe((error) => {
  console.error(error)
})

Event: 'undici:websocket:ping'

Published after the client receives a ping frame.

  • message {Object}
    • payload {Buffer|undefined} The optional application data carried by the frame.
    • websocket {WebSocket} The WebSocket instance.
import diagnosticsChannel from 'node:diagnostics_channel'

diagnosticsChannel.channel('undici:websocket:ping').subscribe(({ payload, websocket }) => {
  console.log(payload)
})

Event: 'undici:websocket:pong'

Published after the client receives a pong frame.

  • message {Object}
    • payload {Buffer|undefined} The optional application data carried by the frame.
    • websocket {WebSocket} The WebSocket instance.
import diagnosticsChannel from 'node:diagnostics_channel'

diagnosticsChannel.channel('undici:websocket:pong').subscribe(({ payload, websocket }) => {
  console.log(payload)
})

Event: 'undici:proxy:connected'

Published after a ProxyAgent has established a tunnel to the proxy server.

  • message {Object}
    • socket {net.Socket} The socket connected to the proxy.
    • connectParams {Object} The parameters used to establish the tunnel.
      • origin {string|URL} The proxy origin.
      • port {string} The proxy port.
      • path {string} The requested tunnel target, e.g. 'example.com:443'.
      • signal {AbortSignal|undefined} The signal associated with the request.
      • headers {Object} The headers sent in the CONNECT request.
      • servername {string|undefined} The TLS server name used for the proxy.
import diagnosticsChannel from 'node:diagnostics_channel'

diagnosticsChannel.channel('undici:proxy:connected').subscribe(({ socket, connectParams }) => {
  const { origin, port, path, signal, headers, servername } = connectParams
})

Event: 'undici:request:pending-requests'

Published when the dedupe interceptor's set of pending requests changes. The interceptor coalesces concurrent identical requests so that only one reaches the origin; this channel exposes that bookkeeping for monitoring and debugging.

  • message {Object}
    • type {string} Either 'added' when a new pending request is registered, or 'removed' when a pending request completes, whether successfully or with an error.
    • size {number} The number of pending requests after the change.
    • key {string} The deduplication key for the request, composed of the origin, method, path, and request headers.
import diagnosticsChannel from 'node:diagnostics_channel'

diagnosticsChannel.channel('undici:request:pending-requests').subscribe(({ type, size, key }) => {
  if (type === 'added') {
    console.log(`New pending request: ${key} (${size} total pending)`)
  } else {
    console.log(`Request completed: ${key} (${size} remaining)`)
  }
})

This is useful for verifying that deduplication is working, monitoring the number of concurrent in-flight requests, and debugging deduplication behaviour in production.