@reproapp/node-sdk 0.0.33 → 0.0.34

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 CHANGED
@@ -824,6 +824,19 @@ const getCtx = () => als.getStore() || {};
824
824
  function normalizeNativeMongoSuppressionOp(op) {
825
825
  return String(op ?? '').trim();
826
826
  }
827
+ const NATIVE_MONGO_WRITE_OPS = new Set([
828
+ 'insertOne',
829
+ 'insertMany',
830
+ 'updateOne',
831
+ 'updateMany',
832
+ 'replaceOne',
833
+ 'deleteOne',
834
+ 'deleteMany',
835
+ 'bulkWrite',
836
+ 'findOneAndUpdate',
837
+ 'findOneAndDelete',
838
+ 'findOneAndReplace',
839
+ ]);
827
840
  function pushNativeMongoSuppression(collection, ops) {
828
841
  const store = als.getStore();
829
842
  if (!store)
@@ -887,6 +900,8 @@ function isNativeMongoSuppressed(collection, op) {
887
900
  return false;
888
901
  const normalizedCollection = collection == null ? null : String(collection);
889
902
  const normalizedOp = normalizeNativeMongoSuppressionOp(op);
903
+ if (NATIVE_MONGO_WRITE_OPS.has(normalizedOp))
904
+ return false;
890
905
  const now = Date.now();
891
906
  const matchingTokens = [];
892
907
  for (let i = suppressions.length - 1; i >= 0; i -= 1) {
@@ -3899,7 +3914,7 @@ function estimateTraceBatchSerializedBytes(batch, requestRid, actionId, batchInd
3899
3914
  function chunkTraceEventsForTransport(events, requestRid, actionId) {
3900
3915
  if (!Array.isArray(events) || events.length === 0)
3901
3916
  return [];
3902
- const boundedEvents = events.slice(0, TRACE_MAX_EVENTS_PER_REQUEST);
3917
+ const boundedEvents = boundTraceEventsForTransport(events);
3903
3918
  const countBatches = chunkArray(boundedEvents, TRACE_BATCH_SIZE);
3904
3919
  const sizedBatches = [];
3905
3920
  let current = [];
@@ -3928,6 +3943,13 @@ function chunkTraceEventsForTransport(events, requestRid, actionId) {
3928
3943
  }
3929
3944
  return sizedBatches;
3930
3945
  }
3946
+ function boundTraceEventsForTransport(events) {
3947
+ if (events.length <= TRACE_MAX_EVENTS_PER_REQUEST)
3948
+ return events;
3949
+ const headCount = Math.floor(TRACE_MAX_EVENTS_PER_REQUEST / 2);
3950
+ const tailCount = TRACE_MAX_EVENTS_PER_REQUEST - headCount;
3951
+ return events.slice(0, headCount).concat(events.slice(events.length - tailCount));
3952
+ }
3931
3953
  function createCapturedValueEntry(params) {
3932
3954
  if (!__FULL_VALUE_CAPTURE_ENABLED)
3933
3955
  return undefined;
@@ -5175,6 +5197,9 @@ function emitDbQuery(cfg, sid, aid, payload) {
5175
5197
  const spanContext = payload?.spanContext ?? captureSpanContextFromTracer();
5176
5198
  if (!shouldCaptureDbSpan(spanContext))
5177
5199
  return;
5200
+ if (ctx.captureScope) {
5201
+ ctx.captureScope.dbChangeCount += 1;
5202
+ }
5178
5203
  const runCtx = {
5179
5204
  sid: ctx.sid,
5180
5205
  aid: ctx.aid,
@@ -5302,9 +5327,6 @@ async function emitDbQueryAsync(cfg, sid, aid, payload) {
5302
5327
  t: payload.t,
5303
5328
  }]
5304
5329
  });
5305
- if (enqueued && ctx.captureScope) {
5306
- ctx.captureScope.dbChangeCount += 1;
5307
- }
5308
5330
  }
5309
5331
  function buildMinimalUpdate(before, after) {
5310
5332
  const set = {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reproapp/node-sdk",
3
- "version": "0.0.33",
3
+ "version": "0.0.34",
4
4
  "description": "Repro Nest SDK",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
package/src/index.ts CHANGED
@@ -1227,6 +1227,20 @@ function normalizeNativeMongoSuppressionOp(op: string | null | undefined): strin
1227
1227
  return String(op ?? '').trim();
1228
1228
  }
1229
1229
 
1230
+ const NATIVE_MONGO_WRITE_OPS = new Set([
1231
+ 'insertOne',
1232
+ 'insertMany',
1233
+ 'updateOne',
1234
+ 'updateMany',
1235
+ 'replaceOne',
1236
+ 'deleteOne',
1237
+ 'deleteMany',
1238
+ 'bulkWrite',
1239
+ 'findOneAndUpdate',
1240
+ 'findOneAndDelete',
1241
+ 'findOneAndReplace',
1242
+ ]);
1243
+
1230
1244
  function pushNativeMongoSuppression(collection: any, ops?: string[] | readonly string[]): NativeMongoSuppression | null {
1231
1245
  const store = als.getStore();
1232
1246
  if (!store) return null;
@@ -1284,6 +1298,7 @@ function isNativeMongoSuppressed(collection: any, op: string): boolean {
1284
1298
  if (!Array.isArray(suppressions) || suppressions.length === 0) return false;
1285
1299
  const normalizedCollection = collection == null ? null : String(collection);
1286
1300
  const normalizedOp = normalizeNativeMongoSuppressionOp(op);
1301
+ if (NATIVE_MONGO_WRITE_OPS.has(normalizedOp)) return false;
1287
1302
  const now = Date.now();
1288
1303
  const matchingTokens: NativeMongoSuppression[] = [];
1289
1304
  for (let i = suppressions.length - 1; i >= 0; i -= 1) {
@@ -4627,7 +4642,7 @@ function chunkTraceEventsForTransport(
4627
4642
  ): TraceEventRecord[][] {
4628
4643
  if (!Array.isArray(events) || events.length === 0) return [];
4629
4644
 
4630
- const boundedEvents = events.slice(0, TRACE_MAX_EVENTS_PER_REQUEST);
4645
+ const boundedEvents = boundTraceEventsForTransport(events);
4631
4646
  const countBatches = chunkArray(boundedEvents, TRACE_BATCH_SIZE);
4632
4647
  const sizedBatches: TraceEventRecord[][] = [];
4633
4648
  let current: TraceEventRecord[] = [];
@@ -4671,6 +4686,13 @@ function chunkTraceEventsForTransport(
4671
4686
  return sizedBatches;
4672
4687
  }
4673
4688
 
4689
+ function boundTraceEventsForTransport(events: TraceEventRecord[]): TraceEventRecord[] {
4690
+ if (events.length <= TRACE_MAX_EVENTS_PER_REQUEST) return events;
4691
+ const headCount = Math.floor(TRACE_MAX_EVENTS_PER_REQUEST / 2);
4692
+ const tailCount = TRACE_MAX_EVENTS_PER_REQUEST - headCount;
4693
+ return events.slice(0, headCount).concat(events.slice(events.length - tailCount));
4694
+ }
4695
+
4674
4696
  function createCapturedValueEntry(
4675
4697
  params: {
4676
4698
  target:
@@ -6132,6 +6154,9 @@ function emitDbQuery(cfg: any, sid?: string, aid?: string, payload?: any) {
6132
6154
  const ctx = getCtx() as Ctx;
6133
6155
  const spanContext = payload?.spanContext ?? captureSpanContextFromTracer();
6134
6156
  if (!shouldCaptureDbSpan(spanContext)) return;
6157
+ if (ctx.captureScope) {
6158
+ ctx.captureScope.dbChangeCount += 1;
6159
+ }
6135
6160
  const runCtx: Ctx = {
6136
6161
  sid: ctx.sid,
6137
6162
  aid: ctx.aid,
@@ -6258,9 +6283,6 @@ async function emitDbQueryAsync(cfg: any, sid?: string, aid?: string, payload?:
6258
6283
  t: payload.t,
6259
6284
  }]
6260
6285
  });
6261
- if (enqueued && ctx.captureScope) {
6262
- ctx.captureScope.dbChangeCount += 1;
6263
- }
6264
6286
  }
6265
6287
 
6266
6288
  function buildMinimalUpdate(before: any, after: any) {
@@ -139,6 +139,13 @@ function dbChanges(events) {
139
139
  .flatMap((event) => Array.isArray(event.payload?.db) ? event.payload.db : []);
140
140
  }
141
141
 
142
+ function requestCaptureManifests(events) {
143
+ return events
144
+ .filter((event) => event.event_type === 'request_capture_manifest')
145
+ .map((event) => event.payload?.requestCaptureManifest ?? event.payload)
146
+ .filter(Boolean);
147
+ }
148
+
142
149
  async function testMongooseSuppressionDoesNotHideExplicitNativeInsertOne() {
143
150
  await withCapturedFetch(async (capturedBodies) => {
144
151
  __reproTestHooks.resetSdkBackgroundQueuesForTest();
@@ -185,9 +192,11 @@ async function testMongooseSuppressionDoesNotHideExplicitNativeInsertOne() {
185
192
  });
186
193
 
187
194
  await waitFor(() => dbChanges(flattenEvents(capturedBodies)).length === 1);
195
+ await waitFor(() => requestCaptureManifests(flattenEvents(capturedBodies)).length === 1);
188
196
  await drainSdk();
189
197
 
190
198
  const [change] = dbChanges(flattenEvents(capturedBodies));
199
+ const [manifest] = requestCaptureManifests(flattenEvents(capturedBodies));
191
200
  assert.strictEqual(change.type, 'mongo');
192
201
  assert.strictEqual(change.collection, 'subjects');
193
202
  assert.strictEqual(change.op, 'insertOne');
@@ -198,6 +207,7 @@ async function testMongooseSuppressionDoesNotHideExplicitNativeInsertOne() {
198
207
  assert.strictEqual(change.query.options.session.__kind, 'mongodb_client_session');
199
208
  assert.strictEqual(change.query.options.session.id, 'native-explicit-session-1');
200
209
  assert.strictEqual(change.after.subjectNumber, '10013038');
210
+ assert.strictEqual(manifest.expected.dbChange, 1);
201
211
  });
202
212
  }
203
213
 
@@ -34,6 +34,13 @@ function dbChanges(events) {
34
34
  .flatMap((event) => Array.isArray(event.payload?.db) ? event.payload.db : []);
35
35
  }
36
36
 
37
+ function requestCaptureManifests(events) {
38
+ return events
39
+ .filter((event) => event.event_type === 'request_capture_manifest')
40
+ .map((event) => event.payload?.requestCaptureManifest ?? event.payload)
41
+ .filter(Boolean);
42
+ }
43
+
37
44
  function makeReqRes(sessionId, actionId) {
38
45
  const req = new EventEmitter();
39
46
  req.method = 'POST';
@@ -131,16 +138,29 @@ async function main() {
131
138
  await Subject.create({ subjectNumber: '10013038', status: 'screened' });
132
139
  });
133
140
 
134
- await waitFor(() => dbChanges(flattenEvents(capturedBodies)).length === 1);
141
+ await waitFor(() => dbChanges(flattenEvents(capturedBodies)).length >= 2);
142
+ await waitFor(() => requestCaptureManifests(flattenEvents(capturedBodies)).length === 1);
135
143
  await __reproTestHooks.drainSdkBackgroundQueueForTest();
136
144
  await flushIngestQueue();
137
145
 
138
146
  const changes = dbChanges(flattenEvents(capturedBodies));
139
- assert.strictEqual(changes.length, 1);
140
- assert.strictEqual(changes[0].type, 'mongo');
141
- assert.strictEqual(changes[0].collection, 'subjects');
142
- assert.strictEqual(changes[0].op, 'insert');
143
- assert.strictEqual(changes[0].after.subjectNumber, '10013038');
147
+ const manifest = requestCaptureManifests(flattenEvents(capturedBodies))[0];
148
+ const mongooseWrite = changes.find((change) => (
149
+ change.type === 'mongo' &&
150
+ change.collection === 'subjects' &&
151
+ change.op === 'insert' &&
152
+ change.after?.subjectNumber === '10013038'
153
+ ));
154
+ const nativeWrite = changes.find((change) => (
155
+ change.type === 'mongo' &&
156
+ change.collection === 'subjects' &&
157
+ change.op === 'insertOne' &&
158
+ change.query?.driver === 'mongodb' &&
159
+ change.after?.subjectNumber === '10013038'
160
+ ));
161
+ assert.ok(mongooseWrite, 'expected mongoose-level insert evidence');
162
+ assert.ok(nativeWrite, 'expected native mongodb insertOne evidence');
163
+ assert.ok(manifest.expected.dbChange >= 2);
144
164
 
145
165
  console.log('mongodb mongoose native suppression testcontainers OK');
146
166
  } finally {
@@ -66,6 +66,11 @@ function main() {
66
66
  cappedEventCount <= 1000,
67
67
  `expected trace transport to cap events per request, got ${cappedEventCount}`,
68
68
  );
69
+ const cappedEvents = cappedBatches.flat();
70
+ assert.strictEqual(cappedEvents[0].fn, 'fn0');
71
+ assert.strictEqual(cappedEvents[499].fn, 'fn499');
72
+ assert.strictEqual(cappedEvents[500].fn, 'fn1000');
73
+ assert.strictEqual(cappedEvents[cappedEvents.length - 1].fn, 'fn1499');
69
74
 
70
75
  // eslint-disable-next-line no-console
71
76
  console.log('trace batch size chunking OK');