@dudousxd/nestjs-diagnostics 0.8.0 → 0.9.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.
Files changed (64) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +31 -1
  3. package/dist/channel.d.ts +1 -1
  4. package/dist/channel.d.ts.map +1 -1
  5. package/dist/channel.js +3 -1
  6. package/dist/channel.js.map +1 -1
  7. package/dist/index.d.ts +2 -0
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +2 -0
  10. package/dist/index.js.map +1 -1
  11. package/dist/nestjs/delivery.d.ts +92 -0
  12. package/dist/nestjs/delivery.d.ts.map +1 -0
  13. package/dist/nestjs/delivery.js +2 -0
  14. package/dist/nestjs/delivery.js.map +1 -0
  15. package/dist/nestjs/diagnostics.explorer.d.ts +51 -11
  16. package/dist/nestjs/diagnostics.explorer.d.ts.map +1 -1
  17. package/dist/nestjs/diagnostics.explorer.js +209 -53
  18. package/dist/nestjs/diagnostics.explorer.js.map +1 -1
  19. package/dist/nestjs/diagnostics.module.d.ts +9 -2
  20. package/dist/nestjs/diagnostics.module.d.ts.map +1 -1
  21. package/dist/nestjs/diagnostics.module.js +23 -3
  22. package/dist/nestjs/diagnostics.module.js.map +1 -1
  23. package/dist/nestjs/diagnostics.options.d.ts +31 -0
  24. package/dist/nestjs/diagnostics.options.d.ts.map +1 -0
  25. package/dist/nestjs/diagnostics.options.js +3 -0
  26. package/dist/nestjs/diagnostics.options.js.map +1 -0
  27. package/dist/nestjs/index.d.ts +6 -3
  28. package/dist/nestjs/index.d.ts.map +1 -1
  29. package/dist/nestjs/index.js +4 -2
  30. package/dist/nestjs/index.js.map +1 -1
  31. package/dist/nestjs/on-diagnostic.decorator.d.ts +33 -7
  32. package/dist/nestjs/on-diagnostic.decorator.d.ts.map +1 -1
  33. package/dist/nestjs/on-diagnostic.decorator.js +0 -9
  34. package/dist/nestjs/on-diagnostic.decorator.js.map +1 -1
  35. package/dist/nestjs/queue-transport.d.ts +47 -0
  36. package/dist/nestjs/queue-transport.d.ts.map +1 -0
  37. package/dist/nestjs/queue-transport.js +45 -0
  38. package/dist/nestjs/queue-transport.js.map +1 -0
  39. package/dist/nestjs/role.d.ts +13 -0
  40. package/dist/nestjs/role.d.ts.map +1 -0
  41. package/dist/nestjs/role.js +13 -0
  42. package/dist/nestjs/role.js.map +1 -0
  43. package/dist/nestjs/transports.d.ts +125 -0
  44. package/dist/nestjs/transports.d.ts.map +1 -0
  45. package/dist/nestjs/transports.js +127 -0
  46. package/dist/nestjs/transports.js.map +1 -0
  47. package/dist/official.d.ts +2 -2
  48. package/dist/redis-relay.d.ts +60 -0
  49. package/dist/redis-relay.d.ts.map +1 -0
  50. package/dist/redis-relay.js +170 -0
  51. package/dist/redis-relay.js.map +1 -0
  52. package/dist/relayed.d.ts +8 -0
  53. package/dist/relayed.d.ts.map +1 -0
  54. package/dist/relayed.js +31 -0
  55. package/dist/relayed.js.map +1 -0
  56. package/dist/trace.d.ts.map +1 -1
  57. package/dist/trace.js +2 -0
  58. package/dist/trace.js.map +1 -1
  59. package/dist/types.d.ts +9 -0
  60. package/dist/types.d.ts.map +1 -1
  61. package/package.json +14 -6
  62. package/skills/emit-diagnostics/SKILL.md +5 -2
  63. package/skills/react-with-on-diagnostic/SKILL.md +41 -13
  64. package/skills/trace-spans/SKILL.md +2 -1
@@ -0,0 +1,170 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { CHANNEL_PREFIX, channelName, getChannel } from './channel.js';
3
+ import { onChannelRegistered, registeredChannels } from './registry.js';
4
+ import { publishRelayed } from './relayed.js';
5
+ const DEFAULT_REDIS_CHANNEL = 'aviary:diagnostics:relay';
6
+ /** Strip the `aviary:` prefix and split on the FIRST colon — the event segment may contain dots
7
+ * (e.g. `durable:run.failed`), but the lib/event boundary is the first colon after the prefix. */
8
+ function parseChannelName(name) {
9
+ const prefix = `${CHANNEL_PREFIX}:`;
10
+ if (!name.startsWith(prefix))
11
+ return null;
12
+ const rest = name.slice(prefix.length);
13
+ const idx = rest.indexOf(':');
14
+ if (idx <= 0 || idx === rest.length - 1)
15
+ return null;
16
+ return { lib: rest.slice(0, idx), event: rest.slice(idx + 1) };
17
+ }
18
+ /**
19
+ * Relay diagnostics events across processes over Redis pub/sub. The envelope crosses as JSON with
20
+ * its `id` intact, and the re-emitted copy is marked as relayed (see {@link publishRelayed}). Forwards selected local
21
+ * `aviary:<lib>:<event>` channels to Redis and re-emits Redis-received events onto the local bus, so
22
+ * `@OnDiagnostic` handlers / `getChannel(...).subscribe(...)` fire cross-process. Loop-safe via nodeId
23
+ * echo suppression and a re-emit guard. Never throws into `emit()` or the Redis handler. Does NOT
24
+ * close the `pub`/`sub` connections — the caller owns them.
25
+ *
26
+ * Forwarding happens off the emitter's call stack: selected events are queued and, once per event
27
+ * loop turn, serialized and published in emit order (one Redis message per event, sent as a single
28
+ * pipeline when `pub` supports it).
29
+ *
30
+ * @returns a teardown that publishes any queued events, then removes all local subscriptions and
31
+ * the Redis message handler.
32
+ */
33
+ export function createDiagnosticsRedisRelay(options) {
34
+ const { pub } = options;
35
+ const sub = options.receive === false ? undefined : options.sub;
36
+ if (options.receive !== false && sub === undefined) {
37
+ throw new Error('@dudousxd/nestjs-diagnostics: the Redis relay needs a `sub` connection, or `receive: false` for a publish-only relay');
38
+ }
39
+ const redisChannel = options.redisChannel ?? DEFAULT_REDIS_CHANNEL;
40
+ const nodeId = options.nodeId ?? randomUUID();
41
+ const forwardAll = options.all === true;
42
+ const libs = options.libs ?? [];
43
+ const exact = options.channels ?? [];
44
+ const subscriptions = [];
45
+ const subscribed = new Set();
46
+ const reEmitting = new WeakSet();
47
+ const pending = [];
48
+ let scheduled = null;
49
+ const publishOne = (message) => {
50
+ try {
51
+ pub.publish(redisChannel, message);
52
+ }
53
+ catch {
54
+ // a failing publish drops only its own event
55
+ }
56
+ };
57
+ const flush = () => {
58
+ if (scheduled !== null) {
59
+ clearImmediate(scheduled);
60
+ scheduled = null;
61
+ }
62
+ if (pending.length === 0)
63
+ return;
64
+ const messages = [];
65
+ for (const env of pending.splice(0)) {
66
+ try {
67
+ messages.push(JSON.stringify({ node: nodeId, env }));
68
+ }
69
+ catch {
70
+ // an unserializable event is dropped without affecting the rest of the batch
71
+ }
72
+ }
73
+ if (messages.length > 1 && typeof pub.pipeline === 'function') {
74
+ try {
75
+ const pipeline = pub.pipeline();
76
+ for (const message of messages)
77
+ pipeline.publish(redisChannel, message);
78
+ pipeline.exec();
79
+ }
80
+ catch {
81
+ // never throw out of the flush
82
+ }
83
+ return;
84
+ }
85
+ for (const message of messages)
86
+ publishOne(message);
87
+ };
88
+ const forward = (msg) => {
89
+ if (typeof msg !== 'object' || msg === null)
90
+ return;
91
+ if (reEmitting.has(msg))
92
+ return; // a re-emitted remote event — do not send it back
93
+ pending.push(msg);
94
+ scheduled ??= setImmediate(flush);
95
+ };
96
+ const subscribeRef = (ref) => {
97
+ const name = channelName(ref.lib, ref.event);
98
+ if (subscribed.has(name))
99
+ return;
100
+ getChannel(ref.lib, ref.event).subscribe(forward);
101
+ subscribed.add(name);
102
+ subscriptions.push({ ref, listener: forward });
103
+ };
104
+ const wildcardMatches = (name) => {
105
+ if (forwardAll)
106
+ return name.startsWith(`${CHANNEL_PREFIX}:`);
107
+ return libs.some((lib) => name.startsWith(`${CHANNEL_PREFIX}:${lib}:`));
108
+ };
109
+ for (const ref of exact)
110
+ subscribeRef(ref);
111
+ const hasWildcard = forwardAll || libs.length > 0;
112
+ if (hasWildcard) {
113
+ for (const name of registeredChannels()) {
114
+ if (wildcardMatches(name)) {
115
+ const ref = parseChannelName(name);
116
+ if (ref)
117
+ subscribeRef(ref);
118
+ }
119
+ }
120
+ }
121
+ const offRegistered = hasWildcard
122
+ ? onChannelRegistered((name) => {
123
+ if (wildcardMatches(name)) {
124
+ const ref = parseChannelName(name);
125
+ if (ref)
126
+ subscribeRef(ref);
127
+ }
128
+ })
129
+ : null;
130
+ const onMessage = (channel, raw) => {
131
+ if (channel !== redisChannel)
132
+ return;
133
+ let parsed;
134
+ try {
135
+ parsed = JSON.parse(raw);
136
+ }
137
+ catch {
138
+ return; // ignore malformed
139
+ }
140
+ if (parsed.node === nodeId)
141
+ return; // our own echo
142
+ const env = parsed.env;
143
+ if (!env || typeof env.lib !== 'string' || typeof env.event !== 'string')
144
+ return;
145
+ reEmitting.add(env);
146
+ try {
147
+ publishRelayed(env, () => getChannel(env.lib, env.event).publish(env));
148
+ }
149
+ catch {
150
+ // a local subscriber threw — never propagate into the message handler
151
+ }
152
+ finally {
153
+ reEmitting.delete(env);
154
+ }
155
+ };
156
+ sub?.subscribe(redisChannel);
157
+ sub?.on('message', onMessage);
158
+ return () => {
159
+ flush();
160
+ for (const { ref, listener } of subscriptions) {
161
+ getChannel(ref.lib, ref.event).unsubscribe(listener);
162
+ }
163
+ subscriptions.length = 0;
164
+ subscribed.clear();
165
+ offRegistered?.();
166
+ sub?.removeListener('message', onMessage);
167
+ sub?.unsubscribe(redisChannel);
168
+ };
169
+ }
170
+ //# sourceMappingURL=redis-relay.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redis-relay.js","sourceRoot":"","sources":["../src/redis-relay.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Run `publish` with `env` marked as a relayed copy. Call it from a relay that re-emits an event
3
+ * received from another process onto the local bus.
4
+ */
5
+ export declare function publishRelayed(env: object, publish: () => void): void;
6
+ /** Whether `env` is a relayed copy being re-emitted right now (it was emitted in another process). */
7
+ export declare function isRelayed(env: object): boolean;
8
+ //# sourceMappingURL=relayed.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relayed.d.ts","sourceRoot":"","sources":["../src/relayed.ts"],"names":[],"mappings":"AAcA;;;GAGG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,IAAI,GAAG,IAAI,CAOrE;AAED,sGAAsG;AACtG,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAE9C"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Envelopes a relay is re-emitting right now: copies of an event that was emitted in ANOTHER
3
+ * process. Listener dispatch reads it to deliver only at the origin. With a delivering transport
4
+ * (`queue`, `durable`), the process that called `emit` hands each `(listener, event)` pair over
5
+ * once, and a relayed copy of the same event is never handed over again.
6
+ *
7
+ * Held on a `Symbol.for` slot of `globalThis`, so relays and dispatch agree even when more than
8
+ * one copy of this package is loaded.
9
+ */
10
+ const RELAYED_KEY = Symbol.for('@dudousxd/nestjs-diagnostics:relayed');
11
+ const slots = globalThis;
12
+ const relayed = slots[RELAYED_KEY] ?? new WeakSet();
13
+ slots[RELAYED_KEY] = relayed;
14
+ /**
15
+ * Run `publish` with `env` marked as a relayed copy. Call it from a relay that re-emits an event
16
+ * received from another process onto the local bus.
17
+ */
18
+ export function publishRelayed(env, publish) {
19
+ relayed.add(env);
20
+ try {
21
+ publish();
22
+ }
23
+ finally {
24
+ relayed.delete(env);
25
+ }
26
+ }
27
+ /** Whether `env` is a relayed copy being re-emitted right now (it was emitted in another process). */
28
+ export function isRelayed(env) {
29
+ return relayed.has(env);
30
+ }
31
+ //# sourceMappingURL=relayed.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relayed.js","sourceRoot":"","sources":["../src/relayed.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,WAAW,GAAG,MAAM,CAAC,GAAG,CAAC,sCAAsC,CAAC,CAAC;AACvE,MAAM,KAAK,GAAG,UAAqE,CAAC;AACpF,MAAM,OAAO,GAAoB,KAAK,CAAC,WAAW,CAAC,IAAI,IAAI,OAAO,EAAU,CAAC;AAC7E,KAAK,CAAC,WAAW,CAAC,GAAG,OAAO,CAAC;AAE7B;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,GAAW,EAAE,OAAmB;IAC7D,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACjB,IAAI,CAAC;QACH,OAAO,EAAE,CAAC;IACZ,CAAC;YAAS,CAAC;QACT,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACtB,CAAC;AACH,CAAC;AAED,sGAAsG;AACtG,MAAM,UAAU,SAAS,CAAC,GAAW;IACnC,OAAO,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAC1B,CAAC"}
@@ -1 +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"}
1
+ {"version":3,"file":"trace.d.ts","sourceRoot":"","sources":["../src/trace.ts"],"names":[],"mappings":"AAKA,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;AA2GD;;;;;;;;;;;;;;;;;;;;;;;;;;;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 CHANGED
@@ -1,3 +1,4 @@
1
+ import { randomUUID } from 'node:crypto';
1
2
  import diagnostics_channel from 'node:diagnostics_channel';
2
3
  import { channelName } from './channel.js';
3
4
  import { resolveTraceId } from './context-accessor.js';
@@ -77,6 +78,7 @@ function publishPhase(channel, phase, lib, event, spanId, traceId, extra) {
77
78
  try {
78
79
  const envelope = {
79
80
  v: SPAN_SCHEMA_VERSION,
81
+ id: randomUUID(),
80
82
  ts: Date.now(),
81
83
  lib,
82
84
  event,
package/dist/trace.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"trace.js","sourceRoot":"","sources":["../src/trace.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"trace.js","sourceRoot":"","sources":["../src/trace.ts"],"names":[],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -14,6 +14,13 @@ export interface DiagnosticEvent<TPayload = unknown> {
14
14
  * versioning existed (treat an absent `v` as the original, unversioned shape).
15
15
  */
16
16
  v?: number;
17
+ /**
18
+ * Unique id of this envelope (a UUID), stamped by `emit`. Relays carry it unchanged, so the
19
+ * same event has the same `id` in every process it reaches. Delivering transports use it as
20
+ * the idempotency key: one delivery per `(listener, id)`. Optional on the type so observers
21
+ * stay tolerant of envelopes published before ids existed.
22
+ */
23
+ id?: string;
17
24
  /** Epoch millis when the event was emitted (`Date.now()` at publish time). */
18
25
  ts: number;
19
26
  /** The emitting library, e.g. `'billing'` — the `<lib>` in `aviary:<lib>:<event>`. */
@@ -116,6 +123,8 @@ export interface SpanEvent<TPayload = unknown, TResult = unknown> {
116
123
  * so observers stay tolerant of legacy/untagged envelopes.
117
124
  */
118
125
  v?: number;
126
+ /** Unique id of this phase envelope (a UUID), stamped by `trace`. Correlate phases with `spanId`. */
127
+ id?: string;
119
128
  /** Epoch millis when this phase event was published (`Date.now()`). */
120
129
  ts: number;
121
130
  /** The emitting library — the `<lib>` in `aviary:<lib>:<event>`. */
@@ -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;;;;;;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;IAClB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;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;IACvB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,sCAAsC;AACtC,MAAM,WAAW,YAAY;IAC3B;;;;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;;;;;OAKG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,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;IAClB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;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,qGAAqG;IACrG,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,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;IACvB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;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.8.0",
3
+ "version": "0.9.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": {
@@ -40,7 +40,8 @@
40
40
  "peerDependencies": {
41
41
  "@nestjs/common": "^10 || ^11 || ^12",
42
42
  "@nestjs/core": "^10 || ^11 || ^12",
43
- "reflect-metadata": "^0.2"
43
+ "reflect-metadata": "^0.2",
44
+ "bullmq": "^5"
44
45
  },
45
46
  "peerDependenciesMeta": {
46
47
  "@nestjs/common": {
@@ -51,6 +52,9 @@
51
52
  },
52
53
  "reflect-metadata": {
53
54
  "optional": true
55
+ },
56
+ "bullmq": {
57
+ "optional": true
54
58
  }
55
59
  },
56
60
  "files": [
@@ -68,18 +72,22 @@
68
72
  "**/channel.js",
69
73
  "**/channel.ts",
70
74
  "**/trace.js",
71
- "**/trace.ts"
75
+ "**/trace.ts",
76
+ "**/relayed.js",
77
+ "**/relayed.ts"
72
78
  ],
73
79
  "devDependencies": {
74
80
  "@nestjs/authentication": "0.1.5",
75
81
  "@nestjs/authorization": "0.1.3",
76
- "@nestjs/common": "12.0.4",
77
- "@nestjs/core": "12.0.4",
82
+ "@nestjs/common": "12.3.3",
83
+ "@nestjs/core": "12.3.3",
78
84
  "@nestjs/mail": "0.0.2",
79
85
  "@nestjs/resilience": "0.0.3",
80
- "@nestjs/testing": "12.0.4",
86
+ "@nestjs/testing": "12.3.3",
81
87
  "@nestjs/workflows": "0.0.5",
82
88
  "@types/node": "20.19.43",
89
+ "bullmq": "5.81.5",
90
+ "ioredis": "5.11.1",
83
91
  "reflect-metadata": "0.2.2",
84
92
  "typescript": "5.9.3",
85
93
  "unplugin-swc": "1.6.0",
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: emit-diagnostics
3
- description: Emit observability events from @dudousxd/nestjs-diagnostics with emit(lib, event, payload, opts) over node:diagnostics_channel on aviary:<lib>:<event>. Covers the DiagnosticEvent envelope (v, ts, lib, event, traceId, payload, durationMs), zero-overhead hasSubscribers gating, EmitOptions sampling and durationMs, typed ChannelRegistry declaration merging, and trace correlation via setContextAccessor / CONTEXT_ACCESSOR. No module to register; the core barrel is framework-agnostic.
3
+ description: Emit observability events from @dudousxd/nestjs-diagnostics with emit(lib, event, payload, opts) over node:diagnostics_channel on aviary:<lib>:<event>. Covers the DiagnosticEvent envelope (v, id, ts, lib, event, traceId, payload, durationMs), zero-overhead hasSubscribers gating, EmitOptions sampling and durationMs, typed ChannelRegistry declaration merging, and trace correlation via setContextAccessor / CONTEXT_ACCESSOR. No module to register; the core barrel is framework-agnostic.
4
4
  license: MIT
5
5
  metadata:
6
6
  type: core
@@ -47,6 +47,7 @@ standard `DiagnosticEvent` envelope:
47
47
  ```ts
48
48
  interface DiagnosticEvent<TPayload = unknown> {
49
49
  v?: number; // SCHEMA_VERSION stamped by emit (currently 1)
50
+ id?: string; // unique UUID stamped by emit; relays keep it so the same event has the same id in every process
50
51
  ts: number; // Date.now() at publish time
51
52
  lib: string; // the <lib>, e.g. "billing"
52
53
  event: string; // the <event>, e.g. "invoice-paid"
@@ -189,7 +190,9 @@ emit('billing', 'invoice-paid', payload);
189
190
  ```
190
191
 
191
192
  `emit` returns `void` and swallows every internal error so a broken observer can
192
- never break the producer. There is no delivery guarantee, ordering, or replay.
193
+ never break the producer. `emit` itself offers no ack, ordering, or replay;
194
+ `@OnDiagnostic` delivery guarantees (retry, run-once) depend on the selected
195
+ transport (see the `react-with-on-diagnostic` skill).
193
196
  Source: `packages/core/src/channel.ts` (`emit` `try/catch`).
194
197
 
195
198
  ### Putting the prefix or colons into lib/event yourself
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: react-with-on-diagnostic
3
- description: React to diagnostics events inside a NestJS app with @OnDiagnostic(lib, event?) from @dudousxd/nestjs-diagnostics/nestjs, wired by DiagnosticsModule.forRoot(). Decorate provider methods to handle one exact aviary:<lib>:<event> channel or every aviary:<lib>:* channel (current and future). Handlers run on the DI-resolved instance; sync throws and async rejections are logged and swallowed so a reaction can never break the synchronous emit() that triggered it.
3
+ description: React to diagnostics events inside a NestJS app with @OnDiagnostic(lib, event?) from @dudousxd/nestjs-diagnostics/nestjs, wired by DiagnosticsModule.forRoot()/forRootAsync({ default, transports, role, nodeId }). Decorate provider methods to handle one exact aviary:<lib>:<event> channel, a RegExp match, or every aviary:<lib>:* channel (current and future). The handler parameter is checked against the ChannelRegistry payload for registered channels; each listener has a stable <ClassName>#<method> id. Handlers run on the DI-resolved instance; without a delivering transport sync throws and async rejections are logged and swallowed, while queue/durable transports propagate the handler error for retry with delivery once from the emitting process. role 'api' never consumes or runs listeners.
4
4
  license: MIT
5
5
  metadata:
6
6
  type: core
@@ -44,21 +44,37 @@ export class Reactions {
44
44
  @OnDiagnostic('resilience', 'circuit-opened') // one exact channel
45
45
  onCircuitOpen(e: DiagnosticEvent) { /* … */ }
46
46
 
47
+ @OnDiagnostic('durable', /^run\./) // every event of the lib whose name matches
48
+ onRun(e: DiagnosticEvent) { /* … */ }
49
+
47
50
  @OnDiagnostic('resilience') // every aviary:resilience:* channel
48
51
  onAnyResilience(e: DiagnosticEvent) { /* … */ }
49
52
  }
50
53
  ```
51
54
 
55
+ For a channel declared in the `ChannelRegistry`, the handler's parameter is
56
+ checked against the declared payload (see `DiagnosticEventOf`); untyped
57
+ channels accept any annotation. Each listener has a stable id,
58
+ `<ClassName>#<method>`; two listener classes with the same name fail the
59
+ bootstrap. To run listeners across processes, pass
60
+ `{ default, transports, role, nodeId }` to `forRoot()` (or `forRootAsync()`):
61
+ `transports.redis()`, `transports.queue()`, or `transports.durable()` select
62
+ the delivery, and `role: 'api'` emits and hands work to the transport but
63
+ never consumes or runs listeners (`'api'`/`'worker'` without a `default`
64
+ transport fail the bootstrap).
65
+
52
66
  Source: `packages/core/src/nestjs/diagnostics.module.ts`,
53
67
  `packages/core/src/nestjs/on-diagnostic.decorator.ts`,
54
68
  `packages/core/src/nestjs/diagnostics.explorer.ts`.
55
69
 
56
70
  ## Core patterns
57
71
 
58
- ### 1. Exact channel vs library wildcard
72
+ ### 1. Exact channel, RegExp match, or library wildcard
59
73
 
60
74
  - `@OnDiagnostic('resilience', 'circuit-opened')` subscribes to the exact
61
75
  `aviary:resilience:circuit-opened` channel.
76
+ - `@OnDiagnostic('durable', /^run\./)` subscribes to every
77
+ `aviary:durable:*` channel whose event name matches the `RegExp`.
62
78
  - `@OnDiagnostic('resilience')` (no `event`) subscribes to **every**
63
79
  `aviary:resilience:*` channel — both those already registered at bootstrap and
64
80
  any that appear later (a library's first `emit('resilience', 'newevent', …)`).
@@ -69,6 +85,12 @@ automatically.
69
85
 
70
86
  Source: `packages/core/src/nestjs/diagnostics.explorer.ts` (`onApplicationBootstrap`).
71
87
 
88
+ Each discovered method gets a stable listener id, `<ClassName>#<method>`,
89
+ which delivering transports (`queue`, `durable`) use to route work; keep it
90
+ stable while deliveries may be pending. Two listener classes with the same
91
+ name fail the bootstrap. `role: 'api'` never consumes or runs listeners —
92
+ it emits and hands work to the transport.
93
+
72
94
  ### 2. Handlers run on the DI-resolved instance
73
95
 
74
96
  The decorated method is invoked on the real provider instance, so injected
@@ -86,17 +108,21 @@ export class AlertReactions {
86
108
  }
87
109
  ```
88
110
 
89
- Source: `packages/core/src/nestjs/diagnostics.explorer.ts` (`safeInvoke` calls `fn.call(instance, event)`).
111
+ Source: `packages/core/src/nestjs/diagnostics.explorer.ts` (`invoke` calls `fn.call(instance, event)`).
90
112
 
91
- ### 3. Never-throw isolation
113
+ ### 3. Never-throw isolation without a delivering transport
92
114
 
93
115
  `diagnostics_channel.publish` is **synchronous**, so a subscriber that throws
94
- would propagate into the emitter's call stack. The explorer's `safeInvoke`
116
+ would propagate into the emitter's call stack. Without a delivering transport,
117
+ the explorer's `invoke` path
95
118
  catches synchronous throws and attaches a `.catch` to rejected promises, logging
96
119
  both — a reaction can never break the `emit()` that triggered it. Async handlers
97
- are therefore fire-and-forget (publish cannot await).
120
+ are therefore fire-and-forget (publish cannot await). With a delivering
121
+ transport (`queue`, `durable`), delivery happens once, from the emitting
122
+ process, and the handler's error rejects `invoke` so the transport can retry
123
+ instead of being swallowed.
98
124
 
99
- Source: `packages/core/src/nestjs/diagnostics.explorer.ts` (`safeInvoke`, `logError`).
125
+ Source: `packages/core/src/nestjs/diagnostics.explorer.ts` (`invoke`, `onEvent`, `deliver`).
100
126
 
101
127
  ## Common mistakes
102
128
 
@@ -143,21 +169,23 @@ Source: `packages/core/src/nestjs/diagnostics.explorer.ts` (`discovery.getProvid
143
169
  ### Throwing in a handler expecting the framework to retry
144
170
 
145
171
  ```ts
146
- // Wrong — assuming a throw bubbles up or triggers a retry.
172
+ // Wrong — assuming a throw bubbles up or triggers a retry (without a delivering transport it will NOT — it is logged and swallowed).
147
173
  @OnDiagnostic('billing', 'invoice-paid')
148
174
  onPaid(e: DiagnosticEvent) {
149
- throw new Error('will be retried'); // it will NOT — it is logged and swallowed
175
+ throw new Error('will be retried'); // only retried with transports.queue()/durable()
150
176
  }
151
177
  ```
152
178
 
153
179
  ```ts
154
- // Correct — handle failures inside the reaction; it is fire-and-forget.
180
+ // Correct — handle failures inside the reaction when running without a delivering transport; it is fire-and-forget.
155
181
  @OnDiagnostic('billing', 'invoice-paid')
156
182
  async onPaid(e: DiagnosticEvent) {
157
183
  try { await this.work(e); } catch (err) { this.logger.warn(err); }
158
184
  }
159
185
  ```
160
186
 
161
- `safeInvoke` swallows throws/rejections by design, so emission stays safe — there
162
- is no delivery guarantee, retry, or replay.
163
- Source: `packages/core/src/nestjs/diagnostics.explorer.ts` (`safeInvoke`).
187
+ Without a delivering transport, the explorer swallows throws/rejections by design, so emission stays safe — there
188
+ is no delivery guarantee, retry, or replay. With `transports.queue()` or
189
+ `transports.durable()`, the handler error propagates to the transport and is
190
+ retried (delivery happens once, from the emitting process).
191
+ Source: `packages/core/src/nestjs/diagnostics.explorer.ts` (`invoke`, `onEvent`).
@@ -42,7 +42,8 @@ export class AuthzService {
42
42
  ```
43
43
 
44
44
  Span events ride `aviary:<lib>:<event>:<phase>`; the base `aviary:<lib>:<event>`
45
- name is what gets registered for discovery. A `SpanEvent` carries `v`, `ts`,
45
+ name is what gets registered for discovery. A `SpanEvent` carries `v`, a unique
46
+ `id` (a UUID stamped by `trace`; correlate phases with `spanId`), `ts`,
46
47
  `lib`, `event`, `phase`, a per-span `spanId`, optional `traceId`, and
47
48
  `payload` / `result` / `error` / `durationMs` depending on the phase.
48
49