@dudousxd/nestjs-diagnostics 0.2.3 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -0
- package/LICENSE +21 -0
- package/dist/channel.d.ts +20 -2
- package/dist/channel.d.ts.map +1 -1
- package/dist/channel.js +30 -1
- package/dist/channel.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/trace.d.ts +74 -0
- package/dist/trace.d.ts.map +1 -0
- package/dist/trace.js +196 -0
- package/dist/trace.js.map +1 -0
- package/dist/types.d.ts +137 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +12 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# @dudousxd/nestjs-diagnostics
|
|
2
2
|
|
|
3
|
+
## 0.3.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#7](https://github.com/DavideCarvalho/nestjs-diagnostics/pull/7) [`a78672e`](https://github.com/DavideCarvalho/nestjs-diagnostics/commit/a78672ef871610df13fb3cb875d15bc993c564ad) Thanks [@DavideCarvalho](https://github.com/DavideCarvalho)! - feat: ecosystem improvements across the diagnostics core and Telescope watcher.
|
|
8
|
+
|
|
9
|
+
- **Envelope schema version (`v`):** every emitted envelope now carries an explicit schema-version field (`v`) so recorders and watchers can evolve the payload shape over time and detect/route by version. The Telescope watcher reads `v` when recording entries.
|
|
10
|
+
- **Per-emit sampling hook:** emit accepts an optional per-emit sampling decision, letting callers cheaply drop a fraction of events at the emit site (before payload work is done) without disabling a channel wholesale.
|
|
11
|
+
- **`tracingChannel()` + `trace()` helper:** a span-like wrapper over `node:diagnostics_channel`'s tracing-channel semantics that pairs `start`/`end`/`asyncStart`/`asyncEnd`/`error` events for a single logical operation, so a synchronous block or a promise can be traced with correct begin/finish/error correlation. The `trace()` helper wraps a function (sync or async) and publishes the matched lifecycle events automatically, including the `error` channel on throw/reject.
|
|
12
|
+
- **Typed channel registry:** the channel registry is now generic over a compile-time payload-type map, so `channel(name)` and the corresponding publish/subscribe surfaces are typed to the registered payload for that channel name — catching mismatched payloads at compile time while staying erased at runtime.
|
|
13
|
+
- **Packaging hygiene:** the core package declares a conservative `sideEffects` allowlist (rather than `false`) that preserves the module-level `globalThis` / `Symbol.for` registry and context-accessor registration so a bundler can never tree-shake the cross-copy-stable global state away; pure modules remain tree-shakeable.
|
|
14
|
+
|
|
15
|
+
Also includes a `LICENSE` file at the repo root.
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- [#7](https://github.com/DavideCarvalho/nestjs-diagnostics/pull/7) [`a78672e`](https://github.com/DavideCarvalho/nestjs-diagnostics/commit/a78672ef871610df13fb3cb875d15bc993c564ad) Thanks [@DavideCarvalho](https://github.com/DavideCarvalho)! - chore: packaging hygiene — declare `sideEffects` for safe tree-shaking.
|
|
20
|
+
|
|
21
|
+
The core package now declares `sideEffects` as an explicit allowlist of the modules that register process-global state at import time (the cross-copy-stable channel registry and context accessor on `globalThis` via `Symbol.for`, plus the reset hooks): `registry`, `context-accessor`, `channel`, and `trace`. It is deliberately **not** `false`, so a bundler can never tree-shake those global registrations away and break cross-copy registry stability; pure modules stay tree-shakeable.
|
|
22
|
+
|
|
23
|
+
The telescope package declares `sideEffects: false` — it has no module-level side effects (the watcher subscribes to channels only at runtime, inside `register()`), so consumers get full tree-shaking.
|
|
24
|
+
|
|
25
|
+
No runtime behavior changes; the `exports`/`types` maps already resolve correctly under NodeNext.
|
|
26
|
+
|
|
3
27
|
## 0.2.3
|
|
4
28
|
|
|
5
29
|
### Patch Changes
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Davi Carvalho
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/channel.d.ts
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
import { type Channel } from 'node:diagnostics_channel';
|
|
2
|
-
import type { EmitOptions } from './types.js';
|
|
2
|
+
import type { EmitOptions, EventOf, LibOf, PayloadOf } from './types.js';
|
|
3
3
|
/** The prefix all channels created by this convention share. */
|
|
4
4
|
export declare const CHANNEL_PREFIX = "aviary";
|
|
5
|
+
/**
|
|
6
|
+
* Current envelope schema version, stamped onto every emitted
|
|
7
|
+
* {@link DiagnosticEvent} as `v`. Bump this only when the wire shape changes in a
|
|
8
|
+
* way observers must adapt to. Observers should tolerate envelopes without `v`
|
|
9
|
+
* (legacy emitters published before versioning) and treat them as version `1`.
|
|
10
|
+
*/
|
|
11
|
+
export declare const SCHEMA_VERSION = 1;
|
|
5
12
|
/**
|
|
6
13
|
* The channel name for a `<lib>`/`<event>` pair: `aviary:<lib>:<event>`. This is
|
|
7
14
|
* the cross-repo wire contract — keep it identical on producer and observer.
|
|
@@ -28,11 +35,22 @@ export declare function getChannel(lib: string, event: string): Channel;
|
|
|
28
35
|
* registered context accessor (if resolvable), else left undefined.
|
|
29
36
|
* - The envelope is built and published ONLY when the channel `hasSubscribers`,
|
|
30
37
|
* so emitting is effectively free when nothing is listening.
|
|
38
|
+
* - When `opts.sample` is given, it is consulted AFTER the `hasSubscribers` gate
|
|
39
|
+
* and BEFORE the envelope is built: a falsy result sheds this event without
|
|
40
|
+
* allocating anything. Default (no `sample`) always publishes when subscribed.
|
|
41
|
+
* - The envelope carries the current {@link SCHEMA_VERSION} as `v`.
|
|
31
42
|
* - Never throws: emitting observability must not break the caller.
|
|
32
43
|
*
|
|
33
44
|
* ```ts
|
|
34
45
|
* emit('billing', 'invoice-paid', { invoiceId: 'inv_123', amount: 4200 });
|
|
46
|
+
* // Shed 90% of a hot event:
|
|
47
|
+
* emit('authz', 'decision', payload, { sample: () => Math.random() < 0.1 });
|
|
35
48
|
* ```
|
|
49
|
+
*
|
|
50
|
+
* When `(lib, event)` is declared in the typed
|
|
51
|
+
* {@link import('./types.js').ChannelRegistry ChannelRegistry}, `payload` is
|
|
52
|
+
* checked against the declared type at compile time; every other pair keeps the
|
|
53
|
+
* untyped `unknown` payload. The runtime behavior is identical either way.
|
|
36
54
|
*/
|
|
37
|
-
export declare function emit(lib:
|
|
55
|
+
export declare function emit<TLib extends LibOf, TEvent extends EventOf<TLib>>(lib: TLib, event: TEvent, payload: PayloadOf<TLib, TEvent>, opts?: EmitOptions): void;
|
|
38
56
|
//# sourceMappingURL=channel.d.ts.map
|
package/dist/channel.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../src/channel.ts"],"names":[],"mappings":"AAAA,OAA4B,EAAE,KAAK,OAAO,EAAE,MAAM,0BAA0B,CAAC;AAG7E,OAAO,KAAK,EAAmB,WAAW,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../src/channel.ts"],"names":[],"mappings":"AAAA,OAA4B,EAAE,KAAK,OAAO,EAAE,MAAM,0BAA0B,CAAC;AAG7E,OAAO,KAAK,EAAmB,WAAW,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE1F,gEAAgE;AAChE,eAAO,MAAM,cAAc,WAAW,CAAC;AAEvC;;;;;GAKG;AACH,eAAO,MAAM,cAAc,IAAI,CAAC;AAEhC;;;GAGG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAE9D;AAqBD;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAc9D;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,IAAI,CAAC,IAAI,SAAS,KAAK,EAAE,MAAM,SAAS,OAAO,CAAC,IAAI,CAAC,EACnE,GAAG,EAAE,IAAI,EACT,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,EAChC,IAAI,CAAC,EAAE,WAAW,GACjB,IAAI,CAoBN"}
|
package/dist/channel.js
CHANGED
|
@@ -3,6 +3,13 @@ import { resolveTraceId } from './context-accessor.js';
|
|
|
3
3
|
import { onRegistryReset, registerChannel } from './registry.js';
|
|
4
4
|
/** The prefix all channels created by this convention share. */
|
|
5
5
|
export const CHANNEL_PREFIX = 'aviary';
|
|
6
|
+
/**
|
|
7
|
+
* Current envelope schema version, stamped onto every emitted
|
|
8
|
+
* {@link DiagnosticEvent} as `v`. Bump this only when the wire shape changes in a
|
|
9
|
+
* way observers must adapt to. Observers should tolerate envelopes without `v`
|
|
10
|
+
* (legacy emitters published before versioning) and treat them as version `1`.
|
|
11
|
+
*/
|
|
12
|
+
export const SCHEMA_VERSION = 1;
|
|
6
13
|
/**
|
|
7
14
|
* The channel name for a `<lib>`/`<event>` pair: `aviary:<lib>:<event>`. This is
|
|
8
15
|
* the cross-repo wire contract — keep it identical on producer and observer.
|
|
@@ -64,19 +71,41 @@ export function getChannel(lib, event) {
|
|
|
64
71
|
* registered context accessor (if resolvable), else left undefined.
|
|
65
72
|
* - The envelope is built and published ONLY when the channel `hasSubscribers`,
|
|
66
73
|
* so emitting is effectively free when nothing is listening.
|
|
74
|
+
* - When `opts.sample` is given, it is consulted AFTER the `hasSubscribers` gate
|
|
75
|
+
* and BEFORE the envelope is built: a falsy result sheds this event without
|
|
76
|
+
* allocating anything. Default (no `sample`) always publishes when subscribed.
|
|
77
|
+
* - The envelope carries the current {@link SCHEMA_VERSION} as `v`.
|
|
67
78
|
* - Never throws: emitting observability must not break the caller.
|
|
68
79
|
*
|
|
69
80
|
* ```ts
|
|
70
81
|
* emit('billing', 'invoice-paid', { invoiceId: 'inv_123', amount: 4200 });
|
|
82
|
+
* // Shed 90% of a hot event:
|
|
83
|
+
* emit('authz', 'decision', payload, { sample: () => Math.random() < 0.1 });
|
|
71
84
|
* ```
|
|
85
|
+
*
|
|
86
|
+
* When `(lib, event)` is declared in the typed
|
|
87
|
+
* {@link import('./types.js').ChannelRegistry ChannelRegistry}, `payload` is
|
|
88
|
+
* checked against the declared type at compile time; every other pair keeps the
|
|
89
|
+
* untyped `unknown` payload. The runtime behavior is identical either way.
|
|
72
90
|
*/
|
|
73
91
|
export function emit(lib, event, payload, opts) {
|
|
74
92
|
const channel = getChannel(lib, event);
|
|
75
93
|
if (!channel.hasSubscribers)
|
|
76
94
|
return;
|
|
77
95
|
try {
|
|
96
|
+
// Load-shedding gate: consulted only when subscribed, before any allocation.
|
|
97
|
+
// A throwing sampler is treated as a skip (caught below) — never published.
|
|
98
|
+
if (opts?.sample !== undefined && !opts.sample())
|
|
99
|
+
return;
|
|
78
100
|
const traceId = opts?.traceId ?? resolveTraceId();
|
|
79
|
-
const envelope = {
|
|
101
|
+
const envelope = {
|
|
102
|
+
v: SCHEMA_VERSION,
|
|
103
|
+
ts: Date.now(),
|
|
104
|
+
lib,
|
|
105
|
+
event,
|
|
106
|
+
traceId,
|
|
107
|
+
payload,
|
|
108
|
+
};
|
|
80
109
|
channel.publish(envelope);
|
|
81
110
|
}
|
|
82
111
|
catch {
|
package/dist/channel.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"channel.js","sourceRoot":"","sources":["../src/channel.ts"],"names":[],"mappings":"AAAA,OAAO,mBAAqC,MAAM,0BAA0B,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAGjE,gEAAgE;AAChE,MAAM,CAAC,MAAM,cAAc,GAAG,QAAQ,CAAC;AAEvC;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,GAAW,EAAE,KAAa;IACpD,OAAO,GAAG,cAAc,IAAI,GAAG,IAAI,KAAK,EAAE,CAAC;AAC7C,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,YAAY,GAAG,IAAI,GAAG,EAAgC,CAAC;AAE7D,8EAA8E;AAC9E,6EAA6E;AAC7E,eAAe,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC,CAAC;AAE5C;;;;;;;;;;GAUG;AACH,MAAM,UAAU,UAAU,CAAC,GAAW,EAAE,KAAa;IACnD,IAAI,OAAO,GAAG,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACpC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAClC,IAAI,MAAM,KAAK,SAAS;YAAE,OAAO,MAAM,CAAC;IAC1C,CAAC;SAAM,CAAC;QACN,OAAO,GAAG,IAAI,GAAG,EAAmB,CAAC;QACrC,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IACjC,CAAC;IACD,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACrC,MAAM,OAAO,GAAG,mBAAmB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAClD,eAAe,CAAC,IAAI,CAAC,CAAC;IACtB,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAC5B,OAAO,OAAO,CAAC;AACjB,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"channel.js","sourceRoot":"","sources":["../src/channel.ts"],"names":[],"mappings":"AAAA,OAAO,mBAAqC,MAAM,0BAA0B,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAGjE,gEAAgE;AAChE,MAAM,CAAC,MAAM,cAAc,GAAG,QAAQ,CAAC;AAEvC;;;;;GAKG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC;AAEhC;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,GAAW,EAAE,KAAa;IACpD,OAAO,GAAG,cAAc,IAAI,GAAG,IAAI,KAAK,EAAE,CAAC;AAC7C,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,YAAY,GAAG,IAAI,GAAG,EAAgC,CAAC;AAE7D,8EAA8E;AAC9E,6EAA6E;AAC7E,eAAe,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC,CAAC;AAE5C;;;;;;;;;;GAUG;AACH,MAAM,UAAU,UAAU,CAAC,GAAW,EAAE,KAAa;IACnD,IAAI,OAAO,GAAG,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACpC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAClC,IAAI,MAAM,KAAK,SAAS;YAAE,OAAO,MAAM,CAAC;IAC1C,CAAC;SAAM,CAAC;QACN,OAAO,GAAG,IAAI,GAAG,EAAmB,CAAC;QACrC,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IACjC,CAAC;IACD,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACrC,MAAM,OAAO,GAAG,mBAAmB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAClD,eAAe,CAAC,IAAI,CAAC,CAAC;IACtB,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAC5B,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,UAAU,IAAI,CAClB,GAAS,EACT,KAAa,EACb,OAAgC,EAChC,IAAkB;IAElB,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACvC,IAAI,CAAC,OAAO,CAAC,cAAc;QAAE,OAAO;IACpC,IAAI,CAAC;QACH,6EAA6E;QAC7E,4EAA4E;QAC5E,IAAI,IAAI,EAAE,MAAM,KAAK,SAAS,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE;YAAE,OAAO;QACzD,MAAM,OAAO,GAAG,IAAI,EAAE,OAAO,IAAI,cAAc,EAAE,CAAC;QAClD,MAAM,QAAQ,GAAoB;YAChC,CAAC,EAAE,cAAc;YACjB,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE;YACd,GAAG;YACH,KAAK;YACL,OAAO;YACP,OAAO;SACR,CAAC;QACF,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,yDAAyD;IAC3D,CAAC;AACH,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
export { CHANNEL_PREFIX, channelName, emit, getChannel } from './channel.js';
|
|
1
|
+
export { CHANNEL_PREFIX, channelName, emit, getChannel, SCHEMA_VERSION } from './channel.js';
|
|
2
2
|
export { CONTEXT_ACCESSOR, type ContextAccessor, type ContextStore, getContextAccessor, resolveTraceId, setContextAccessor, type UserRef, } from './context-accessor.js';
|
|
3
3
|
export { onChannelRegistered, registerChannel, registeredChannels, resetRegistry, } from './registry.js';
|
|
4
|
-
export type
|
|
4
|
+
export { SPAN_SCHEMA_VERSION, trace, type TraceChannelNames, traceChannelNames, type TracingChannel, tracingChannel, } from './trace.js';
|
|
5
|
+
export type { ChannelRegistry, DiagnosticEvent, EmitOptions, EventOf, LibOf, PayloadOf, SpanEvent, SpanPhase, TraceOptions, } from './types.js';
|
|
5
6
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC7F,OAAO,EACL,gBAAgB,EAChB,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,kBAAkB,EAClB,cAAc,EACd,kBAAkB,EAClB,KAAK,OAAO,GACb,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,mBAAmB,EACnB,eAAe,EACf,kBAAkB,EAClB,aAAa,GACd,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,mBAAmB,EACnB,KAAK,EACL,KAAK,iBAAiB,EACtB,iBAAiB,EACjB,KAAK,cAAc,EACnB,cAAc,GACf,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,eAAe,EACf,eAAe,EACf,WAAW,EACX,OAAO,EACP,KAAK,EACL,SAAS,EACT,SAAS,EACT,SAAS,EACT,YAAY,GACb,MAAM,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
export { CHANNEL_PREFIX, channelName, emit, getChannel } from './channel.js';
|
|
1
|
+
export { CHANNEL_PREFIX, channelName, emit, getChannel, SCHEMA_VERSION } from './channel.js';
|
|
2
2
|
export { CONTEXT_ACCESSOR, getContextAccessor, resolveTraceId, setContextAccessor, } from './context-accessor.js';
|
|
3
3
|
export { onChannelRegistered, registerChannel, registeredChannels, resetRegistry, } from './registry.js';
|
|
4
|
+
export { SPAN_SCHEMA_VERSION, trace, traceChannelNames, tracingChannel, } from './trace.js';
|
|
4
5
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC7F,OAAO,EACL,gBAAgB,EAGhB,kBAAkB,EAClB,cAAc,EACd,kBAAkB,GAEnB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,mBAAmB,EACnB,eAAe,EACf,kBAAkB,EAClB,aAAa,GACd,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,mBAAmB,EACnB,KAAK,EAEL,iBAAiB,EAEjB,cAAc,GACf,MAAM,YAAY,CAAC"}
|
package/dist/trace.d.ts
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { EventOf, LibOf, PayloadOf, TraceOptions } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Span envelope schema version, stamped onto every {@link SpanEvent} as `v`.
|
|
4
|
+
* Versioned independently of the POINT `SCHEMA_VERSION` so the two wire shapes
|
|
5
|
+
* can evolve apart. Observers should treat an absent `v` as version `1`.
|
|
6
|
+
*/
|
|
7
|
+
export declare const SPAN_SCHEMA_VERSION = 1;
|
|
8
|
+
/**
|
|
9
|
+
* The five span sub-channel names for a `(lib, event)` pair. They extend the
|
|
10
|
+
* POINT `aviary:<lib>:<event>` name with a `:<phase>` suffix, mirroring Node's
|
|
11
|
+
* own `tracingChannel` sub-channels (start/end/asyncStart/asyncEnd/error) while
|
|
12
|
+
* staying inside the `aviary:` convention so the same generic observer can read
|
|
13
|
+
* both POINT and SPAN traffic.
|
|
14
|
+
*/
|
|
15
|
+
export interface TraceChannelNames {
|
|
16
|
+
start: string;
|
|
17
|
+
end: string;
|
|
18
|
+
asyncStart: string;
|
|
19
|
+
asyncEnd: string;
|
|
20
|
+
error: string;
|
|
21
|
+
}
|
|
22
|
+
/** Build the five span sub-channel names for a `(lib, event)` pair. */
|
|
23
|
+
export declare function traceChannelNames(lib: string, event: string): TraceChannelNames;
|
|
24
|
+
/**
|
|
25
|
+
* Wrap an (async) operation and publish span-like start / end / asyncStart /
|
|
26
|
+
* asyncEnd / error events over `node:diagnostics_channel`, so consumers get real
|
|
27
|
+
* start/end/error pairing with timing for authz decisions, durable steps, etc.
|
|
28
|
+
*
|
|
29
|
+
* Naming follows the existing convention: events ride
|
|
30
|
+
* `aviary:<lib>:<event>:<phase>` (see {@link traceChannelNames}). `emit` is
|
|
31
|
+
* unchanged — `trace` is the additional span surface.
|
|
32
|
+
*
|
|
33
|
+
* Lifecycle:
|
|
34
|
+
* - Sync `fn`: publishes `start` then, on return, `end` (with `result`); on
|
|
35
|
+
* throw, `error`. The value/throw is propagated to the caller unchanged.
|
|
36
|
+
* - Async `fn` (returns a promise): publishes `start` synchronously, `asyncStart`
|
|
37
|
+
* when the promise settles begins resolving, then `asyncEnd` (with `result`)
|
|
38
|
+
* on fulfilment or `error` on rejection. The promise is returned to the caller.
|
|
39
|
+
*
|
|
40
|
+
* Cost: when NO span sub-channel has a subscriber, `trace` calls `fn` and returns
|
|
41
|
+
* its value directly — no span id, no envelope, no timing — so the hot path is a
|
|
42
|
+
* handful of `hasSubscribers` reads.
|
|
43
|
+
*
|
|
44
|
+
* Trace id: resolved once at span start from `opts.traceId` (wins) else the
|
|
45
|
+
* registered context accessor, and stamped on every phase event.
|
|
46
|
+
*
|
|
47
|
+
* ```ts
|
|
48
|
+
* const decision = trace('authz', 'decision', () => evaluate(req), { subject });
|
|
49
|
+
* const out = await trace('durable', 'step', () => runStep(), { name });
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
export declare function trace<TLib extends LibOf, TEvent extends EventOf<TLib>, R>(lib: TLib, event: TEvent, fn: () => R, payload?: PayloadOf<TLib, TEvent>, opts?: TraceOptions): R;
|
|
53
|
+
/** A {@link trace} bound to one `(lib, event)` pair — see {@link tracingChannel}. */
|
|
54
|
+
export interface TracingChannel<TPayload = unknown> {
|
|
55
|
+
/** The base `aviary:<lib>:<event>` channel name. */
|
|
56
|
+
readonly name: string;
|
|
57
|
+
/** The five span sub-channel names. */
|
|
58
|
+
readonly channels: TraceChannelNames;
|
|
59
|
+
/** Trace an operation on this channel; same semantics as {@link trace}. */
|
|
60
|
+
trace<R>(fn: () => R, payload?: TPayload, opts?: TraceOptions): R;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* A {@link trace} factory bound to a single `(lib, event)` pair — the ergonomic,
|
|
64
|
+
* reusable form for a hot call site that always traces the same operation. Named
|
|
65
|
+
* after Node's `diagnostics_channel.tracingChannel()` (whose sub-channels we
|
|
66
|
+
* mirror) but kept inside the `aviary:` convention.
|
|
67
|
+
*
|
|
68
|
+
* ```ts
|
|
69
|
+
* const decision = tracingChannel('authz', 'decision');
|
|
70
|
+
* decision.trace(() => evaluate(req), { subject });
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
export declare function tracingChannel<TLib extends LibOf, TEvent extends EventOf<TLib>>(lib: TLib, event: TEvent): TracingChannel<PayloadOf<TLib, TEvent>>;
|
|
74
|
+
//# sourceMappingURL=trace.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trace.d.ts","sourceRoot":"","sources":["../src/trace.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAwB,YAAY,EAAE,MAAM,YAAY,CAAC;AAEhG;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,IAAI,CAAC;AAErC;;;;;;GAMG;AACH,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,uEAAuE;AACvE,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,iBAAiB,CAS/E;AA0GD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,KAAK,CAAC,IAAI,SAAS,KAAK,EAAE,MAAM,SAAS,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,EACvE,GAAG,EAAE,IAAI,EACT,KAAK,EAAE,MAAM,EACb,EAAE,EAAE,MAAM,CAAC,EACX,OAAO,CAAC,EAAE,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,EACjC,IAAI,CAAC,EAAE,YAAY,GAClB,CAAC,CAyDH;AAED,qFAAqF;AACrF,MAAM,WAAW,cAAc,CAAC,QAAQ,GAAG,OAAO;IAChD,oDAAoD;IACpD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,uCAAuC;IACvC,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,CAAC;IACrC,2EAA2E;IAC3E,KAAK,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,EAAE,YAAY,GAAG,CAAC,CAAC;CACnE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,IAAI,SAAS,KAAK,EAAE,MAAM,SAAS,OAAO,CAAC,IAAI,CAAC,EAC7E,GAAG,EAAE,IAAI,EACT,KAAK,EAAE,MAAM,GACZ,cAAc,CAAC,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAMzC"}
|
package/dist/trace.js
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import diagnostics_channel from 'node:diagnostics_channel';
|
|
2
|
+
import { channelName } from './channel.js';
|
|
3
|
+
import { resolveTraceId } from './context-accessor.js';
|
|
4
|
+
import { onRegistryReset, registerChannel } from './registry.js';
|
|
5
|
+
/**
|
|
6
|
+
* Span envelope schema version, stamped onto every {@link SpanEvent} as `v`.
|
|
7
|
+
* Versioned independently of the POINT `SCHEMA_VERSION` so the two wire shapes
|
|
8
|
+
* can evolve apart. Observers should treat an absent `v` as version `1`.
|
|
9
|
+
*/
|
|
10
|
+
export const SPAN_SCHEMA_VERSION = 1;
|
|
11
|
+
/** Build the five span sub-channel names for a `(lib, event)` pair. */
|
|
12
|
+
export function traceChannelNames(lib, event) {
|
|
13
|
+
const base = channelName(lib, event);
|
|
14
|
+
return {
|
|
15
|
+
start: `${base}:start`,
|
|
16
|
+
end: `${base}:end`,
|
|
17
|
+
asyncStart: `${base}:asyncStart`,
|
|
18
|
+
asyncEnd: `${base}:asyncEnd`,
|
|
19
|
+
error: `${base}:error`,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Per-`(lib, event)` cache of the resolved span {@link Channel}s, keyed by `lib`
|
|
24
|
+
* then `event` — the same two-level memo strategy `getChannel` uses, so the
|
|
25
|
+
* steady state is two `Map.get`s with no string allocation. The first trace of a
|
|
26
|
+
* pair pays the name builds + `diagnostics_channel.channel()` lookups + registry
|
|
27
|
+
* insert; every call after returns the cached object.
|
|
28
|
+
*/
|
|
29
|
+
const spanCache = new Map();
|
|
30
|
+
// Drop the memo cache whenever the registry is reset (test-only), so the next
|
|
31
|
+
// trace re-registers the base channel. Mirrors channel.ts.
|
|
32
|
+
onRegistryReset(() => spanCache.clear());
|
|
33
|
+
function getSpanChannels(lib, event) {
|
|
34
|
+
let byEvent = spanCache.get(lib);
|
|
35
|
+
if (byEvent !== undefined) {
|
|
36
|
+
const cached = byEvent.get(event);
|
|
37
|
+
if (cached !== undefined)
|
|
38
|
+
return cached;
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
byEvent = new Map();
|
|
42
|
+
spanCache.set(lib, byEvent);
|
|
43
|
+
}
|
|
44
|
+
const names = traceChannelNames(lib, event);
|
|
45
|
+
const channels = {
|
|
46
|
+
base: channelName(lib, event),
|
|
47
|
+
start: diagnostics_channel.channel(names.start),
|
|
48
|
+
end: diagnostics_channel.channel(names.end),
|
|
49
|
+
asyncStart: diagnostics_channel.channel(names.asyncStart),
|
|
50
|
+
asyncEnd: diagnostics_channel.channel(names.asyncEnd),
|
|
51
|
+
error: diagnostics_channel.channel(names.error),
|
|
52
|
+
};
|
|
53
|
+
// Register the BASE channel name for discovery: a generic observer that knows
|
|
54
|
+
// the base name can derive all five span sub-channels via traceChannelNames.
|
|
55
|
+
registerChannel(channels.base);
|
|
56
|
+
byEvent.set(event, channels);
|
|
57
|
+
return channels;
|
|
58
|
+
}
|
|
59
|
+
/** True when ANY of the five span sub-channels currently has a subscriber. */
|
|
60
|
+
function anySubscribed(ch) {
|
|
61
|
+
return (ch.start.hasSubscribers ||
|
|
62
|
+
ch.end.hasSubscribers ||
|
|
63
|
+
ch.asyncStart.hasSubscribers ||
|
|
64
|
+
ch.asyncEnd.hasSubscribers ||
|
|
65
|
+
ch.error.hasSubscribers);
|
|
66
|
+
}
|
|
67
|
+
let spanCounter = 0;
|
|
68
|
+
/** A cheap, process-unique span id. Allocated only when a span is observed. */
|
|
69
|
+
function nextSpanId() {
|
|
70
|
+
spanCounter = (spanCounter + 1) >>> 0;
|
|
71
|
+
return `${Date.now().toString(36)}-${spanCounter.toString(36)}`;
|
|
72
|
+
}
|
|
73
|
+
/** Publish one phase event on its sub-channel, never throwing. */
|
|
74
|
+
function publishPhase(channel, phase, lib, event, spanId, traceId, extra) {
|
|
75
|
+
if (!channel.hasSubscribers)
|
|
76
|
+
return;
|
|
77
|
+
try {
|
|
78
|
+
const envelope = {
|
|
79
|
+
v: SPAN_SCHEMA_VERSION,
|
|
80
|
+
ts: Date.now(),
|
|
81
|
+
lib,
|
|
82
|
+
event,
|
|
83
|
+
phase,
|
|
84
|
+
spanId,
|
|
85
|
+
traceId,
|
|
86
|
+
...extra,
|
|
87
|
+
};
|
|
88
|
+
channel.publish(envelope);
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
// Observability must never break the traced code path.
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/** Detect a thenable so a sync `fn` returning a promise is traced as async. */
|
|
95
|
+
function isPromiseLike(value) {
|
|
96
|
+
return (value != null &&
|
|
97
|
+
(typeof value === 'object' || typeof value === 'function') &&
|
|
98
|
+
typeof value.then === 'function');
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Wrap an (async) operation and publish span-like start / end / asyncStart /
|
|
102
|
+
* asyncEnd / error events over `node:diagnostics_channel`, so consumers get real
|
|
103
|
+
* start/end/error pairing with timing for authz decisions, durable steps, etc.
|
|
104
|
+
*
|
|
105
|
+
* Naming follows the existing convention: events ride
|
|
106
|
+
* `aviary:<lib>:<event>:<phase>` (see {@link traceChannelNames}). `emit` is
|
|
107
|
+
* unchanged — `trace` is the additional span surface.
|
|
108
|
+
*
|
|
109
|
+
* Lifecycle:
|
|
110
|
+
* - Sync `fn`: publishes `start` then, on return, `end` (with `result`); on
|
|
111
|
+
* throw, `error`. The value/throw is propagated to the caller unchanged.
|
|
112
|
+
* - Async `fn` (returns a promise): publishes `start` synchronously, `asyncStart`
|
|
113
|
+
* when the promise settles begins resolving, then `asyncEnd` (with `result`)
|
|
114
|
+
* on fulfilment or `error` on rejection. The promise is returned to the caller.
|
|
115
|
+
*
|
|
116
|
+
* Cost: when NO span sub-channel has a subscriber, `trace` calls `fn` and returns
|
|
117
|
+
* its value directly — no span id, no envelope, no timing — so the hot path is a
|
|
118
|
+
* handful of `hasSubscribers` reads.
|
|
119
|
+
*
|
|
120
|
+
* Trace id: resolved once at span start from `opts.traceId` (wins) else the
|
|
121
|
+
* registered context accessor, and stamped on every phase event.
|
|
122
|
+
*
|
|
123
|
+
* ```ts
|
|
124
|
+
* const decision = trace('authz', 'decision', () => evaluate(req), { subject });
|
|
125
|
+
* const out = await trace('durable', 'step', () => runStep(), { name });
|
|
126
|
+
* ```
|
|
127
|
+
*/
|
|
128
|
+
export function trace(lib, event, fn, payload, opts) {
|
|
129
|
+
const channels = getSpanChannels(lib, event);
|
|
130
|
+
// Hot path: nothing is listening → run fn directly, allocate nothing.
|
|
131
|
+
if (!anySubscribed(channels)) {
|
|
132
|
+
return fn();
|
|
133
|
+
}
|
|
134
|
+
const spanId = nextSpanId();
|
|
135
|
+
const traceId = opts?.traceId ?? resolveTraceId();
|
|
136
|
+
const startedAt = performance.now();
|
|
137
|
+
publishPhase(channels.start, 'start', lib, event, spanId, traceId, { payload });
|
|
138
|
+
let result;
|
|
139
|
+
try {
|
|
140
|
+
result = fn();
|
|
141
|
+
}
|
|
142
|
+
catch (error) {
|
|
143
|
+
publishPhase(channels.error, 'error', lib, event, spanId, traceId, {
|
|
144
|
+
error,
|
|
145
|
+
durationMs: performance.now() - startedAt,
|
|
146
|
+
});
|
|
147
|
+
throw error;
|
|
148
|
+
}
|
|
149
|
+
if (isPromiseLike(result)) {
|
|
150
|
+
// Async op: end marks the synchronous portion completing; asyncStart marks
|
|
151
|
+
// the continuation; asyncEnd carries the settled result/error + duration.
|
|
152
|
+
publishPhase(channels.end, 'end', lib, event, spanId, traceId, {
|
|
153
|
+
durationMs: performance.now() - startedAt,
|
|
154
|
+
});
|
|
155
|
+
publishPhase(channels.asyncStart, 'asyncStart', lib, event, spanId, traceId, {});
|
|
156
|
+
const settled = Promise.resolve(result).then((value) => {
|
|
157
|
+
publishPhase(channels.asyncEnd, 'asyncEnd', lib, event, spanId, traceId, {
|
|
158
|
+
result: value,
|
|
159
|
+
durationMs: performance.now() - startedAt,
|
|
160
|
+
});
|
|
161
|
+
return value;
|
|
162
|
+
}, (error) => {
|
|
163
|
+
publishPhase(channels.error, 'error', lib, event, spanId, traceId, {
|
|
164
|
+
error,
|
|
165
|
+
durationMs: performance.now() - startedAt,
|
|
166
|
+
});
|
|
167
|
+
throw error;
|
|
168
|
+
});
|
|
169
|
+
return settled;
|
|
170
|
+
}
|
|
171
|
+
// Sync success.
|
|
172
|
+
publishPhase(channels.end, 'end', lib, event, spanId, traceId, {
|
|
173
|
+
result,
|
|
174
|
+
durationMs: performance.now() - startedAt,
|
|
175
|
+
});
|
|
176
|
+
return result;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* A {@link trace} factory bound to a single `(lib, event)` pair — the ergonomic,
|
|
180
|
+
* reusable form for a hot call site that always traces the same operation. Named
|
|
181
|
+
* after Node's `diagnostics_channel.tracingChannel()` (whose sub-channels we
|
|
182
|
+
* mirror) but kept inside the `aviary:` convention.
|
|
183
|
+
*
|
|
184
|
+
* ```ts
|
|
185
|
+
* const decision = tracingChannel('authz', 'decision');
|
|
186
|
+
* decision.trace(() => evaluate(req), { subject });
|
|
187
|
+
* ```
|
|
188
|
+
*/
|
|
189
|
+
export function tracingChannel(lib, event) {
|
|
190
|
+
return {
|
|
191
|
+
name: channelName(lib, event),
|
|
192
|
+
channels: traceChannelNames(lib, event),
|
|
193
|
+
trace: (fn, payload, opts) => trace(lib, event, fn, payload, opts),
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
//# sourceMappingURL=trace.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trace.js","sourceRoot":"","sources":["../src/trace.ts"],"names":[],"mappings":"AAAA,OAAO,mBAAqC,MAAM,0BAA0B,CAAC;AAC7E,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAGjE;;;;GAIG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC;AAiBrC,uEAAuE;AACvE,MAAM,UAAU,iBAAiB,CAAC,GAAW,EAAE,KAAa;IAC1D,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACrC,OAAO;QACL,KAAK,EAAE,GAAG,IAAI,QAAQ;QACtB,GAAG,EAAE,GAAG,IAAI,MAAM;QAClB,UAAU,EAAE,GAAG,IAAI,aAAa;QAChC,QAAQ,EAAE,GAAG,IAAI,WAAW;QAC5B,KAAK,EAAE,GAAG,IAAI,QAAQ;KACvB,CAAC;AACJ,CAAC;AAYD;;;;;;GAMG;AACH,MAAM,SAAS,GAAG,IAAI,GAAG,EAAqC,CAAC;AAE/D,8EAA8E;AAC9E,2DAA2D;AAC3D,eAAe,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,CAAC;AAEzC,SAAS,eAAe,CAAC,GAAW,EAAE,KAAa;IACjD,IAAI,OAAO,GAAG,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACjC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAClC,IAAI,MAAM,KAAK,SAAS;YAAE,OAAO,MAAM,CAAC;IAC1C,CAAC;SAAM,CAAC;QACN,OAAO,GAAG,IAAI,GAAG,EAAwB,CAAC;QAC1C,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAC9B,CAAC;IACD,MAAM,KAAK,GAAG,iBAAiB,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC5C,MAAM,QAAQ,GAAiB;QAC7B,IAAI,EAAE,WAAW,CAAC,GAAG,EAAE,KAAK,CAAC;QAC7B,KAAK,EAAE,mBAAmB,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC;QAC/C,GAAG,EAAE,mBAAmB,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC;QAC3C,UAAU,EAAE,mBAAmB,CAAC,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC;QACzD,QAAQ,EAAE,mBAAmB,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC;QACrD,KAAK,EAAE,mBAAmB,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC;KAChD,CAAC;IACF,8EAA8E;IAC9E,6EAA6E;IAC7E,eAAe,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC/B,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IAC7B,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,8EAA8E;AAC9E,SAAS,aAAa,CAAC,EAAgB;IACrC,OAAO,CACL,EAAE,CAAC,KAAK,CAAC,cAAc;QACvB,EAAE,CAAC,GAAG,CAAC,cAAc;QACrB,EAAE,CAAC,UAAU,CAAC,cAAc;QAC5B,EAAE,CAAC,QAAQ,CAAC,cAAc;QAC1B,EAAE,CAAC,KAAK,CAAC,cAAc,CACxB,CAAC;AACJ,CAAC;AAED,IAAI,WAAW,GAAG,CAAC,CAAC;AAEpB,+EAA+E;AAC/E,SAAS,UAAU;IACjB,WAAW,GAAG,CAAC,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;IACtC,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;AAClE,CAAC;AAED,kEAAkE;AAClE,SAAS,YAAY,CACnB,OAAgB,EAChB,KAAgB,EAChB,GAAW,EACX,KAAa,EACb,MAAc,EACd,OAA2B,EAC3B,KAAoF;IAEpF,IAAI,CAAC,OAAO,CAAC,cAAc;QAAE,OAAO;IACpC,IAAI,CAAC;QACH,MAAM,QAAQ,GAAc;YAC1B,CAAC,EAAE,mBAAmB;YACtB,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE;YACd,GAAG;YACH,KAAK;YACL,KAAK;YACL,MAAM;YACN,OAAO;YACP,GAAG,KAAK;SACT,CAAC;QACF,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,uDAAuD;IACzD,CAAC;AACH,CAAC;AAED,+EAA+E;AAC/E,SAAS,aAAa,CAAC,KAAc;IACnC,OAAO,CACL,KAAK,IAAI,IAAI;QACb,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,UAAU,CAAC;QAC1D,OAAQ,KAA4B,CAAC,IAAI,KAAK,UAAU,CACzD,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,UAAU,KAAK,CACnB,GAAS,EACT,KAAa,EACb,EAAW,EACX,OAAiC,EACjC,IAAmB;IAEnB,MAAM,QAAQ,GAAG,eAAe,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAE7C,sEAAsE;IACtE,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC7B,OAAO,EAAE,EAAE,CAAC;IACd,CAAC;IAED,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,MAAM,OAAO,GAAG,IAAI,EAAE,OAAO,IAAI,cAAc,EAAE,CAAC;IAClD,MAAM,SAAS,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;IAEpC,YAAY,CAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;IAEhF,IAAI,MAAS,CAAC;IACd,IAAI,CAAC;QACH,MAAM,GAAG,EAAE,EAAE,CAAC;IAChB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,YAAY,CAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE;YACjE,KAAK;YACL,UAAU,EAAE,WAAW,CAAC,GAAG,EAAE,GAAG,SAAS;SAC1C,CAAC,CAAC;QACH,MAAM,KAAK,CAAC;IACd,CAAC;IAED,IAAI,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC;QAC1B,2EAA2E;QAC3E,0EAA0E;QAC1E,YAAY,CAAC,QAAQ,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE;YAC7D,UAAU,EAAE,WAAW,CAAC,GAAG,EAAE,GAAG,SAAS;SAC1C,CAAC,CAAC;QACH,YAAY,CAAC,QAAQ,CAAC,UAAU,EAAE,YAAY,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC;QACjF,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CAC1C,CAAC,KAAK,EAAE,EAAE;YACR,YAAY,CAAC,QAAQ,CAAC,QAAQ,EAAE,UAAU,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE;gBACvE,MAAM,EAAE,KAAK;gBACb,UAAU,EAAE,WAAW,CAAC,GAAG,EAAE,GAAG,SAAS;aAC1C,CAAC,CAAC;YACH,OAAO,KAAK,CAAC;QACf,CAAC,EACD,CAAC,KAAK,EAAE,EAAE;YACR,YAAY,CAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE;gBACjE,KAAK;gBACL,UAAU,EAAE,WAAW,CAAC,GAAG,EAAE,GAAG,SAAS;aAC1C,CAAC,CAAC;YACH,MAAM,KAAK,CAAC;QACd,CAAC,CACF,CAAC;QACF,OAAO,OAAuB,CAAC;IACjC,CAAC;IAED,gBAAgB;IAChB,YAAY,CAAC,QAAQ,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE;QAC7D,MAAM;QACN,UAAU,EAAE,WAAW,CAAC,GAAG,EAAE,GAAG,SAAS;KAC1C,CAAC,CAAC;IACH,OAAO,MAAM,CAAC;AAChB,CAAC;AAYD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,cAAc,CAC5B,GAAS,EACT,KAAa;IAEb,OAAO;QACL,IAAI,EAAE,WAAW,CAAC,GAAG,EAAE,KAAK,CAAC;QAC7B,QAAQ,EAAE,iBAAiB,CAAC,GAAG,EAAE,KAAK,CAAC;QACvC,KAAK,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,CAAC;KACnE,CAAC;AACJ,CAAC"}
|
package/dist/types.d.ts
CHANGED
|
@@ -6,6 +6,14 @@
|
|
|
6
6
|
* emitting library and identified by `lib` + `event`.
|
|
7
7
|
*/
|
|
8
8
|
export interface DiagnosticEvent<TPayload = unknown> {
|
|
9
|
+
/**
|
|
10
|
+
* Envelope schema version — bumped only when this wire shape changes in a way
|
|
11
|
+
* observers must adapt to. Stamped by `emit` with the current
|
|
12
|
+
* {@link import('./channel.js').SCHEMA_VERSION SCHEMA_VERSION}. Optional on the
|
|
13
|
+
* type so observers stay tolerant of legacy envelopes published before
|
|
14
|
+
* versioning existed (treat an absent `v` as the original, unversioned shape).
|
|
15
|
+
*/
|
|
16
|
+
v?: number;
|
|
9
17
|
/** Epoch millis when the event was emitted (`Date.now()` at publish time). */
|
|
10
18
|
ts: number;
|
|
11
19
|
/** The emitting library, e.g. `'billing'` — the `<lib>` in `aviary:<lib>:<event>`. */
|
|
@@ -21,6 +29,116 @@ export interface DiagnosticEvent<TPayload = unknown> {
|
|
|
21
29
|
/** The library-defined payload. Opaque to this package and to observers. */
|
|
22
30
|
payload: TPayload;
|
|
23
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* The optional, consumer-augmented typed channel registry: a `lib → event →
|
|
34
|
+
* payload` map. It is EMPTY by default — the untyped path (`payload: unknown`)
|
|
35
|
+
* is always available and unchanged. A library declares its channels by
|
|
36
|
+
* augmenting this interface via TypeScript declaration merging:
|
|
37
|
+
*
|
|
38
|
+
* ```ts
|
|
39
|
+
* declare module '@dudousxd/nestjs-diagnostics' {
|
|
40
|
+
* interface ChannelRegistry {
|
|
41
|
+
* billing: {
|
|
42
|
+
* 'invoice-paid': { invoiceId: string; amount: number };
|
|
43
|
+
* };
|
|
44
|
+
* }
|
|
45
|
+
* }
|
|
46
|
+
* ```
|
|
47
|
+
*
|
|
48
|
+
* Once augmented, `emit('billing', 'invoice-paid', ...)` and
|
|
49
|
+
* `trace('billing', 'invoice-paid', ...)` get compile-time payload checking for
|
|
50
|
+
* that channel; every other `(lib, event)` pair keeps the untyped `unknown`
|
|
51
|
+
* payload. This is purely a type-level mechanism: there is no runtime registry
|
|
52
|
+
* of payload shapes and nothing is allocated.
|
|
53
|
+
*/
|
|
54
|
+
export interface ChannelRegistry {
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* `string`, kept assignable from any literal but offering autocomplete for the
|
|
58
|
+
* registered names. The `& {}` defeats literal-union widening so registered
|
|
59
|
+
* keys still surface as suggestions while every other string is accepted — this
|
|
60
|
+
* is what keeps the untyped path open even after the registry is augmented.
|
|
61
|
+
*/
|
|
62
|
+
type LooseString = string & {};
|
|
63
|
+
/**
|
|
64
|
+
* Every `lib` declared in the {@link ChannelRegistry} (for autocomplete), plus
|
|
65
|
+
* any other `string` (the untyped path). Collapses to plain `string` when the
|
|
66
|
+
* registry is empty.
|
|
67
|
+
*/
|
|
68
|
+
export type LibOf = (keyof ChannelRegistry & string) | LooseString;
|
|
69
|
+
/**
|
|
70
|
+
* Every `event` declared for `TLib` in the {@link ChannelRegistry} (for
|
|
71
|
+
* autocomplete), plus any other `string` (the untyped path). Collapses to plain
|
|
72
|
+
* `string` when `TLib` is not a registered lib.
|
|
73
|
+
*/
|
|
74
|
+
export type EventOf<TLib extends string> = TLib extends keyof ChannelRegistry ? (keyof ChannelRegistry[TLib] & string) | LooseString : string;
|
|
75
|
+
/**
|
|
76
|
+
* The declared payload type for `(TLib, TEvent)` in the {@link ChannelRegistry},
|
|
77
|
+
* or `unknown` when the pair is not registered. This is what gives `emit`/`trace`
|
|
78
|
+
* their compile-time payload types for registered channels while leaving every
|
|
79
|
+
* other call on the original untyped `unknown` path.
|
|
80
|
+
*/
|
|
81
|
+
export type PayloadOf<TLib extends string, TEvent extends string> = TLib extends keyof ChannelRegistry ? TEvent extends keyof ChannelRegistry[TLib] ? ChannelRegistry[TLib][TEvent] : unknown : unknown;
|
|
82
|
+
/**
|
|
83
|
+
* The phase of a traced operation, published as `phase` on every
|
|
84
|
+
* {@link SpanEvent}. Mirrors Node's `tracingChannel` sub-channels so observers
|
|
85
|
+
* can pair start/end and start/error into span-like records.
|
|
86
|
+
*/
|
|
87
|
+
export type SpanPhase = 'start' | 'end' | 'asyncStart' | 'asyncEnd' | 'error';
|
|
88
|
+
/**
|
|
89
|
+
* The envelope published on the span sub-channels by `trace`. Extends the
|
|
90
|
+
* {@link DiagnosticEvent} POINT shape with span correlation + timing so a
|
|
91
|
+
* consumer can reconstruct real start/end/error pairs:
|
|
92
|
+
*
|
|
93
|
+
* - `aviary:<lib>:<event>:start` — `phase: 'start'`, carries `payload`.
|
|
94
|
+
* - `aviary:<lib>:<event>:end` — sync (or settled) completion, carries `result`
|
|
95
|
+
* + `durationMs`.
|
|
96
|
+
* - `aviary:<lib>:<event>:asyncStart` / `:asyncEnd` — the async continuation of
|
|
97
|
+
* a promise-returning op; `asyncEnd` carries `result`/`error` + `durationMs`.
|
|
98
|
+
* - `aviary:<lib>:<event>:error` — `phase: 'error'`, carries `error` (+
|
|
99
|
+
* `durationMs`).
|
|
100
|
+
*
|
|
101
|
+
* Every event of a single span shares a `spanId` so observers can correlate
|
|
102
|
+
* them without relying on subscription ordering.
|
|
103
|
+
*/
|
|
104
|
+
export interface SpanEvent<TPayload = unknown, TResult = unknown> {
|
|
105
|
+
/**
|
|
106
|
+
* Span envelope schema version, stamped by `trace` with
|
|
107
|
+
* {@link import('./trace.js').SPAN_SCHEMA_VERSION SPAN_SCHEMA_VERSION}.
|
|
108
|
+
* Versioned independently of the POINT {@link DiagnosticEvent} `v`. Optional
|
|
109
|
+
* so observers stay tolerant of legacy/untagged envelopes.
|
|
110
|
+
*/
|
|
111
|
+
v?: number;
|
|
112
|
+
/** Epoch millis when this phase event was published (`Date.now()`). */
|
|
113
|
+
ts: number;
|
|
114
|
+
/** The emitting library — the `<lib>` in `aviary:<lib>:<event>`. */
|
|
115
|
+
lib: string;
|
|
116
|
+
/** The traced operation name — the `<event>` in `aviary:<lib>:<event>`. */
|
|
117
|
+
event: string;
|
|
118
|
+
/** Which phase of the span this is. */
|
|
119
|
+
phase: SpanPhase;
|
|
120
|
+
/**
|
|
121
|
+
* Stable per-span correlation id shared by every phase event of one `trace`
|
|
122
|
+
* call. Lets observers pair start↔end / start↔error regardless of ordering.
|
|
123
|
+
*/
|
|
124
|
+
spanId: string;
|
|
125
|
+
/**
|
|
126
|
+
* Trace id for the current request, when resolvable. Same semantics + stable
|
|
127
|
+
* monomorphic shape as {@link DiagnosticEvent.traceId}.
|
|
128
|
+
*/
|
|
129
|
+
traceId?: string | undefined;
|
|
130
|
+
/** The caller-supplied payload, present on the `start` event. */
|
|
131
|
+
payload?: TPayload;
|
|
132
|
+
/** The operation's return value, present on `end`/`asyncEnd` on success. */
|
|
133
|
+
result?: TResult;
|
|
134
|
+
/** The thrown/rejected value, present on `error` (and `asyncEnd` on failure). */
|
|
135
|
+
error?: unknown;
|
|
136
|
+
/**
|
|
137
|
+
* Wall-clock duration in fractional millis from `start` to this phase,
|
|
138
|
+
* present on `end`/`asyncEnd`/`error`. Measured with `performance.now()`.
|
|
139
|
+
*/
|
|
140
|
+
durationMs?: number;
|
|
141
|
+
}
|
|
24
142
|
/** Optional per-emit overrides. */
|
|
25
143
|
export interface EmitOptions {
|
|
26
144
|
/**
|
|
@@ -29,5 +147,24 @@ export interface EmitOptions {
|
|
|
29
147
|
* any), or leave `traceId` undefined.
|
|
30
148
|
*/
|
|
31
149
|
traceId?: string;
|
|
150
|
+
/**
|
|
151
|
+
* Optional load-shedding hook. Consulted by `emit` only AFTER the channel has
|
|
152
|
+
* subscribers and BEFORE the envelope is built/published: return `false` to
|
|
153
|
+
* drop this event without allocating the envelope, `true` to publish. Omit for
|
|
154
|
+
* the default (always publish when subscribed). A thrown sampler is treated as
|
|
155
|
+
* a skip — observability must never break the caller. Hot libraries can pass a
|
|
156
|
+
* cheap probabilistic predicate, e.g. `{ sample: () => Math.random() < 0.1 }`.
|
|
157
|
+
*/
|
|
158
|
+
sample?: () => boolean;
|
|
159
|
+
}
|
|
160
|
+
/** Optional per-`trace` overrides. */
|
|
161
|
+
export interface TraceOptions {
|
|
162
|
+
/**
|
|
163
|
+
* An explicit trace id for the whole span. When provided it wins over the
|
|
164
|
+
* registered {@link ContextAccessor} and is stamped on every phase event.
|
|
165
|
+
* Omit to auto-fill from the accessor (resolved once at span start).
|
|
166
|
+
*/
|
|
167
|
+
traceId?: string;
|
|
32
168
|
}
|
|
169
|
+
export {};
|
|
33
170
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,WAAW,eAAe,CAAC,QAAQ,GAAG,OAAO;IACjD,8EAA8E;IAC9E,EAAE,EAAE,MAAM,CAAC;IACX,sFAAsF;IACtF,GAAG,EAAE,MAAM,CAAC;IACZ,uFAAuF;IACvF,KAAK,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,4EAA4E;IAC5E,OAAO,EAAE,QAAQ,CAAC;CACnB;AAED,mCAAmC;AACnC,MAAM,WAAW,WAAW;IAC1B;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,WAAW,eAAe,CAAC,QAAQ,GAAG,OAAO;IACjD;;;;;;OAMG;IACH,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,8EAA8E;IAC9E,EAAE,EAAE,MAAM,CAAC;IACX,sFAAsF;IACtF,GAAG,EAAE,MAAM,CAAC;IACZ,uFAAuF;IACvF,KAAK,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,4EAA4E;IAC5E,OAAO,EAAE,QAAQ,CAAC;CACnB;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,WAAW,eAAe;CAAG;AAEnC;;;;;GAKG;AACH,KAAK,WAAW,GAAG,MAAM,GAAG,EAAE,CAAC;AAE/B;;;;GAIG;AACH,MAAM,MAAM,KAAK,GAAG,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC,GAAG,WAAW,CAAC;AAEnE;;;;GAIG;AACH,MAAM,MAAM,OAAO,CAAC,IAAI,SAAS,MAAM,IAAI,IAAI,SAAS,MAAM,eAAe,GACzE,CAAC,MAAM,eAAe,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,GAAG,WAAW,GACpD,MAAM,CAAC;AAEX;;;;;GAKG;AACH,MAAM,MAAM,SAAS,CACnB,IAAI,SAAS,MAAM,EACnB,MAAM,SAAS,MAAM,IACnB,IAAI,SAAS,MAAM,eAAe,GAClC,MAAM,SAAS,MAAM,eAAe,CAAC,IAAI,CAAC,GACxC,eAAe,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,GAC7B,OAAO,GACT,OAAO,CAAC;AAEZ;;;;GAIG;AACH,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,KAAK,GAAG,YAAY,GAAG,UAAU,GAAG,OAAO,CAAC;AAE9E;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,SAAS,CAAC,QAAQ,GAAG,OAAO,EAAE,OAAO,GAAG,OAAO;IAC9D;;;;;OAKG;IACH,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,uEAAuE;IACvE,EAAE,EAAE,MAAM,CAAC;IACX,oEAAoE;IACpE,GAAG,EAAE,MAAM,CAAC;IACZ,2EAA2E;IAC3E,KAAK,EAAE,MAAM,CAAC;IACd,uCAAuC;IACvC,KAAK,EAAE,SAAS,CAAC;IACjB;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,iEAAiE;IACjE,OAAO,CAAC,EAAE,QAAQ,CAAC;IACnB,4EAA4E;IAC5E,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,iFAAiF;IACjF,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,mCAAmC;AACnC,MAAM,WAAW,WAAW;IAC1B;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,MAAM,OAAO,CAAC;CACxB;AAED,sCAAsC;AACtC,MAAM,WAAW,YAAY;IAC3B;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dudousxd/nestjs-diagnostics",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "A standard convention for @dudousxd/nestjs-* libs to emit observability events over node:diagnostics_channel.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -24,6 +24,17 @@
|
|
|
24
24
|
"README.md",
|
|
25
25
|
"CHANGELOG.md"
|
|
26
26
|
],
|
|
27
|
+
"//sideEffects": "NOT false: registry.ts and context-accessor.ts register process-global state on globalThis via Symbol.for AT IMPORT TIME (the cross-copy-stable channel registry + context accessor), and channel.ts/trace.ts register a reset hook at module load. A bundler told sideEffects:false could tree-shake these initializers away, breaking cross-copy global stability. The array lists exactly the side-effectful modules (matching both src and published dist paths); pure modules (index, types) stay tree-shakeable.",
|
|
28
|
+
"sideEffects": [
|
|
29
|
+
"**/registry.js",
|
|
30
|
+
"**/registry.ts",
|
|
31
|
+
"**/context-accessor.js",
|
|
32
|
+
"**/context-accessor.ts",
|
|
33
|
+
"**/channel.js",
|
|
34
|
+
"**/channel.ts",
|
|
35
|
+
"**/trace.js",
|
|
36
|
+
"**/trace.ts"
|
|
37
|
+
],
|
|
27
38
|
"devDependencies": {
|
|
28
39
|
"@types/node": "^20.0.0",
|
|
29
40
|
"typescript": "^5.4.0",
|