Skip to content

Commit b649130

Browse files
committed
add diagnostic channel and polyfill for non-node envs
1 parent b2ad0ca commit b649130

File tree

3 files changed

+81
-0
lines changed

3 files changed

+81
-0
lines changed

src/diagnostics-channel-esm.mts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// this is used in ESM environments where top level await is allowed,
2+
// but node:diagnostics_channel might not be present, such as browsers.
3+
import {
4+
type Channel,
5+
type TracingChannel,
6+
} from 'node:diagnostics_channel'
7+
export type { TracingChannel, Channel }
8+
9+
/**
10+
* no-op polyfills for non-node environments. tries to load the actual
11+
* diagnostics_channel module on platforms (bun, deno) that support it, but
12+
* fails gracefully if not found. This means that the first tick of metrics
13+
* and tracing will be missed, but that probably doesn't matter much.
14+
*/
15+
16+
// conditionally import from diagnostic_channel, fall back to dummyfill
17+
// all we actually have to mock is the hasSubscribers, since we alwasy check
18+
/* v8 ignore next */
19+
const dummy = { hasSubscribers: false }
20+
type LRUCacheDC = [Channel<unknown>, TracingChannel<unknown>]
21+
export const [metrics, tracing]: LRUCacheDC =
22+
await import('node:diagnostics_channel')
23+
.then(
24+
dc =>
25+
[
26+
dc.channel('lru-cache:metrics'),
27+
dc.tracingChannel('lru-cache'),
28+
] as LRUCacheDC,
29+
)
30+
.catch(() => [dummy, dummy] as unknown as LRUCacheDC)

src/diagnostics-channel.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// simple node version that imports from node builtin
2+
// this gets compiled to a require() commonjs-style override,
3+
// not using top level await on a conditional dynamic import
4+
import { tracingChannel, channel } from 'node:diagnostics_channel'
5+
export { tracingChannel, channel }
6+
import type { TracingChannel, Channel } from 'node:diagnostics_channel'
7+
export type { TracingChannel, Channel }
8+
export const metrics: Channel<unknown> = channel('lru-cache:metrics')
9+
export const tracing: TracingChannel<unknown> = tracingChannel('lru-cache')

test/dummy-diagnostics-channel.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import t from 'tap'
2+
import actualDC from 'node:diagnostics_channel'
3+
4+
t.test('diagnostics channel loads polyfills then fills in', async t => {
5+
const dc = await t.mockImport<
6+
typeof import('../src/diagnostics-channel-esm.mjs')
7+
>('../src/diagnostics-channel-esm.mjs', {
8+
'node:diagnostics_channel': actualDC,
9+
})
10+
actualDC.subscribe('lru-cache:metrics', () => {})
11+
const tc = actualDC.tracingChannel('lru-cache')
12+
tc.subscribe({
13+
start: () => {},
14+
asyncStart: () => {},
15+
asyncEnd: () => {},
16+
error: () => {},
17+
end: () => {},
18+
})
19+
20+
// verify that the dummies were not used
21+
t.equal(dc.metrics.hasSubscribers, true)
22+
t.equal(dc.tracing.hasSubscribers, true)
23+
t.equal(actualDC.channel('lru-cache:metrics').hasSubscribers, true)
24+
t.equal(tc.hasSubscribers, true)
25+
})
26+
27+
t.test('dummy dc that just says no subs', async t => {
28+
const dc = await t.mockImport<
29+
typeof import('../src/diagnostics-channel-esm.mjs')
30+
>('../src/diagnostics-channel-esm.mjs', {
31+
'node:diagnostics_channel': {
32+
get default() {
33+
throw new Error('no diagnostics channel for you!')
34+
},
35+
},
36+
})
37+
t.equal(dc.metrics.hasSubscribers, false)
38+
t.equal(dc.tracing.hasSubscribers, false)
39+
// these still have subs from previous test though
40+
t.equal(actualDC.channel('lru-cache:metrics').hasSubscribers, true)
41+
t.equal(actualDC.tracingChannel('lru-cache').hasSubscribers, true)
42+
})

0 commit comments

Comments
 (0)