@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.
- package/LICENSE +21 -0
- package/README.md +109 -0
- package/build/hooks/attach-hooks.d.ts +3 -0
- package/build/hooks/attach-hooks.d.ts.map +1 -0
- package/build/hooks/attach-hooks.js +52 -0
- package/build/index.d.ts +32 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +32 -0
- package/build/providers/async-flow.provider.d.ts +40 -0
- package/build/providers/async-flow.provider.d.ts.map +1 -0
- package/build/providers/async-flow.provider.js +128 -0
- package/build/providers/dive-otel.provider.d.ts +51 -0
- package/build/providers/dive-otel.provider.d.ts.map +1 -0
- package/build/providers/dive-otel.provider.js +238 -0
- package/build/providers/mnemonica-otel.provider.d.ts +12 -0
- package/build/providers/mnemonica-otel.provider.d.ts.map +1 -0
- package/build/providers/mnemonica-otel.provider.js +113 -0
- package/build/request-scope.d.ts +41 -0
- package/build/request-scope.d.ts.map +1 -0
- package/build/request-scope.js +35 -0
- package/build/thunderstruck/feed-from-request.d.ts +21 -0
- package/build/thunderstruck/feed-from-request.d.ts.map +1 -0
- package/build/thunderstruck/feed-from-request.js +34 -0
- package/build/thunderstruck/pre-root.d.ts +67 -0
- package/build/thunderstruck/pre-root.d.ts.map +1 -0
- package/build/thunderstruck/pre-root.js +78 -0
- package/build/unblind.d.ts +46 -0
- package/build/unblind.d.ts.map +1 -0
- package/build/unblind.js +120 -0
- package/build/utils/dive-flow.d.ts +24 -0
- package/build/utils/dive-flow.d.ts.map +1 -0
- package/build/utils/dive-flow.js +33 -0
- package/build/utils/is-mnemonica-instance.d.ts +2 -0
- package/build/utils/is-mnemonica-instance.d.ts.map +1 -0
- package/build/utils/is-mnemonica-instance.js +9 -0
- package/build-cjs/hooks/attach-hooks.js +55 -0
- package/build-cjs/index.js +52 -0
- package/build-cjs/package.json +1 -0
- package/build-cjs/providers/async-flow.provider.js +132 -0
- package/build-cjs/providers/dive-otel.provider.js +242 -0
- package/build-cjs/providers/mnemonica-otel.provider.js +117 -0
- package/build-cjs/request-scope.js +38 -0
- package/build-cjs/thunderstruck/feed-from-request.js +37 -0
- package/build-cjs/thunderstruck/pre-root.js +83 -0
- package/build-cjs/unblind.js +127 -0
- package/build-cjs/utils/dive-flow.js +37 -0
- package/build-cjs/utils/is-mnemonica-instance.js +12 -0
- 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==
|