@mnemonica/otel 0.1.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 (48) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +109 -0
  3. package/build/hooks/attach-hooks.d.ts +3 -0
  4. package/build/hooks/attach-hooks.d.ts.map +1 -0
  5. package/build/hooks/attach-hooks.js +52 -0
  6. package/build/index.d.ts +32 -0
  7. package/build/index.d.ts.map +1 -0
  8. package/build/index.js +32 -0
  9. package/build/providers/async-flow.provider.d.ts +40 -0
  10. package/build/providers/async-flow.provider.d.ts.map +1 -0
  11. package/build/providers/async-flow.provider.js +128 -0
  12. package/build/providers/dive-otel.provider.d.ts +51 -0
  13. package/build/providers/dive-otel.provider.d.ts.map +1 -0
  14. package/build/providers/dive-otel.provider.js +238 -0
  15. package/build/providers/mnemonica-otel.provider.d.ts +12 -0
  16. package/build/providers/mnemonica-otel.provider.d.ts.map +1 -0
  17. package/build/providers/mnemonica-otel.provider.js +113 -0
  18. package/build/request-scope.d.ts +41 -0
  19. package/build/request-scope.d.ts.map +1 -0
  20. package/build/request-scope.js +35 -0
  21. package/build/thunderstruck/feed-from-request.d.ts +21 -0
  22. package/build/thunderstruck/feed-from-request.d.ts.map +1 -0
  23. package/build/thunderstruck/feed-from-request.js +34 -0
  24. package/build/thunderstruck/pre-root.d.ts +67 -0
  25. package/build/thunderstruck/pre-root.d.ts.map +1 -0
  26. package/build/thunderstruck/pre-root.js +78 -0
  27. package/build/unblind.d.ts +46 -0
  28. package/build/unblind.d.ts.map +1 -0
  29. package/build/unblind.js +120 -0
  30. package/build/utils/dive-flow.d.ts +24 -0
  31. package/build/utils/dive-flow.d.ts.map +1 -0
  32. package/build/utils/dive-flow.js +33 -0
  33. package/build/utils/is-mnemonica-instance.d.ts +2 -0
  34. package/build/utils/is-mnemonica-instance.d.ts.map +1 -0
  35. package/build/utils/is-mnemonica-instance.js +9 -0
  36. package/build-cjs/hooks/attach-hooks.js +55 -0
  37. package/build-cjs/index.js +52 -0
  38. package/build-cjs/package.json +1 -0
  39. package/build-cjs/providers/async-flow.provider.js +132 -0
  40. package/build-cjs/providers/dive-otel.provider.js +242 -0
  41. package/build-cjs/providers/mnemonica-otel.provider.js +117 -0
  42. package/build-cjs/request-scope.js +38 -0
  43. package/build-cjs/thunderstruck/feed-from-request.js +37 -0
  44. package/build-cjs/thunderstruck/pre-root.js +83 -0
  45. package/build-cjs/unblind.js +127 -0
  46. package/build-cjs/utils/dive-flow.js +37 -0
  47. package/build-cjs/utils/is-mnemonica-instance.js +12 -0
  48. package/package.json +69 -0
@@ -0,0 +1,132 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AsyncFlowProvider = void 0;
4
+ /**
5
+ * Async-flow provider — the ALS backbone for dive attribution.
6
+ *
7
+ * Design: reports/async-flow-tracking-design.md (2026-09-02).
8
+ *
9
+ * One AsyncLocalStorage carrying a linked list of FlowFrames. The root
10
+ * frame is created per HTTP request by MnemonicaTraceMiddleware (or
11
+ * manually via runInScope). Every dive 'enter' hook pushes a child frame
12
+ * (edgeId = the entering edge); 'leave' restores the parent. ALS
13
+ * propagation then does the tracking for free: an UNWRAPPED async hop
14
+ * (setTimeout, promise continuation, async-generator suspension) fires
15
+ * with the scheduling frame in als.getStore() — the parental dive edge
16
+ * is known without wrapping anything.
17
+ *
18
+ * The scoped pin: the root frame owns a pinSet of context instances
19
+ * (strong refs), filled on enter/create from edge.instance. Lifetime is
20
+ * the request's async executions — when they die, the store and pinSet
21
+ * die with them. edge.instance never derefs to undefined mid-request.
22
+ *
23
+ * Node-only by design: dive imports no async_hooks (Deno/Bun), the
24
+ * adapter is the Node boundary where ALS is free.
25
+ */
26
+ const async_hooks_1 = require("async_hooks");
27
+ const dive_1 = require("@mnemonica/dive");
28
+ const als = new async_hooks_1.AsyncLocalStorage();
29
+ class AsyncFlowProvider {
30
+ // edgeId → the frame entered for it, so leave restores the exact parent
31
+ frames = new Map();
32
+ detachers = [];
33
+ /**
34
+ * Subscribe to dive's edge lifecycle. Idempotent: attaching twice would
35
+ * double every frame push. Dive's clear() wipes subscribers — re-attach
36
+ * after it.
37
+ */
38
+ attach() {
39
+ if (this.detachers.length > 0) {
40
+ return;
41
+ }
42
+ this.detachers.push((0, dive_1.registerHook)('enter', (payload) => {
43
+ this.onEnter(payload);
44
+ }), (0, dive_1.registerHook)('leave', (payload) => {
45
+ this.onLeave(payload);
46
+ }));
47
+ try {
48
+ this.detachers.push((0, dive_1.registerHook)('create', (payload) => {
49
+ this.onCreate(payload);
50
+ }));
51
+ }
52
+ catch {
53
+ // 'create' exists since dive 0.8.0; on 0.7.x registerHook throws —
54
+ // skipping preserves exactly the pre-subscription behavior.
55
+ }
56
+ }
57
+ detach() {
58
+ for (const detach of this.detachers) {
59
+ detach();
60
+ }
61
+ this.detachers = [];
62
+ this.frames.clear();
63
+ }
64
+ /**
65
+ * Establish a root frame for non-HTTP scopes (queue consumers, CLI,
66
+ * tests). The middleware is the HTTP root.
67
+ */
68
+ runInScope(fn) {
69
+ const root = {
70
+ edgeId: null,
71
+ parent: null,
72
+ pinSet: new Set(),
73
+ };
74
+ const result = als.run(root, fn);
75
+ return result;
76
+ }
77
+ /**
78
+ * The frame active RIGHT NOW — in an uncaughtException handler this is
79
+ * the failing execution's frame: the parental edge id plus every
80
+ * context instance pinned by the scope. Undefined outside any scope.
81
+ */
82
+ currentFrame() {
83
+ const frame = als.getStore();
84
+ if (!frame) {
85
+ return undefined;
86
+ }
87
+ const result = {
88
+ edgeId: frame.edgeId,
89
+ instances: [...frame.pinSet],
90
+ };
91
+ return result;
92
+ }
93
+ onEnter({ edge }) {
94
+ const current = als.getStore();
95
+ if (!current) {
96
+ return;
97
+ }
98
+ const frame = {
99
+ edgeId: edge.id,
100
+ parent: current,
101
+ pinSet: current.pinSet,
102
+ };
103
+ if (edge.instance !== undefined) {
104
+ frame.pinSet.add(edge.instance);
105
+ }
106
+ this.frames.set(edge.id, frame);
107
+ als.enterWith(frame);
108
+ }
109
+ onLeave({ edge }) {
110
+ const frame = this.frames.get(edge.id);
111
+ if (!frame) {
112
+ return;
113
+ }
114
+ this.frames.delete(edge.id);
115
+ if (frame.parent) {
116
+ als.enterWith(frame.parent);
117
+ }
118
+ }
119
+ onCreate({ edge }) {
120
+ const current = als.getStore();
121
+ if (!current) {
122
+ return;
123
+ }
124
+ // Constructions are one-shot edges (no leave) — no frame of their
125
+ // own, but the constructed instance is DATA: pin it into the scope.
126
+ if (edge.instance !== undefined) {
127
+ current.pinSet.add(edge.instance);
128
+ }
129
+ }
130
+ }
131
+ exports.AsyncFlowProvider = AsyncFlowProvider;
132
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXN5bmMtZmxvdy5wcm92aWRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9wcm92aWRlcnMvYXN5bmMtZmxvdy5wcm92aWRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBcUJHO0FBQ0gsNkNBQWdEO0FBQ2hELDBDQUErQztBQXVCL0MsTUFBTSxHQUFHLEdBQUcsSUFBSSwrQkFBaUIsRUFBYSxDQUFDO0FBRS9DLE1BQWEsaUJBQWlCO0lBQzdCLHdFQUF3RTtJQUNoRSxNQUFNLEdBQUcsSUFBSSxHQUFHLEVBQXFCLENBQUM7SUFDdEMsU0FBUyxHQUFzQixFQUFFLENBQUM7SUFFMUM7Ozs7T0FJRztJQUNILE1BQU07UUFDTCxJQUFJLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQy9CLE9BQU87UUFDUixDQUFDO1FBQ0QsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQ2xCLElBQUEsbUJBQVksRUFBQyxPQUFPLEVBQUUsQ0FBQyxPQUFPLEVBQUUsRUFBRTtZQUNqQyxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ3ZCLENBQUMsQ0FBQyxFQUNGLElBQUEsbUJBQVksRUFBQyxPQUFPLEVBQUUsQ0FBQyxPQUFPLEVBQUUsRUFBRTtZQUNqQyxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ3ZCLENBQUMsQ0FBQyxDQUNGLENBQUM7UUFDRixJQUFJLENBQUM7WUFDSixJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FDbEIsSUFBQSxtQkFBWSxFQUFDLFFBQVEsRUFBRSxDQUFDLE9BQU8sRUFBRSxFQUFFO2dCQUNsQyxJQUFJLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQ3hCLENBQUMsQ0FBQyxDQUNGLENBQUM7UUFDSCxDQUFDO1FBQUMsTUFBTSxDQUFDO1lBQ1IsbUVBQW1FO1lB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Q0Q7QUFoSEQsOENBZ0hDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBBc3luYy1mbG93IHByb3ZpZGVyIOKAlCB0aGUgQUxTIGJhY2tib25lIGZvciBkaXZlIGF0dHJpYnV0aW9uLlxuICpcbiAqIERlc2lnbjogcmVwb3J0cy9hc3luYy1mbG93LXRyYWNraW5nLWRlc2lnbi5tZCAoMjAyNi0wOS0wMikuXG4gKlxuICogT25lIEFzeW5jTG9jYWxTdG9yYWdlIGNhcnJ5aW5nIGEgbGlua2VkIGxpc3Qgb2YgRmxvd0ZyYW1lcy4gVGhlIHJvb3RcbiAqIGZyYW1lIGlzIGNyZWF0ZWQgcGVyIEhUVFAgcmVxdWVzdCBieSBNbmVtb25pY2FUcmFjZU1pZGRsZXdhcmUgKG9yXG4gKiBtYW51YWxseSB2aWEgcnVuSW5TY29wZSkuIEV2ZXJ5IGRpdmUgJ2VudGVyJyBob29rIHB1c2hlcyBhIGNoaWxkIGZyYW1lXG4gKiAoZWRnZUlkID0gdGhlIGVudGVyaW5nIGVkZ2UpOyAnbGVhdmUnIHJlc3RvcmVzIHRoZSBwYXJlbnQuIEFMU1xuICogcHJvcGFnYXRpb24gdGhlbiBkb2VzIHRoZSB0cmFja2luZyBmb3IgZnJlZTogYW4gVU5XUkFQUEVEIGFzeW5jIGhvcFxuICogKHNldFRpbWVvdXQsIHByb21pc2UgY29udGludWF0aW9uLCBhc3luYy1nZW5lcmF0b3Igc3VzcGVuc2lvbikgZmlyZXNcbiAqIHdpdGggdGhlIHNjaGVkdWxpbmcgZnJhbWUgaW4gYWxzLmdldFN0b3JlKCkg4oCUIHRoZSBwYXJlbnRhbCBkaXZlIGVkZ2VcbiAqIGlzIGtub3duIHdpdGhvdXQgd3JhcHBpbmcgYW55dGhpbmcuXG4gKlxuICogVGhlIHNjb3BlZCBwaW46IHRoZSByb290IGZyYW1lIG93bnMgYSBwaW5TZXQgb2YgY29udGV4dCBpbnN0YW5jZXNcbiAqIChzdHJvbmcgcmVmcyksIGZpbGxlZCBvbiBlbnRlci9jcmVhdGUgZnJvbSBlZGdlLmluc3RhbmNlLiBMaWZldGltZSBpc1xuICogdGhlIHJlcXVlc3QncyBhc3luYyBleGVjdXRpb25zIOKAlCB3aGVuIHRoZXkgZGllLCB0aGUgc3RvcmUgYW5kIHBpblNldFxuICogZGllIHdpdGggdGhlbS4gZWRnZS5pbnN0YW5jZSBuZXZlciBkZXJlZnMgdG8gdW5kZWZpbmVkIG1pZC1yZXF1ZXN0LlxuICpcbiAqIE5vZGUtb25seSBieSBkZXNpZ246IGRpdmUgaW1wb3J0cyBubyBhc3luY19ob29rcyAoRGVuby9CdW4pLCB0aGVcbiAqIGFkYXB0ZXIgaXMgdGhlIE5vZGUgYm91bmRhcnkgd2hlcmUgQUxTIGlzIGZyZWUuXG4gKi9cbmltcG9ydCB7IEFzeW5jTG9jYWxTdG9yYWdlIH0gZnJvbSAnYXN5bmNfaG9va3MnO1xuaW1wb3J0IHsgcmVnaXN0ZXJIb29rIH0gZnJvbSAnQG1uZW1vbmljYS9kaXZlJztcbmltcG9ydCB0eXBlIHtcblx0RGl2ZUNyZWF0ZVBheWxvYWQsXG5cdERpdmVFbnRlclBheWxvYWQsXG5cdERpdmVMZWF2ZVBheWxvYWQsXG59IGZyb20gJ0BtbmVtb25pY2EvZGl2ZSc7XG5cbmV4cG9ydCB0eXBlIEZsb3dGcmFtZSA9IHtcblx0LyoqIHRoZSBkaXZlIGVkZ2UgdGhpcyBmcmFtZSBiZWxvbmdzIHRvIChudWxsIG9uIHRoZSByb290IGZyYW1lKSAqL1xuXHRlZGdlSWQgICA6IG51bWJlciB8IG51bGw7XG5cdC8qKiB0aGUgZnJhbWUgYWN0aXZlIHdoZW4gdGhpcyBvbmUgd2FzIGVudGVyZWQgKi9cblx0cGFyZW50ICAgOiBGbG93RnJhbWUgfCBudWxsO1xuXHQvKiogc3Ryb25nIHBpbnMgb2YgY29udGV4dCBpbnN0YW5jZXMg4oCUIE9ORSBzZXQgcGVyIHNjb3BlLCBzaGFyZWQgZG93blxuXHQgKiAgdGhlIGNoYWluIGJ5IHJlZmVyZW5jZTsgZGllcyB3aXRoIHRoZSBzY29wZSdzIGFzeW5jIGV4ZWN1dGlvbnMgKi9cblx0cGluU2V0ICAgOiBTZXQ8b2JqZWN0Pjtcbn07XG5cbi8qKiBSZWFkLW9ubHkgY3Jhc2gtdGltZSB2aWV3IG9mIHRoZSBhY3RpdmUgZnJhbWUuICovXG5leHBvcnQgdHlwZSBDcmFzaENvbnRleHQgPSB7XG5cdGVkZ2VJZCAgICA6IG51bWJlciB8IG51bGw7XG5cdGluc3RhbmNlcyA6IG9iamVjdFtdO1xufTtcblxuY29uc3QgYWxzID0gbmV3IEFzeW5jTG9jYWxTdG9yYWdlPEZsb3dGcmFtZT4oKTtcblxuZXhwb3J0IGNsYXNzIEFzeW5jRmxvd1Byb3ZpZGVyIHtcblx0Ly8gZWRnZUlkIOKGkiB0aGUgZnJhbWUgZW50ZXJlZCBmb3IgaXQsIHNvIGxlYXZlIHJlc3RvcmVzIHRoZSBleGFjdCBwYXJlbnRcblx0cHJpdmF0ZSBmcmFtZXMgPSBuZXcgTWFwPG51bWJlciwgRmxvd0ZyYW1lPigpO1xuXHRwcml2YXRlIGRldGFjaGVyczogQXJyYXk8KCkgPT4gdm9pZD4gPSBbXTtcblxuXHQvKipcblx0ICogU3Vic2NyaWJlIHRvIGRpdmUncyBlZGdlIGxpZmVjeWNsZS4gSWRlbXBvdGVudDogYXR0YWNoaW5nIHR3aWNlIHdvdWxkXG5cdCAqIGRvdWJsZSBldmVyeSBmcmFtZSBwdXNoLiBEaXZlJ3MgY2xlYXIoKSB3aXBlcyBzdWJzY3JpYmVycyDigJQgcmUtYXR0YWNoXG5cdCAqIGFmdGVyIGl0LlxuXHQgKi9cblx0YXR0YWNoICgpOiB2b2lkIHtcblx0XHRpZiAodGhpcy5kZXRhY2hlcnMubGVuZ3RoID4gMCkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHR0aGlzLmRldGFjaGVycy5wdXNoKFxuXHRcdFx0cmVnaXN0ZXJIb29rKCdlbnRlcicsIChwYXlsb2FkKSA9PiB7XG5cdFx0XHRcdHRoaXMub25FbnRlcihwYXlsb2FkKTtcblx0XHRcdH0pLFxuXHRcdFx0cmVnaXN0ZXJIb29rKCdsZWF2ZScsIChwYXlsb2FkKSA9PiB7XG5cdFx0XHRcdHRoaXMub25MZWF2ZShwYXlsb2FkKTtcblx0XHRcdH0pLFxuXHRcdCk7XG5cdFx0dHJ5IHtcblx0XHRcdHRoaXMuZGV0YWNoZXJzLnB1c2goXG5cdFx0XHRcdHJlZ2lzdGVySG9vaygnY3JlYXRlJywgKHBheWxvYWQpID0+IHtcblx0XHRcdFx0XHR0aGlzLm9uQ3JlYXRlKHBheWxvYWQpO1xuXHRcdFx0XHR9KSxcblx0XHRcdCk7XG5cdFx0fSBjYXRjaCB7XG5cdFx0XHQvLyAnY3JlYXRlJyBleGlzdHMgc2luY2UgZGl2ZSAwLjguMDsgb24gMC43LnggcmVnaXN0ZXJIb29rIHRocm93cyDigJRcblx0XHRcdC8vIHNraXBwaW5nIHByZXNlcnZlcyBleGFjdGx5IHRoZSBwcmUtc3Vic2NyaXB0aW9uIGJlaGF2aW9yLlxuXHRcdH1cblx0fVxuXG5cdGRldGFjaCAoKTogdm9pZCB7XG5cdFx0Zm9yIChjb25zdCBkZXRhY2ggb2YgdGhpcy5kZXRhY2hlcnMpIHtcblx0XHRcdGRldGFjaCgpO1xuXHRcdH1cblx0XHR0aGlzLmRldGFjaGVycyA9IFtdO1xuXHRcdHRoaXMuZnJhbWVzLmNsZWFyKCk7XG5cdH1cblxuXHQvKipcblx0ICogRXN0YWJsaXNoIGEgcm9vdCBmcmFtZSBmb3Igbm9uLUhUVFAgc2NvcGVzIChxdWV1ZSBjb25zdW1lcnMsIENMSSxcblx0ICogdGVzdHMpLiBUaGUgbWlkZGxld2FyZSBpcyB0aGUgSFRUUCByb290LlxuXHQgKi9cblx0cnVuSW5TY29wZTxUPiAoZm46ICgpID0+IFQpOiBUIHtcblx0XHRjb25zdCByb290OiBGbG93RnJhbWUgPSB7XG5cdFx0XHRlZGdlSWQgOiBudWxsLFxuXHRcdFx0cGFyZW50IDogbnVsbCxcblx0XHRcdHBpblNldCA6IG5ldyBTZXQ8b2JqZWN0PigpLFxuXHRcdH07XG5cdFx0Y29uc3QgcmVzdWx0ID0gYWxzLnJ1bihyb290LCBmbik7XG5cdFx0cmV0dXJuIHJlc3VsdDtcblx0fVxuXG5cdC8qKlxuXHQgKiBUaGUgZnJhbWUgYWN0aXZlIFJJR0hUIE5PVyDigJQgaW4gYW4gdW5jYXVnaHRFeGNlcHRpb24gaGFuZGxlciB0aGlzIGlzXG5cdCAqIHRoZSBmYWlsaW5nIGV4ZWN1dGlvbidzIGZyYW1lOiB0aGUgcGFyZW50YWwgZWRnZSBpZCBwbHVzIGV2ZXJ5XG5cdCAqIGNvbnRleHQgaW5zdGFuY2UgcGlubmVkIGJ5IHRoZSBzY29wZS4gVW5kZWZpbmVkIG91dHNpZGUgYW55IHNjb3BlLlxuXHQgKi9cblx0Y3VycmVudEZyYW1lICgpOiBDcmFzaENvbnRleHQgfCB1bmRlZmluZWQge1xuXHRcdGNvbnN0IGZyYW1lID0gYWxzLmdldFN0b3JlKCk7XG5cdFx0aWYgKCFmcmFtZSkge1xuXHRcdFx0cmV0dXJuIHVuZGVmaW5lZDtcblx0XHR9XG5cdFx0Y29uc3QgcmVzdWx0OiBDcmFzaENvbnRleHQgPSB7XG5cdFx0XHRlZGdlSWQgICAgOiBmcmFtZS5lZGdlSWQsXG5cdFx0XHRpbnN0YW5jZXMgOiBbLi4uZnJhbWUucGluU2V0XSxcblx0XHR9O1xuXHRcdHJldHVybiByZXN1bHQ7XG5cdH1cblxuXHRwcml2YXRlIG9uRW50ZXIgKHsgZWRnZSB9OiBEaXZlRW50ZXJQYXlsb2FkKTogdm9pZCB7XG5cdFx0Y29uc3QgY3VycmVudCA9IGFscy5nZXRTdG9yZSgpO1xuXHRcdGlmICghY3VycmVudCkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHRjb25zdCBmcmFtZTogRmxvd0ZyYW1lID0ge1xuXHRcdFx0ZWRnZUlkIDogZWRnZS5pZCxcblx0XHRcdHBhcmVudCA6IGN1cnJlbnQsXG5cdFx0XHRwaW5TZXQgOiBjdXJyZW50LnBpblNldCxcblx0XHR9O1xuXHRcdGlmIChlZGdlLmluc3RhbmNlICE9PSB1bmRlZmluZWQpIHtcblx0XHRcdGZyYW1lLnBpblNldC5hZGQoZWRnZS5pbnN0YW5jZSk7XG5cdFx0fVxuXHRcdHRoaXMuZnJhbWVzLnNldChlZGdlLmlkLCBmcmFtZSk7XG5cdFx0YWxzLmVudGVyV2l0aChmcmFtZSk7XG5cdH1cblxuXHRwcml2YXRlIG9uTGVhdmUgKHsgZWRnZSB9OiBEaXZlTGVhdmVQYXlsb2FkKTogdm9pZCB7XG5cdFx0Y29uc3QgZnJhbWUgPSB0aGlzLmZyYW1lcy5nZXQoZWRnZS5pZCk7XG5cdFx0aWYgKCFmcmFtZSkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHR0aGlzLmZyYW1lcy5kZWxldGUoZWRnZS5pZCk7XG5cdFx0aWYgKGZyYW1lLnBhcmVudCkge1xuXHRcdFx0YWxzLmVudGVyV2l0aChmcmFtZS5wYXJlbnQpO1xuXHRcdH1cblx0fVxuXG5cdHByaXZhdGUgb25DcmVhdGUgKHsgZWRnZSB9OiBEaXZlQ3JlYXRlUGF5bG9hZCk6IHZvaWQge1xuXHRcdGNvbnN0IGN1cnJlbnQgPSBhbHMuZ2V0U3RvcmUoKTtcblx0XHRpZiAoIWN1cnJlbnQpIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cdFx0Ly8gQ29uc3RydWN0aW9ucyBhcmUgb25lLXNob3QgZWRnZXMgKG5vIGxlYXZlKSDigJQgbm8gZnJhbWUgb2YgdGhlaXJcblx0XHQvLyBvd24sIGJ1dCB0aGUgY29uc3RydWN0ZWQgaW5zdGFuY2UgaXMgREFUQTogcGluIGl0IGludG8gdGhlIHNjb3BlLlxuXHRcdGlmIChlZGdlLmluc3RhbmNlICE9PSB1bmRlZmluZWQpIHtcblx0XHRcdGN1cnJlbnQucGluU2V0LmFkZChlZGdlLmluc3RhbmNlKTtcblx0XHR9XG5cdH1cbn1cbiJdfQ==
@@ -0,0 +1,242 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DiveOtelProvider = void 0;
4
+ const api_1 = require("@opentelemetry/api");
5
+ const dive_1 = require("@mnemonica/dive");
6
+ // Call/method/construct edges carry their callsite as `name`
7
+ // (`/abs/file.ts:line:col`, 1-based) — surfaced as OTEL semconv code.*
8
+ // attributes so Jaeger can link straight to the source (Wanted #4).
9
+ const CALLSITE_RE = /^(.*):(\d+):(\d+)$/;
10
+ // Wanted #2 (2026-09-01): the strategy push channel (an injected script,
11
+ // see strategy/cdp-scripts/ws-server.js) cannot see OTEL spans, so the
12
+ // adapter publishes edgeId → traceId on a bounded global map; the push
13
+ // mapper forwards it and mnemographica's Live Trace gains the "Open in
14
+ // Jaeger" jump. globalThis because adapter and injected script share a
15
+ // process, not a module graph.
16
+ const EDGE_TRACES_LIMIT = 10000;
17
+ function edgeTraceMap() {
18
+ const g = globalThis;
19
+ if (!g.__mnemonicaDiveTraceIds) {
20
+ g.__mnemonicaDiveTraceIds = new Map();
21
+ }
22
+ const map = g.__mnemonicaDiveTraceIds;
23
+ return map;
24
+ }
25
+ function recordEdgeTrace(edgeId, traceId) {
26
+ const map = edgeTraceMap();
27
+ if (map.has(edgeId)) {
28
+ map.delete(edgeId);
29
+ }
30
+ else if (map.size >= EDGE_TRACES_LIMIT) {
31
+ // FIFO: the oldest entry dies first — Map iterates insertion order
32
+ const oldest = map.keys().next();
33
+ if (!oldest.done) {
34
+ map.delete(oldest.value);
35
+ }
36
+ }
37
+ map.set(edgeId, traceId);
38
+ }
39
+ class DiveOtelProvider {
40
+ tracer;
41
+ // open spans, keyed on dive edge id — drained by leave/settle
42
+ spans = new Map();
43
+ // edge id → parentId, for the root-edge walk (dive.root_edge_id span
44
+ // attribute). Never drained mid-flight: a completed edge can still
45
+ // parent later children (a create edge adopts the next wrapped call),
46
+ // so the map is bounded coarsely instead.
47
+ edgeParents = new Map();
48
+ static EDGE_PARENTS_LIMIT = 20000;
49
+ detachers = [];
50
+ constructor(tracer) {
51
+ this.tracer = tracer ?? api_1.trace.getTracer('@mnemonica/otel');
52
+ }
53
+ /**
54
+ * Subscribe to dive's edge lifecycle. Idempotent: attaching twice would
55
+ * double every span. Dive's clear() wipes subscribers — re-attach after it.
56
+ */
57
+ attach() {
58
+ if (this.detachers.length > 0) {
59
+ return;
60
+ }
61
+ this.detachers.push((0, dive_1.registerHook)('enter', (payload) => {
62
+ this.onEnter(payload);
63
+ }), (0, dive_1.registerHook)('leave', (payload) => {
64
+ this.onLeave(payload);
65
+ }), (0, dive_1.registerHook)('settle', (payload) => {
66
+ this.onSettle(payload);
67
+ }), (0, dive_1.registerHook)('recontext', (payload) => {
68
+ this.onRecontext(payload);
69
+ }));
70
+ try {
71
+ this.detachers.push((0, dive_1.registerHook)('create', (payload) => {
72
+ this.onCreate(payload);
73
+ }));
74
+ }
75
+ catch {
76
+ // The 'create' event exists since dive 0.8.0; on 0.7.x registerHook
77
+ // throws on the unknown event. Skipping it there preserves exactly
78
+ // the pre-subscription behavior (constructions stay unspanned), so
79
+ // the widened ^0.7.0 || ^0.8.0 peer range stays honest.
80
+ }
81
+ }
82
+ detach() {
83
+ for (const detach of this.detachers) {
84
+ detach();
85
+ }
86
+ this.detachers = [];
87
+ }
88
+ onEnter({ edge }) {
89
+ const parentSpan = this.findParentSpan(edge);
90
+ const ctx = parentSpan
91
+ ? api_1.trace.setSpan(api_1.context.active(), parentSpan)
92
+ : undefined;
93
+ const name = `dive.${edge.kind}:${edge.name}`;
94
+ const span = ctx
95
+ ? this.tracer.startSpan(name, {}, ctx)
96
+ : this.tracer.startSpan(name);
97
+ span.setAttribute('dive.edge_id', edge.id);
98
+ span.setAttribute('dive.kind', edge.kind);
99
+ span.setAttribute('dive.name', edge.name);
100
+ this.decorateSpan(span, edge);
101
+ this.spans.set(edge.id, span);
102
+ }
103
+ onLeave({ edge, result }) {
104
+ if (result instanceof Promise) {
105
+ // async work: the span closes at settle, not at the sync head —
106
+ // "the function returned" is not "the work is done"
107
+ return;
108
+ }
109
+ this.closeSpan(edge);
110
+ }
111
+ onSettle({ edge, error }) {
112
+ this.closeSpan(edge, error);
113
+ }
114
+ onRecontext({ edge, previousContext, context }) {
115
+ // One-shot span: the ownership transfer itself, parented on the OLD
116
+ // context's span (the handoff edge's parentId), so the trace shows
117
+ // where the callback's story crossed flows.
118
+ const parentSpan = this.findParentSpan(edge);
119
+ const ctx = parentSpan
120
+ ? api_1.trace.setSpan(api_1.context.active(), parentSpan)
121
+ : undefined;
122
+ const name = `dive.${edge.kind}:${edge.name}`;
123
+ const span = ctx
124
+ ? this.tracer.startSpan(name, {}, ctx)
125
+ : this.tracer.startSpan(name);
126
+ span.setAttribute('dive.edge_id', edge.id);
127
+ span.setAttribute('dive.kind', edge.kind);
128
+ span.setAttribute('dive.name', edge.name);
129
+ span.setAttribute('dive.handoff', true);
130
+ span.setAttribute('dive.handoff.had_previous', previousContext !== undefined);
131
+ span.setAttribute('dive.handoff.has_context', context !== undefined);
132
+ this.decorateSpan(span, edge);
133
+ span.end();
134
+ }
135
+ onCreate({ edge, error }) {
136
+ // One-shot span: the construction already completed when recordCreation
137
+ // fired (the hook moment IS the completion), so the span starts and
138
+ // ends here — same shape as recontext. findParentSpan adopts the
139
+ // wrapped call's span via edge.parentId, or the active request span at
140
+ // a boundary, so constructions join the request trace instead of
141
+ // opening a root trace of their own.
142
+ const parentSpan = this.findParentSpan(edge);
143
+ const ctx = parentSpan
144
+ ? api_1.trace.setSpan(api_1.context.active(), parentSpan)
145
+ : undefined;
146
+ const name = `dive.${edge.kind}:${edge.name}`;
147
+ const span = ctx
148
+ ? this.tracer.startSpan(name, {}, ctx)
149
+ : this.tracer.startSpan(name);
150
+ span.setAttribute('dive.edge_id', edge.id);
151
+ span.setAttribute('dive.kind', edge.kind);
152
+ span.setAttribute('dive.name', edge.name);
153
+ span.setAttribute('dive.status', edge.status);
154
+ if (edge.duration !== undefined) {
155
+ span.setAttribute('dive.duration_ms', edge.duration);
156
+ }
157
+ this.decorateSpan(span, edge);
158
+ if (edge.status === 'error') {
159
+ span.setStatus({ code: api_1.SpanStatusCode.ERROR });
160
+ if (error instanceof Error) {
161
+ span.recordException(error);
162
+ }
163
+ }
164
+ span.end();
165
+ }
166
+ findParentSpan(edge) {
167
+ if (edge.parentId !== null) {
168
+ const own = this.spans.get(edge.parentId);
169
+ if (own) {
170
+ return own;
171
+ }
172
+ }
173
+ // Boundary (or evicted parent): adopt the active OTel span — the HTTP
174
+ // request span becomes the root of the dive branch.
175
+ const active = api_1.trace.getSpan(api_1.context.active());
176
+ return active;
177
+ }
178
+ closeSpan(edge, error) {
179
+ const span = this.spans.get(edge.id);
180
+ if (!span) {
181
+ return;
182
+ }
183
+ this.spans.delete(edge.id);
184
+ span.setAttribute('dive.status', edge.status);
185
+ if (edge.duration !== undefined) {
186
+ span.setAttribute('dive.duration_ms', edge.duration);
187
+ }
188
+ if (edge.status === 'error') {
189
+ // sync throws carry no error value in the leave payload — the
190
+ // edge's own status is the truthful signal; the exception record
191
+ // is available only when settle carried the rejection itself
192
+ span.setStatus({ code: api_1.SpanStatusCode.ERROR });
193
+ if (error instanceof Error) {
194
+ span.recordException(error);
195
+ }
196
+ }
197
+ span.end();
198
+ }
199
+ /**
200
+ * Cross-surface attributes every span gets, on every hook path:
201
+ * the edge's trace root id (Jaeger link → mnemographica's Live Trace,
202
+ * Wanted #1), the edgeId→traceId publication for the strategy push
203
+ * channel (Wanted #2), and code.filepath/line/column parsed from the
204
+ * callsite name (Wanted #4).
205
+ */
206
+ decorateSpan(span, edge) {
207
+ span.setAttribute('dive.root_edge_id', this.rootEdgeIdOf(edge));
208
+ recordEdgeTrace(edge.id, span.spanContext().traceId);
209
+ if (edge.kind !== 'call' && edge.kind !== 'method' && edge.kind !== 'construct') {
210
+ return;
211
+ }
212
+ const match = CALLSITE_RE.exec(edge.name);
213
+ if (!match) {
214
+ return;
215
+ }
216
+ span.setAttribute('code.filepath', match[1]);
217
+ span.setAttribute('code.lineno', Number(match[2]));
218
+ span.setAttribute('code.column', Number(match[3]));
219
+ }
220
+ // Walk dive's parentage to the root edge id. Parents are recorded as
221
+ // edges arrive (enter fires parent-before-child), so the chain is
222
+ // complete for anything still in flight; an evicted/unknown parent
223
+ // simply ends the walk at the deepest known id.
224
+ rootEdgeIdOf(edge) {
225
+ if (this.edgeParents.size >= DiveOtelProvider.EDGE_PARENTS_LIMIT) {
226
+ this.edgeParents.clear();
227
+ }
228
+ this.edgeParents.set(edge.id, edge.parentId);
229
+ let id = edge.id;
230
+ let parent = edge.parentId;
231
+ const seen = new Set([id]);
232
+ while (parent !== null && !seen.has(parent)) {
233
+ seen.add(parent);
234
+ id = parent;
235
+ const next = this.edgeParents.get(parent);
236
+ parent = next === undefined ? null : next;
237
+ }
238
+ return id;
239
+ }
240
+ }
241
+ exports.DiveOtelProvider = DiveOtelProvider;
242
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGl2ZS1vdGVsLnByb3ZpZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3Byb3ZpZGVycy9kaXZlLW90ZWwucHJvdmlkZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBb0JBLDRDQUFtRjtBQUNuRiwwQ0FReUI7QUFFekIsNkRBQTZEO0FBQzdELHVFQUF1RTtBQUN2RSxvRUFBb0U7QUFDcEUsTUFBTSxXQUFXLEdBQUcsb0JBQW9CLENBQUM7QUFFekMseUVBQXlFO0FBQ3pFLHVFQUF1RTtBQUN2RSx1RUFBdUU7QUFDdkUsdUVBQXVFO0FBQ3ZFLHVFQUF1RTtBQUN2RSwrQkFBK0I7QUFDL0IsTUFBTSxpQkFBaUIsR0FBRyxLQUFLLENBQUM7QUFFaEMsU0FBUyxZQUFZO0lBQ3BCLE1BQU0sQ0FBQyxHQUFHLFVBQXdELENBQUM7SUFDbkUsSUFBSSxDQUFDLENBQUMsQ0FBQyx1QkFBdUIsRUFBRSxDQUFDO1FBQ2hDLENBQUMsQ0FBQyx1QkFBdUIsR0FBRyxJQUFJLEdBQUcsRUFBRSxDQUFDO0lBQ3ZDLENBQUM7SUFDRCxNQUFNLEdBQUcsR0FBRyxDQUFDLENBQUMsdUJBQXVCLENBQUM7SUFDdEMsT0FBTyxHQUFHLENBQUM7QUFDWixDQUFDO0FBQ0QsU0FBUyxlQUFlLENBQUUsTUFBYyxFQUFFLE9BQWU7SUFDeEQsTUFBTSxHQUFHLEdBQUcsWUFBWSxFQUFFLENBQUM7SUFDM0IsSUFBSSxHQUFHLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7UUFDckIsR0FBRyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUNwQixDQUFDO1NBQU0sSUFBSSxHQUFHLENBQUMsSUFBSSxJQUFJLGlCQUFpQixFQUFFLENBQUM7UUFDMUMsbUVBQW1FO1FBQ25FLE1BQU0sTUFBTSxHQUFHLEdBQUcsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUNqQyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUks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QUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNwRCxDQUFDO0lBRUQscUVBQXFFO0lBQ3JFLGtFQUFrRTtJQUNsRSxtRUFBbUU7SUFDbkUsZ0RBQWdEO0lBQ3hDLFlBQVksQ0FBRSxJQUFjO1FBQ25DLElBQUksSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLElBQUksZ0JBQWdCLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztZQUNsRSxJQUFJLENBQUMsV0FBVyxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQzFCLENBQUM7UUFDRCxJQUFJLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUM3QyxJQUFJLEVBQUUsR0FBRyxJQUFJLENBQUMsRUFBRSxDQUFDO1FBQ2pCLElBQUksTUFBTSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUM7UUFDM0IsTUFBTSxJQUFJLEdBQUcsSUFBSSxHQUFHLENBQVMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQ25DLE9BQU8sTUFBTSxLQUFLLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQztZQUM3QyxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ2pCLEVBQUUsR0FBRyxNQUFNLENBQUM7WUFDWixNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUMxQyxNQUFNLEdBQUcsSUFBSSxLQUFLLFNBQVMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7UUFDM0MsQ0FBQztRQUNELE9BQU8sRUFBRSxDQUFDO0lBQ1gsQ0FBQzs7QUE5TkYsNENBK05DIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBPcGVuVGVsZW1ldHJ5IHByb3ZpZGVyIGZvciBkaXZlJ3MgZWRnZSBsaWZlY3ljbGUgaG9va3MuXG4gKlxuICogV2hlcmUgTW5lbW9uaWNhT3RlbFByb3ZpZGVyIHNwYW5zIENPTlNUUlVDVElPTlMgKG1uZW1vbmljYSBob29rcyksIHRoaXNcbiAqIHByb3ZpZGVyIHNwYW5zIEVWRVJZIFdSQVBQRUQgQ0FMTCAoZGl2ZSBob29rcyk6IGNhbGwgLyBjb25zdHJ1Y3QgLyBtZXRob2QgL1xuICogcmVjb250ZXh0IGVkZ2VzIGVhY2ggYmVjb21lIGEgc3BhbiwgcGFyZW50ZWQgb24gdGhlIHNwYW4gb2YgdGhlIGVkZ2Unc1xuICogcGFyZW50SWQg4oCUIGRpdmUncyBvd24gdHJhY2UgcGFyZW50YWdlLCBub3QgQUxTLiBBdCB1bndyYXBwZWQgYm91bmRhcmllc1xuICogKHBhcmVudElkIG51bGwpIHRoZSBzcGFuIGFkb3B0cyB0aGUgY3VycmVudGx5IEFDVElWRSBPVGVsIHNwYW4gYXMgcGFyZW50LFxuICogc28gYW5cbiAqIEhUVFAgcmVxdWVzdCBzcGFuIGFkb3B0cyB0aGUgd2hvbGUgZGl2ZSBicmFuY2guICdjcmVhdGUnIGVkZ2VzIChtbmVtb25pY2FcbiAqIGNvbnN0cnVjdGlvbnMgcmVjb3JkZWQgdmlhIHJlY29yZENyZWF0aW9uL3JlY29yZENyZWF0aW9uRXJyb3IpIGJlY29tZVxuICogb25lLXNob3Qgc3BhbnMgb24gdGhlIHNhbWUgcGFyZW50YWdlIOKAlCB0aGUgY29uc3RydWN0aW9uIEhBUyBjb21wbGV0ZWQgd2hlblxuICogdGhlIGhvb2sgZmlyZXMsIHNvIHRoZSBzcGFuIHN0YXJ0cyBhbmQgZW5kcyBpbnNpZGUgdGhlIGhhbmRsZXIuXG4gKlxuICogQXN5bmMgdHJ1dGhmdWxuZXNzOiBhIHNwYW4gZG9lcyBOT1QgZW5kIGF0IHRoZSBzeW5jIGNsb3NlIHdoZW4gdGhlIHdyYXBcbiAqIHByb2R1Y2VkIGEgdGFwcGVkIHByb21pc2Ug4oCUIGl0IGVuZHMgYXQgc2V0dGxlLCB3aXRoIHRoZSBjaGFpbidzIG91dGNvbWUuXG4gKiBTcGFucyBhcmUga2V5ZWQgb24gZWRnZSBpZDsgZXZlcnkgcmVjb3JkZWQgZWRnZSBmaXJlcyBsZWF2ZSAoYW5kLCB3aGVuXG4gKiBhc3luYywgc2V0dGxlKSwgc28gdGhlIG1hcCBhbHdheXMgZHJhaW5zLlxuICovXG5pbXBvcnQgdHlwZSB7IFNwYW4sIFRyYWNlciB9IGZyb20gJ0BvcGVudGVsZW1ldHJ5L2FwaSc7XG5pbXBvcnQgeyBTcGFuU3RhdHVzQ29kZSwgY29udGV4dCBhcyBvdGVsQ29udGV4dCwgdHJhY2UgfSBmcm9tICdAb3BlbnRlbGVtZXRyeS9hcGknO1xuaW1wb3J0IHtcblx0cmVnaXN0ZXJIb29rLFxuXHR0eXBlIERpdmVDcmVhdGVQYXlsb2FkLFxuXHR0eXBlIERpdmVFbnRlclBheWxvYWQsXG5cdHR5cGUgRGl2ZUxlYXZlUGF5bG9hZCxcblx0dHlwZSBEaXZlUmVjb250ZXh0UGF5bG9hZCxcblx0dHlwZSBEaXZlU2V0dGxlUGF5bG9hZCxcblx0dHlwZSBGbG93RWRnZSxcbn0gZnJvbSAnQG1uZW1vbmljYS9kaXZlJztcblxuLy8gQ2FsbC9tZXRob2QvY29uc3RydWN0IGVkZ2VzIGNhcnJ5IHRoZWlyIGNhbGxzaXRlIGFzIGBuYW1lYFxuLy8gKGAvYWJzL2ZpbGUudHM6bGluZTpjb2xgLCAxLWJhc2VkKSDigJQgc3VyZmFjZWQgYXMgT1RFTCBzZW1jb252IGNvZGUuKlxuLy8gYXR0cmlidXRlcyBzbyBKYWVnZXIgY2FuIGxpbmsgc3RyYWlnaHQgdG8gdGhlIHNvdXJjZSAoV2FudGVkICM0KS5cbmNvbnN0IENBTExTSVRFX1JFID0gL14oLiopOihcXGQrKTooXFxkKykkLztcblxuLy8gV2FudGVkICMyICgyMDI2LTA5LTAxKTogdGhlIHN0cmF0ZWd5IHB1c2ggY2hhbm5lbCAoYW4gaW5qZWN0ZWQgc2NyaXB0LFxuLy8gc2VlIHN0cmF0ZWd5L2NkcC1zY3JpcHRzL3dzLXNlcnZlci5qcykgY2Fubm90IHNlZSBPVEVMIHNwYW5zLCBzbyB0aGVcbi8vIGFkYXB0ZXIgcHVibGlzaGVzIGVkZ2VJZCDihpIgdHJhY2VJZCBvbiBhIGJvdW5kZWQgZ2xvYmFsIG1hcDsgdGhlIHB1c2hcbi8vIG1hcHBlciBmb3J3YXJkcyBpdCBhbmQgbW5lbW9ncmFwaGljYSdzIExpdmUgVHJhY2UgZ2FpbnMgdGhlIFwiT3BlbiBpblxuLy8gSmFlZ2VyXCIganVtcC4gZ2xvYmFsVGhpcyBiZWNhdXNlIGFkYXB0ZXIgYW5kIGluamVjdGVkIHNjcmlwdCBzaGFyZSBhXG4vLyBwcm9jZXNzLCBub3QgYSBtb2R1bGUgZ3JhcGguXG5jb25zdCBFREdFX1RSQUNFU19MSU1JVCA9IDEwMDAwO1xudHlwZSBFZGdlVHJhY2VNYXAgPSBNYXA8bnVtYmVyLCBzdHJpbmc+O1xuZnVuY3Rpb24gZWRnZVRyYWNlTWFwICgpOiBFZGdlVHJhY2VNYXAge1xuXHRjb25zdCBnID0gZ2xvYmFsVGhpcyBhcyB7IF9fbW5lbW9uaWNhRGl2ZVRyYWNlSWRzPzogRWRnZVRyYWNlTWFwIH07XG5cdGlmICghZy5fX21uZW1vbmljYURpdmVUcmFjZUlkcykge1xuXHRcdGcuX19tbmVtb25pY2FEaXZlVHJhY2VJZHMgPSBuZXcgTWFwKCk7XG5cdH1cblx0Y29uc3QgbWFwID0gZy5fX21uZW1vbmljYURpdmVUcmFjZUlkcztcblx0cmV0dXJuIG1hcDtcbn1cbmZ1bmN0aW9uIHJlY29yZEVkZ2VUcmFjZSAoZWRnZUlkOiBudW1iZXIsIHRyYWNlSWQ6IHN0cmluZyk6IHZvaWQge1xuXHRjb25zdCBtYXAgPSBlZGdlVHJhY2VNYXAoKTtcblx0aWYgKG1hcC5oYXMoZWRnZUlkKSkge1xuXHRcdG1hcC5kZWxldGUoZWRnZUlkKTtcblx0fSBlbHNlIGlmIChtYXAuc2l6ZSA+PSBFREdFX1RSQUNFU19MSU1JVCkge1xuXHRcdC8vIEZJRk86IHRoZSBvbGRlc3QgZW50cnkgZGllcyBmaXJzdCDigJQgTWFwIGl0ZXJhdGVzIGluc2VydGlvbiBvcmRlclxuXHRcdGNvbnN0IG9sZGVzdCA9IG1hcC5rZXlzKCkubmV4dCgpO1xuXHRcdGlmICghb2xkZXN0LmRvbmUpIHtcblx0XHRcdG1hcC5kZWxldGUob2xkZXN0LnZhbHVlKTtcblx0XHR9XG5cdH1cblx0bWFwLnNldChlZGdlSWQsIHRyYWNlSWQpO1xufVxuXG5leHBvcnQgY2xhc3MgRGl2ZU90ZWxQcm92aWRlciB7XG5cdHByaXZhdGUgdHJhY2VyOiBUcmFjZXI7XG5cdC8vIG9wZW4gc3BhbnMsIGtleWVkIG9uIGRpdmUgZWRnZSBpZCDigJQgZHJhaW5lZCBieSBsZWF2ZS9zZXR0bGVcblx0cHJpdmF0ZSBzcGFucyA9IG5ldyBNYXA8bnVtYmVyLCBTcGFuPigpO1xuXHQvLyBlZGdlIGlkIOKGkiBwYXJlbnRJZCwgZm9yIHRoZSByb290LWVkZ2Ugd2FsayAoZGl2ZS5yb290X2VkZ2VfaWQgc3BhblxuXHQvLyBhdHRyaWJ1dGUpLiBOZXZlciBkcmFpbmVkIG1pZC1mbGlnaHQ6IGEgY29tcGxldGVkIGVkZ2UgY2FuIHN0aWxsXG5cdC8vIHBhcmVudCBsYXRlciBjaGlsZHJlbiAoYSBjcmVhdGUgZWRnZSBhZG9wdHMgdGhlIG5leHQgd3JhcHBlZCBjYWxsKSxcblx0Ly8gc28gdGhlIG1hcCBpcyBib3VuZGVkIGNvYXJzZWx5IGluc3RlYWQuXG5cdHByaXZhdGUgZWRnZVBhcmVudHMgPSBuZXcgTWFwPG51bWJlciwgbnVtYmVyIHwgbnVsbD4oKTtcblx0cHJpdmF0ZSBzdGF0aWMgcmVhZG9ubHkgRURHRV9QQVJFTlRTX0xJTUlUID0gMjAwMDA7XG5cdHByaXZhdGUgZGV0YWNoZXJzOiBBcnJheTwoKSA9PiB2b2lkPiA9IFtdO1xuXG5cdGNvbnN0cnVjdG9yICh0cmFjZXI/OiBUcmFjZXIpIHtcblx0XHR0aGlzLnRyYWNlciA9IHRyYWNlciA/PyB0cmFjZS5nZXRUcmFjZXIoJ0BtbmVtb25pY2Evb3RlbCcpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFN1YnNjcmliZSB0byBkaXZlJ3MgZWRnZSBsaWZlY3ljbGUuIElkZW1wb3RlbnQ6IGF0dGFjaGluZyB0d2ljZSB3b3VsZFxuXHQgKiBkb3VibGUgZXZlcnkgc3Bhbi4gRGl2ZSdzIGNsZWFyKCkgd2lwZXMgc3Vic2NyaWJlcnMg4oCUIHJlLWF0dGFjaCBhZnRlciBpdC5cblx0ICovXG5cdGF0dGFjaCAoKTogdm9pZCB7XG5cdFx0aWYgKHRoaXMuZGV0YWNoZXJzLmxlbmd0aCA+IDApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cdFx0dGhpcy5kZXRhY2hlcnMucHVzaChcblx0XHRcdHJlZ2lzdGVySG9vaygnZW50ZXInLCAocGF5bG9hZCkgPT4ge1xuXHRcdFx0XHR0aGlzLm9uRW50ZXIocGF5bG9hZCk7XG5cdFx0XHR9KSxcblx0XHRcdHJlZ2lzdGVySG9vaygnbGVhdmUnLCAocGF5bG9hZCkgPT4ge1xuXHRcdFx0XHR0aGlzLm9uTGVhdmUocGF5bG9hZCk7XG5cdFx0XHR9KSxcblx0XHRcdHJlZ2lzdGVySG9vaygnc2V0dGxlJywgKHBheWxvYWQpID0+IHtcblx0XHRcdFx0dGhpcy5vblNldHRsZShwYXlsb2FkKTtcblx0XHRcdH0pLFxuXHRcdFx0cmVnaXN0ZXJIb29rKCdyZWNvbnRleHQnLCAocGF5bG9hZCkgPT4ge1xuXHRcdFx0XHR0aGlzLm9uUmVjb250ZXh0KHBheWxvYWQpO1xuXHRcdFx0fSksXG5cdFx0KTtcblx0XHR0cnkge1xuXHRcdFx0dGhpcy5kZXRhY2hlcnMucHVzaChcblx0XHRcdFx0cmVnaXN0ZXJIb29rKCdjcmVhdGUnLCAocGF5bG9hZCkgPT4ge1xuXHRcdFx0XHRcdHRoaXMub25DcmVhdGUocGF5bG9hZCk7XG5cdFx0XHRcdH0pLFxuXHRcdFx0KTtcblx0XHR9IGNhdGNoIHtcblx0XHRcdC8vIFRoZSAnY3JlYXRlJyBldmVudCBleGlzdHMgc2luY2UgZGl2ZSAwLjguMDsgb24gMC43LnggcmVnaXN0ZXJIb29rXG5cdFx0XHQvLyB0aHJvd3Mgb24gdGhlIHVua25vd24gZXZlbnQuIFNraXBwaW5nIGl0IHRoZXJlIHByZXNlcnZlcyBleGFjdGx5XG5cdFx0XHQvLyB0aGUgcHJlLXN1YnNjcmlwdGlvbiBiZWhhdmlvciAoY29uc3RydWN0aW9ucyBzdGF5IHVuc3Bhbm5lZCksIHNvXG5cdFx0XHQvLyB0aGUgd2lkZW5lZCBeMC43LjAgfHwgXjAuOC4wIHBlZXIgcmFuZ2Ugc3RheXMgaG9uZXN0LlxuXHRcdH1cblx0fVxuXG5cdGRldGFjaCAoKTogdm9pZCB7XG5cdFx0Zm9yIChjb25zdCBkZXRhY2ggb2YgdGhpcy5kZXRhY2hlcnMpIHtcblx0XHRcdGRldGFjaCgpO1xuXHRcdH1cblx0XHR0aGlzLmRldGFjaGVycyA9IFtdO1xuXHR9XG5cblx0cHJpdmF0ZSBvbkVudGVyICh7IGVkZ2UgfTogRGl2ZUVudGVyUGF5bG9hZCk6IHZvaWQge1xuXHRcdGNvbnN0IHBhcmVudFNwYW4gPSB0aGlzLmZpbmRQYXJlbnRTcGFuKGVkZ2UpO1xuXHRcdGNvbnN0IGN0eCA9IHBhcmVudFNwYW5cblx0XHRcdD8gdHJhY2Uuc2V0U3BhbihvdGVsQ29udGV4dC5hY3RpdmUoKSwgcGFyZW50U3Bhbilcblx0XHRcdDogdW5kZWZpbmVkO1xuXHRcdGNvbnN0IG5hbWUgPSBgZGl2ZS4ke2VkZ2Uua2luZH06JHtlZGdlLm5hbWV9YDtcblx0XHRjb25zdCBzcGFuID0gY3R4XG5cdFx0XHQ/IHRoaXMudHJhY2VyLnN0YXJ0U3BhbihuYW1lLCB7fSwgY3R4KVxuXHRcdFx0OiB0aGlzLnRyYWNlci5zdGFydFNwYW4obmFtZSk7XG5cblx0XHRzcGFuLnNldEF0dHJpYnV0ZSgnZGl2ZS5lZGdlX2lkJywgZWRnZS5pZCk7XG5cdFx0c3Bhbi5zZXRBdHRyaWJ1dGUoJ2RpdmUua2luZCcsIGVkZ2Uua2luZCk7XG5cdFx0c3Bhbi5zZXRBdHRyaWJ1dGUoJ2RpdmUubmFtZScsIGVkZ2UubmFtZSk7XG5cdFx0dGhpcy5kZWNvcmF0ZVNwYW4oc3BhbiwgZWRnZSk7XG5cblx0XHR0aGlzLnNwYW5zLnNldChlZGdlLmlkLCBzcGFuKTtcblx0fVxuXG5cdHByaXZhdGUgb25MZWF2ZSAoeyBlZGdlLCByZXN1bHQgfTogRGl2ZUxlYXZlUGF5bG9hZCk6IHZvaWQge1xuXHRcdGlmIChyZXN1bHQgaW5zdGFuY2VvZiBQcm9taXNlKSB7XG5cdFx0XHQvLyBhc3luYyB3b3JrOiB0aGUgc3BhbiBjbG9zZXMgYXQgc2V0dGxlLCBub3QgYXQgdGhlIHN5bmMgaGVhZCDigJRcblx0XHRcdC8vIFwidGhlIGZ1bmN0aW9uIHJldHVybmVkXCIgaXMgbm90IFwidGhlIHdvcmsgaXMgZG9uZVwiXG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXHRcdHRoaXMuY2xvc2VTcGFuKGVkZ2UpO1xuXHR9XG5cblx0cHJpdmF0ZSBvblNldHRsZSAoeyBlZGdlLCBlcnJvciB9OiBEaXZlU2V0dGxlUGF5bG9hZCk6IHZvaWQge1xuXHRcdHRoaXMuY2xvc2VTcGFuKGVkZ2UsIGVycm9yKTtcblx0fVxuXG5cdHByaXZhdGUgb25SZWNvbnRleHQgKHsgZWRnZSwgcHJldmlvdXNDb250ZXh0LCBjb250ZXh0IH06IERpdmVSZWNvbnRleHRQYXlsb2FkKTogdm9pZCB7XG5cdFx0Ly8gT25lLXNob3Qgc3BhbjogdGhlIG93bmVyc2hpcCB0cmFuc2ZlciBpdHNlbGYsIHBhcmVudGVkIG9uIHRoZSBPTERcblx0XHQvLyBjb250ZXh0J3Mgc3BhbiAodGhlIGhhbmRvZmYgZWRnZSdzIHBhcmVudElkKSwgc28gdGhlIHRyYWNlIHNob3dzXG5cdFx0Ly8gd2hlcmUgdGhlIGNhbGxiYWNrJ3Mgc3RvcnkgY3Jvc3NlZCBmbG93cy5cblx0XHRjb25zdCBwYXJlbnRTcGFuID0gdGhpcy5maW5kUGFyZW50U3BhbihlZGdlKTtcblx0XHRjb25zdCBjdHggPSBwYXJlbnRTcGFuXG5cdFx0XHQ/IHRyYWNlLnNldFNwYW4ob3RlbENvbnRleHQuYWN0aXZlKCksIHBhcmVudFNwYW4pXG5cdFx0XHQ6IHVuZGVmaW5lZDtcblx0XHRjb25zdCBuYW1lID0gYGRpdmUuJHtlZGdlLmtpbmR9OiR7ZWRnZS5uYW1lfWA7XG5cdFx0Y29uc3Qgc3BhbiA9IGN0eFxuXHRcdFx0PyB0aGlzLnRyYWNlci5zdGFydFNwYW4obmFtZSwge30sIGN0eClcblx0XHRcdDogdGhpcy50cmFjZXIuc3RhcnRTcGFuKG5hbWUpO1xuXG5cdFx0c3Bhbi5zZXRBdHRyaWJ1dGUoJ2RpdmUuZWRnZV9pZCcsIGVkZ2UuaWQpO1xuXHRcdHNwYW4uc2V0QXR0cmlidXRlKCdkaXZlLmtpbmQnLCBlZGdlLmtpbmQpO1xuXHRcdHNwYW4uc2V0QXR0cmlidXRlKCdkaXZlLm5hbWUnLCBlZGdlLm5hbWUpO1xuXHRcdHNwYW4uc2V0QXR0cmlidXRlKCdkaXZlLmhhbmRvZmYnLCB0cnVlKTtcblx0XHRzcGFuLnNldEF0dHJpYnV0ZSgnZGl2ZS5oYW5kb2ZmLmhhZF9wcmV2aW91cycsIHByZXZpb3VzQ29udGV4dCAhPT0gdW5kZWZpbmVkKTtcblx0XHRzcGFuLnNldEF0dHJpYnV0ZSgnZGl2ZS5oYW5kb2ZmLmhhc19jb250ZXh0JywgY29udGV4dCAhPT0gdW5kZWZpbmVkKTtcblx0XHR0aGlzLmRlY29yYXRlU3BhbihzcGFuLCBlZGdlKTtcblx0XHRzcGFuLmVuZCgpO1xuXHR9XG5cblx0cHJpdmF0ZSBvbkNyZWF0ZSAoeyBlZGdlLCBlcnJvciB9OiBEaXZlQ3JlYXRlUGF5bG9hZCk6IHZvaWQge1xuXHRcdC8vIE9uZS1zaG90IHNwYW46IHRoZSBjb25zdHJ1Y3Rpb24gYWxyZWFkeSBjb21wbGV0ZWQgd2hlbiByZWNvcmRDcmVhdGlvblxuXHRcdC8vIGZpcmVkICh0aGUgaG9vayBtb21lbnQgSVMgdGhlIGNvbXBsZXRpb24pLCBzbyB0aGUgc3BhbiBzdGFydHMgYW5kXG5cdFx0Ly8gZW5kcyBoZXJlIOKAlCBzYW1lIHNoYXBlIGFzIHJlY29udGV4dC4gZmluZFBhcmVudFNwYW4gYWRvcHRzIHRoZVxuXHRcdC8vIHdyYXBwZWQgY2FsbCdzIHNwYW4gdmlhIGVkZ2UucGFyZW50SWQsIG9yIHRoZSBhY3RpdmUgcmVxdWVzdCBzcGFuIGF0XG5cdFx0Ly8gYSBib3VuZGFyeSwgc28gY29uc3RydWN0aW9ucyBqb2luIHRoZSByZXF1ZXN0IHRyYWNlIGluc3RlYWQgb2Zcblx0XHQvLyBvcGVuaW5nIGEgcm9vdCB0cmFjZSBvZiB0aGVpciBvd24uXG5cdFx0Y29uc3QgcGFyZW50U3BhbiA9IHRoaXMuZmluZFBhcmVudFNwYW4oZWRnZSk7XG5cdFx0Y29uc3QgY3R4ID0gcGFyZW50U3BhblxuXHRcdFx0PyB0cmFjZS5zZXRTcGFuKG90ZWxDb250ZXh0LmFjdGl2ZSgpLCBwYXJlbnRTcGFuKVxuXHRcdFx0OiB1bmRlZmluZWQ7XG5cdFx0Y29uc3QgbmFtZSA9IGBkaXZlLiR7ZWRnZS5raW5kfToke2VkZ2UubmFtZX1gO1xuXHRcdGNvbnN0IHNwYW4gPSBjdHhcblx0XHRcdD8gdGhpcy50cmFjZXIuc3RhcnRTcGFuKG5hbWUsIHt9LCBjdHgpXG5cdFx0XHQ6IHRoaXMudHJhY2VyLnN0YXJ0U3BhbihuYW1lKTtcblxuXHRcdHNwYW4uc2V0QXR0cmlidXRlKCdkaXZlLmVkZ2VfaWQnLCBlZGdlLmlkKTtcblx0XHRzcGFuLnNldEF0dHJpYnV0ZSgnZGl2ZS5raW5kJywgZWRnZS5raW5kKTtcblx0XHRzcGFuLnNldEF0dHJpYnV0ZSgnZGl2ZS5uYW1lJywgZWRnZS5uYW1lKTtcblx0XHRzcGFuLnNldEF0dHJpYnV0ZSgnZGl2ZS5zdGF0dXMnLCBlZGdlLnN0YXR1cyk7XG5cdFx0aWYgKGVkZ2UuZHVyYXRpb24gIT09IHVuZGVmaW5lZCkge1xuXHRcdFx0c3Bhbi5zZXRBdHRyaWJ1dGUoJ2RpdmUuZHVyYXRpb25fbXMnLCBlZGdlLmR1cmF0aW9uKTtcblx0XHR9XG5cdFx0dGhpcy5kZWNvcmF0ZVNwYW4oc3BhbiwgZWRnZSk7XG5cdFx0aWYgKGVkZ2Uuc3RhdHVzID09PSAnZXJyb3InKSB7XG5cdFx0XHRzcGFuLnNldFN0YXR1cyh7IGNvZGU6IFNwYW5TdGF0dXNDb2RlLkVSUk9SIH0pO1xuXHRcdFx0aWYgKGVycm9yIGluc3RhbmNlb2YgRXJyb3IpIHtcblx0XHRcdFx0c3Bhbi5yZWNvcmRFeGNlcHRpb24oZXJyb3IpO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRzcGFuLmVuZCgpO1xuXHR9XG5cblx0cHJpdmF0ZSBmaW5kUGFyZW50U3BhbiAoZWRnZTogRmxvd0VkZ2UpOiBTcGFuIHwgdW5kZWZpbmVkIHtcdFx0aWYgKGVkZ2UucGFyZW50SWQgIT09IG51bGwpIHtcblx0XHRcdGNvbnN0IG93biA9IHRoaXMuc3BhbnMuZ2V0KGVkZ2UucGFyZW50SWQpO1xuXHRcdFx0aWYgKG93bikge1xuXHRcdFx0XHRyZXR1cm4gb3duO1xuXHRcdFx0fVxuXHRcdH1cblx0XHQvLyBCb3VuZGFyeSAob3IgZXZpY3RlZCBwYXJlbnQpOiBhZG9wdCB0aGUgYWN0aXZlIE9UZWwgc3BhbiDigJQgdGhlIEhUVFBcblx0XHQvLyByZXF1ZXN0IHNwYW4gYmVjb21lcyB0aGUgcm9vdCBvZiB0aGUgZGl2ZSBicmFuY2guXG5cdFx0Y29uc3QgYWN0aXZlID0gdHJhY2UuZ2V0U3BhbihvdGVsQ29udGV4dC5hY3RpdmUoKSk7XG5cdFx0cmV0dXJuIGFjdGl2ZTtcblx0fVxuXG5cdHByaXZhdGUgY2xvc2VTcGFuIChlZGdlOiBGbG93RWRnZSwgZXJyb3I/OiB1bmtub3duKTogdm9pZCB7XG5cdFx0Y29uc3Qgc3BhbiA9IHRoaXMuc3BhbnMuZ2V0KGVkZ2UuaWQpO1xuXHRcdGlmICghc3Bhbikge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHR0aGlzLnNwYW5zLmRlbGV0ZShlZGdlLmlkKTtcblxuXHRcdHNwYW4uc2V0QXR0cmlidXRlKCdkaXZlLnN0YXR1cycsIGVkZ2Uuc3RhdHVzKTtcblx0XHRpZiAoZWRnZS5kdXJhdGlvbiAhPT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRzcGFuLnNldEF0dHJpYnV0ZSgnZGl2ZS5kdXJhdGlvbl9tcycsIGVkZ2UuZHVyYXRpb24pO1xuXHRcdH1cblx0XHRpZiAoZWRnZS5zdGF0dXMgPT09ICdlcnJvcicpIHtcblx0XHRcdC8vIHN5bmMgdGhyb3dzIGNhcnJ5IG5vIGVycm9yIHZhbHVlIGluIHRoZSBsZWF2ZSBwYXlsb2FkIOKAlCB0aGVcblx0XHRcdC8vIGVkZ2UncyBvd24gc3RhdHVzIGlzIHRoZSB0cnV0aGZ1bCBzaWduYWw7IHRoZSBleGNlcHRpb24gcmVjb3JkXG5cdFx0XHQvLyBpcyBhdmFpbGFibGUgb25seSB3aGVuIHNldHRsZSBjYXJyaWVkIHRoZSByZWplY3Rpb24gaXRzZWxmXG5cdFx0XHRzcGFuLnNldFN0YXR1cyh7IGNvZGU6IFNwYW5TdGF0dXNDb2RlLkVSUk9SIH0pO1xuXHRcdFx0aWYgKGVycm9yIGluc3RhbmNlb2YgRXJyb3IpIHtcblx0XHRcdFx0c3Bhbi5yZWNvcmRFeGNlcHRpb24oZXJyb3IpO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRzcGFuLmVuZCgpO1xuXHR9XG5cblx0LyoqXG5cdCAqIENyb3NzLXN1cmZhY2UgYXR0cmlidXRlcyBldmVyeSBzcGFuIGdldHMsIG9uIGV2ZXJ5IGhvb2sgcGF0aDpcblx0ICogdGhlIGVkZ2UncyB0cmFjZSByb290IGlkIChKYWVnZXIgbGluayDihpIgbW5lbW9ncmFwaGljYSdzIExpdmUgVHJhY2UsXG5cdCAqIFdhbnRlZCAjMSksIHRoZSBlZGdlSWTihpJ0cmFjZUlkIHB1YmxpY2F0aW9uIGZvciB0aGUgc3RyYXRlZ3kgcHVzaFxuXHQgKiBjaGFubmVsIChXYW50ZWQgIzIpLCBhbmQgY29kZS5maWxlcGF0aC9saW5lL2NvbHVtbiBwYXJzZWQgZnJvbSB0aGVcblx0ICogY2FsbHNpdGUgbmFtZSAoV2FudGVkICM0KS5cblx0ICovXG5cdHByaXZhdGUgZGVjb3JhdGVTcGFuIChzcGFuOiBTcGFuLCBlZGdlOiBGbG93RWRnZSk6IHZvaWQge1xuXHRcdHNwYW4uc2V0QXR0cmlidXRlKCdkaXZlLnJvb3RfZWRnZV9pZCcsIHRoaXMucm9vdEVkZ2VJZE9mKGVkZ2UpKTtcblx0XHRyZWNvcmRFZGdlVHJhY2UoZWRnZS5pZCwgc3Bhbi5zcGFuQ29udGV4dCgpLnRyYWNlSWQpO1xuXHRcdGlmIChlZGdlLmtpbmQgIT09ICdjYWxsJyAmJiBlZGdlLmtpbmQgIT09ICdtZXRob2QnICYmIGVkZ2Uua2luZCAhPT0gJ2NvbnN0cnVjdCcpIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cdFx0Y29uc3QgbWF0Y2ggPSBDQUxMU0lURV9SRS5leGVjKGVkZ2UubmFtZSk7XG5cdFx0aWYgKCFtYXRjaCkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHRzcGFuLnNldEF0dHJpYnV0ZSgnY29kZS5maWxlcGF0aCcsIG1hdGNoWzFdKTtcblx0XHRzcGFuLnNldEF0dHJpYnV0ZSgnY29kZS5saW5lbm8nLCBOdW1iZXIobWF0Y2hbMl0pKTtcblx0XHRzcGFuLnNldEF0dHJpYnV0ZSgnY29kZS5jb2x1bW4nLCBOdW1iZXIobWF0Y2hbM10pKTtcblx0fVxuXG5cdC8vIFdhbGsgZGl2ZSdzIHBhcmVudGFnZSB0byB0aGUgcm9vdCBlZGdlIGlkLiBQYXJlbnRzIGFyZSByZWNvcmRlZCBhc1xuXHQvLyBlZGdlcyBhcnJpdmUgKGVudGVyIGZpcmVzIHBhcmVudC1iZWZvcmUtY2hpbGQpLCBzbyB0aGUgY2hhaW4gaXNcblx0Ly8gY29tcGxldGUgZm9yIGFueXRoaW5nIHN0aWxsIGluIGZsaWdodDsgYW4gZXZpY3RlZC91bmtub3duIHBhcmVudFxuXHQvLyBzaW1wbHkgZW5kcyB0aGUgd2FsayBhdCB0aGUgZGVlcGVzdCBrbm93biBpZC5cblx0cHJpdmF0ZSByb290RWRnZUlkT2YgKGVkZ2U6IEZsb3dFZGdlKTogbnVtYmVyIHtcblx0XHRpZiAodGhpcy5lZGdlUGFyZW50cy5zaXplID49IERpdmVPdGVsUHJvdmlkZXIuRURHRV9QQVJFTlRTX0xJTUlUKSB7XG5cdFx0XHR0aGlzLmVkZ2VQYXJlbnRzLmNsZWFyKCk7XG5cdFx0fVxuXHRcdHRoaXMuZWRnZVBhcmVudHMuc2V0KGVkZ2UuaWQsIGVkZ2UucGFyZW50SWQpO1xuXHRcdGxldCBpZCA9IGVkZ2UuaWQ7XG5cdFx0bGV0IHBhcmVudCA9IGVkZ2UucGFyZW50SWQ7XG5cdFx0Y29uc3Qgc2VlbiA9IG5ldyBTZXQ8bnVtYmVyPihbaWRdKTtcblx0XHR3aGlsZSAocGFyZW50ICE9PSBudWxsICYmICFzZWVuLmhhcyhwYXJlbnQpKSB7XG5cdFx0XHRzZWVuLmFkZChwYXJlbnQpO1xuXHRcdFx0aWQgPSBwYXJlbnQ7XG5cdFx0XHRjb25zdCBuZXh0ID0gdGhpcy5lZGdlUGFyZW50cy5nZXQocGFyZW50KTtcblx0XHRcdHBhcmVudCA9IG5leHQgPT09IHVuZGVmaW5lZCA/IG51bGwgOiBuZXh0O1xuXHRcdH1cblx0XHRyZXR1cm4gaWQ7XG5cdH1cbn1cbiJdfQ==
@@ -0,0 +1,117 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MnemonicaOtelProvider = void 0;
4
+ /**
5
+ * OpenTelemetry provider for mnemonica lifecycle hooks.
6
+ *
7
+ * Creates spans for preCreation / postCreation / creationError,
8
+ * parents them along the prototype chain, and propagates
9
+ * context via AsyncLocalStorage.
10
+ */
11
+ const async_hooks_1 = require("async_hooks");
12
+ const api_1 = require("@opentelemetry/api");
13
+ const SymbolParentSpan = Symbol.for('mnemonica.span.parent');
14
+ const asyncStorage = new async_hooks_1.AsyncLocalStorage();
15
+ class MnemonicaOtelProvider {
16
+ tracer;
17
+ // spans of constructions in flight, keyed on the per-call args array
18
+ // (the only value core guarantees identical between pre and post hooks)
19
+ pendingSpans = new WeakMap();
20
+ constructor(tracer) {
21
+ this.tracer = tracer ?? api_1.trace.getTracer('@mnemonica/otel');
22
+ }
23
+ getCurrentSpan() {
24
+ return asyncStorage.getStore();
25
+ }
26
+ runWithSpan(span, fn) {
27
+ return asyncStorage.run(span, fn);
28
+ }
29
+ attachHooks(collection) {
30
+ collection.registerHook('preCreation', (hookData) => {
31
+ const parentSpan = this.findParentSpan(hookData);
32
+ const ctx = parentSpan
33
+ ? api_1.trace.setSpan(api_1.context.active(), parentSpan)
34
+ : undefined;
35
+ const span = parentSpan
36
+ ? this.tracer.startSpan(`mnemonica.${hookData.TypeName}`, {}, ctx)
37
+ : this.tracer.startSpan(`mnemonica.${hookData.TypeName}`);
38
+ span.setAttribute('mnemonica.type_name', hookData.TypeName);
39
+ span.setAttribute('mnemonica.hook', 'preCreation');
40
+ // Store the pending span keyed on the construction's args array:
41
+ // core passes the identical args reference to preCreation and to
42
+ // postCreation/creationError, and it is unique per construction call.
43
+ // Keying on the parent instance would collide when async constructions
44
+ // of siblings interleave (preA, preB, postB, postA — the second
45
+ // preCreation would overwrite the first).
46
+ this.pendingSpans.set(hookData.args, span);
47
+ });
48
+ collection.registerHook('postCreation', (hookData) => {
49
+ const newInstance = hookData.inheritedInstance;
50
+ if (newInstance == null || typeof newInstance !== 'object') {
51
+ return;
52
+ }
53
+ // Retrieve and remove the pending span for this construction
54
+ let span = this.pendingSpans.get(hookData.args);
55
+ this.pendingSpans.delete(hookData.args);
56
+ if (!span) {
57
+ // Fallback: create span here if preCreation didn't (shouldn't happen)
58
+ span = this.tracer.startSpan(`mnemonica.${hookData.TypeName}`);
59
+ span.setAttribute('mnemonica.type_name', hookData.TypeName);
60
+ }
61
+ span.setAttribute('mnemonica.hook', 'postCreation');
62
+ span.end();
63
+ // Store on new instance so its children can find the parent span
64
+ Object.defineProperty(newInstance, SymbolParentSpan, {
65
+ value: span,
66
+ configurable: true,
67
+ enumerable: false,
68
+ writable: true,
69
+ });
70
+ });
71
+ collection.registerHook('creationError', (hookData) => {
72
+ const newInstance = hookData.inheritedInstance;
73
+ if (newInstance == null || typeof newInstance !== 'object') {
74
+ return;
75
+ }
76
+ // Retrieve and remove the pending span for this construction
77
+ let span = this.pendingSpans.get(hookData.args);
78
+ this.pendingSpans.delete(hookData.args);
79
+ if (!span) {
80
+ span = this.tracer.startSpan(`mnemonica.${hookData.TypeName}`);
81
+ span.setAttribute('mnemonica.type_name', hookData.TypeName);
82
+ }
83
+ span.setAttribute('mnemonica.hook', 'creationError');
84
+ span.setAttribute('error.type', 'Error');
85
+ span.recordException(newInstance);
86
+ span.end();
87
+ // Store on error instance for chain tracing
88
+ Object.defineProperty(newInstance, SymbolParentSpan, {
89
+ value: span,
90
+ configurable: true,
91
+ enumerable: false,
92
+ writable: true,
93
+ });
94
+ });
95
+ }
96
+ findParentSpan(hookData) {
97
+ const stored = asyncStorage.getStore();
98
+ if (stored) {
99
+ return stored;
100
+ }
101
+ const parent = hookData.existentInstance;
102
+ if (parent == null || typeof parent !== 'object') {
103
+ return undefined;
104
+ }
105
+ let current = parent;
106
+ while (current) {
107
+ const span = current[SymbolParentSpan];
108
+ if (span) {
109
+ return span;
110
+ }
111
+ current = Object.getPrototypeOf(current);
112
+ }
113
+ return undefined;
114
+ }
115
+ }
116
+ exports.MnemonicaOtelProvider = MnemonicaOtelProvider;
117
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW5lbW9uaWNhLW90ZWwucHJvdmlkZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcHJvdmlkZXJzL21uZW1vbmljYS1vdGVsLnByb3ZpZGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBOzs7Ozs7R0FNRztBQUNILDZDQUFnRDtBQUVoRCw0Q0FBbUU7QUFHbkUsTUFBTSxnQkFBZ0IsR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDLHVCQUF1QixDQUFDLENBQUM7QUFDN0QsTUFBTSxZQUFZLEdBQUcsSUFBSSwrQkFBaUIsRUFBUSxDQUFDO0FBRW5ELE1BQWEscUJBQXFCO0lBQ3pCLE1BQU0sQ0FBUztJQUN2QixxRUFBcUU7SUFDckUsd0VBQXdFO0lBQ2hFLFlBQVksR0FBRyxJQUFJLE9BQU8sRUFBZ0IsQ0FBQztJQUVuRCxZQUFhLE1BQWU7UUFDM0IsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLElBQUksV0FBSyxDQUFDLFNBQVMsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO0lBQzVELENBQUM7SUFFRCxjQUFjO1FBQ2IsT0FBTyxZQUFZLENBQUMsUUFBUSxFQUFFLENBQUM7SUFDaEMsQ0FBQztJQUVELFdBQVcsQ0FBSyxJQUFVLEVBQUUsRUFBVztRQUN0QyxPQUFPLFlBQVksQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ25DLENBQUM7SUFFRCxXQUFXLENBQUUsVUFBMkI7UUFDdkMsVUFBVSxDQUFDLFlBQVksQ0FBQyxhQUFhLEVBQUUsQ0FBQyxRQUFtQixFQUFFLEVBQUU7WUFDOUQsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUNqRCxNQUFNLEdBQUcsR0FBRyxVQUFVO2dCQUNyQixDQUFDLENBQUMsV0FBSyxDQUFDLE9BQU8sQ0FBQyxhQUFXLENBQUMsTUFBTSxFQUFFLEVBQUUsVUFBVSxDQUFDO2dCQUNqRCxDQUFDLENBQUMsU0FBUyxD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O0FBNUhELHNEQTRIQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogT3BlblRlbGVtZXRyeSBwcm92aWRlciBmb3IgbW5lbW9uaWNhIGxpZmVjeWNsZSBob29rcy5cbiAqXG4gKiBDcmVhdGVzIHNwYW5zIGZvciBwcmVDcmVhdGlvbiAvIHBvc3RDcmVhdGlvbiAvIGNyZWF0aW9uRXJyb3IsXG4gKiBwYXJlbnRzIHRoZW0gYWxvbmcgdGhlIHByb3RvdHlwZSBjaGFpbiwgYW5kIHByb3BhZ2F0ZXNcbiAqIGNvbnRleHQgdmlhIEFzeW5jTG9jYWxTdG9yYWdlLlxuICovXG5pbXBvcnQgeyBBc3luY0xvY2FsU3RvcmFnZSB9IGZyb20gJ2FzeW5jX2hvb2tzJztcbmltcG9ydCB0eXBlIHsgVHJhY2VyLCBTcGFuIH0gZnJvbSAnQG9wZW50ZWxlbWV0cnkvYXBpJztcbmltcG9ydCB7IHRyYWNlLCBjb250ZXh0IGFzIG90ZWxDb250ZXh0IH0gZnJvbSAnQG9wZW50ZWxlbWV0cnkvYXBpJztcbmltcG9ydCB0eXBlIHsgaG9va3NPcHRzLCBUeXBlc0NvbGxlY3Rpb24gfSBmcm9tICdtbmVtb25pY2EvbW9kdWxlJztcblxuY29uc3QgU3ltYm9sUGFyZW50U3BhbiA9IFN5bWJvbC5mb3IoJ21uZW1vbmljYS5zcGFuLnBhcmVudCcpO1xuY29uc3QgYXN5bmNTdG9yYWdlID0gbmV3IEFzeW5jTG9jYWxTdG9yYWdlPFNwYW4+KCk7XG5cbmV4cG9ydCBjbGFzcyBNbmVtb25pY2FPdGVsUHJvdmlkZXIge1xuXHRwcml2YXRlIHRyYWNlcjogVHJhY2VyO1xuXHQvLyBzcGFucyBvZiBjb25zdHJ1Y3Rpb25zIGluIGZsaWdodCwga2V5ZWQgb24gdGhlIHBlci1jYWxsIGFyZ3MgYXJyYXlcblx0Ly8gKHRoZSBvbmx5IHZhbHVlIGNvcmUgZ3VhcmFudGVlcyBpZGVudGljYWwgYmV0d2VlbiBwcmUgYW5kIHBvc3QgaG9va3MpXG5cdHByaXZhdGUgcGVuZGluZ1NwYW5zID0gbmV3IFdlYWtNYXA8b2JqZWN0LCBTcGFuPigpO1xuXG5cdGNvbnN0cnVjdG9yICh0cmFjZXI/OiBUcmFjZXIpIHtcblx0XHR0aGlzLnRyYWNlciA9IHRyYWNlciA/PyB0cmFjZS5nZXRUcmFjZXIoJ0BtbmVtb25pY2Evb3RlbCcpO1xuXHR9XG5cblx0Z2V0Q3VycmVudFNwYW4gKCk6IFNwYW4gfCB1bmRlZmluZWQge1xuXHRcdHJldHVybiBhc3luY1N0b3JhZ2UuZ2V0U3RvcmUoKTtcblx0fVxuXG5cdHJ1bldpdGhTcGFuPFQ+IChzcGFuOiBTcGFuLCBmbjogKCkgPT4gVCk6IFQge1xuXHRcdHJldHVybiBhc3luY1N0b3JhZ2UucnVuKHNwYW4sIGZuKTtcblx0fVxuXG5cdGF0dGFjaEhvb2tzIChjb2xsZWN0aW9uOiBUeXBlc0NvbGxlY3Rpb24pOiB2b2lkIHtcblx0XHRjb2xsZWN0aW9uLnJlZ2lzdGVySG9vaygncHJlQ3JlYXRpb24nLCAoaG9va0RhdGE6IGhvb2tzT3B0cykgPT4ge1xuXHRcdFx0Y29uc3QgcGFyZW50U3BhbiA9IHRoaXMuZmluZFBhcmVudFNwYW4oaG9va0RhdGEpO1xuXHRcdFx0Y29uc3QgY3R4ID0gcGFyZW50U3BhblxuXHRcdFx0XHQ/IHRyYWNlLnNldFNwYW4ob3RlbENvbnRleHQuYWN0aXZlKCksIHBhcmVudFNwYW4pXG5cdFx0XHRcdDogdW5kZWZpbmVkO1xuXHRcdFx0Y29uc3Qgc3BhbiA9IHBhcmVudFNwYW5cblx0XHRcdFx0PyB0aGlzLnRyYWNlci5zdGFydFNwYW4oXG5cdFx0XHRcdFx0YG1uZW1vbmljYS4ke2hvb2tEYXRhLlR5cGVOYW1lfWAsXG5cdFx0XHRcdFx0e30sXG5cdFx0XHRcdFx0Y3R4XG5cdFx0XHRcdClcblx0XHRcdFx0OiB0aGlzLnRyYWNlci5zdGFydFNwYW4oYG1uZW1vbmljYS4ke2hvb2tEYXRhLlR5cGVOYW1lfWApO1xuXG5cdFx0XHRzcGFuLnNldEF0dHJpYnV0ZSgnbW5lbW9uaWNhLnR5cGVfbmFtZScsIGhvb2tEYXRhLlR5cGVOYW1lKTtcblx0XHRcdHNwYW4uc2V0QXR0cmlidXRlKCdtbmVtb25pY2EuaG9vaycsICdwcmVDcmVhdGlvbicpO1xuXG5cdFx0XHQvLyBTdG9yZSB0aGUgcGVuZGluZyBzcGFuIGtleWVkIG9uIHRoZSBjb25zdHJ1Y3Rpb24ncyBhcmdzIGFycmF5OlxuXHRcdFx0Ly8gY29yZSBwYXNzZXMgdGhlIGlkZW50aWNhbCBhcmdzIHJlZmVyZW5jZSB0byBwcmVDcmVhdGlvbiBhbmQgdG9cblx0XHRcdC8vIHBvc3RDcmVhdGlvbi9jcmVhdGlvbkVycm9yLCBhbmQgaXQgaXMgdW5pcXVlIHBlciBjb25zdHJ1Y3Rpb24gY2FsbC5cblx0XHRcdC8vIEtleWluZyBvbiB0aGUgcGFyZW50IGluc3RhbmNlIHdvdWxkIGNvbGxpZGUgd2hlbiBhc3luYyBjb25zdHJ1Y3Rpb25zXG5cdFx0XHQvLyBvZiBzaWJsaW5ncyBpbnRlcmxlYXZlIChwcmVBLCBwcmVCLCBwb3N0QiwgcG9zdEEg4oCUIHRoZSBzZWNvbmRcblx0XHRcdC8vIHByZUNyZWF0aW9uIHdvdWxkIG92ZXJ3cml0ZSB0aGUgZmlyc3QpLlxuXHRcdFx0dGhpcy5wZW5kaW5nU3BhbnMuc2V0KGhvb2tEYXRhLmFyZ3MsIHNwYW4pO1xuXHRcdH0pO1xuXG5cdFx0Y29sbGVjdGlvbi5yZWdpc3Rlckhvb2soJ3Bvc3RDcmVhdGlvbicsIChob29rRGF0YTogaG9va3NPcHRzKSA9PiB7XG5cdFx0XHRjb25zdCBuZXdJbnN0YW5jZSA9IGhvb2tEYXRhLmluaGVyaXRlZEluc3RhbmNlO1xuXHRcdFx0aWYgKG5ld0luc3RhbmNlID09IG51bGwgfHwgdHlwZW9mIG5ld0luc3RhbmNlICE9PSAnb2JqZWN0Jykge1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cblx0XHRcdC8vIFJldHJpZXZlIGFuZCByZW1vdmUgdGhlIHBlbmRpbmcgc3BhbiBmb3IgdGhpcyBjb25zdHJ1Y3Rpb25cblx0XHRcdGxldCBzcGFuID0gdGhpcy5wZW5kaW5nU3BhbnMuZ2V0KGhvb2tEYXRhLmFyZ3MpO1xuXHRcdFx0dGhpcy5wZW5kaW5nU3BhbnMuZGVsZXRlKGhvb2tEYXRhLmFyZ3MpO1xuXG5cdFx0XHRpZiAoIXNwYW4pIHtcblx0XHRcdFx0Ly8gRmFsbGJhY2s6IGNyZWF0ZSBzcGFuIGhlcmUgaWYgcHJlQ3JlYXRpb24gZGlkbid0IChzaG91bGRuJ3QgaGFwcGVuKVxuXHRcdFx0XHRzcGFuID0gdGhpcy50cmFjZXIuc3RhcnRTcGFuKGBtbmVtb25pY2EuJHtob29rRGF0YS5UeXBlTmFtZX1gKTtcblx0XHRcdFx0c3Bhbi5zZXRBdHRyaWJ1dGUoJ21uZW1vbmljYS50eXBlX25hbWUnLCBob29rRGF0YS5UeXBlTmFtZSk7XG5cdFx0XHR9XG5cblx0XHRcdHNwYW4uc2V0QXR0cmlidXRlKCdtbmVtb25pY2EuaG9vaycsICdwb3N0Q3JlYXRpb24nKTtcblx0XHRcdHNwYW4uZW5kKCk7XG5cblx0XHRcdC8vIFN0b3JlIG9uIG5ldyBpbnN0YW5jZSBzbyBpdHMgY2hpbGRyZW4gY2FuIGZpbmQgdGhlIHBhcmVudCBzcGFuXG5cdFx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkobmV3SW5zdGFuY2UsIFN5bWJvbFBhcmVudFNwYW4sIHtcblx0XHRcdFx0dmFsdWUgICAgICAgOiBzcGFuLFxuXHRcdFx0XHRjb25maWd1cmFibGU6IHRydWUsXG5cdFx0XHRcdGVudW1lcmFibGUgIDogZmFsc2UsXG5cdFx0XHRcdHdyaXRhYmxlICAgIDogdHJ1ZSxcblx0XHRcdH0pO1xuXHRcdH0pO1xuXG5cdFx0Y29sbGVjdGlvbi5yZWdpc3Rlckhvb2soJ2NyZWF0aW9uRXJyb3InLCAoaG9va0RhdGE6IGhvb2tzT3B0cykgPT4ge1xuXHRcdFx0Y29uc3QgbmV3SW5zdGFuY2UgPSBob29rRGF0YS5pbmhlcml0ZWRJbnN0YW5jZTtcblx0XHRcdGlmIChuZXdJbnN0YW5jZSA9PSBudWxsIHx8IHR5cGVvZiBuZXdJbnN0YW5jZSAhPT0gJ29iamVjdCcpIHtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBSZXRyaWV2ZSBhbmQgcmVtb3ZlIHRoZSBwZW5kaW5nIHNwYW4gZm9yIHRoaXMgY29uc3RydWN0aW9uXG5cdFx0XHRsZXQgc3BhbiA9IHRoaXMucGVuZGluZ1NwYW5zLmdldChob29rRGF0YS5hcmdzKTtcblx0XHRcdHRoaXMucGVuZGluZ1NwYW5zLmRlbGV0ZShob29rRGF0YS5hcmdzKTtcblxuXHRcdFx0aWYgKCFzcGFuKSB7XG5cdFx0XHRcdHNwYW4gPSB0aGlzLnRyYWNlci5zdGFydFNwYW4oYG1uZW1vbmljYS4ke2hvb2tEYXRhLlR5cGVOYW1lfWApO1xuXHRcdFx0XHRzcGFuLnNldEF0dHJpYnV0ZSgnbW5lbW9uaWNhLnR5cGVfbmFtZScsIGhvb2tEYXRhLlR5cGVOYW1lKTtcblx0XHRcdH1cblxuXHRcdFx0c3Bhbi5zZXRBdHRyaWJ1dGUoJ21uZW1vbmljYS5ob29rJywgJ2NyZWF0aW9uRXJyb3InKTtcblx0XHRcdHNwYW4uc2V0QXR0cmlidXRlKCdlcnJvci50eXBlJywgJ0Vycm9yJyk7XG5cdFx0XHRzcGFuLnJlY29yZEV4Y2VwdGlvbihuZXdJbnN0YW5jZSBhcyBFcnJvcik7XG5cdFx0XHRzcGFuLmVuZCgpO1xuXG5cdFx0XHQvLyBTdG9yZSBvbiBlcnJvciBpbnN0YW5jZSBmb3IgY2hhaW4gdHJhY2luZ1xuXHRcdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KG5ld0luc3RhbmNlLCBTeW1ib2xQYXJlbnRTcGFuLCB7XG5cdFx0XHRcdHZhbHVlICAgICAgIDogc3Bhbixcblx0XHRcdFx0Y29uZmlndXJhYmxlOiB0cnVlLFxuXHRcdFx0XHRlbnVtZXJhYmxlICA6IGZhbHNlLFxuXHRcdFx0XHR3cml0YWJsZSAgICA6IHRydWUsXG5cdFx0XHR9KTtcblx0XHR9KTtcblx0fVxuXG5cdHByaXZhdGUgZmluZFBhcmVudFNwYW4gKGhvb2tEYXRhOiBob29rc09wdHMpOiBTcGFuIHwgdW5kZWZpbmVkIHtcblx0XHRjb25zdCBzdG9yZWQgPSBhc3luY1N0b3JhZ2UuZ2V0U3RvcmUoKTtcblx0XHRpZiAoc3RvcmVkKSB7XG5cdFx0XHRyZXR1cm4gc3RvcmVkO1xuXHRcdH1cblxuXHRcdGNvbnN0IHBhcmVudCA9IGhvb2tEYXRhLmV4aXN0ZW50SW5zdGFuY2U7XG5cdFx0aWYgKHBhcmVudCA9PSBudWxsIHx8IHR5cGVvZiBwYXJlbnQgIT09ICdvYmplY3QnKSB7XG5cdFx0XHRyZXR1cm4gdW5kZWZpbmVkO1xuXHRcdH1cblxuXHRcdGxldCBjdXJyZW50OiBvYmplY3QgfCBudWxsID0gcGFyZW50O1xuXHRcdHdoaWxlIChjdXJyZW50KSB7XG5cdFx0XHRjb25zdCBzcGFuID0gKGN1cnJlbnQgYXMgUmVjb3JkPHN5bWJvbCwgdW5rbm93bj4pW1N5bWJvbFBhcmVudFNwYW5dIGFzIFNwYW4gfCB1bmRlZmluZWQ7XG5cdFx0XHRpZiAoc3Bhbikge1xuXHRcdFx0XHRyZXR1cm4gc3Bhbjtcblx0XHRcdH1cblx0XHRcdGN1cnJlbnQgPSBPYmplY3QuZ2V0UHJvdG90eXBlT2YoY3VycmVudCk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHVuZGVmaW5lZDtcblx0fVxufVxuIl19
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runInRequestScope = runInRequestScope;
4
+ const api_1 = require("@opentelemetry/api");
5
+ /**
6
+ * Start the request span, hang its ending on response 'finish', and run
7
+ * `fn` inside the triple scope (provider ALS + OTEL global context +
8
+ * async-flow root frame). `fn` is the framework's "continue" callback.
9
+ */
10
+ function runInRequestScope(req, res, deps, fn) {
11
+ const route = req.route?.path ?? req.url;
12
+ const span = deps.tracer.startSpan(`HTTP ${req.method} ${route}`);
13
+ span.setAttribute('http.method', req.method);
14
+ span.setAttribute('http.url', req.url);
15
+ res.on('finish', () => {
16
+ span.setAttribute('http.status_code', res.statusCode);
17
+ span.end();
18
+ });
19
+ // runWithSpan covers the mnemonica-hook side (the provider's own ALS);
20
+ // the OTEL global context is what DiveOtelProvider reads when it looks
21
+ // for a parent span at wrap boundaries — without this second entry
22
+ // dive spans never adopt the request span and stay root traces.
23
+ // The async-flow root frame (when provided) is the outermost scope:
24
+ // every async hop of this request — wrapped or not — inherits it via
25
+ // ALS propagation.
26
+ const activeCtx = api_1.trace.setSpan(api_1.context.active(), span);
27
+ const run = () => {
28
+ deps.otel.runWithSpan(span, () => {
29
+ api_1.context.with(activeCtx, fn);
30
+ });
31
+ };
32
+ if (deps.asyncFlow) {
33
+ deps.asyncFlow.runInScope(run);
34
+ return;
35
+ }
36
+ run();
37
+ }
38
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVxdWVzdC1zY29wZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9yZXF1ZXN0LXNjb3BlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBMENBLDhDQWtDQztBQS9ERCw0Q0FBbUU7QUF3Qm5FOzs7O0dBSUc7QUFDSCxTQUFnQixpQkFBaUIsQ0FDaEMsR0FBc0IsRUFDdEIsR0FBdUIsRUFDdkIsSUFBdUIsRUFDdkIsRUFBaUI7SUFFakIsTUFBTSxLQUFLLEdBQUcsR0FBRyxDQUFDLEtBQUssRUFBRSxJQUFJLElBQUksR0FBRyxDQUFDLEdBQUcsQ0FBQztJQUN6QyxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxRQUFRLEdBQUcsQ0FBQyxNQUFNLElBQUksS0FBSyxFQUFFLENBQUMsQ0FBQztJQUNsRSxJQUFJLENBQUMsWUFBWSxDQUFDLGFBQWEsRUFBRSxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDN0MsSUFBSSxDQUFDLFlBQVksQ0FBQyxVQUFVLEVBQUUsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBRXZDLEdBQUcsQ0FBQyxFQUFFLENBQUMsUUFBUSxFQUFFLEdBQUcsRUFBRTtRQUNyQixJQUFJLENBQUMsWUFBWSxDQUFDLGtCQUFrQixFQUFFLEdBQUcsQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUN0RCxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7SUFDWixDQUFDLENBQUMsQ0FBQztJQUVILHVFQUF1RTtJQUN2RSx1RUFBdUU7SUFDdkUsbUVBQW1FO0lBQ25FLGdFQUFnRTtJQUNoRSxvRUFBb0U7SUFDcEUscUVBQXFFO0lBQ3JFLG1CQUFtQjtJQUNuQixNQUFNLFNBQVMsR0FBRyxXQUFLLENBQUMsT0FBTyxDQUFDLGFBQVcsQ0FBQyxNQUFNLEVBQUUsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUM1RCxNQUFNLEdBQUcsR0FBRyxHQUFTLEVBQUU7UUFDdEIsSUFBSSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxFQUFFLEdBQUcsRUFBRTtZQUNoQyxhQUFXLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxFQUFFLENBQUMsQ0FBQztRQUNqQyxDQUFDLENBQUMsQ0FBQztJQUNKLENBQUMsQ0FBQztJQUNGLElBQUksSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1FBQ3BCLElBQUksQ0FBQyxTQUFTLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQy9CLE9BQU87SUFDUixDQUFDO0lBQ0QsR0FBRyxFQUFFLENBQUM7QUFDUCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBIVFRQIHJlcXVlc3Qgc2NvcGUg4oCUIHRoZSBmcmFtZXdvcmstZnJlZSBoYWxmIG9mIHRoZSBhZGFwdGVyJ3MgdHJhY2VcbiAqIG1pZGRsZXdhcmU6IG9uZSBPVGVsIHNwYW4gcGVyIEhUVFAgcmVxdWVzdCwgdmlzaWJsZSB0byBtbmVtb25pY2EgaG9va3NcbiAqIHRocm91Z2ggdGhlIHByb3ZpZGVyJ3Mgb3duIEFMUyBBTkQgdG8gZGl2ZSBzcGFucyB0aHJvdWdoIHRoZSBPVEVMIGdsb2JhbFxuICogY29udGV4dCwgd2l0aCB0aGUgYXN5bmMtZmxvdyByb290IGZyYW1lIG91dGVybW9zdCB3aGVuIHByb3ZpZGVkLlxuICpcbiAqIEZyYW1ld29yayBtYXBwaW5nIG5vdGVzOlxuICogIC0gRXhwcmVzcy1zdHlsZSBtaWRkbGV3YXJlOiBjYWxsIHdpdGggKHJlcSwgcmVzLCBkZXBzLCAoKSA9PiBuZXh0KCkpLlxuICogIC0gRmFzdGlmeTogb25SZXF1ZXN0IGhvb2sg4oCUIGNhbGwgd2l0aCAocmVxdWVzdC5yYXcsIHJlcGx5LnJhdywgZGVwcyxcbiAqICAgICgpID0+IGRvbmUoKSk7IHJlcGx5LnJhdyBpcyB0aGUgdW5kZXJseWluZyBTZXJ2ZXJSZXNwb25zZS5cbiAqICAtIHJhdyBodHRwOiB3cmFwIHRoZSByZXF1ZXN0IGxpc3RlbmVyOyBTZXJ2ZXJSZXNwb25zZSBlbWl0cyAnZmluaXNoJy5cbiAqL1xuaW1wb3J0IHR5cGUgeyBUcmFjZXIgfSBmcm9tICdAb3BlbnRlbGVtZXRyeS9hcGknO1xuaW1wb3J0IHsgY29udGV4dCBhcyBvdGVsQ29udGV4dCwgdHJhY2UgfSBmcm9tICdAb3BlbnRlbGVtZXRyeS9hcGknO1xuaW1wb3J0IHsgTW5lbW9uaWNhT3RlbFByb3ZpZGVyIH0gZnJvbSAnLi9wcm92aWRlcnMvbW5lbW9uaWNhLW90ZWwucHJvdmlkZXIuanMnO1xuaW1wb3J0IHsgQXN5bmNGbG93UHJvdmlkZXIgfSBmcm9tICcuL3Byb3ZpZGVycy9hc3luYy1mbG93LnByb3ZpZGVyLmpzJztcblxuLyoqIFN0cnVjdHVyYWwgbWluaW11bSBvZiB0aGUgcmVxdWVzdC4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgSHR0cFJlcXVlc3RMaWtlIHtcblx0bWV0aG9kIDogc3RyaW5nO1xuXHR1cmwgICAgOiBzdHJpbmc7XG5cdC8qKiBFeHByZXNzIGV4cG9zZXMgdGhlIG1hdGNoZWQgcm91dGUgYXMgcmVxLnJvdXRlLnBhdGggKi9cblx0cm91dGU/IDogeyBwYXRoPzogc3RyaW5nIH07XG59XG5cbi8qKiBTdHJ1Y3R1cmFsIG1pbmltdW0gb2YgdGhlIHJlc3BvbnNlOiBhICdmaW5pc2gnIGV2ZW50ICsgc3RhdHVzQ29kZS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgSHR0cFJlc3BvbnNlTGlrZSB7XG5cdHN0YXR1c0NvZGUgOiBudW1iZXI7XG5cdG9uIChldmVudDogJ2ZpbmlzaCcsIGxpc3RlbmVyOiAoKSA9PiB2b2lkKTogdW5rbm93bjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSZXF1ZXN0U2NvcGVEZXBzIHtcblx0dHJhY2VyICAgICA6IFRyYWNlcjtcblx0b3RlbCAgICAgICA6IE1uZW1vbmljYU90ZWxQcm92aWRlcjtcblx0YXN5bmNGbG93PyA6IEFzeW5jRmxvd1Byb3ZpZGVyO1xufVxuXG4vKipcbiAqIFN0YXJ0IHRoZSByZXF1ZXN0IHNwYW4sIGhhbmcgaXRzIGVuZGluZyBvbiByZXNwb25zZSAnZmluaXNoJywgYW5kIHJ1blxuICogYGZuYCBpbnNpZGUgdGhlIHRyaXBsZSBzY29wZSAocHJvdmlkZXIgQUxTICsgT1RFTCBnbG9iYWwgY29udGV4dCArXG4gKiBhc3luYy1mbG93IHJvb3QgZnJhbWUpLiBgZm5gIGlzIHRoZSBmcmFtZXdvcmsncyBcImNvbnRpbnVlXCIgY2FsbGJhY2suXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBydW5JblJlcXVlc3RTY29wZSAoXG5cdHJlcSAgOiBIdHRwUmVxdWVzdExpa2UsXG5cdHJlcyAgOiBIdHRwUmVzcG9uc2VMaWtlLFxuXHRkZXBzIDogUmVxdWVzdFNjb3BlRGVwcyxcblx0Zm4gICA6ICgpID0+IHZvaWQsXG4pOiB2b2lkIHtcblx0Y29uc3Qgcm91dGUgPSByZXEucm91dGU/LnBhdGggPz8gcmVxLnVybDtcblx0Y29uc3Qgc3BhbiA9IGRlcHMudHJhY2VyLnN0YXJ0U3BhbihgSFRUUCAke3JlcS5tZXRob2R9ICR7cm91dGV9YCk7XG5cdHNwYW4uc2V0QXR0cmlidXRlKCdodHRwLm1ldGhvZCcsIHJlcS5tZXRob2QpO1xuXHRzcGFuLnNldEF0dHJpYnV0ZSgnaHR0cC51cmwnLCByZXEudXJsKTtcblxuXHRyZXMub24oJ2ZpbmlzaCcsICgpID0+IHtcblx0XHRzcGFuLnNldEF0dHJpYnV0ZSgnaHR0cC5zdGF0dXNfY29kZScsIHJlcy5zdGF0dXNDb2RlKTtcblx0XHRzcGFuLmVuZCgpO1xuXHR9KTtcblxuXHQvLyBydW5XaXRoU3BhbiBjb3ZlcnMgdGhlIG1uZW1vbmljYS1ob29rIHNpZGUgKHRoZSBwcm92aWRlcidzIG93biBBTFMpO1xuXHQvLyB0aGUgT1RFTCBnbG9iYWwgY29udGV4dCBpcyB3aGF0IERpdmVPdGVsUHJvdmlkZXIgcmVhZHMgd2hlbiBpdCBsb29rc1xuXHQvLyBmb3IgYSBwYXJlbnQgc3BhbiBhdCB3cmFwIGJvdW5kYXJpZXMg4oCUIHdpdGhvdXQgdGhpcyBzZWNvbmQgZW50cnlcblx0Ly8gZGl2ZSBzcGFucyBuZXZlciBhZG9wdCB0aGUgcmVxdWVzdCBzcGFuIGFuZCBzdGF5IHJvb3QgdHJhY2VzLlxuXHQvLyBUaGUgYXN5bmMtZmxvdyByb290IGZyYW1lICh3aGVuIHByb3ZpZGVkKSBpcyB0aGUgb3V0ZXJtb3N0IHNjb3BlOlxuXHQvLyBldmVyeSBhc3luYyBob3Agb2YgdGhpcyByZXF1ZXN0IOKAlCB3cmFwcGVkIG9yIG5vdCDigJQgaW5oZXJpdHMgaXQgdmlhXG5cdC8vIEFMUyBwcm9wYWdhdGlvbi5cblx0Y29uc3QgYWN0aXZlQ3R4ID0gdHJhY2Uuc2V0U3BhbihvdGVsQ29udGV4dC5hY3RpdmUoKSwgc3Bhbik7XG5cdGNvbnN0IHJ1biA9ICgpOiB2b2lkID0+IHtcblx0XHRkZXBzLm90ZWwucnVuV2l0aFNwYW4oc3BhbiwgKCkgPT4ge1xuXHRcdFx0b3RlbENvbnRleHQud2l0aChhY3RpdmVDdHgsIGZuKTtcblx0XHR9KTtcblx0fTtcblx0aWYgKGRlcHMuYXN5bmNGbG93KSB7XG5cdFx0ZGVwcy5hc3luY0Zsb3cucnVuSW5TY29wZShydW4pO1xuXHRcdHJldHVybjtcblx0fVxuXHRydW4oKTtcbn1cbiJdfQ==