repro-nest 0.0.203 → 0.0.205
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/dist/index.js +90 -52
- package/package.json +1 -1
- package/src/index.ts +83 -47
- package/tracer/runtime.js +5 -0
package/dist/index.js
CHANGED
|
@@ -92,40 +92,97 @@ function flushQueryFinalizers(query, value, threw, error) {
|
|
|
92
92
|
}
|
|
93
93
|
catch { }
|
|
94
94
|
}
|
|
95
|
-
function patchMongooseExecCapture() {
|
|
95
|
+
function patchMongooseExecCapture(targetMongoose = mongoose) {
|
|
96
|
+
// Patch Query.prototype.exec to capture resolved results for trace return values.
|
|
96
97
|
try {
|
|
97
|
-
const Qp =
|
|
98
|
-
if (
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
98
|
+
const Qp = targetMongoose?.Query?.prototype;
|
|
99
|
+
if (Qp && !Qp.__repro_exec_patched) {
|
|
100
|
+
const origExec = Qp.exec;
|
|
101
|
+
if (typeof origExec === 'function') {
|
|
102
|
+
Qp.__repro_exec_patched = true;
|
|
103
|
+
Qp.exec = function reproPatchedExec(...args) {
|
|
104
|
+
try {
|
|
105
|
+
this.__repro_is_query = true;
|
|
106
|
+
}
|
|
107
|
+
catch { }
|
|
108
|
+
const p = origExec.apply(this, args);
|
|
109
|
+
try {
|
|
110
|
+
if (p && typeof p.then === 'function') {
|
|
111
|
+
this.__repro_result_promise = p;
|
|
112
|
+
p.then((res) => {
|
|
113
|
+
try {
|
|
114
|
+
this.__repro_result = res;
|
|
115
|
+
}
|
|
116
|
+
catch { }
|
|
117
|
+
flushQueryFinalizers(this, res, false, null);
|
|
118
|
+
return res;
|
|
119
|
+
}, (err) => {
|
|
120
|
+
flushQueryFinalizers(this, undefined, true, err);
|
|
121
|
+
return err;
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
catch { }
|
|
126
|
+
return p;
|
|
127
|
+
};
|
|
107
128
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
catch { }
|
|
132
|
+
// Patch Aggregate.prototype.exec as well so aggregation pipelines surface their results in traces.
|
|
133
|
+
try {
|
|
134
|
+
const Ap = targetMongoose?.Aggregate?.prototype;
|
|
135
|
+
if (Ap && !Ap.__repro_agg_exec_patched) {
|
|
136
|
+
const origAggExec = Ap.exec;
|
|
137
|
+
if (typeof origAggExec === 'function') {
|
|
138
|
+
Ap.__repro_agg_exec_patched = true;
|
|
139
|
+
Ap.exec = function reproPatchedAggExec(...args) {
|
|
140
|
+
try {
|
|
141
|
+
this.__repro_is_query = true;
|
|
142
|
+
}
|
|
143
|
+
catch { }
|
|
144
|
+
const p = origAggExec.apply(this, args);
|
|
145
|
+
try {
|
|
146
|
+
if (p && typeof p.then === 'function') {
|
|
147
|
+
this.__repro_result_promise = p;
|
|
148
|
+
p.then((res) => {
|
|
149
|
+
try {
|
|
150
|
+
this.__repro_result = res;
|
|
151
|
+
}
|
|
152
|
+
catch { }
|
|
153
|
+
flushQueryFinalizers(this, res, false, null);
|
|
154
|
+
return res;
|
|
155
|
+
}, (err) => {
|
|
156
|
+
flushQueryFinalizers(this, undefined, true, err);
|
|
157
|
+
return err;
|
|
158
|
+
});
|
|
116
159
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
flushQueryFinalizers(this, undefined, true, err);
|
|
122
|
-
return err;
|
|
123
|
-
});
|
|
124
|
-
}
|
|
160
|
+
}
|
|
161
|
+
catch { }
|
|
162
|
+
return p;
|
|
163
|
+
};
|
|
125
164
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
catch { }
|
|
168
|
+
}
|
|
169
|
+
function patchAllKnownMongooseInstances() {
|
|
170
|
+
// Patch the SDK's bundled mongoose first.
|
|
171
|
+
patchMongooseExecCapture(mongoose);
|
|
172
|
+
// Also patch any other mongoose copies the host app might have installed (e.g., different versions).
|
|
173
|
+
try {
|
|
174
|
+
const cache = require?.cache || {};
|
|
175
|
+
const seen = new Set();
|
|
176
|
+
Object.keys(cache).forEach((key) => {
|
|
177
|
+
if (!/node_modules[\\/](mongoose)[\\/]/i.test(key))
|
|
178
|
+
return;
|
|
179
|
+
const mod = cache[key];
|
|
180
|
+
const exp = mod?.exports;
|
|
181
|
+
if (!exp || seen.has(exp))
|
|
182
|
+
return;
|
|
183
|
+
seen.add(exp);
|
|
184
|
+
patchMongooseExecCapture(exp);
|
|
185
|
+
});
|
|
129
186
|
}
|
|
130
187
|
catch { }
|
|
131
188
|
}
|
|
@@ -384,7 +441,9 @@ function initReproTracing(opts) {
|
|
|
384
441
|
tracerPkg.patchHttp?.();
|
|
385
442
|
applyTraceLogPreference(tracerPkg);
|
|
386
443
|
__TRACER_READY = true;
|
|
387
|
-
|
|
444
|
+
patchAllKnownMongooseInstances();
|
|
445
|
+
// Patch again on the next tick to catch mongoose copies that load after init (different versions/copies).
|
|
446
|
+
setImmediate(() => patchAllKnownMongooseInstances());
|
|
388
447
|
}
|
|
389
448
|
catch {
|
|
390
449
|
__TRACER__ = null; // SDK still works without tracer
|
|
@@ -1289,27 +1348,6 @@ function reproMiddleware(cfg) {
|
|
|
1289
1348
|
depth: evt.depth,
|
|
1290
1349
|
library: inferLibraryNameFromFile(evt.file),
|
|
1291
1350
|
};
|
|
1292
|
-
if (evt.type === 'exit') {
|
|
1293
|
-
// If the function returned a Mongoose Query, update the exit value when the query settles.
|
|
1294
|
-
const rv = ev.returnValue;
|
|
1295
|
-
const setReturnValue = (val) => {
|
|
1296
|
-
try {
|
|
1297
|
-
evt.returnValue = sanitizeTraceValue(val);
|
|
1298
|
-
}
|
|
1299
|
-
catch { }
|
|
1300
|
-
};
|
|
1301
|
-
const qp = rv && rv.__repro_result_promise;
|
|
1302
|
-
const hasResult = rv && Object.prototype.hasOwnProperty.call(rv, '__repro_result');
|
|
1303
|
-
if (hasResult) {
|
|
1304
|
-
setReturnValue(rv.__repro_result);
|
|
1305
|
-
}
|
|
1306
|
-
else if (qp && typeof qp.then === 'function') {
|
|
1307
|
-
try {
|
|
1308
|
-
qp.then((val) => setReturnValue(val), () => { });
|
|
1309
|
-
}
|
|
1310
|
-
catch { }
|
|
1311
|
-
}
|
|
1312
|
-
}
|
|
1313
1351
|
const spanKey = normalizeSpanId(evt.spanId);
|
|
1314
1352
|
if (evt.type === 'enter') {
|
|
1315
1353
|
lastEventAt = Date.now();
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -86,34 +86,88 @@ function flushQueryFinalizers(query: any, value: any, threw: boolean, error: any
|
|
|
86
86
|
} catch {}
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
-
function patchMongooseExecCapture() {
|
|
89
|
+
function patchMongooseExecCapture(targetMongoose: any = mongoose) {
|
|
90
|
+
// Patch Query.prototype.exec to capture resolved results for trace return values.
|
|
90
91
|
try {
|
|
91
|
-
const Qp: any =
|
|
92
|
-
if (
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
92
|
+
const Qp: any = targetMongoose?.Query?.prototype;
|
|
93
|
+
if (Qp && !Qp.__repro_exec_patched) {
|
|
94
|
+
const origExec = Qp.exec;
|
|
95
|
+
if (typeof origExec === 'function') {
|
|
96
|
+
Qp.__repro_exec_patched = true;
|
|
97
|
+
Qp.exec = function reproPatchedExec(this: any, ...args: any[]) {
|
|
98
|
+
try { (this as any).__repro_is_query = true; } catch {}
|
|
99
|
+
const p = origExec.apply(this, args);
|
|
100
|
+
try {
|
|
101
|
+
if (p && typeof p.then === 'function') {
|
|
102
|
+
this.__repro_result_promise = p;
|
|
103
|
+
p.then(
|
|
104
|
+
(res: any) => {
|
|
105
|
+
try { this.__repro_result = res; } catch {}
|
|
106
|
+
flushQueryFinalizers(this, res, false, null);
|
|
107
|
+
return res;
|
|
108
|
+
},
|
|
109
|
+
(err: any) => {
|
|
110
|
+
flushQueryFinalizers(this, undefined, true, err);
|
|
111
|
+
return err;
|
|
112
|
+
}
|
|
113
|
+
);
|
|
111
114
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
}
|
|
115
|
+
} catch {}
|
|
116
|
+
return p;
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
} catch {}
|
|
121
|
+
|
|
122
|
+
// Patch Aggregate.prototype.exec as well so aggregation pipelines surface their results in traces.
|
|
123
|
+
try {
|
|
124
|
+
const Ap: any = targetMongoose?.Aggregate?.prototype;
|
|
125
|
+
if (Ap && !Ap.__repro_agg_exec_patched) {
|
|
126
|
+
const origAggExec = Ap.exec;
|
|
127
|
+
if (typeof origAggExec === 'function') {
|
|
128
|
+
Ap.__repro_agg_exec_patched = true;
|
|
129
|
+
Ap.exec = function reproPatchedAggExec(this: any, ...args: any[]) {
|
|
130
|
+
try { (this as any).__repro_is_query = true; } catch {}
|
|
131
|
+
const p = origAggExec.apply(this, args);
|
|
132
|
+
try {
|
|
133
|
+
if (p && typeof p.then === 'function') {
|
|
134
|
+
this.__repro_result_promise = p;
|
|
135
|
+
p.then(
|
|
136
|
+
(res: any) => {
|
|
137
|
+
try { this.__repro_result = res; } catch {}
|
|
138
|
+
flushQueryFinalizers(this, res, false, null);
|
|
139
|
+
return res;
|
|
140
|
+
},
|
|
141
|
+
(err: any) => {
|
|
142
|
+
flushQueryFinalizers(this, undefined, true, err);
|
|
143
|
+
return err;
|
|
144
|
+
}
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
} catch {}
|
|
148
|
+
return p;
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
} catch {}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function patchAllKnownMongooseInstances() {
|
|
156
|
+
// Patch the SDK's bundled mongoose first.
|
|
157
|
+
patchMongooseExecCapture(mongoose as any);
|
|
158
|
+
|
|
159
|
+
// Also patch any other mongoose copies the host app might have installed (e.g., different versions).
|
|
160
|
+
try {
|
|
161
|
+
const cache = (require as any)?.cache || {};
|
|
162
|
+
const seen = new Set<any>();
|
|
163
|
+
Object.keys(cache).forEach((key) => {
|
|
164
|
+
if (!/node_modules[\\/](mongoose)[\\/]/i.test(key)) return;
|
|
165
|
+
const mod = cache[key];
|
|
166
|
+
const exp = mod?.exports;
|
|
167
|
+
if (!exp || seen.has(exp)) return;
|
|
168
|
+
seen.add(exp);
|
|
169
|
+
patchMongooseExecCapture(exp);
|
|
170
|
+
});
|
|
117
171
|
} catch {}
|
|
118
172
|
}
|
|
119
173
|
|
|
@@ -570,7 +624,9 @@ export function initReproTracing(opts?: ReproTracingInitOptions) {
|
|
|
570
624
|
tracerPkg.patchHttp?.();
|
|
571
625
|
applyTraceLogPreference(tracerPkg);
|
|
572
626
|
__TRACER_READY = true;
|
|
573
|
-
|
|
627
|
+
patchAllKnownMongooseInstances();
|
|
628
|
+
// Patch again on the next tick to catch mongoose copies that load after init (different versions/copies).
|
|
629
|
+
setImmediate(() => patchAllKnownMongooseInstances());
|
|
574
630
|
} catch {
|
|
575
631
|
__TRACER__ = null; // SDK still works without tracer
|
|
576
632
|
} finally {
|
|
@@ -1499,26 +1555,6 @@ export function reproMiddleware(cfg: ReproMiddlewareConfig) {
|
|
|
1499
1555
|
library: inferLibraryNameFromFile(evt.file),
|
|
1500
1556
|
};
|
|
1501
1557
|
|
|
1502
|
-
if (evt.type === 'exit') {
|
|
1503
|
-
// If the function returned a Mongoose Query, update the exit value when the query settles.
|
|
1504
|
-
const rv: any = ev.returnValue;
|
|
1505
|
-
const setReturnValue = (val: any) => {
|
|
1506
|
-
try { evt.returnValue = sanitizeTraceValue(val); } catch {}
|
|
1507
|
-
};
|
|
1508
|
-
const qp = rv && rv.__repro_result_promise;
|
|
1509
|
-
const hasResult = rv && Object.prototype.hasOwnProperty.call(rv, '__repro_result');
|
|
1510
|
-
if (hasResult) {
|
|
1511
|
-
setReturnValue(rv.__repro_result);
|
|
1512
|
-
} else if (qp && typeof qp.then === 'function') {
|
|
1513
|
-
try {
|
|
1514
|
-
qp.then(
|
|
1515
|
-
(val: any) => setReturnValue(val),
|
|
1516
|
-
() => {}
|
|
1517
|
-
);
|
|
1518
|
-
} catch {}
|
|
1519
|
-
}
|
|
1520
|
-
}
|
|
1521
|
-
|
|
1522
1558
|
const spanKey = normalizeSpanId(evt.spanId);
|
|
1523
1559
|
if (evt.type === 'enter') {
|
|
1524
1560
|
lastEventAt = Date.now();
|
package/tracer/runtime.js
CHANGED