Skip to content

Commit

Permalink
Diagnostics channel support
Browse files Browse the repository at this point in the history
  • Loading branch information
crysmags committed May 2, 2024
1 parent e93dbd5 commit 01cd0f6
Show file tree
Hide file tree
Showing 5 changed files with 390 additions and 90 deletions.
57 changes: 57 additions & 0 deletions docs/docs/api/DiagnosticsChannel.md
Expand Up @@ -202,3 +202,60 @@ diagnosticsChannel.channel('undici:websocket:pong').subscribe(({ payload }) => {
console.log(payload)
})
```
The below channels collectively act as [`tracingChannel.tracePromise`](https://nodejs.org/api/diagnostics_channel.html#tracingchanneltracepromisefn-context-thisarg-args) on `fetch`. So all of them will publish the arguments passed to `fetch`.

## `tracing:undici:fetch:start`

This message is published when `fetch` is called, and will publish the arguments passed to `fetch`.

```js
import diagnosticsChannel from 'diagnostics_channel'
diagnosticsChannel.channel('tracing:undici:fetch:start').subscribe(({ input, init }) => {
console.log('input', input)
console.log('init', init)
})
```

## `tracing:undici:fetch:end`

This message is published at the end of `fetch`'s execution, and will publish any `error` from the synchronous part of `fetch`. Since `fetch` is asynchronous, this should be empty. This channel will publish the same values as `undici:fetch:start`, but we are including it to track when `fetch` finishes execution and to be consistent with [`TracingChannel`](https://nodejs.org/api/diagnostics_channel.html#class-tracingchannel).
```js
import diagnosticsChannel from 'diagnostics_channel'
diagnosticsChannel.channel('tracing:undici:fetch:end').subscribe(({ input, init, error }) => {
console.log('input', input)
console.log('init', init)
console.log('error', error) // should be empty
})
```
## `tracing:undici:fetch:asyncStart`
This message is published after `fetch` resolves or rejects. If `fetch` resolves, it publishes the response in `result`. If it rejects, it publishes the error in `error`.
```js
import diagnosticsChannel from 'diagnostics_channel'
diagnosticsChannel.channel('tracing:undici:fetch:asyncStart').subscribe(({ input, init, result, error }) => {
console.log('input', input)
console.log('init', init)
console.log('response', result)
console.log('error', error)
})
```
## `tracing:undici:fetch:asyncEnd`
This channel gets published the same values as and at the same time as `tracing:undici:fetch:asyncStart` in the case of [`tracingChannel.tracePromise`](https://nodejs.org/api/diagnostics_channel.html#tracingchanneltracepromisefn-context-thisarg-args)
```js
import diagnosticsChannel from 'diagnostics_channel'
diagnosticsChannel.channel('tracing:undici:fetch:asyncEnd').subscribe(({ input, init, result, error }) => {
console.log('input', input)
console.log('init', init)
console.log('response', result)
console.log('error', error)
})
```
## `tracing:undici:fetch:error`
This message is published when an error is thrown or promise rejects while calling `fetch`.
```js
import diagnosticsChannel from 'diagnostics_channel'
diagnosticsChannel.channel('tracing:undici:fetch:error').subscribe(({ input, init, error }) => {
console.log('input', input)
console.log('init', init)
console.log('error', error)
})
```
79 changes: 78 additions & 1 deletion lib/core/diagnostics.js
Expand Up @@ -6,6 +6,12 @@ const undiciDebugLog = util.debuglog('undici')
const fetchDebuglog = util.debuglog('fetch')
const websocketDebuglog = util.debuglog('websocket')
let isClientSet = false
let tracingChannel

if (diagnosticsChannel.tracingChannel) {
tracingChannel = diagnosticsChannel.tracingChannel('undici:fetch')
}

const channels = {
// Client
beforeConnect: diagnosticsChannel.channel('undici:client:beforeConnect'),
Expand All @@ -23,7 +29,9 @@ const channels = {
close: diagnosticsChannel.channel('undici:websocket:close'),
socketError: diagnosticsChannel.channel('undici:websocket:socket_error'),
ping: diagnosticsChannel.channel('undici:websocket:ping'),
pong: diagnosticsChannel.channel('undici:websocket:pong')
pong: diagnosticsChannel.channel('undici:websocket:pong'),
// Fetch channels
tracingChannel
}

if (undiciDebugLog.enabled || fetchDebuglog.enabled) {
Expand Down Expand Up @@ -114,6 +122,75 @@ if (undiciDebugLog.enabled || fetchDebuglog.enabled) {
isClientSet = true
}

// Track fetch requests
if (fetchDebuglog.enabled && diagnosticsChannel.tracingChannel) {
const debuglog = fetchDebuglog

tracingChannel.start.subscribe(evt => {
const {
input
} = evt
debuglog(
'fetch has started request to %s',
input
)
})

tracingChannel.end.subscribe(evt => {
const {
input
} = evt
debuglog(
'fetch has received response from %s',
input
)
})

tracingChannel.asyncStart.subscribe(evt => {
const {
input,
result,
error
} = evt
if (result && error) {
debuglog(
'fetch has received response for %s - HTTP %d, error is %s',
input,
result.status,
error.message
)
} else if (result) {
debuglog(
'fetch has received response for %s - HTTP %d',
input,
result.status
)
} else if (error) {
debuglog(
'fetch has errored for %s - %s',
input,
error.message
)
} else {
debuglog(
'fetch has started request to %s',
input
)
}
})

tracingChannel.error.subscribe(evt => {
const {
error
} = evt
debuglog(
'fetch error event received response %s',
error.message
)
})
isClientSet = true
}

if (websocketDebuglog.enabled) {
if (!isClientSet) {
const debuglog = undiciDebugLog.enabled ? undiciDebugLog : websocketDebuglog
Expand Down

0 comments on commit 01cd0f6

Please sign in to comment.