@reproapp/node-sdk 0.0.31 → 0.0.32
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 +27 -0
- package/dist/index.js +212 -156
- package/package.json +2 -2
- package/src/index.ts +194 -147
- package/test/mongodb-suppression-cleanup.test.js +72 -0
package/dist/index.d.ts
CHANGED
|
@@ -262,6 +262,31 @@ export type ReproTracingInitOptions = TracerInitOpts & {
|
|
|
262
262
|
export declare function initReproTracing(opts?: ReproTracingInitOptions): TracerApi | null;
|
|
263
263
|
/** Optional helper if users want to check it. */
|
|
264
264
|
export declare function isReproTracingEnabled(): boolean;
|
|
265
|
+
type Ctx = {
|
|
266
|
+
sid?: string;
|
|
267
|
+
aid?: string;
|
|
268
|
+
rid?: string;
|
|
269
|
+
clockSkewMs?: number;
|
|
270
|
+
excludedSpanIds?: Set<string>;
|
|
271
|
+
maskReq?: MaskRequestContext;
|
|
272
|
+
privacyTasks?: Set<Promise<void>>;
|
|
273
|
+
captureScope?: RequestCaptureScopeState;
|
|
274
|
+
nativeMongoSuppressions?: NativeMongoSuppression[];
|
|
275
|
+
};
|
|
276
|
+
type NativeMongoSuppression = {
|
|
277
|
+
collection?: string | null;
|
|
278
|
+
ops?: Set<string>;
|
|
279
|
+
startedAt: number;
|
|
280
|
+
ownerStore?: Ctx;
|
|
281
|
+
};
|
|
282
|
+
type RequestCaptureScopeState = {
|
|
283
|
+
requestRid: string;
|
|
284
|
+
transport: 'http' | 'kafka' | 'amqp' | 'background';
|
|
285
|
+
backendRequestCount: number;
|
|
286
|
+
traceBatchCount: number;
|
|
287
|
+
dbChangeCount: number;
|
|
288
|
+
emailEventCount: number;
|
|
289
|
+
};
|
|
265
290
|
declare function sanitizeTraceValueForPrivacy(value: any): any;
|
|
266
291
|
declare function sanitizeMaterializedTraceValue(value: any): any;
|
|
267
292
|
export declare function __materializePendingTraceEventsForWorker(payload: TraceMaterializationWorkerPayload): Promise<PendingTraceEventRecord[]>;
|
|
@@ -382,6 +407,8 @@ export declare const __reproTestHooks: {
|
|
|
382
407
|
}): void;
|
|
383
408
|
drainSdkBackgroundQueueForTest(): Promise<void>;
|
|
384
409
|
resetSdkBackgroundQueuesForTest(): void;
|
|
410
|
+
runWithRequestContextForTest<T>(ctx: Partial<Ctx>, fn: () => T): T;
|
|
411
|
+
getNativeMongoSuppressionCountForTest(): number;
|
|
385
412
|
getRuntimePrivacyPolicyForTest(cfg: ReproMiddlewareConfig): NormalizedRuntimePrivacyPolicy | null;
|
|
386
413
|
setRuntimePrivacyPolicyForTest(cfg: ReproMiddlewareConfig, policy: NormalizedRuntimePrivacyPolicy | null): void;
|
|
387
414
|
recordKafkaTraceEventAsyncForTest: typeof recordKafkaTraceEventAsync;
|
package/dist/index.js
CHANGED
|
@@ -835,6 +835,7 @@ function pushNativeMongoSuppression(collection, ops) {
|
|
|
835
835
|
collection: collection == null ? null : String(collection),
|
|
836
836
|
ops: normalizedOps.length ? new Set(normalizedOps) : undefined,
|
|
837
837
|
startedAt: Date.now(),
|
|
838
|
+
ownerStore: store,
|
|
838
839
|
};
|
|
839
840
|
if (!Array.isArray(store.nativeMongoSuppressions)) {
|
|
840
841
|
store.nativeMongoSuppressions = [];
|
|
@@ -845,13 +846,27 @@ function pushNativeMongoSuppression(collection, ops) {
|
|
|
845
846
|
function popNativeMongoSuppression(token) {
|
|
846
847
|
if (!token)
|
|
847
848
|
return;
|
|
848
|
-
const store = als.getStore();
|
|
849
|
+
const store = token.ownerStore ?? als.getStore();
|
|
849
850
|
const suppressions = store?.nativeMongoSuppressions;
|
|
850
|
-
if (
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
851
|
+
if (Array.isArray(suppressions) && suppressions.length > 0) {
|
|
852
|
+
const index = suppressions.indexOf(token);
|
|
853
|
+
if (index >= 0) {
|
|
854
|
+
suppressions.splice(index, 1);
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
token.ownerStore = undefined;
|
|
858
|
+
}
|
|
859
|
+
function releaseNativeMongoSuppression(target) {
|
|
860
|
+
const token = target?.__repro_native_mongo_suppression;
|
|
861
|
+
popNativeMongoSuppression(token);
|
|
862
|
+
try {
|
|
863
|
+
delete target.__repro_native_mongo_suppression;
|
|
864
|
+
}
|
|
865
|
+
catch {
|
|
866
|
+
try {
|
|
867
|
+
target.__repro_native_mongo_suppression = undefined;
|
|
868
|
+
}
|
|
869
|
+
catch { }
|
|
855
870
|
}
|
|
856
871
|
}
|
|
857
872
|
function isNativeMongoSuppressed(collection, op) {
|
|
@@ -861,9 +876,12 @@ function isNativeMongoSuppressed(collection, op) {
|
|
|
861
876
|
const normalizedCollection = collection == null ? null : String(collection);
|
|
862
877
|
const normalizedOp = normalizeNativeMongoSuppressionOp(op);
|
|
863
878
|
const now = Date.now();
|
|
864
|
-
for (
|
|
865
|
-
|
|
879
|
+
for (let i = suppressions.length - 1; i >= 0; i -= 1) {
|
|
880
|
+
const token = suppressions[i];
|
|
881
|
+
if (!token || now - token.startedAt > 60000) {
|
|
882
|
+
suppressions.splice(i, 1);
|
|
866
883
|
continue;
|
|
884
|
+
}
|
|
867
885
|
if (token.collection && normalizedCollection && token.collection !== normalizedCollection)
|
|
868
886
|
continue;
|
|
869
887
|
if (token.ops && token.ops.size > 0 && !token.ops.has(normalizedOp))
|
|
@@ -4634,40 +4652,44 @@ function reproMongoosePlugin(cfg) {
|
|
|
4634
4652
|
next();
|
|
4635
4653
|
});
|
|
4636
4654
|
schema.post('save', { document: true }, function () {
|
|
4637
|
-
|
|
4638
|
-
|
|
4639
|
-
|
|
4640
|
-
|
|
4641
|
-
|
|
4642
|
-
|
|
4643
|
-
|
|
4644
|
-
|
|
4645
|
-
|
|
4646
|
-
|
|
4647
|
-
|
|
4648
|
-
|
|
4649
|
-
|
|
4650
|
-
|
|
4651
|
-
|
|
4652
|
-
|
|
4653
|
-
|
|
4654
|
-
|
|
4655
|
-
|
|
4656
|
-
|
|
4657
|
-
|
|
4658
|
-
|
|
4659
|
-
|
|
4660
|
-
|
|
4661
|
-
|
|
4662
|
-
|
|
4663
|
-
|
|
4664
|
-
|
|
4665
|
-
|
|
4666
|
-
|
|
4667
|
-
|
|
4655
|
+
try {
|
|
4656
|
+
const { sid, aid } = getCtx();
|
|
4657
|
+
if (!sid || !aid)
|
|
4658
|
+
return;
|
|
4659
|
+
if (this.$isSubdocument)
|
|
4660
|
+
return;
|
|
4661
|
+
const meta = this.__repro_meta || {};
|
|
4662
|
+
const before = null;
|
|
4663
|
+
const after = this;
|
|
4664
|
+
const collection = meta.collection || resolveCollectionOrWarn(this, 'doc');
|
|
4665
|
+
const spanContext = meta.spanContext || captureSpanContextFromTracer(this);
|
|
4666
|
+
if (!shouldCaptureDbSpan(spanContext))
|
|
4667
|
+
return;
|
|
4668
|
+
const modifiedPaths = Array.isArray(meta.modifiedPaths) ? meta.modifiedPaths : [];
|
|
4669
|
+
const query = meta.wasNew
|
|
4670
|
+
? { op: 'insertOne', doc: after }
|
|
4671
|
+
: {
|
|
4672
|
+
filter: { _id: this._id },
|
|
4673
|
+
update: buildModifiedPathUpdate(this, modifiedPaths),
|
|
4674
|
+
options: { upsert: false },
|
|
4675
|
+
};
|
|
4676
|
+
emitDbQuery(cfg, sid, aid ?? undefined, {
|
|
4677
|
+
collection,
|
|
4678
|
+
pk: { _id: this._id },
|
|
4679
|
+
before,
|
|
4680
|
+
after,
|
|
4681
|
+
op: meta.wasNew ? 'insert' : 'update',
|
|
4682
|
+
query,
|
|
4683
|
+
t: alignTimestamp(meta.t0 ?? Date.now()),
|
|
4684
|
+
spanContext,
|
|
4685
|
+
});
|
|
4686
|
+
}
|
|
4687
|
+
finally {
|
|
4688
|
+
releaseNativeMongoSuppression(this);
|
|
4689
|
+
}
|
|
4668
4690
|
});
|
|
4669
4691
|
schema.post('save', { document: true }, function (error, _doc, next) {
|
|
4670
|
-
|
|
4692
|
+
releaseNativeMongoSuppression(this);
|
|
4671
4693
|
next(error);
|
|
4672
4694
|
});
|
|
4673
4695
|
// -------- findOneAndUpdate capture (unchanged) --------
|
|
@@ -4689,34 +4711,38 @@ function reproMongoosePlugin(cfg) {
|
|
|
4689
4711
|
next();
|
|
4690
4712
|
});
|
|
4691
4713
|
schema.post('findOneAndUpdate', function (res) {
|
|
4692
|
-
|
|
4693
|
-
|
|
4694
|
-
|
|
4695
|
-
|
|
4696
|
-
|
|
4697
|
-
|
|
4698
|
-
|
|
4699
|
-
|
|
4700
|
-
|
|
4701
|
-
|
|
4702
|
-
|
|
4703
|
-
|
|
4704
|
-
|
|
4705
|
-
|
|
4706
|
-
|
|
4707
|
-
|
|
4708
|
-
|
|
4709
|
-
|
|
4710
|
-
|
|
4711
|
-
|
|
4712
|
-
|
|
4713
|
-
|
|
4714
|
-
|
|
4715
|
-
|
|
4716
|
-
|
|
4714
|
+
try {
|
|
4715
|
+
const { sid, aid } = getCtx();
|
|
4716
|
+
if (!sid || !aid)
|
|
4717
|
+
return;
|
|
4718
|
+
const before = null;
|
|
4719
|
+
const after = res ?? null;
|
|
4720
|
+
const collection = this.__repro_collection || resolveCollectionOrWarn(this, 'query');
|
|
4721
|
+
const spanContext = this.__repro_spanContext || captureSpanContextFromTracer(this);
|
|
4722
|
+
if (!shouldCaptureDbSpan(spanContext))
|
|
4723
|
+
return;
|
|
4724
|
+
const filter = this.__repro_filter;
|
|
4725
|
+
const pk = after?._id ?? (filter && typeof filter === 'object' ? filter._id : undefined);
|
|
4726
|
+
emitDbQuery(cfg, sid, aid ?? undefined, {
|
|
4727
|
+
collection,
|
|
4728
|
+
pk: { _id: pk },
|
|
4729
|
+
before,
|
|
4730
|
+
after,
|
|
4731
|
+
op: 'update',
|
|
4732
|
+
queryRaw: {
|
|
4733
|
+
filter,
|
|
4734
|
+
update: this.__repro_update,
|
|
4735
|
+
},
|
|
4736
|
+
t: alignTimestamp(this.__repro_t0 ?? Date.now()),
|
|
4737
|
+
spanContext,
|
|
4738
|
+
});
|
|
4739
|
+
}
|
|
4740
|
+
finally {
|
|
4741
|
+
releaseNativeMongoSuppression(this);
|
|
4742
|
+
}
|
|
4717
4743
|
});
|
|
4718
4744
|
schema.post('findOneAndUpdate', function (error, _res, next) {
|
|
4719
|
-
|
|
4745
|
+
releaseNativeMongoSuppression(this);
|
|
4720
4746
|
next(error);
|
|
4721
4747
|
});
|
|
4722
4748
|
// -------- deleteOne capture (unchanged) --------
|
|
@@ -4736,29 +4762,33 @@ function reproMongoosePlugin(cfg) {
|
|
|
4736
4762
|
next();
|
|
4737
4763
|
});
|
|
4738
4764
|
schema.post('deleteOne', { document: false, query: true }, function () {
|
|
4739
|
-
|
|
4740
|
-
|
|
4741
|
-
|
|
4742
|
-
|
|
4743
|
-
|
|
4744
|
-
|
|
4745
|
-
|
|
4746
|
-
|
|
4747
|
-
|
|
4748
|
-
|
|
4749
|
-
|
|
4750
|
-
|
|
4751
|
-
|
|
4752
|
-
|
|
4753
|
-
|
|
4754
|
-
|
|
4755
|
-
|
|
4756
|
-
|
|
4757
|
-
|
|
4758
|
-
|
|
4765
|
+
try {
|
|
4766
|
+
const { sid, aid } = getCtx();
|
|
4767
|
+
if (!sid || !aid)
|
|
4768
|
+
return;
|
|
4769
|
+
const before = null;
|
|
4770
|
+
const collection = this.__repro_collection || resolveCollectionOrWarn(this, 'query');
|
|
4771
|
+
const filter = this.__repro_filter ?? undefined;
|
|
4772
|
+
const spanContext = this.__repro_spanContext || captureSpanContextFromTracer(this);
|
|
4773
|
+
if (!shouldCaptureDbSpan(spanContext))
|
|
4774
|
+
return;
|
|
4775
|
+
emitDbQuery(cfg, sid, aid ?? undefined, {
|
|
4776
|
+
collection,
|
|
4777
|
+
pk: filter && typeof filter === 'object' && '_id' in filter ? { _id: filter._id } : undefined,
|
|
4778
|
+
before,
|
|
4779
|
+
after: null,
|
|
4780
|
+
op: 'delete',
|
|
4781
|
+
queryRaw: { filter },
|
|
4782
|
+
t: alignTimestamp(this.__repro_t0 ?? Date.now()),
|
|
4783
|
+
spanContext,
|
|
4784
|
+
});
|
|
4785
|
+
}
|
|
4786
|
+
finally {
|
|
4787
|
+
releaseNativeMongoSuppression(this);
|
|
4788
|
+
}
|
|
4759
4789
|
});
|
|
4760
4790
|
schema.post('deleteOne', { document: false, query: true }, function (error, _res, next) {
|
|
4761
|
-
|
|
4791
|
+
releaseNativeMongoSuppression(this);
|
|
4762
4792
|
next(error);
|
|
4763
4793
|
});
|
|
4764
4794
|
// -------- NON-intrusive generic query telemetry via schema hooks -------
|
|
@@ -4814,29 +4844,33 @@ function reproMongoosePlugin(cfg) {
|
|
|
4814
4844
|
next();
|
|
4815
4845
|
});
|
|
4816
4846
|
schema.post(op, function (res) {
|
|
4817
|
-
|
|
4818
|
-
|
|
4819
|
-
|
|
4820
|
-
|
|
4821
|
-
|
|
4822
|
-
|
|
4823
|
-
|
|
4824
|
-
|
|
4825
|
-
|
|
4826
|
-
|
|
4827
|
-
|
|
4828
|
-
|
|
4829
|
-
|
|
4830
|
-
|
|
4831
|
-
|
|
4832
|
-
|
|
4833
|
-
|
|
4834
|
-
|
|
4835
|
-
|
|
4836
|
-
|
|
4847
|
+
try {
|
|
4848
|
+
const { sid, aid } = getCtx();
|
|
4849
|
+
if (!sid)
|
|
4850
|
+
return;
|
|
4851
|
+
const meta = this.__repro_qmeta || { t0: Date.now(), collection: 'unknown', op };
|
|
4852
|
+
const spanContext = meta.spanContext || captureSpanContextFromTracer(this);
|
|
4853
|
+
emitDbQuery(cfg, sid, aid, {
|
|
4854
|
+
collection: meta.collection,
|
|
4855
|
+
op,
|
|
4856
|
+
queryRaw: {
|
|
4857
|
+
filter: meta.rawFilter,
|
|
4858
|
+
update: meta.rawUpdate,
|
|
4859
|
+
projection: meta.rawProjection,
|
|
4860
|
+
options: meta.rawOptions,
|
|
4861
|
+
},
|
|
4862
|
+
resultMetaRaw: res,
|
|
4863
|
+
durMs: Date.now() - meta.t0,
|
|
4864
|
+
t: alignedNow(),
|
|
4865
|
+
spanContext,
|
|
4866
|
+
});
|
|
4867
|
+
}
|
|
4868
|
+
finally {
|
|
4869
|
+
releaseNativeMongoSuppression(this);
|
|
4870
|
+
}
|
|
4837
4871
|
});
|
|
4838
4872
|
schema.post(op, function (error, _res, next) {
|
|
4839
|
-
|
|
4873
|
+
releaseNativeMongoSuppression(this);
|
|
4840
4874
|
next(error);
|
|
4841
4875
|
});
|
|
4842
4876
|
}
|
|
@@ -4865,24 +4899,28 @@ function reproMongoosePlugin(cfg) {
|
|
|
4865
4899
|
next();
|
|
4866
4900
|
});
|
|
4867
4901
|
schema.post('insertMany', { document: false, query: false }, function (docs) {
|
|
4868
|
-
|
|
4869
|
-
|
|
4870
|
-
|
|
4871
|
-
|
|
4872
|
-
|
|
4873
|
-
|
|
4874
|
-
|
|
4875
|
-
|
|
4876
|
-
|
|
4877
|
-
|
|
4878
|
-
|
|
4879
|
-
|
|
4880
|
-
|
|
4881
|
-
|
|
4882
|
-
|
|
4902
|
+
try {
|
|
4903
|
+
const { sid, aid } = getCtx();
|
|
4904
|
+
if (!sid)
|
|
4905
|
+
return;
|
|
4906
|
+
const meta = this.__repro_insert_meta || { t0: Date.now(), collection: 'unknown' };
|
|
4907
|
+
const spanContext = meta.spanContext || captureSpanContextFromTracer(this);
|
|
4908
|
+
emitDbQuery(cfg, sid, aid ?? undefined, {
|
|
4909
|
+
collection: meta.collection,
|
|
4910
|
+
op: 'insertMany',
|
|
4911
|
+
queryRaw: { docs: meta.rawDocs ?? undefined },
|
|
4912
|
+
resultMetaRaw: docs,
|
|
4913
|
+
durMs: Date.now() - meta.t0,
|
|
4914
|
+
t: alignedNow(),
|
|
4915
|
+
spanContext,
|
|
4916
|
+
});
|
|
4917
|
+
}
|
|
4918
|
+
finally {
|
|
4919
|
+
releaseNativeMongoSuppression(this);
|
|
4920
|
+
}
|
|
4883
4921
|
});
|
|
4884
4922
|
schema.post('insertMany', { document: false, query: false }, function (error, _res, next) {
|
|
4885
|
-
|
|
4923
|
+
releaseNativeMongoSuppression(this);
|
|
4886
4924
|
next(error);
|
|
4887
4925
|
});
|
|
4888
4926
|
schema.pre('bulkWrite', { document: false, query: false }, function (next, ops) {
|
|
@@ -4907,24 +4945,28 @@ function reproMongoosePlugin(cfg) {
|
|
|
4907
4945
|
next();
|
|
4908
4946
|
});
|
|
4909
4947
|
schema.post('bulkWrite', { document: false, query: false }, function (res) {
|
|
4910
|
-
|
|
4911
|
-
|
|
4912
|
-
|
|
4913
|
-
|
|
4914
|
-
|
|
4915
|
-
|
|
4916
|
-
|
|
4917
|
-
|
|
4918
|
-
|
|
4919
|
-
|
|
4920
|
-
|
|
4921
|
-
|
|
4922
|
-
|
|
4923
|
-
|
|
4924
|
-
|
|
4948
|
+
try {
|
|
4949
|
+
const { sid, aid } = getCtx();
|
|
4950
|
+
if (!sid)
|
|
4951
|
+
return;
|
|
4952
|
+
const meta = this.__repro_bulk_meta || { t0: Date.now(), collection: 'unknown' };
|
|
4953
|
+
const spanContext = meta.spanContext || captureSpanContextFromTracer(this);
|
|
4954
|
+
emitDbQuery(cfg, sid, aid, {
|
|
4955
|
+
collection: meta.collection,
|
|
4956
|
+
op: 'bulkWrite',
|
|
4957
|
+
queryRaw: { ops: meta.rawOps ?? undefined },
|
|
4958
|
+
resultMetaRaw: res,
|
|
4959
|
+
durMs: Date.now() - meta.t0,
|
|
4960
|
+
t: alignedNow(),
|
|
4961
|
+
spanContext,
|
|
4962
|
+
});
|
|
4963
|
+
}
|
|
4964
|
+
finally {
|
|
4965
|
+
releaseNativeMongoSuppression(this);
|
|
4966
|
+
}
|
|
4925
4967
|
});
|
|
4926
4968
|
schema.post('bulkWrite', { document: false, query: false }, function (error, _res, next) {
|
|
4927
|
-
|
|
4969
|
+
releaseNativeMongoSuppression(this);
|
|
4928
4970
|
next(error);
|
|
4929
4971
|
});
|
|
4930
4972
|
// Aggregate middleware (non-intrusive)
|
|
@@ -4954,24 +4996,28 @@ function reproMongoosePlugin(cfg) {
|
|
|
4954
4996
|
next();
|
|
4955
4997
|
});
|
|
4956
4998
|
schema.post('aggregate', function (res) {
|
|
4957
|
-
|
|
4958
|
-
|
|
4959
|
-
|
|
4960
|
-
|
|
4961
|
-
|
|
4962
|
-
|
|
4963
|
-
|
|
4964
|
-
|
|
4965
|
-
|
|
4966
|
-
|
|
4967
|
-
|
|
4968
|
-
|
|
4969
|
-
|
|
4970
|
-
|
|
4971
|
-
|
|
4999
|
+
try {
|
|
5000
|
+
const { sid, aid } = getCtx();
|
|
5001
|
+
if (!sid)
|
|
5002
|
+
return;
|
|
5003
|
+
const meta = this.__repro_aggmeta || { t0: Date.now(), collection: 'unknown' };
|
|
5004
|
+
const spanContext = meta.spanContext || captureSpanContextFromTracer(this);
|
|
5005
|
+
emitDbQuery(cfg, sid, aid, {
|
|
5006
|
+
collection: meta.collection,
|
|
5007
|
+
op: 'aggregate',
|
|
5008
|
+
queryRaw: { pipeline: meta.rawPipeline },
|
|
5009
|
+
resultMetaRaw: res,
|
|
5010
|
+
durMs: Date.now() - meta.t0,
|
|
5011
|
+
t: alignedNow(),
|
|
5012
|
+
spanContext,
|
|
5013
|
+
});
|
|
5014
|
+
}
|
|
5015
|
+
finally {
|
|
5016
|
+
releaseNativeMongoSuppression(this);
|
|
5017
|
+
}
|
|
4972
5018
|
});
|
|
4973
5019
|
schema.post('aggregate', function (error, _res, next) {
|
|
4974
|
-
|
|
5020
|
+
releaseNativeMongoSuppression(this);
|
|
4975
5021
|
next(error);
|
|
4976
5022
|
});
|
|
4977
5023
|
};
|
|
@@ -8721,6 +8767,16 @@ exports.__reproTestHooks = {
|
|
|
8721
8767
|
lastClientActivityAt = 0;
|
|
8722
8768
|
sdkBackgroundQuietUntil = 0;
|
|
8723
8769
|
},
|
|
8770
|
+
runWithRequestContextForTest(ctx, fn) {
|
|
8771
|
+
return als.run({
|
|
8772
|
+
...ctx,
|
|
8773
|
+
excludedSpanIds: ctx.excludedSpanIds ?? new Set(),
|
|
8774
|
+
}, fn);
|
|
8775
|
+
},
|
|
8776
|
+
getNativeMongoSuppressionCountForTest() {
|
|
8777
|
+
const suppressions = getCtx().nativeMongoSuppressions;
|
|
8778
|
+
return Array.isArray(suppressions) ? suppressions.length : 0;
|
|
8779
|
+
},
|
|
8724
8780
|
getRuntimePrivacyPolicyForTest(cfg) {
|
|
8725
8781
|
return getRuntimePrivacyState(cfg).policy;
|
|
8726
8782
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reproapp/node-sdk",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.32",
|
|
4
4
|
"description": "Repro Nest SDK",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"build": "tsc -p tsconfig.json",
|
|
13
13
|
"dev": "tsc -p tsconfig.json --watch --preserveWatchOutput",
|
|
14
14
|
"prepublishOnly": "npm run build",
|
|
15
|
-
"test": "npm run build && node test/unawaited.test.js && node test/integration-unawaited.js && node test/request-flush-timing.test.js && node test/request-capture-background.test.js && node test/init-auto-http-server.test.js && node test/client-performance-regression.test.js && node test/request-manifest-priority.test.js && node test/runtime-no-double-invoke.test.js && node test/express-trace-http-args.test.js && node test/trace-batch-size.test.js && node test/sdk-background-priority.test.js && node test/ingest-queue-retention.test.js && node test/ingest-high-priority-retention.test.js && node test/ingest-critical-retention.test.js && node test/ingest-critical-retry-retention.test.js && node test/ingest-timeout.test.js && node -r ./tracer/register test/promise-map.test.js && node test/disable-subtree.test.js && node test/circular-capture.test.js && node test/wrap-plugin-arrow-args.test.js && node test/wrap-plugin-super-call.test.js && node test/function-arg-identity.test.js && node test/privacy-runtime-policy.test.js && node test/runtime-privacy-materialization.test.js && node test/kafka-runtime-privacy-policy.test.js && node test/amqplib-integration.test.js && node test/mongodb-integration.test.js && node test/mongodb-esm-import-hook.test.js",
|
|
15
|
+
"test": "npm run build && node test/unawaited.test.js && node test/integration-unawaited.js && node test/request-flush-timing.test.js && node test/request-capture-background.test.js && node test/init-auto-http-server.test.js && node test/client-performance-regression.test.js && node test/request-manifest-priority.test.js && node test/runtime-no-double-invoke.test.js && node test/express-trace-http-args.test.js && node test/trace-batch-size.test.js && node test/sdk-background-priority.test.js && node test/ingest-queue-retention.test.js && node test/ingest-high-priority-retention.test.js && node test/ingest-critical-retention.test.js && node test/ingest-critical-retry-retention.test.js && node test/ingest-timeout.test.js && node -r ./tracer/register test/promise-map.test.js && node test/disable-subtree.test.js && node test/circular-capture.test.js && node test/wrap-plugin-arrow-args.test.js && node test/wrap-plugin-super-call.test.js && node test/function-arg-identity.test.js && node test/privacy-runtime-policy.test.js && node test/runtime-privacy-materialization.test.js && node test/kafka-runtime-privacy-policy.test.js && node test/amqplib-integration.test.js && node test/mongodb-integration.test.js && node test/mongodb-esm-import-hook.test.js && node test/mongodb-suppression-cleanup.test.js",
|
|
16
16
|
"test:containers": "npm run build && node test/runtime-no-double-invoke.testcontainers.test.js && node test/wrap-plugin-super-call.testcontainers.test.js && node test/function-arg-identity.testcontainers.test.js"
|
|
17
17
|
},
|
|
18
18
|
"peerDependencies": {
|
package/src/index.ts
CHANGED
|
@@ -1163,6 +1163,7 @@ type NativeMongoSuppression = {
|
|
|
1163
1163
|
collection?: string | null;
|
|
1164
1164
|
ops?: Set<string>;
|
|
1165
1165
|
startedAt: number;
|
|
1166
|
+
ownerStore?: Ctx;
|
|
1166
1167
|
};
|
|
1167
1168
|
|
|
1168
1169
|
type RequestCaptureScopeState = {
|
|
@@ -1236,6 +1237,7 @@ function pushNativeMongoSuppression(collection: any, ops?: string[] | readonly s
|
|
|
1236
1237
|
collection: collection == null ? null : String(collection),
|
|
1237
1238
|
ops: normalizedOps.length ? new Set(normalizedOps) : undefined,
|
|
1238
1239
|
startedAt: Date.now(),
|
|
1240
|
+
ownerStore: store,
|
|
1239
1241
|
};
|
|
1240
1242
|
if (!Array.isArray(store.nativeMongoSuppressions)) {
|
|
1241
1243
|
store.nativeMongoSuppressions = [];
|
|
@@ -1246,12 +1248,22 @@ function pushNativeMongoSuppression(collection: any, ops?: string[] | readonly s
|
|
|
1246
1248
|
|
|
1247
1249
|
function popNativeMongoSuppression(token: NativeMongoSuppression | null | undefined): void {
|
|
1248
1250
|
if (!token) return;
|
|
1249
|
-
const store = als.getStore();
|
|
1251
|
+
const store = token.ownerStore ?? als.getStore();
|
|
1250
1252
|
const suppressions = store?.nativeMongoSuppressions;
|
|
1251
|
-
if (
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1253
|
+
if (Array.isArray(suppressions) && suppressions.length > 0) {
|
|
1254
|
+
const index = suppressions.indexOf(token);
|
|
1255
|
+
if (index >= 0) {
|
|
1256
|
+
suppressions.splice(index, 1);
|
|
1257
|
+
}
|
|
1258
|
+
}
|
|
1259
|
+
token.ownerStore = undefined;
|
|
1260
|
+
}
|
|
1261
|
+
|
|
1262
|
+
function releaseNativeMongoSuppression(target: any): void {
|
|
1263
|
+
const token = target?.__repro_native_mongo_suppression;
|
|
1264
|
+
popNativeMongoSuppression(token);
|
|
1265
|
+
try { delete target.__repro_native_mongo_suppression; } catch {
|
|
1266
|
+
try { target.__repro_native_mongo_suppression = undefined; } catch {}
|
|
1255
1267
|
}
|
|
1256
1268
|
}
|
|
1257
1269
|
|
|
@@ -1261,8 +1273,12 @@ function isNativeMongoSuppressed(collection: any, op: string): boolean {
|
|
|
1261
1273
|
const normalizedCollection = collection == null ? null : String(collection);
|
|
1262
1274
|
const normalizedOp = normalizeNativeMongoSuppressionOp(op);
|
|
1263
1275
|
const now = Date.now();
|
|
1264
|
-
for (
|
|
1265
|
-
|
|
1276
|
+
for (let i = suppressions.length - 1; i >= 0; i -= 1) {
|
|
1277
|
+
const token = suppressions[i];
|
|
1278
|
+
if (!token || now - token.startedAt > 60000) {
|
|
1279
|
+
suppressions.splice(i, 1);
|
|
1280
|
+
continue;
|
|
1281
|
+
}
|
|
1266
1282
|
if (token.collection && normalizedCollection && token.collection !== normalizedCollection) continue;
|
|
1267
1283
|
if (token.ops && token.ops.size > 0 && !token.ops.has(normalizedOp)) continue;
|
|
1268
1284
|
return true;
|
|
@@ -5572,41 +5588,44 @@ export function reproMongoosePlugin(cfg: ReproMiddlewareConfig) {
|
|
|
5572
5588
|
});
|
|
5573
5589
|
|
|
5574
5590
|
schema.post('save', { document: true }, function () {
|
|
5575
|
-
|
|
5576
|
-
|
|
5577
|
-
|
|
5578
|
-
|
|
5579
|
-
const meta = (this as any).__repro_meta || {};
|
|
5580
|
-
const before = null;
|
|
5581
|
-
const after = this;
|
|
5582
|
-
const collection = meta.collection || resolveCollectionOrWarn(this, 'doc');
|
|
5583
|
-
const spanContext = meta.spanContext || captureSpanContextFromTracer(this);
|
|
5584
|
-
if (!shouldCaptureDbSpan(spanContext)) return;
|
|
5585
|
-
const modifiedPaths = Array.isArray(meta.modifiedPaths) ? meta.modifiedPaths : [];
|
|
5586
|
-
|
|
5587
|
-
const query = meta.wasNew
|
|
5588
|
-
? { op: 'insertOne', doc: after }
|
|
5589
|
-
: {
|
|
5590
|
-
filter: { _id: this._id },
|
|
5591
|
-
update: buildModifiedPathUpdate(this, modifiedPaths),
|
|
5592
|
-
options: { upsert: false },
|
|
5593
|
-
};
|
|
5591
|
+
try {
|
|
5592
|
+
const { sid, aid } = getCtx();
|
|
5593
|
+
if (!sid || !aid) return;
|
|
5594
|
+
if ((this as any).$isSubdocument) return;
|
|
5594
5595
|
|
|
5595
|
-
|
|
5596
|
-
|
|
5597
|
-
|
|
5598
|
-
|
|
5599
|
-
|
|
5600
|
-
|
|
5601
|
-
|
|
5602
|
-
|
|
5603
|
-
|
|
5604
|
-
|
|
5605
|
-
|
|
5596
|
+
const meta = (this as any).__repro_meta || {};
|
|
5597
|
+
const before = null;
|
|
5598
|
+
const after = this;
|
|
5599
|
+
const collection = meta.collection || resolveCollectionOrWarn(this, 'doc');
|
|
5600
|
+
const spanContext = meta.spanContext || captureSpanContextFromTracer(this);
|
|
5601
|
+
if (!shouldCaptureDbSpan(spanContext)) return;
|
|
5602
|
+
const modifiedPaths = Array.isArray(meta.modifiedPaths) ? meta.modifiedPaths : [];
|
|
5603
|
+
|
|
5604
|
+
const query = meta.wasNew
|
|
5605
|
+
? { op: 'insertOne', doc: after }
|
|
5606
|
+
: {
|
|
5607
|
+
filter: { _id: this._id },
|
|
5608
|
+
update: buildModifiedPathUpdate(this, modifiedPaths),
|
|
5609
|
+
options: { upsert: false },
|
|
5610
|
+
};
|
|
5611
|
+
|
|
5612
|
+
emitDbQuery(cfg, sid, aid ?? undefined, {
|
|
5613
|
+
collection,
|
|
5614
|
+
pk: { _id: (this as any)._id },
|
|
5615
|
+
before,
|
|
5616
|
+
after,
|
|
5617
|
+
op: meta.wasNew ? 'insert' : 'update',
|
|
5618
|
+
query,
|
|
5619
|
+
t: alignTimestamp(meta.t0 ?? Date.now()),
|
|
5620
|
+
spanContext,
|
|
5621
|
+
});
|
|
5622
|
+
} finally {
|
|
5623
|
+
releaseNativeMongoSuppression(this);
|
|
5624
|
+
}
|
|
5606
5625
|
});
|
|
5607
5626
|
|
|
5608
5627
|
schema.post('save', { document: true }, function (error: any, _doc: any, next: Function) {
|
|
5609
|
-
|
|
5628
|
+
releaseNativeMongoSuppression(this);
|
|
5610
5629
|
next(error);
|
|
5611
5630
|
});
|
|
5612
5631
|
|
|
@@ -5631,35 +5650,38 @@ export function reproMongoosePlugin(cfg: ReproMiddlewareConfig) {
|
|
|
5631
5650
|
});
|
|
5632
5651
|
|
|
5633
5652
|
schema.post<Query<any, any>>('findOneAndUpdate', function (res: any) {
|
|
5634
|
-
|
|
5635
|
-
|
|
5653
|
+
try {
|
|
5654
|
+
const { sid, aid } = getCtx();
|
|
5655
|
+
if (!sid || !aid) return;
|
|
5636
5656
|
|
|
5637
|
-
|
|
5638
|
-
|
|
5639
|
-
|
|
5640
|
-
|
|
5641
|
-
|
|
5642
|
-
|
|
5643
|
-
|
|
5657
|
+
const before = null;
|
|
5658
|
+
const after = res ?? null;
|
|
5659
|
+
const collection = (this as any).__repro_collection || resolveCollectionOrWarn(this, 'query');
|
|
5660
|
+
const spanContext = (this as any).__repro_spanContext || captureSpanContextFromTracer(this);
|
|
5661
|
+
if (!shouldCaptureDbSpan(spanContext)) return;
|
|
5662
|
+
const filter = (this as any).__repro_filter;
|
|
5663
|
+
const pk = after?._id ?? (filter && typeof filter === 'object' ? (filter as any)._id : undefined);
|
|
5644
5664
|
|
|
5645
|
-
|
|
5646
|
-
|
|
5647
|
-
|
|
5648
|
-
|
|
5649
|
-
|
|
5650
|
-
|
|
5651
|
-
|
|
5652
|
-
|
|
5653
|
-
|
|
5654
|
-
|
|
5655
|
-
|
|
5656
|
-
|
|
5657
|
-
|
|
5658
|
-
|
|
5665
|
+
emitDbQuery(cfg, sid, aid ?? undefined, {
|
|
5666
|
+
collection,
|
|
5667
|
+
pk: { _id: pk },
|
|
5668
|
+
before,
|
|
5669
|
+
after,
|
|
5670
|
+
op: 'update',
|
|
5671
|
+
queryRaw: {
|
|
5672
|
+
filter,
|
|
5673
|
+
update: (this as any).__repro_update,
|
|
5674
|
+
},
|
|
5675
|
+
t: alignTimestamp((this as any).__repro_t0 ?? Date.now()),
|
|
5676
|
+
spanContext,
|
|
5677
|
+
});
|
|
5678
|
+
} finally {
|
|
5679
|
+
releaseNativeMongoSuppression(this);
|
|
5680
|
+
}
|
|
5659
5681
|
});
|
|
5660
5682
|
|
|
5661
5683
|
schema.post<Query<any, any>>('findOneAndUpdate', function (this: any, error: any, _res: any, next: Function) {
|
|
5662
|
-
|
|
5684
|
+
releaseNativeMongoSuppression(this);
|
|
5663
5685
|
next(error);
|
|
5664
5686
|
} as any);
|
|
5665
5687
|
|
|
@@ -5681,27 +5703,30 @@ export function reproMongoosePlugin(cfg: ReproMiddlewareConfig) {
|
|
|
5681
5703
|
});
|
|
5682
5704
|
|
|
5683
5705
|
schema.post<Query<any, any>>('deleteOne', { document: false, query: true }, function () {
|
|
5684
|
-
|
|
5685
|
-
|
|
5686
|
-
|
|
5687
|
-
|
|
5688
|
-
|
|
5689
|
-
|
|
5690
|
-
|
|
5691
|
-
|
|
5692
|
-
|
|
5693
|
-
|
|
5694
|
-
|
|
5695
|
-
|
|
5696
|
-
|
|
5697
|
-
|
|
5698
|
-
|
|
5699
|
-
|
|
5700
|
-
|
|
5706
|
+
try {
|
|
5707
|
+
const { sid, aid } = getCtx(); if (!sid || !aid) return;
|
|
5708
|
+
const before = null;
|
|
5709
|
+
const collection = (this as any).__repro_collection || resolveCollectionOrWarn(this, 'query');
|
|
5710
|
+
const filter = (this as any).__repro_filter ?? undefined;
|
|
5711
|
+
const spanContext = (this as any).__repro_spanContext || captureSpanContextFromTracer(this);
|
|
5712
|
+
if (!shouldCaptureDbSpan(spanContext)) return;
|
|
5713
|
+
emitDbQuery(cfg, sid, aid ?? undefined, {
|
|
5714
|
+
collection,
|
|
5715
|
+
pk: filter && typeof filter === 'object' && '_id' in filter ? { _id: (filter as any)._id } : undefined,
|
|
5716
|
+
before,
|
|
5717
|
+
after: null,
|
|
5718
|
+
op: 'delete',
|
|
5719
|
+
queryRaw: { filter },
|
|
5720
|
+
t: alignTimestamp((this as any).__repro_t0 ?? Date.now()),
|
|
5721
|
+
spanContext,
|
|
5722
|
+
});
|
|
5723
|
+
} finally {
|
|
5724
|
+
releaseNativeMongoSuppression(this);
|
|
5725
|
+
}
|
|
5701
5726
|
});
|
|
5702
5727
|
|
|
5703
5728
|
schema.post<Query<any, any>>('deleteOne', { document: false, query: true }, function (this: any, error: any, _res: any, next: Function) {
|
|
5704
|
-
|
|
5729
|
+
releaseNativeMongoSuppression(this);
|
|
5705
5730
|
next(error);
|
|
5706
5731
|
} as any);
|
|
5707
5732
|
|
|
@@ -5766,31 +5791,34 @@ export function reproMongoosePlugin(cfg: ReproMiddlewareConfig) {
|
|
|
5766
5791
|
});
|
|
5767
5792
|
|
|
5768
5793
|
schema.post(op as any, function (this: any, res: any) {
|
|
5769
|
-
|
|
5770
|
-
|
|
5794
|
+
try {
|
|
5795
|
+
const { sid, aid } = getCtx();
|
|
5796
|
+
if (!sid) return;
|
|
5771
5797
|
|
|
5772
|
-
|
|
5773
|
-
|
|
5798
|
+
const meta = (this as any).__repro_qmeta || { t0: Date.now(), collection: 'unknown', op };
|
|
5799
|
+
const spanContext = meta.spanContext || captureSpanContextFromTracer(this);
|
|
5774
5800
|
|
|
5775
|
-
|
|
5776
|
-
|
|
5777
|
-
|
|
5778
|
-
|
|
5779
|
-
|
|
5780
|
-
|
|
5781
|
-
|
|
5782
|
-
|
|
5783
|
-
|
|
5784
|
-
|
|
5785
|
-
|
|
5786
|
-
|
|
5787
|
-
|
|
5788
|
-
|
|
5789
|
-
|
|
5801
|
+
emitDbQuery(cfg, sid, aid, {
|
|
5802
|
+
collection: meta.collection,
|
|
5803
|
+
op,
|
|
5804
|
+
queryRaw: {
|
|
5805
|
+
filter: meta.rawFilter,
|
|
5806
|
+
update: meta.rawUpdate,
|
|
5807
|
+
projection: meta.rawProjection,
|
|
5808
|
+
options: meta.rawOptions,
|
|
5809
|
+
},
|
|
5810
|
+
resultMetaRaw: res,
|
|
5811
|
+
durMs: Date.now() - meta.t0,
|
|
5812
|
+
t: alignedNow(),
|
|
5813
|
+
spanContext,
|
|
5814
|
+
});
|
|
5815
|
+
} finally {
|
|
5816
|
+
releaseNativeMongoSuppression(this);
|
|
5817
|
+
}
|
|
5790
5818
|
});
|
|
5791
5819
|
|
|
5792
5820
|
schema.post(op as any, function (this: any, error: any, _res: any, next: Function) {
|
|
5793
|
-
|
|
5821
|
+
releaseNativeMongoSuppression(this);
|
|
5794
5822
|
next(error);
|
|
5795
5823
|
} as any);
|
|
5796
5824
|
}
|
|
@@ -5824,25 +5852,28 @@ export function reproMongoosePlugin(cfg: ReproMiddlewareConfig) {
|
|
|
5824
5852
|
} as any);
|
|
5825
5853
|
|
|
5826
5854
|
schema.post<any>('insertMany' as any, { document: false, query: false } as any, function (this: any, docs: any[]) {
|
|
5827
|
-
|
|
5828
|
-
|
|
5829
|
-
|
|
5830
|
-
|
|
5831
|
-
|
|
5832
|
-
|
|
5833
|
-
|
|
5834
|
-
|
|
5835
|
-
|
|
5836
|
-
|
|
5837
|
-
|
|
5838
|
-
|
|
5839
|
-
|
|
5840
|
-
|
|
5841
|
-
|
|
5855
|
+
try {
|
|
5856
|
+
const { sid, aid } = getCtx();
|
|
5857
|
+
if (!sid) return;
|
|
5858
|
+
const meta = (this as any).__repro_insert_meta || { t0: Date.now(), collection: 'unknown' };
|
|
5859
|
+
const spanContext = meta.spanContext || captureSpanContextFromTracer(this);
|
|
5860
|
+
|
|
5861
|
+
emitDbQuery(cfg, sid, aid ?? undefined, {
|
|
5862
|
+
collection: meta.collection,
|
|
5863
|
+
op: 'insertMany',
|
|
5864
|
+
queryRaw: { docs: meta.rawDocs ?? undefined },
|
|
5865
|
+
resultMetaRaw: docs,
|
|
5866
|
+
durMs: Date.now() - meta.t0,
|
|
5867
|
+
t: alignedNow(),
|
|
5868
|
+
spanContext,
|
|
5869
|
+
});
|
|
5870
|
+
} finally {
|
|
5871
|
+
releaseNativeMongoSuppression(this);
|
|
5872
|
+
}
|
|
5842
5873
|
} as any);
|
|
5843
5874
|
|
|
5844
5875
|
schema.post<any>('insertMany' as any, { document: false, query: false } as any, function (this: any, error: any, _res: any, next: Function) {
|
|
5845
|
-
|
|
5876
|
+
releaseNativeMongoSuppression(this);
|
|
5846
5877
|
next(error);
|
|
5847
5878
|
} as any);
|
|
5848
5879
|
|
|
@@ -5871,25 +5902,28 @@ export function reproMongoosePlugin(cfg: ReproMiddlewareConfig) {
|
|
|
5871
5902
|
} as any);
|
|
5872
5903
|
|
|
5873
5904
|
schema.post<any>('bulkWrite' as any, { document: false, query: false } as any, function (this: any, res: any) {
|
|
5874
|
-
|
|
5875
|
-
|
|
5876
|
-
|
|
5877
|
-
|
|
5878
|
-
|
|
5879
|
-
|
|
5880
|
-
|
|
5881
|
-
|
|
5882
|
-
|
|
5883
|
-
|
|
5884
|
-
|
|
5885
|
-
|
|
5886
|
-
|
|
5887
|
-
|
|
5888
|
-
|
|
5905
|
+
try {
|
|
5906
|
+
const { sid, aid } = getCtx();
|
|
5907
|
+
if (!sid) return;
|
|
5908
|
+
const meta = (this as any).__repro_bulk_meta || { t0: Date.now(), collection: 'unknown' };
|
|
5909
|
+
const spanContext = meta.spanContext || captureSpanContextFromTracer(this);
|
|
5910
|
+
|
|
5911
|
+
emitDbQuery(cfg, sid, aid, {
|
|
5912
|
+
collection: meta.collection,
|
|
5913
|
+
op: 'bulkWrite',
|
|
5914
|
+
queryRaw: { ops: meta.rawOps ?? undefined },
|
|
5915
|
+
resultMetaRaw: res,
|
|
5916
|
+
durMs: Date.now() - meta.t0,
|
|
5917
|
+
t: alignedNow(),
|
|
5918
|
+
spanContext,
|
|
5919
|
+
});
|
|
5920
|
+
} finally {
|
|
5921
|
+
releaseNativeMongoSuppression(this);
|
|
5922
|
+
}
|
|
5889
5923
|
} as any);
|
|
5890
5924
|
|
|
5891
5925
|
schema.post<any>('bulkWrite' as any, { document: false, query: false } as any, function (this: any, error: any, _res: any, next: Function) {
|
|
5892
|
-
|
|
5926
|
+
releaseNativeMongoSuppression(this);
|
|
5893
5927
|
next(error);
|
|
5894
5928
|
} as any);
|
|
5895
5929
|
|
|
@@ -5924,26 +5958,29 @@ export function reproMongoosePlugin(cfg: ReproMiddlewareConfig) {
|
|
|
5924
5958
|
});
|
|
5925
5959
|
|
|
5926
5960
|
schema.post('aggregate', function (this: any, res: any[]) {
|
|
5927
|
-
|
|
5928
|
-
|
|
5961
|
+
try {
|
|
5962
|
+
const { sid, aid } = getCtx();
|
|
5963
|
+
if (!sid) return;
|
|
5929
5964
|
|
|
5930
|
-
|
|
5931
|
-
|
|
5965
|
+
const meta = (this as any).__repro_aggmeta || { t0: Date.now(), collection: 'unknown' };
|
|
5966
|
+
const spanContext = meta.spanContext || captureSpanContextFromTracer(this);
|
|
5932
5967
|
|
|
5933
|
-
|
|
5934
|
-
|
|
5935
|
-
|
|
5936
|
-
|
|
5937
|
-
|
|
5938
|
-
|
|
5939
|
-
|
|
5940
|
-
|
|
5941
|
-
|
|
5942
|
-
|
|
5968
|
+
emitDbQuery(cfg, sid, aid, {
|
|
5969
|
+
collection: meta.collection,
|
|
5970
|
+
op: 'aggregate',
|
|
5971
|
+
queryRaw: { pipeline: meta.rawPipeline },
|
|
5972
|
+
resultMetaRaw: res,
|
|
5973
|
+
durMs: Date.now() - meta.t0,
|
|
5974
|
+
t: alignedNow(),
|
|
5975
|
+
spanContext,
|
|
5976
|
+
});
|
|
5977
|
+
} finally {
|
|
5978
|
+
releaseNativeMongoSuppression(this);
|
|
5979
|
+
}
|
|
5943
5980
|
});
|
|
5944
5981
|
|
|
5945
5982
|
schema.post('aggregate', function (this: any, error: any, _res: any, next: Function) {
|
|
5946
|
-
|
|
5983
|
+
releaseNativeMongoSuppression(this);
|
|
5947
5984
|
next(error);
|
|
5948
5985
|
} as any);
|
|
5949
5986
|
};
|
|
@@ -9966,6 +10003,16 @@ export const __reproTestHooks = {
|
|
|
9966
10003
|
lastClientActivityAt = 0;
|
|
9967
10004
|
sdkBackgroundQuietUntil = 0;
|
|
9968
10005
|
},
|
|
10006
|
+
runWithRequestContextForTest<T>(ctx: Partial<Ctx>, fn: () => T): T {
|
|
10007
|
+
return als.run({
|
|
10008
|
+
...ctx,
|
|
10009
|
+
excludedSpanIds: ctx.excludedSpanIds ?? new Set<string>(),
|
|
10010
|
+
}, fn);
|
|
10011
|
+
},
|
|
10012
|
+
getNativeMongoSuppressionCountForTest(): number {
|
|
10013
|
+
const suppressions = getCtx().nativeMongoSuppressions;
|
|
10014
|
+
return Array.isArray(suppressions) ? suppressions.length : 0;
|
|
10015
|
+
},
|
|
9969
10016
|
getRuntimePrivacyPolicyForTest(cfg: ReproMiddlewareConfig): NormalizedRuntimePrivacyPolicy | null {
|
|
9970
10017
|
return getRuntimePrivacyState(cfg).policy;
|
|
9971
10018
|
},
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
const assert = require('assert');
|
|
2
|
+
const mongoose = require('mongoose');
|
|
3
|
+
const { reproMongoosePlugin, __reproTestHooks } = require('../dist');
|
|
4
|
+
|
|
5
|
+
function execPre(hooks, name, context) {
|
|
6
|
+
return new Promise((resolve, reject) => {
|
|
7
|
+
hooks.execPre(name, context, [], (error) => (error ? reject(error) : resolve()));
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function execPost(hooks, name, context, args = []) {
|
|
12
|
+
return new Promise((resolve, reject) => {
|
|
13
|
+
hooks.execPost(name, context, args, {}, (error) => (error ? reject(error) : resolve()));
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async function testPostSaveEarlyReturnReleasesSuppression() {
|
|
18
|
+
const schema = new mongoose.Schema({ name: String });
|
|
19
|
+
reproMongoosePlugin({
|
|
20
|
+
tenantId: 'TENANT_test',
|
|
21
|
+
appId: 'APP_test',
|
|
22
|
+
appSecret: 'secret',
|
|
23
|
+
privacy: { environment: 'dev', captureRaw: true },
|
|
24
|
+
ingestBase: 'http://127.0.0.1:65535',
|
|
25
|
+
})(schema);
|
|
26
|
+
const Model = mongoose.model(`ReproSuppressionCleanup${Date.now()}`, schema, 'subjects');
|
|
27
|
+
const doc = new Model({ name: 'subject' });
|
|
28
|
+
|
|
29
|
+
await __reproTestHooks.runWithRequestContextForTest({ sid: 'S_cleanup', aid: 'A_cleanup' }, async () => {
|
|
30
|
+
await execPre(schema.s.hooks, 'save', doc);
|
|
31
|
+
assert.equal(__reproTestHooks.getNativeMongoSuppressionCountForTest(), 1);
|
|
32
|
+
|
|
33
|
+
// No rid/span is present, so the post hook exits through shouldCaptureDbSpan(false).
|
|
34
|
+
await execPost(schema.s.hooks, 'save', doc, [doc]);
|
|
35
|
+
assert.equal(__reproTestHooks.getNativeMongoSuppressionCountForTest(), 0);
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async function testPostSaveOutsideOriginalAlsReleasesOwnerStoreSuppression() {
|
|
40
|
+
const schema = new mongoose.Schema({ name: String });
|
|
41
|
+
reproMongoosePlugin({
|
|
42
|
+
tenantId: 'TENANT_test',
|
|
43
|
+
appId: 'APP_test',
|
|
44
|
+
appSecret: 'secret',
|
|
45
|
+
privacy: { environment: 'dev', captureRaw: true },
|
|
46
|
+
ingestBase: 'http://127.0.0.1:65535',
|
|
47
|
+
})(schema);
|
|
48
|
+
const Model = mongoose.model(`ReproSuppressionOwnerStore${Date.now()}`, schema, 'subjects');
|
|
49
|
+
const doc = new Model({ name: 'subject' });
|
|
50
|
+
|
|
51
|
+
let token;
|
|
52
|
+
await __reproTestHooks.runWithRequestContextForTest({ sid: 'S_owner', aid: 'A_owner', rid: 'R_owner' }, async () => {
|
|
53
|
+
await execPre(schema.s.hooks, 'save', doc);
|
|
54
|
+
assert.equal(__reproTestHooks.getNativeMongoSuppressionCountForTest(), 1);
|
|
55
|
+
token = doc.__repro_native_mongo_suppression;
|
|
56
|
+
assert.equal(token.ownerStore.nativeMongoSuppressions.length, 1);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
await execPost(schema.s.hooks, 'save', doc, [doc]);
|
|
60
|
+
assert.equal(token.ownerStore, undefined);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async function main() {
|
|
64
|
+
await testPostSaveEarlyReturnReleasesSuppression();
|
|
65
|
+
await testPostSaveOutsideOriginalAlsReleasesOwnerStoreSuppression();
|
|
66
|
+
console.log('mongodb suppression cleanup OK');
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
main().catch((error) => {
|
|
70
|
+
console.error(error);
|
|
71
|
+
process.exit(1);
|
|
72
|
+
});
|