@reproapp/node-sdk 0.0.26 → 0.0.28
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.d.ts +11 -0
- package/dist/index.js +585 -1
- package/dist/ingest/client.js +18 -3
- package/package.json +2 -2
- package/src/index.ts +651 -0
- package/src/ingest/client.ts +25 -3
- package/test/ingest-critical-retention.test.js +147 -0
- package/test/ingest-critical-retry-retention.test.js +57 -0
- package/test/ingest-high-priority-retention.test.js +75 -0
- package/test/mongodb-integration.test.js +389 -0
package/src/index.ts
CHANGED
|
@@ -1154,6 +1154,13 @@ type Ctx = {
|
|
|
1154
1154
|
maskReq?: MaskRequestContext;
|
|
1155
1155
|
privacyTasks?: Set<Promise<void>>;
|
|
1156
1156
|
captureScope?: RequestCaptureScopeState;
|
|
1157
|
+
nativeMongoSuppressions?: NativeMongoSuppression[];
|
|
1158
|
+
};
|
|
1159
|
+
|
|
1160
|
+
type NativeMongoSuppression = {
|
|
1161
|
+
collection?: string | null;
|
|
1162
|
+
ops?: Set<string>;
|
|
1163
|
+
startedAt: number;
|
|
1157
1164
|
};
|
|
1158
1165
|
|
|
1159
1166
|
type RequestCaptureScopeState = {
|
|
@@ -1213,6 +1220,54 @@ function buildRequestCaptureManifestPayload(
|
|
|
1213
1220
|
const als = new AsyncLocalStorage<Ctx>();
|
|
1214
1221
|
const getCtx = () => als.getStore() || {};
|
|
1215
1222
|
|
|
1223
|
+
function normalizeNativeMongoSuppressionOp(op: string | null | undefined): string {
|
|
1224
|
+
return String(op ?? '').trim();
|
|
1225
|
+
}
|
|
1226
|
+
|
|
1227
|
+
function pushNativeMongoSuppression(collection: any, ops?: string[] | readonly string[]): NativeMongoSuppression | null {
|
|
1228
|
+
const store = als.getStore();
|
|
1229
|
+
if (!store) return null;
|
|
1230
|
+
const normalizedOps = Array.isArray(ops)
|
|
1231
|
+
? ops.map(normalizeNativeMongoSuppressionOp).filter(Boolean)
|
|
1232
|
+
: [];
|
|
1233
|
+
const token: NativeMongoSuppression = {
|
|
1234
|
+
collection: collection == null ? null : String(collection),
|
|
1235
|
+
ops: normalizedOps.length ? new Set(normalizedOps) : undefined,
|
|
1236
|
+
startedAt: Date.now(),
|
|
1237
|
+
};
|
|
1238
|
+
if (!Array.isArray(store.nativeMongoSuppressions)) {
|
|
1239
|
+
store.nativeMongoSuppressions = [];
|
|
1240
|
+
}
|
|
1241
|
+
store.nativeMongoSuppressions.push(token);
|
|
1242
|
+
return token;
|
|
1243
|
+
}
|
|
1244
|
+
|
|
1245
|
+
function popNativeMongoSuppression(token: NativeMongoSuppression | null | undefined): void {
|
|
1246
|
+
if (!token) return;
|
|
1247
|
+
const store = als.getStore();
|
|
1248
|
+
const suppressions = store?.nativeMongoSuppressions;
|
|
1249
|
+
if (!Array.isArray(suppressions) || suppressions.length === 0) return;
|
|
1250
|
+
const index = suppressions.indexOf(token);
|
|
1251
|
+
if (index >= 0) {
|
|
1252
|
+
suppressions.splice(index, 1);
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
|
|
1256
|
+
function isNativeMongoSuppressed(collection: any, op: string): boolean {
|
|
1257
|
+
const suppressions = (getCtx() as Ctx).nativeMongoSuppressions;
|
|
1258
|
+
if (!Array.isArray(suppressions) || suppressions.length === 0) return false;
|
|
1259
|
+
const normalizedCollection = collection == null ? null : String(collection);
|
|
1260
|
+
const normalizedOp = normalizeNativeMongoSuppressionOp(op);
|
|
1261
|
+
const now = Date.now();
|
|
1262
|
+
for (const token of suppressions) {
|
|
1263
|
+
if (!token || now - token.startedAt > 60000) continue;
|
|
1264
|
+
if (token.collection && normalizedCollection && token.collection !== normalizedCollection) continue;
|
|
1265
|
+
if (token.ops && token.ops.size > 0 && !token.ops.has(normalizedOp)) continue;
|
|
1266
|
+
return true;
|
|
1267
|
+
}
|
|
1268
|
+
return false;
|
|
1269
|
+
}
|
|
1270
|
+
|
|
1216
1271
|
function currentClockSkewMs(): number {
|
|
1217
1272
|
const store = als.getStore();
|
|
1218
1273
|
const skew = store?.clockSkewMs;
|
|
@@ -4837,6 +4892,7 @@ export type ReproInitConfig = ReproMiddlewareConfig & {
|
|
|
4837
4892
|
|
|
4838
4893
|
export function reproMiddleware(cfg: ReproMiddlewareConfig) {
|
|
4839
4894
|
const masking = normalizeMaskingConfig(cfg.masking);
|
|
4895
|
+
patchMongoDb(cfg);
|
|
4840
4896
|
return async function (req: Request, res: Response, next: NextFunction) {
|
|
4841
4897
|
const querySid = readRequestQueryParam(req, REPRO_QUERY_SESSION_PARAM);
|
|
4842
4898
|
const queryAid = readRequestQueryParam(req, REPRO_QUERY_ACTION_PARAM);
|
|
@@ -5424,6 +5480,15 @@ export function reproMiddleware(cfg: ReproMiddlewareConfig) {
|
|
|
5424
5480
|
// - ONLY schema middleware (pre/post) for specific ops
|
|
5425
5481
|
// - keeps your existing doc-diff hooks
|
|
5426
5482
|
// ===================================================================
|
|
5483
|
+
function nativeMongoOpsForMongooseOp(op: string): string[] {
|
|
5484
|
+
if (op === 'findByIdAndUpdate') return ['findOneAndUpdate'];
|
|
5485
|
+
if (op === 'findByIdAndDelete' || op === 'findByIdAndRemove' || op === 'findOneAndRemove') {
|
|
5486
|
+
return ['findOneAndDelete'];
|
|
5487
|
+
}
|
|
5488
|
+
if (op === 'findByIdAndReplace') return ['findOneAndReplace'];
|
|
5489
|
+
return [op];
|
|
5490
|
+
}
|
|
5491
|
+
|
|
5427
5492
|
export function reproMongoosePlugin(cfg: ReproMiddlewareConfig) {
|
|
5428
5493
|
return function (schema: Schema) {
|
|
5429
5494
|
// -------- pre/post save (unchanged) --------
|
|
@@ -5441,6 +5506,10 @@ export function reproMongoosePlugin(cfg: ReproMiddlewareConfig) {
|
|
|
5441
5506
|
? (this as any).modifiedPaths()
|
|
5442
5507
|
: [],
|
|
5443
5508
|
};
|
|
5509
|
+
(this as any).__repro_native_mongo_suppression = pushNativeMongoSuppression(
|
|
5510
|
+
(this as any).__repro_meta.collection,
|
|
5511
|
+
this.isNew ? ['insertOne'] : ['updateOne', 'replaceOne'],
|
|
5512
|
+
);
|
|
5444
5513
|
next();
|
|
5445
5514
|
});
|
|
5446
5515
|
|
|
@@ -5475,6 +5544,12 @@ export function reproMongoosePlugin(cfg: ReproMiddlewareConfig) {
|
|
|
5475
5544
|
t: alignTimestamp(meta.t0 ?? Date.now()),
|
|
5476
5545
|
spanContext,
|
|
5477
5546
|
});
|
|
5547
|
+
popNativeMongoSuppression((this as any).__repro_native_mongo_suppression);
|
|
5548
|
+
});
|
|
5549
|
+
|
|
5550
|
+
schema.post('save', { document: true }, function (error: any, _doc: any, next: Function) {
|
|
5551
|
+
popNativeMongoSuppression((this as any).__repro_native_mongo_suppression);
|
|
5552
|
+
next(error);
|
|
5478
5553
|
});
|
|
5479
5554
|
|
|
5480
5555
|
// -------- findOneAndUpdate capture (unchanged) --------
|
|
@@ -5489,6 +5564,10 @@ export function reproMongoosePlugin(cfg: ReproMiddlewareConfig) {
|
|
|
5489
5564
|
(this as any).__repro_spanContext = captureSpanContextFromTracer(this);
|
|
5490
5565
|
(this as any).__repro_filter = filter;
|
|
5491
5566
|
(this as any).__repro_update = this.getUpdate?.() ?? (this as any)._update ?? undefined;
|
|
5567
|
+
(this as any).__repro_native_mongo_suppression = pushNativeMongoSuppression(
|
|
5568
|
+
(this as any).__repro_collection,
|
|
5569
|
+
['findOneAndUpdate'],
|
|
5570
|
+
);
|
|
5492
5571
|
} catch {}
|
|
5493
5572
|
next();
|
|
5494
5573
|
});
|
|
@@ -5518,8 +5597,14 @@ export function reproMongoosePlugin(cfg: ReproMiddlewareConfig) {
|
|
|
5518
5597
|
t: alignTimestamp((this as any).__repro_t0 ?? Date.now()),
|
|
5519
5598
|
spanContext,
|
|
5520
5599
|
});
|
|
5600
|
+
popNativeMongoSuppression((this as any).__repro_native_mongo_suppression);
|
|
5521
5601
|
});
|
|
5522
5602
|
|
|
5603
|
+
schema.post<Query<any, any>>('findOneAndUpdate', function (this: any, error: any, _res: any, next: Function) {
|
|
5604
|
+
popNativeMongoSuppression((this as any).__repro_native_mongo_suppression);
|
|
5605
|
+
next(error);
|
|
5606
|
+
} as any);
|
|
5607
|
+
|
|
5523
5608
|
// -------- deleteOne capture (unchanged) --------
|
|
5524
5609
|
schema.pre<Query<any, any>>('deleteOne', { document: false, query: true }, function (next) {
|
|
5525
5610
|
const { sid, aid } = getCtx(); if (!sid || !aid) return next();
|
|
@@ -5529,6 +5614,10 @@ export function reproMongoosePlugin(cfg: ReproMiddlewareConfig) {
|
|
|
5529
5614
|
(this as any).__repro_collection = resolveCollectionOrWarn(this, 'query');
|
|
5530
5615
|
(this as any).__repro_filter = filter;
|
|
5531
5616
|
(this as any).__repro_spanContext = captureSpanContextFromTracer(this);
|
|
5617
|
+
(this as any).__repro_native_mongo_suppression = pushNativeMongoSuppression(
|
|
5618
|
+
(this as any).__repro_collection,
|
|
5619
|
+
['deleteOne'],
|
|
5620
|
+
);
|
|
5532
5621
|
} catch {}
|
|
5533
5622
|
next();
|
|
5534
5623
|
});
|
|
@@ -5550,8 +5639,14 @@ export function reproMongoosePlugin(cfg: ReproMiddlewareConfig) {
|
|
|
5550
5639
|
t: alignTimestamp((this as any).__repro_t0 ?? Date.now()),
|
|
5551
5640
|
spanContext,
|
|
5552
5641
|
});
|
|
5642
|
+
popNativeMongoSuppression((this as any).__repro_native_mongo_suppression);
|
|
5553
5643
|
});
|
|
5554
5644
|
|
|
5645
|
+
schema.post<Query<any, any>>('deleteOne', { document: false, query: true }, function (this: any, error: any, _res: any, next: Function) {
|
|
5646
|
+
popNativeMongoSuppression((this as any).__repro_native_mongo_suppression);
|
|
5647
|
+
next(error);
|
|
5648
|
+
} as any);
|
|
5649
|
+
|
|
5555
5650
|
// -------- NON-intrusive generic query telemetry via schema hooks -------
|
|
5556
5651
|
const READ_OPS = [
|
|
5557
5652
|
'find',
|
|
@@ -5593,6 +5688,10 @@ export function reproMongoosePlugin(cfg: ReproMiddlewareConfig) {
|
|
|
5593
5688
|
rawProjection,
|
|
5594
5689
|
rawOptions,
|
|
5595
5690
|
};
|
|
5691
|
+
(this as any).__repro_native_mongo_suppression = pushNativeMongoSuppression(
|
|
5692
|
+
(this as any).__repro_qmeta.collection,
|
|
5693
|
+
nativeMongoOpsForMongooseOp(op),
|
|
5694
|
+
);
|
|
5596
5695
|
} catch {
|
|
5597
5696
|
(this as any).__repro_qmeta = {
|
|
5598
5697
|
t0: Date.now(),
|
|
@@ -5600,6 +5699,10 @@ export function reproMongoosePlugin(cfg: ReproMiddlewareConfig) {
|
|
|
5600
5699
|
op,
|
|
5601
5700
|
spanContext: captureSpanContextFromTracer(this),
|
|
5602
5701
|
};
|
|
5702
|
+
(this as any).__repro_native_mongo_suppression = pushNativeMongoSuppression(
|
|
5703
|
+
'unknown',
|
|
5704
|
+
nativeMongoOpsForMongooseOp(op),
|
|
5705
|
+
);
|
|
5603
5706
|
}
|
|
5604
5707
|
next();
|
|
5605
5708
|
});
|
|
@@ -5625,7 +5728,13 @@ export function reproMongoosePlugin(cfg: ReproMiddlewareConfig) {
|
|
|
5625
5728
|
t: alignedNow(),
|
|
5626
5729
|
spanContext,
|
|
5627
5730
|
});
|
|
5731
|
+
popNativeMongoSuppression((this as any).__repro_native_mongo_suppression);
|
|
5628
5732
|
});
|
|
5733
|
+
|
|
5734
|
+
schema.post(op as any, function (this: any, error: any, _res: any, next: Function) {
|
|
5735
|
+
popNativeMongoSuppression((this as any).__repro_native_mongo_suppression);
|
|
5736
|
+
next(error);
|
|
5737
|
+
} as any);
|
|
5629
5738
|
}
|
|
5630
5739
|
|
|
5631
5740
|
READ_OPS.forEach(attachQueryHooks);
|
|
@@ -5641,12 +5750,17 @@ export function reproMongoosePlugin(cfg: ReproMiddlewareConfig) {
|
|
|
5641
5750
|
rawDocs,
|
|
5642
5751
|
spanContext: captureSpanContextFromTracer(this),
|
|
5643
5752
|
};
|
|
5753
|
+
(this as any).__repro_native_mongo_suppression = pushNativeMongoSuppression(
|
|
5754
|
+
(this as any).__repro_insert_meta.collection,
|
|
5755
|
+
['insertMany'],
|
|
5756
|
+
);
|
|
5644
5757
|
} catch {
|
|
5645
5758
|
(this as any).__repro_insert_meta = {
|
|
5646
5759
|
t0: Date.now(),
|
|
5647
5760
|
collection: 'unknown',
|
|
5648
5761
|
spanContext: captureSpanContextFromTracer(this),
|
|
5649
5762
|
};
|
|
5763
|
+
(this as any).__repro_native_mongo_suppression = pushNativeMongoSuppression('unknown', ['insertMany']);
|
|
5650
5764
|
}
|
|
5651
5765
|
next();
|
|
5652
5766
|
} as any);
|
|
@@ -5666,6 +5780,12 @@ export function reproMongoosePlugin(cfg: ReproMiddlewareConfig) {
|
|
|
5666
5780
|
t: alignedNow(),
|
|
5667
5781
|
spanContext,
|
|
5668
5782
|
});
|
|
5783
|
+
popNativeMongoSuppression((this as any).__repro_native_mongo_suppression);
|
|
5784
|
+
} as any);
|
|
5785
|
+
|
|
5786
|
+
schema.post<any>('insertMany' as any, { document: false, query: false } as any, function (this: any, error: any, _res: any, next: Function) {
|
|
5787
|
+
popNativeMongoSuppression((this as any).__repro_native_mongo_suppression);
|
|
5788
|
+
next(error);
|
|
5669
5789
|
} as any);
|
|
5670
5790
|
|
|
5671
5791
|
schema.pre<any>('bulkWrite' as any, { document: false, query: false } as any, function (this: any, next: Function, ops?: any[]) {
|
|
@@ -5677,12 +5797,17 @@ export function reproMongoosePlugin(cfg: ReproMiddlewareConfig) {
|
|
|
5677
5797
|
rawOps,
|
|
5678
5798
|
spanContext: captureSpanContextFromTracer(this),
|
|
5679
5799
|
};
|
|
5800
|
+
(this as any).__repro_native_mongo_suppression = pushNativeMongoSuppression(
|
|
5801
|
+
(this as any).__repro_bulk_meta.collection,
|
|
5802
|
+
['bulkWrite'],
|
|
5803
|
+
);
|
|
5680
5804
|
} catch {
|
|
5681
5805
|
(this as any).__repro_bulk_meta = {
|
|
5682
5806
|
t0: Date.now(),
|
|
5683
5807
|
collection: 'unknown',
|
|
5684
5808
|
spanContext: captureSpanContextFromTracer(this),
|
|
5685
5809
|
};
|
|
5810
|
+
(this as any).__repro_native_mongo_suppression = pushNativeMongoSuppression('unknown', ['bulkWrite']);
|
|
5686
5811
|
}
|
|
5687
5812
|
next();
|
|
5688
5813
|
} as any);
|
|
@@ -5702,6 +5827,12 @@ export function reproMongoosePlugin(cfg: ReproMiddlewareConfig) {
|
|
|
5702
5827
|
t: alignedNow(),
|
|
5703
5828
|
spanContext,
|
|
5704
5829
|
});
|
|
5830
|
+
popNativeMongoSuppression((this as any).__repro_native_mongo_suppression);
|
|
5831
|
+
} as any);
|
|
5832
|
+
|
|
5833
|
+
schema.post<any>('bulkWrite' as any, { document: false, query: false } as any, function (this: any, error: any, _res: any, next: Function) {
|
|
5834
|
+
popNativeMongoSuppression((this as any).__repro_native_mongo_suppression);
|
|
5835
|
+
next(error);
|
|
5705
5836
|
} as any);
|
|
5706
5837
|
|
|
5707
5838
|
// Aggregate middleware (non-intrusive)
|
|
@@ -5718,6 +5849,10 @@ export function reproMongoosePlugin(cfg: ReproMiddlewareConfig) {
|
|
|
5718
5849
|
spanContext: captureSpanContextFromTracer(this),
|
|
5719
5850
|
rawPipeline,
|
|
5720
5851
|
};
|
|
5852
|
+
(this as any).__repro_native_mongo_suppression = pushNativeMongoSuppression(
|
|
5853
|
+
(this as any).__repro_aggmeta.collection,
|
|
5854
|
+
['aggregate'],
|
|
5855
|
+
);
|
|
5721
5856
|
} catch {
|
|
5722
5857
|
(this as any).__repro_aggmeta = {
|
|
5723
5858
|
t0: Date.now(),
|
|
@@ -5725,6 +5860,7 @@ export function reproMongoosePlugin(cfg: ReproMiddlewareConfig) {
|
|
|
5725
5860
|
pipeline: undefined,
|
|
5726
5861
|
spanContext: captureSpanContextFromTracer(this),
|
|
5727
5862
|
};
|
|
5863
|
+
(this as any).__repro_native_mongo_suppression = pushNativeMongoSuppression('unknown', ['aggregate']);
|
|
5728
5864
|
}
|
|
5729
5865
|
next();
|
|
5730
5866
|
});
|
|
@@ -5745,7 +5881,13 @@ export function reproMongoosePlugin(cfg: ReproMiddlewareConfig) {
|
|
|
5745
5881
|
t: alignedNow(),
|
|
5746
5882
|
spanContext,
|
|
5747
5883
|
});
|
|
5884
|
+
popNativeMongoSuppression((this as any).__repro_native_mongo_suppression);
|
|
5748
5885
|
});
|
|
5886
|
+
|
|
5887
|
+
schema.post('aggregate', function (this: any, error: any, _res: any, next: Function) {
|
|
5888
|
+
popNativeMongoSuppression((this as any).__repro_native_mongo_suppression);
|
|
5889
|
+
next(error);
|
|
5890
|
+
} as any);
|
|
5749
5891
|
};
|
|
5750
5892
|
}
|
|
5751
5893
|
|
|
@@ -5771,9 +5913,23 @@ function summarizeQueryResult(op: string, res: any) {
|
|
|
5771
5913
|
return summary;
|
|
5772
5914
|
}
|
|
5773
5915
|
|
|
5916
|
+
if (op === 'insertOne') {
|
|
5917
|
+
const summary: Record<string, any> = {
|
|
5918
|
+
insertedId: res?.insertedId ?? undefined,
|
|
5919
|
+
acknowledged: res?.acknowledged ?? undefined,
|
|
5920
|
+
};
|
|
5921
|
+
if (typeof resultPreview !== 'undefined') summary.result = resultPreview;
|
|
5922
|
+
return summary;
|
|
5923
|
+
}
|
|
5924
|
+
|
|
5774
5925
|
if (op === 'insertMany') {
|
|
5775
5926
|
const summary: Record<string, any> = {};
|
|
5776
5927
|
if (Array.isArray(res)) summary.inserted = res.length;
|
|
5928
|
+
else {
|
|
5929
|
+
summary.inserted = res?.insertedCount ?? undefined;
|
|
5930
|
+
summary.insertedIds = res?.insertedIds ?? undefined;
|
|
5931
|
+
summary.acknowledged = res?.acknowledged ?? undefined;
|
|
5932
|
+
}
|
|
5777
5933
|
if (typeof resultPreview !== 'undefined') summary.result = resultPreview;
|
|
5778
5934
|
return summary;
|
|
5779
5935
|
}
|
|
@@ -8588,6 +8744,498 @@ export function patchRedis(cfg: RedisPatchConfig) {
|
|
|
8588
8744
|
}
|
|
8589
8745
|
}
|
|
8590
8746
|
|
|
8747
|
+
// ===================================================================
|
|
8748
|
+
// Native MongoDB driver integration
|
|
8749
|
+
// ===================================================================
|
|
8750
|
+
export type MongoDbPatchConfig = ReproMiddlewareConfig & {
|
|
8751
|
+
resolveContext?: () => { sid?: string; aid?: string } | undefined;
|
|
8752
|
+
};
|
|
8753
|
+
|
|
8754
|
+
const mongoDbPatchConfigs: MongoDbPatchConfig[] = [];
|
|
8755
|
+
let mongoDbRequireHookInstalled = false;
|
|
8756
|
+
|
|
8757
|
+
const MONGODB_PROMISE_OPS = [
|
|
8758
|
+
'insertOne',
|
|
8759
|
+
'insertMany',
|
|
8760
|
+
'updateOne',
|
|
8761
|
+
'updateMany',
|
|
8762
|
+
'replaceOne',
|
|
8763
|
+
'deleteOne',
|
|
8764
|
+
'deleteMany',
|
|
8765
|
+
'findOne',
|
|
8766
|
+
'countDocuments',
|
|
8767
|
+
'estimatedDocumentCount',
|
|
8768
|
+
'distinct',
|
|
8769
|
+
'bulkWrite',
|
|
8770
|
+
'findOneAndUpdate',
|
|
8771
|
+
'findOneAndDelete',
|
|
8772
|
+
'findOneAndReplace',
|
|
8773
|
+
] as const;
|
|
8774
|
+
|
|
8775
|
+
const MONGODB_CURSOR_OPS = ['find', 'aggregate'] as const;
|
|
8776
|
+
const MONGODB_CURSOR_TERMINALS = ['toArray', 'next', 'forEach'] as const;
|
|
8777
|
+
|
|
8778
|
+
function resolveMongoDbRuntimeContext(cfg: MongoDbPatchConfig) {
|
|
8779
|
+
const ctx = getCtx();
|
|
8780
|
+
const fallback = cfg.resolveContext?.() ?? {};
|
|
8781
|
+
return {
|
|
8782
|
+
ctx,
|
|
8783
|
+
sid: ctx.sid ?? fallback.sid ?? null,
|
|
8784
|
+
aid: ctx.aid ?? fallback.aid ?? null,
|
|
8785
|
+
};
|
|
8786
|
+
}
|
|
8787
|
+
|
|
8788
|
+
function resolveMongoCollectionName(collection: any): string {
|
|
8789
|
+
const candidates = [
|
|
8790
|
+
collection?.collectionName,
|
|
8791
|
+
collection?.namespace?.collection,
|
|
8792
|
+
collection?.s?.namespace?.collection,
|
|
8793
|
+
collection?.s?.namespace?.collectionName,
|
|
8794
|
+
];
|
|
8795
|
+
for (const candidate of candidates) {
|
|
8796
|
+
if (typeof candidate === 'string' && candidate.trim()) return candidate;
|
|
8797
|
+
}
|
|
8798
|
+
|
|
8799
|
+
const namespace =
|
|
8800
|
+
typeof collection?.namespace === 'string'
|
|
8801
|
+
? collection.namespace
|
|
8802
|
+
: typeof collection?.s?.namespace === 'string'
|
|
8803
|
+
? collection.s.namespace
|
|
8804
|
+
: typeof collection?.namespace?.toString === 'function'
|
|
8805
|
+
? collection.namespace.toString()
|
|
8806
|
+
: typeof collection?.s?.namespace?.toString === 'function'
|
|
8807
|
+
? collection.s.namespace.toString()
|
|
8808
|
+
: null;
|
|
8809
|
+
if (namespace && namespace.includes('.')) {
|
|
8810
|
+
return namespace.slice(namespace.indexOf('.') + 1) || namespace;
|
|
8811
|
+
}
|
|
8812
|
+
return namespace || 'unknown';
|
|
8813
|
+
}
|
|
8814
|
+
|
|
8815
|
+
function resolveMongoDbName(collection: any): string | undefined {
|
|
8816
|
+
const candidates = [
|
|
8817
|
+
collection?.dbName,
|
|
8818
|
+
collection?.db?.databaseName,
|
|
8819
|
+
collection?.s?.db?.databaseName,
|
|
8820
|
+
collection?.namespace?.db,
|
|
8821
|
+
collection?.s?.namespace?.db,
|
|
8822
|
+
];
|
|
8823
|
+
for (const candidate of candidates) {
|
|
8824
|
+
if (typeof candidate === 'string' && candidate.trim()) return candidate;
|
|
8825
|
+
}
|
|
8826
|
+
const namespace =
|
|
8827
|
+
typeof collection?.namespace === 'string'
|
|
8828
|
+
? collection.namespace
|
|
8829
|
+
: typeof collection?.s?.namespace === 'string'
|
|
8830
|
+
? collection.s.namespace
|
|
8831
|
+
: null;
|
|
8832
|
+
if (namespace && namespace.includes('.')) {
|
|
8833
|
+
return namespace.slice(0, namespace.indexOf('.')) || undefined;
|
|
8834
|
+
}
|
|
8835
|
+
return undefined;
|
|
8836
|
+
}
|
|
8837
|
+
|
|
8838
|
+
function summarizeMongoSession(session: any): any {
|
|
8839
|
+
if (!session || typeof session !== 'object') return session;
|
|
8840
|
+
let inTransaction: any = undefined;
|
|
8841
|
+
try {
|
|
8842
|
+
inTransaction = typeof session.inTransaction === 'function' ? session.inTransaction() : undefined;
|
|
8843
|
+
} catch {}
|
|
8844
|
+
return {
|
|
8845
|
+
__kind: 'mongodb_client_session',
|
|
8846
|
+
id: session.id ?? session.serverSession?.id ?? undefined,
|
|
8847
|
+
hasEnded: session.hasEnded ?? undefined,
|
|
8848
|
+
inTransaction,
|
|
8849
|
+
};
|
|
8850
|
+
}
|
|
8851
|
+
|
|
8852
|
+
function normalizeMongoDriverOptions(options: any): any {
|
|
8853
|
+
if (!options || typeof options !== 'object' || Array.isArray(options)) return options;
|
|
8854
|
+
const normalized: Record<string, any> = {};
|
|
8855
|
+
for (const key of Object.keys(options)) {
|
|
8856
|
+
normalized[key] = key === 'session'
|
|
8857
|
+
? summarizeMongoSession(options[key])
|
|
8858
|
+
: options[key];
|
|
8859
|
+
}
|
|
8860
|
+
return normalized;
|
|
8861
|
+
}
|
|
8862
|
+
|
|
8863
|
+
function summarizeMongoError(error: any): Record<string, any> {
|
|
8864
|
+
return {
|
|
8865
|
+
name: error?.name ?? undefined,
|
|
8866
|
+
message: error?.message ?? String(error),
|
|
8867
|
+
code: error?.code ?? undefined,
|
|
8868
|
+
codeName: error?.codeName ?? undefined,
|
|
8869
|
+
};
|
|
8870
|
+
}
|
|
8871
|
+
|
|
8872
|
+
function extractMongoPkFromFilter(filter: any): any {
|
|
8873
|
+
if (filter && typeof filter === 'object' && Object.prototype.hasOwnProperty.call(filter, '_id')) {
|
|
8874
|
+
return { _id: filter._id };
|
|
8875
|
+
}
|
|
8876
|
+
return undefined;
|
|
8877
|
+
}
|
|
8878
|
+
|
|
8879
|
+
function extractMongoPkFromDoc(doc: any, result?: any): any {
|
|
8880
|
+
const id = doc && typeof doc === 'object' ? doc._id : undefined;
|
|
8881
|
+
const insertedId = result?.insertedId;
|
|
8882
|
+
if (id !== undefined) return { _id: id };
|
|
8883
|
+
if (insertedId !== undefined) return { _id: insertedId };
|
|
8884
|
+
return undefined;
|
|
8885
|
+
}
|
|
8886
|
+
|
|
8887
|
+
function buildMongoQueryPayload(op: string, args: any[], dbName?: string): any {
|
|
8888
|
+
const withDriver = (payload: Record<string, any>) => ({
|
|
8889
|
+
driver: 'mongodb',
|
|
8890
|
+
db: dbName,
|
|
8891
|
+
...payload,
|
|
8892
|
+
});
|
|
8893
|
+
|
|
8894
|
+
if (op === 'insertOne') {
|
|
8895
|
+
return withDriver({ doc: args[0], options: normalizeMongoDriverOptions(args[1]) });
|
|
8896
|
+
}
|
|
8897
|
+
if (op === 'insertMany') {
|
|
8898
|
+
return withDriver({ docs: args[0], options: normalizeMongoDriverOptions(args[1]) });
|
|
8899
|
+
}
|
|
8900
|
+
if (op === 'updateOne' || op === 'updateMany') {
|
|
8901
|
+
return withDriver({ filter: args[0], update: args[1], options: normalizeMongoDriverOptions(args[2]) });
|
|
8902
|
+
}
|
|
8903
|
+
if (op === 'replaceOne') {
|
|
8904
|
+
return withDriver({ filter: args[0], replacement: args[1], options: normalizeMongoDriverOptions(args[2]) });
|
|
8905
|
+
}
|
|
8906
|
+
if (op === 'deleteOne' || op === 'deleteMany') {
|
|
8907
|
+
return withDriver({ filter: args[0], options: normalizeMongoDriverOptions(args[1]) });
|
|
8908
|
+
}
|
|
8909
|
+
if (op === 'findOne' || op === 'find' || op === 'countDocuments') {
|
|
8910
|
+
return withDriver({ filter: args[0], options: normalizeMongoDriverOptions(args[1]) });
|
|
8911
|
+
}
|
|
8912
|
+
if (op === 'estimatedDocumentCount') {
|
|
8913
|
+
return withDriver({ options: normalizeMongoDriverOptions(args[0]) });
|
|
8914
|
+
}
|
|
8915
|
+
if (op === 'distinct') {
|
|
8916
|
+
return withDriver({ key: args[0], filter: args[1], options: normalizeMongoDriverOptions(args[2]) });
|
|
8917
|
+
}
|
|
8918
|
+
if (op === 'bulkWrite') {
|
|
8919
|
+
return withDriver({ ops: args[0], options: normalizeMongoDriverOptions(args[1]) });
|
|
8920
|
+
}
|
|
8921
|
+
if (op === 'findOneAndUpdate') {
|
|
8922
|
+
return withDriver({ filter: args[0], update: args[1], options: normalizeMongoDriverOptions(args[2]) });
|
|
8923
|
+
}
|
|
8924
|
+
if (op === 'findOneAndReplace') {
|
|
8925
|
+
return withDriver({ filter: args[0], replacement: args[1], options: normalizeMongoDriverOptions(args[2]) });
|
|
8926
|
+
}
|
|
8927
|
+
if (op === 'findOneAndDelete') {
|
|
8928
|
+
return withDriver({ filter: args[0], options: normalizeMongoDriverOptions(args[1]) });
|
|
8929
|
+
}
|
|
8930
|
+
if (op === 'aggregate') {
|
|
8931
|
+
return withDriver({ pipeline: args[0], options: normalizeMongoDriverOptions(args[1]) });
|
|
8932
|
+
}
|
|
8933
|
+
return withDriver({ args });
|
|
8934
|
+
}
|
|
8935
|
+
|
|
8936
|
+
function buildMongoPk(op: string, args: any[], result?: any): any {
|
|
8937
|
+
if (op === 'insertOne') return extractMongoPkFromDoc(args[0], result);
|
|
8938
|
+
if (
|
|
8939
|
+
op === 'updateOne' ||
|
|
8940
|
+
op === 'replaceOne' ||
|
|
8941
|
+
op === 'deleteOne' ||
|
|
8942
|
+
op === 'findOne' ||
|
|
8943
|
+
op === 'findOneAndUpdate' ||
|
|
8944
|
+
op === 'findOneAndDelete' ||
|
|
8945
|
+
op === 'findOneAndReplace'
|
|
8946
|
+
) {
|
|
8947
|
+
return extractMongoPkFromFilter(args[0]);
|
|
8948
|
+
}
|
|
8949
|
+
return undefined;
|
|
8950
|
+
}
|
|
8951
|
+
|
|
8952
|
+
function buildMongoAfter(op: string, args: any[], result?: any): any {
|
|
8953
|
+
if (op === 'insertOne') return args[0] ?? null;
|
|
8954
|
+
if (op === 'insertMany') return args[0] ?? null;
|
|
8955
|
+
if (op === 'findOne' || op === 'findOneAndUpdate' || op === 'findOneAndDelete' || op === 'findOneAndReplace') {
|
|
8956
|
+
return result ?? null;
|
|
8957
|
+
}
|
|
8958
|
+
if (op === 'find' || op === 'aggregate') {
|
|
8959
|
+
return Array.isArray(result) ? result : null;
|
|
8960
|
+
}
|
|
8961
|
+
return null;
|
|
8962
|
+
}
|
|
8963
|
+
|
|
8964
|
+
function findMongoCallbackIndex(args: any[]): number {
|
|
8965
|
+
for (let i = args.length - 1; i >= 0; i -= 1) {
|
|
8966
|
+
if (typeof args[i] === 'function') return i;
|
|
8967
|
+
}
|
|
8968
|
+
return -1;
|
|
8969
|
+
}
|
|
8970
|
+
|
|
8971
|
+
function patchMongoCursorInstance(cursor: any, meta: {
|
|
8972
|
+
cfg: MongoDbPatchConfig;
|
|
8973
|
+
sid: string;
|
|
8974
|
+
aid: string | null;
|
|
8975
|
+
collection: string;
|
|
8976
|
+
dbName?: string;
|
|
8977
|
+
op: string;
|
|
8978
|
+
args: any[];
|
|
8979
|
+
spanContext: SpanContext | null;
|
|
8980
|
+
}): any {
|
|
8981
|
+
if (!cursor || typeof cursor !== 'object') return cursor;
|
|
8982
|
+
if (cursor.__repro_mongodb_cursor_patched) return cursor;
|
|
8983
|
+
try {
|
|
8984
|
+
Object.defineProperty(cursor, '__repro_mongodb_cursor_patched', {
|
|
8985
|
+
value: true,
|
|
8986
|
+
configurable: true,
|
|
8987
|
+
});
|
|
8988
|
+
} catch {
|
|
8989
|
+
return cursor;
|
|
8990
|
+
}
|
|
8991
|
+
|
|
8992
|
+
for (const methodName of MONGODB_CURSOR_TERMINALS) {
|
|
8993
|
+
const original = cursor[methodName];
|
|
8994
|
+
if (typeof original !== 'function') continue;
|
|
8995
|
+
|
|
8996
|
+
cursor[methodName] = function reproPatchedMongoCursorTerminal(this: any, ...callArgs: any[]) {
|
|
8997
|
+
const t0 = Date.now();
|
|
8998
|
+
let emitted = false;
|
|
8999
|
+
let forEachDocs: any[] | null = null;
|
|
9000
|
+
const emitSuccess = (value: any) => {
|
|
9001
|
+
if (emitted) return;
|
|
9002
|
+
emitted = true;
|
|
9003
|
+
const terminalQueryArgs = [...meta.args] as any[];
|
|
9004
|
+
const queryRaw = buildMongoQueryPayload(meta.op, terminalQueryArgs, meta.dbName);
|
|
9005
|
+
queryRaw.cursorMethod = methodName;
|
|
9006
|
+
emitDbQuery(meta.cfg, meta.sid, meta.aid ?? undefined, {
|
|
9007
|
+
type: 'mongo',
|
|
9008
|
+
collection: meta.collection,
|
|
9009
|
+
op: meta.op,
|
|
9010
|
+
pk: buildMongoPk(meta.op, meta.args, value),
|
|
9011
|
+
before: null,
|
|
9012
|
+
after: buildMongoAfter(meta.op, meta.args, forEachDocs ?? value),
|
|
9013
|
+
queryRaw,
|
|
9014
|
+
resultMetaRaw: forEachDocs ?? value,
|
|
9015
|
+
durMs: Date.now() - t0,
|
|
9016
|
+
t: alignedNow(),
|
|
9017
|
+
spanContext: meta.spanContext,
|
|
9018
|
+
});
|
|
9019
|
+
};
|
|
9020
|
+
const emitFailure = (error: any) => {
|
|
9021
|
+
if (emitted) return;
|
|
9022
|
+
emitted = true;
|
|
9023
|
+
const terminalQueryArgs = [...meta.args] as any[];
|
|
9024
|
+
const queryRaw = buildMongoQueryPayload(meta.op, terminalQueryArgs, meta.dbName);
|
|
9025
|
+
queryRaw.cursorMethod = methodName;
|
|
9026
|
+
emitDbQuery(meta.cfg, meta.sid, meta.aid ?? undefined, {
|
|
9027
|
+
type: 'mongo',
|
|
9028
|
+
collection: meta.collection,
|
|
9029
|
+
op: meta.op,
|
|
9030
|
+
queryRaw,
|
|
9031
|
+
error: summarizeMongoError(error),
|
|
9032
|
+
durMs: Date.now() - t0,
|
|
9033
|
+
t: alignedNow(),
|
|
9034
|
+
spanContext: meta.spanContext,
|
|
9035
|
+
});
|
|
9036
|
+
};
|
|
9037
|
+
|
|
9038
|
+
const actualArgs = [...callArgs];
|
|
9039
|
+
if (methodName === 'forEach' && typeof actualArgs[0] === 'function') {
|
|
9040
|
+
forEachDocs = [];
|
|
9041
|
+
const originalIterator = actualArgs[0];
|
|
9042
|
+
actualArgs[0] = function reproMongoForEachIterator(this: any, doc: any, ...rest: any[]) {
|
|
9043
|
+
forEachDocs?.push(doc);
|
|
9044
|
+
return originalIterator.call(this, doc, ...rest);
|
|
9045
|
+
};
|
|
9046
|
+
}
|
|
9047
|
+
|
|
9048
|
+
try {
|
|
9049
|
+
const value = original.apply(this, actualArgs);
|
|
9050
|
+
if (value && typeof value.then === 'function') {
|
|
9051
|
+
return value.then(
|
|
9052
|
+
(resolved: any) => {
|
|
9053
|
+
emitSuccess(resolved);
|
|
9054
|
+
return resolved;
|
|
9055
|
+
},
|
|
9056
|
+
(err: any) => {
|
|
9057
|
+
emitFailure(err);
|
|
9058
|
+
throw err;
|
|
9059
|
+
},
|
|
9060
|
+
);
|
|
9061
|
+
}
|
|
9062
|
+
emitSuccess(value);
|
|
9063
|
+
return value;
|
|
9064
|
+
} catch (err) {
|
|
9065
|
+
emitFailure(err);
|
|
9066
|
+
throw err;
|
|
9067
|
+
}
|
|
9068
|
+
};
|
|
9069
|
+
}
|
|
9070
|
+
|
|
9071
|
+
return cursor;
|
|
9072
|
+
}
|
|
9073
|
+
|
|
9074
|
+
function patchMongoCollectionMethod(proto: any, op: string, cursorOp: boolean, cfg: MongoDbPatchConfig): void {
|
|
9075
|
+
if (!proto) return;
|
|
9076
|
+
const marker = `__repro_mongodb_${op}_patched`;
|
|
9077
|
+
if (proto[marker]) return;
|
|
9078
|
+
const original = proto[op];
|
|
9079
|
+
if (typeof original !== 'function') return;
|
|
9080
|
+
proto[marker] = true;
|
|
9081
|
+
|
|
9082
|
+
proto[op] = function reproPatchedMongoCollectionMethod(this: any, ...args: any[]) {
|
|
9083
|
+
const collection = resolveMongoCollectionName(this);
|
|
9084
|
+
if (isNativeMongoSuppressed(collection, op)) {
|
|
9085
|
+
return original.apply(this, args);
|
|
9086
|
+
}
|
|
9087
|
+
|
|
9088
|
+
const { sid, aid } = resolveMongoDbRuntimeContext(cfg);
|
|
9089
|
+
if (!sid) {
|
|
9090
|
+
return original.apply(this, args);
|
|
9091
|
+
}
|
|
9092
|
+
|
|
9093
|
+
const spanContext = captureSpanContextFromTracer(this);
|
|
9094
|
+
const t0 = Date.now();
|
|
9095
|
+
const dbName = resolveMongoDbName(this);
|
|
9096
|
+
const callbackIndex = cursorOp ? -1 : findMongoCallbackIndex(args);
|
|
9097
|
+
const actualArgs = callbackIndex >= 0 ? [...args] : args;
|
|
9098
|
+
let emitted = false;
|
|
9099
|
+
|
|
9100
|
+
const emitSuccess = (result: any) => {
|
|
9101
|
+
if (emitted) return;
|
|
9102
|
+
emitted = true;
|
|
9103
|
+
emitDbQuery(cfg, sid, aid ?? undefined, {
|
|
9104
|
+
type: 'mongo',
|
|
9105
|
+
collection,
|
|
9106
|
+
op,
|
|
9107
|
+
pk: buildMongoPk(op, args, result),
|
|
9108
|
+
before: null,
|
|
9109
|
+
after: buildMongoAfter(op, args, result),
|
|
9110
|
+
queryRaw: buildMongoQueryPayload(op, args, dbName),
|
|
9111
|
+
resultMetaRaw: result,
|
|
9112
|
+
durMs: Date.now() - t0,
|
|
9113
|
+
t: alignedNow(),
|
|
9114
|
+
spanContext,
|
|
9115
|
+
});
|
|
9116
|
+
};
|
|
9117
|
+
const emitFailure = (error: any) => {
|
|
9118
|
+
if (emitted) return;
|
|
9119
|
+
emitted = true;
|
|
9120
|
+
emitDbQuery(cfg, sid, aid ?? undefined, {
|
|
9121
|
+
type: 'mongo',
|
|
9122
|
+
collection,
|
|
9123
|
+
op,
|
|
9124
|
+
queryRaw: buildMongoQueryPayload(op, args, dbName),
|
|
9125
|
+
error: summarizeMongoError(error),
|
|
9126
|
+
durMs: Date.now() - t0,
|
|
9127
|
+
t: alignedNow(),
|
|
9128
|
+
spanContext,
|
|
9129
|
+
});
|
|
9130
|
+
};
|
|
9131
|
+
|
|
9132
|
+
if (callbackIndex >= 0) {
|
|
9133
|
+
const originalCallback = args[callbackIndex];
|
|
9134
|
+
actualArgs[callbackIndex] = function reproMongoCallback(this: any, err: any, result: any, ...rest: any[]) {
|
|
9135
|
+
if (err) emitFailure(err);
|
|
9136
|
+
else emitSuccess(result);
|
|
9137
|
+
return originalCallback.call(this, err, result, ...rest);
|
|
9138
|
+
};
|
|
9139
|
+
}
|
|
9140
|
+
|
|
9141
|
+
try {
|
|
9142
|
+
const result = original.apply(this, actualArgs);
|
|
9143
|
+
if (cursorOp) {
|
|
9144
|
+
return patchMongoCursorInstance(result, {
|
|
9145
|
+
cfg,
|
|
9146
|
+
sid,
|
|
9147
|
+
aid,
|
|
9148
|
+
collection,
|
|
9149
|
+
dbName,
|
|
9150
|
+
op,
|
|
9151
|
+
args,
|
|
9152
|
+
spanContext,
|
|
9153
|
+
});
|
|
9154
|
+
}
|
|
9155
|
+
if (result && typeof result.then === 'function') {
|
|
9156
|
+
return result.then(
|
|
9157
|
+
(value: any) => {
|
|
9158
|
+
emitSuccess(value);
|
|
9159
|
+
return value;
|
|
9160
|
+
},
|
|
9161
|
+
(error: any) => {
|
|
9162
|
+
emitFailure(error);
|
|
9163
|
+
throw error;
|
|
9164
|
+
},
|
|
9165
|
+
);
|
|
9166
|
+
}
|
|
9167
|
+
if (callbackIndex < 0) {
|
|
9168
|
+
emitSuccess(result);
|
|
9169
|
+
}
|
|
9170
|
+
return result;
|
|
9171
|
+
} catch (error) {
|
|
9172
|
+
emitFailure(error);
|
|
9173
|
+
throw error;
|
|
9174
|
+
}
|
|
9175
|
+
};
|
|
9176
|
+
}
|
|
9177
|
+
|
|
9178
|
+
function patchMongoCollectionPrototype(proto: any, cfg: MongoDbPatchConfig): void {
|
|
9179
|
+
if (!proto) return;
|
|
9180
|
+
for (const op of MONGODB_PROMISE_OPS) {
|
|
9181
|
+
patchMongoCollectionMethod(proto, op, false, cfg);
|
|
9182
|
+
}
|
|
9183
|
+
for (const op of MONGODB_CURSOR_OPS) {
|
|
9184
|
+
patchMongoCollectionMethod(proto, op, true, cfg);
|
|
9185
|
+
}
|
|
9186
|
+
}
|
|
9187
|
+
|
|
9188
|
+
function patchMongoDbFromModuleExports(mongoModule: any, cfg: MongoDbPatchConfig): void {
|
|
9189
|
+
if (!mongoModule) return;
|
|
9190
|
+
const constructors = new Set<any>();
|
|
9191
|
+
const addCtor = (candidate: any) => {
|
|
9192
|
+
if (typeof candidate === 'function' && candidate.prototype) {
|
|
9193
|
+
constructors.add(candidate);
|
|
9194
|
+
}
|
|
9195
|
+
};
|
|
9196
|
+
|
|
9197
|
+
addCtor(mongoModule?.Collection);
|
|
9198
|
+
addCtor(mongoModule?.default?.Collection);
|
|
9199
|
+
|
|
9200
|
+
for (const ctor of constructors) {
|
|
9201
|
+
patchMongoCollectionPrototype(ctor.prototype, cfg);
|
|
9202
|
+
}
|
|
9203
|
+
}
|
|
9204
|
+
|
|
9205
|
+
function installMongoDbRequireHook(): void {
|
|
9206
|
+
if (mongoDbRequireHookInstalled) return;
|
|
9207
|
+
mongoDbRequireHookInstalled = true;
|
|
9208
|
+
|
|
9209
|
+
try {
|
|
9210
|
+
const rim = requireOptionalHostModule('require-in-the-middle');
|
|
9211
|
+
const Hook = rim?.Hook ?? rim;
|
|
9212
|
+
if (typeof Hook !== 'function') return;
|
|
9213
|
+
|
|
9214
|
+
// eslint-disable-next-line no-new
|
|
9215
|
+
new Hook(['mongodb'], (exports: any) => {
|
|
9216
|
+
for (const cfg of mongoDbPatchConfigs) {
|
|
9217
|
+
patchMongoDbFromModuleExports(exports, cfg);
|
|
9218
|
+
}
|
|
9219
|
+
return exports;
|
|
9220
|
+
});
|
|
9221
|
+
} catch {}
|
|
9222
|
+
}
|
|
9223
|
+
|
|
9224
|
+
export function patchMongoDb(cfg: MongoDbPatchConfig): void {
|
|
9225
|
+
mongoDbPatchConfigs.push(cfg);
|
|
9226
|
+
installMongoDbRequireHook();
|
|
9227
|
+
|
|
9228
|
+
const mongoModules = new Set<any>();
|
|
9229
|
+
for (const loadedMongoModule of getLoadedModuleExportsByPackage('mongodb')) {
|
|
9230
|
+
mongoModules.add(loadedMongoModule);
|
|
9231
|
+
}
|
|
9232
|
+
if (!mongoModules.size) return;
|
|
9233
|
+
|
|
9234
|
+
for (const mongoModule of mongoModules) {
|
|
9235
|
+
patchMongoDbFromModuleExports(mongoModule, cfg);
|
|
9236
|
+
}
|
|
9237
|
+
}
|
|
9238
|
+
|
|
8591
9239
|
// ===================================================================
|
|
8592
9240
|
// Auto init helpers
|
|
8593
9241
|
// ===================================================================
|
|
@@ -9015,6 +9663,7 @@ export async function initRepro(cfg: ReproInitConfig): Promise<void> {
|
|
|
9015
9663
|
patchKafkaJs(integrationCfg);
|
|
9016
9664
|
patchAmqplib(integrationCfg);
|
|
9017
9665
|
patchRedis(integrationCfg);
|
|
9666
|
+
patchMongoDb(integrationCfg);
|
|
9018
9667
|
patchSendgridMail(integrationCfg);
|
|
9019
9668
|
patchMongooseIntegration(reproAutoMiddlewareConfig);
|
|
9020
9669
|
|
|
@@ -9066,6 +9715,8 @@ export const __reproTestHooks = {
|
|
|
9066
9715
|
patchAmqplibConnectionForTest: patchAmqplibConnection,
|
|
9067
9716
|
patchAmqplibChannelForTest: patchAmqplibChannel,
|
|
9068
9717
|
wrapAmqplibConsumeHandlerForTest: wrapAmqplibConsumeHandler,
|
|
9718
|
+
patchMongoDbModuleForTest: patchMongoDbFromModuleExports,
|
|
9719
|
+
patchMongoCollectionPrototypeForTest: patchMongoCollectionPrototype,
|
|
9069
9720
|
chunkTraceEventsForTransportForTest: chunkTraceEventsForTransport,
|
|
9070
9721
|
estimateTraceBatchSerializedBytesForTest: estimateTraceBatchSerializedBytes,
|
|
9071
9722
|
sanitizeTraceValueForPrivacyForTest: sanitizeTraceValueForPrivacy,
|