@reproapp/node-sdk 0.0.13 → 0.0.14

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
@@ -783,6 +783,37 @@ function attachSpanContext(target, span) {
783
783
  }
784
784
  return target;
785
785
  }
786
+ function createRequestCaptureScope(requestRid, transport) {
787
+ return {
788
+ requestRid,
789
+ transport,
790
+ backendRequestCount: 0,
791
+ traceBatchCount: 0,
792
+ dbChangeCount: 0,
793
+ emailEventCount: 0,
794
+ };
795
+ }
796
+ function buildRequestCaptureManifestPayload(scope, traceBatchTotal) {
797
+ const expectedTraceBatches = Math.max(0, Math.trunc(traceBatchTotal));
798
+ return {
799
+ scopeId: `req:${scope.requestRid}`,
800
+ requestRid: scope.requestRid,
801
+ transport: scope.transport,
802
+ expected: {
803
+ backendRequest: scope.backendRequestCount,
804
+ traceBatch: expectedTraceBatches,
805
+ dbChange: scope.dbChangeCount,
806
+ emailEvent: scope.emailEventCount,
807
+ },
808
+ traceBatch: expectedTraceBatches > 0
809
+ ? {
810
+ from: 0,
811
+ to: expectedTraceBatches - 1,
812
+ }
813
+ : undefined,
814
+ closedAt: alignedNow(),
815
+ };
816
+ }
786
817
  const als = new async_hooks_1.AsyncLocalStorage();
787
818
  const getCtx = () => als.getStore() || {};
788
819
  function currentClockSkewMs() {
@@ -3879,6 +3910,7 @@ function reproMiddleware(cfg) {
3879
3910
  const clockSkewMs = headerTs !== null ? headerTs - requestStartRaw : 0;
3880
3911
  const requestEpochMs = headerTs !== null ? headerTs : requestStartRaw + clockSkewMs;
3881
3912
  const rid = nextRequestId(requestEpochMs);
3913
+ const captureScope = createRequestCaptureScope(rid, 'http');
3882
3914
  const t0 = requestStartRaw;
3883
3915
  const url = req.originalUrl || req.url || '/';
3884
3916
  const urlPathOnly = (url || '/').split('?')[0] || '/';
@@ -3919,7 +3951,7 @@ function reproMiddleware(cfg) {
3919
3951
  }
3920
3952
  return fn();
3921
3953
  };
3922
- runInTrace(() => als.run({ sid, aid, rid, clockSkewMs, excludedSpanIds: new Set(), maskReq }, () => {
3954
+ runInTrace(() => als.run({ sid, aid, rid, clockSkewMs, excludedSpanIds: new Set(), maskReq, captureScope }, () => {
3923
3955
  const events = [];
3924
3956
  let endpointTrace = null;
3925
3957
  let preferredAppTrace = null;
@@ -4190,6 +4222,7 @@ function reproMiddleware(cfg) {
4190
4222
  t: requestEpochMs,
4191
4223
  }]
4192
4224
  });
4225
+ captureScope.backendRequestCount += 1;
4193
4226
  }
4194
4227
  catch {
4195
4228
  // never break user code
@@ -4304,6 +4337,7 @@ function reproMiddleware(cfg) {
4304
4337
  : sortTraceEventsChronologically(baseEvents);
4305
4338
  const traceBatches = chunkTraceEventsForTransport(orderedEvents, rid, aid);
4306
4339
  if (traceBatches.length) {
4340
+ captureScope.traceBatchCount = traceBatches.length;
4307
4341
  for (let i = 0; i < traceBatches.length; i++) {
4308
4342
  const batch = traceBatches[i];
4309
4343
  const traceValues = collectBatchTraceValueEntries(batch, i);
@@ -4322,6 +4356,17 @@ function reproMiddleware(cfg) {
4322
4356
  });
4323
4357
  }
4324
4358
  }
4359
+ else {
4360
+ captureScope.traceBatchCount = 0;
4361
+ }
4362
+ post(cfg, sid, {
4363
+ entries: [{
4364
+ actionId: aid,
4365
+ requestRid: rid,
4366
+ requestCaptureManifest: buildRequestCaptureManifestPayload(captureScope, traceBatches.length),
4367
+ t: alignedNow(),
4368
+ }],
4369
+ });
4325
4370
  }
4326
4371
  catch {
4327
4372
  // never break user code
@@ -4786,6 +4831,12 @@ function dehydrateComplexValue(value) {
4786
4831
  }
4787
4832
  function emitDbQuery(cfg, sid, aid, payload) {
4788
4833
  const ctx = getCtx();
4834
+ const spanContext = payload?.spanContext ?? captureSpanContextFromTracer();
4835
+ if (!shouldCaptureDbSpan(spanContext))
4836
+ return;
4837
+ if (ctx.captureScope) {
4838
+ ctx.captureScope.dbChangeCount += 1;
4839
+ }
4789
4840
  const runCtx = {
4790
4841
  sid: ctx.sid,
4791
4842
  aid: ctx.aid,
@@ -4793,6 +4844,7 @@ function emitDbQuery(cfg, sid, aid, payload) {
4793
4844
  clockSkewMs: ctx.clockSkewMs,
4794
4845
  maskReq: ctx.maskReq,
4795
4846
  excludedSpanIds: ctx.excludedSpanIds ? new Set(ctx.excludedSpanIds) : undefined,
4847
+ captureScope: ctx.captureScope,
4796
4848
  };
4797
4849
  scheduleSdkBackgroundWork(async () => {
4798
4850
  await als.run(runCtx, async () => {
@@ -5575,9 +5627,9 @@ function buildKafkaTraceEntries(actionId, requestRid, events) {
5575
5627
  t: alignedNow(),
5576
5628
  }));
5577
5629
  }
5578
- function scheduleKafkaTraceFlush(cfg, kafkaCtx, actionId, requestRid, rawTraceEvents, maskReq) {
5630
+ function scheduleKafkaTraceFlush(cfg, kafkaCtx, actionId, requestRid, rawTraceEvents, maskReq, captureScope) {
5579
5631
  const sid = kafkaCtx.sid;
5580
- if (!sid || !rawTraceEvents.length)
5632
+ if (!sid)
5581
5633
  return;
5582
5634
  const rawEvents = rawTraceEvents.slice();
5583
5635
  scheduleSdkBackgroundWork(async () => {
@@ -5600,9 +5652,22 @@ function scheduleKafkaTraceFlush(cfg, kafkaCtx, actionId, requestRid, rawTraceEv
5600
5652
  resolvePrivacy: () => getRuntimePrivacyState(cfg).policy ?? null,
5601
5653
  });
5602
5654
  const entries = buildKafkaTraceEntries(actionId, requestRid, materializedEvents);
5655
+ if (captureScope) {
5656
+ captureScope.traceBatchCount = entries.length;
5657
+ }
5603
5658
  if (entries.length) {
5604
5659
  post(cfg, sid, { entries });
5605
5660
  }
5661
+ if (captureScope) {
5662
+ post(cfg, sid, {
5663
+ entries: [{
5664
+ actionId: actionId ?? null,
5665
+ requestRid,
5666
+ requestCaptureManifest: buildRequestCaptureManifestPayload(captureScope, entries.length),
5667
+ t: alignedNow(),
5668
+ }],
5669
+ });
5670
+ }
5606
5671
  });
5607
5672
  }, { priority: 'high' });
5608
5673
  }
@@ -5619,6 +5684,7 @@ function patchKafkaProducerInstance(producer, cfg) {
5619
5684
  const aid = ctx.aid ?? fallback.aid ?? null;
5620
5685
  const span = captureSpanContextFromTracer();
5621
5686
  const publishRid = nextRequestId(alignedNow());
5687
+ const captureScope = createRequestCaptureScope(publishRid, 'kafka');
5622
5688
  const payloadObj = payload && typeof payload === 'object' ? payload : {};
5623
5689
  const topic = sanitizeKafkaTopic(payloadObj.topic);
5624
5690
  const rawMessages = Array.isArray(payloadObj.messages) ? payloadObj.messages : [];
@@ -5705,6 +5771,15 @@ function patchKafkaProducerInstance(producer, cfg) {
5705
5771
  },
5706
5772
  ],
5707
5773
  });
5774
+ captureScope.backendRequestCount += 1;
5775
+ post(cfg, sid, {
5776
+ entries: [{
5777
+ actionId: aid ?? null,
5778
+ requestRid: publishRid,
5779
+ requestCaptureManifest: buildRequestCaptureManifestPayload(captureScope, 0),
5780
+ t: alignedNow(),
5781
+ }],
5782
+ });
5708
5783
  }
5709
5784
  };
5710
5785
  }
@@ -5717,6 +5792,7 @@ function patchKafkaProducerInstance(producer, cfg) {
5717
5792
  const aid = ctx.aid ?? fallback.aid ?? null;
5718
5793
  const span = captureSpanContextFromTracer();
5719
5794
  const publishRid = nextRequestId(alignedNow());
5795
+ const captureScope = createRequestCaptureScope(publishRid, 'kafka');
5720
5796
  const payloadObj = payload && typeof payload === 'object' ? payload : {};
5721
5797
  const topicMessages = Array.isArray(payloadObj.topicMessages)
5722
5798
  ? payloadObj.topicMessages
@@ -5834,6 +5910,15 @@ function patchKafkaProducerInstance(producer, cfg) {
5834
5910
  },
5835
5911
  ],
5836
5912
  });
5913
+ captureScope.backendRequestCount += 1;
5914
+ post(cfg, sid, {
5915
+ entries: [{
5916
+ actionId: aid ?? null,
5917
+ requestRid: publishRid,
5918
+ requestCaptureManifest: buildRequestCaptureManifestPayload(captureScope, 0),
5919
+ t: alignedNow(),
5920
+ }],
5921
+ });
5837
5922
  }
5838
5923
  };
5839
5924
  }
@@ -5848,6 +5933,7 @@ function wrapKafkaEachMessageHandler(eachMessage, cfg, consumer) {
5848
5933
  const aid = runtime.aid;
5849
5934
  const consumeRid = nextRequestId(`${topic}-${message?.offset ?? alignedNow()}`);
5850
5935
  const traceId = consumeRid;
5936
+ const captureScope = createRequestCaptureScope(consumeRid, 'kafka');
5851
5937
  const rawTraceEvents = [];
5852
5938
  const maskReq = {
5853
5939
  method: 'KAFKA_CONSUME',
@@ -5862,6 +5948,7 @@ function wrapKafkaEachMessageHandler(eachMessage, cfg, consumer) {
5862
5948
  excludedSpanIds: new Set(),
5863
5949
  maskReq,
5864
5950
  privacyTasks: new Set(),
5951
+ captureScope,
5865
5952
  };
5866
5953
  let unsubscribe;
5867
5954
  const invoke = async () => {
@@ -5944,7 +6031,8 @@ function wrapKafkaEachMessageHandler(eachMessage, cfg, consumer) {
5944
6031
  t: alignedNow(),
5945
6032
  }],
5946
6033
  });
5947
- scheduleKafkaTraceFlush(cfg, kafkaCtx, aid, consumeRid, rawTraceEvents, maskReq);
6034
+ captureScope.backendRequestCount += 1;
6035
+ scheduleKafkaTraceFlush(cfg, kafkaCtx, aid, consumeRid, rawTraceEvents, maskReq, captureScope);
5948
6036
  }
5949
6037
  };
5950
6038
  }
@@ -5959,6 +6047,7 @@ function wrapKafkaEachBatchHandler(eachBatch, cfg, consumer) {
5959
6047
  const aid = runtime.aid;
5960
6048
  const consumeRid = nextRequestId(`${topic}-batch-${alignedNow()}`);
5961
6049
  const traceId = consumeRid;
6050
+ const captureScope = createRequestCaptureScope(consumeRid, 'kafka');
5962
6051
  const rawTraceEvents = [];
5963
6052
  const maskReq = {
5964
6053
  method: 'KAFKA_CONSUME_BATCH',
@@ -5973,6 +6062,7 @@ function wrapKafkaEachBatchHandler(eachBatch, cfg, consumer) {
5973
6062
  excludedSpanIds: new Set(),
5974
6063
  maskReq,
5975
6064
  privacyTasks: new Set(),
6065
+ captureScope,
5976
6066
  };
5977
6067
  let unsubscribe;
5978
6068
  const invoke = async () => {
@@ -6053,7 +6143,8 @@ function wrapKafkaEachBatchHandler(eachBatch, cfg, consumer) {
6053
6143
  t: alignedNow(),
6054
6144
  }],
6055
6145
  });
6056
- scheduleKafkaTraceFlush(cfg, kafkaCtx, aid, consumeRid, rawTraceEvents, maskReq);
6146
+ captureScope.backendRequestCount += 1;
6147
+ scheduleKafkaTraceFlush(cfg, kafkaCtx, aid, consumeRid, rawTraceEvents, maskReq, captureScope);
6057
6148
  }
6058
6149
  };
6059
6150
  }
@@ -6705,10 +6796,14 @@ function patchSendgridFromModuleExports(sgMail, cfg) {
6705
6796
  const aid = ctx.aid ?? cfg.resolveContext?.()?.aid;
6706
6797
  if (!sid)
6707
6798
  return;
6799
+ if (ctx.captureScope) {
6800
+ ctx.captureScope.emailEventCount += 1;
6801
+ }
6708
6802
  const norm = normalizeSendgridMessage(rawMsg);
6709
6803
  post(cfg, sid, {
6710
6804
  entries: [{
6711
6805
  actionId: aid ?? null,
6806
+ requestRid: ctx.rid ?? null,
6712
6807
  email: {
6713
6808
  provider: 'sendgrid',
6714
6809
  kind,
@@ -6,6 +6,10 @@ const toIso = (timestamp) => {
6
6
  return new Date(numeric).toISOString();
7
7
  };
8
8
  const inferEventType = (entry) => {
9
+ if (entry.requestCaptureManifest !== undefined)
10
+ return 'request_capture_manifest';
11
+ if (entry.sessionCaptureManifest !== undefined)
12
+ return 'session_capture_manifest';
9
13
  if (entry.request !== undefined)
10
14
  return 'backend_request';
11
15
  if (entry.db !== undefined)
@@ -17,6 +17,8 @@ export interface LegacyEntry {
17
17
  requestRid?: string | null;
18
18
  request?: unknown;
19
19
  requestValues?: unknown[];
20
+ requestCaptureManifest?: unknown;
21
+ sessionCaptureManifest?: unknown;
20
22
  db?: unknown;
21
23
  dbValues?: unknown[];
22
24
  trace?: unknown[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reproapp/node-sdk",
3
- "version": "0.0.13",
3
+ "version": "0.0.14",
4
4
  "description": "Repro Nest SDK",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
package/src/index.ts CHANGED
@@ -1152,7 +1152,58 @@ type Ctx = {
1152
1152
  excludedSpanIds?: Set<string>;
1153
1153
  maskReq?: MaskRequestContext;
1154
1154
  privacyTasks?: Set<Promise<void>>;
1155
+ captureScope?: RequestCaptureScopeState;
1155
1156
  };
1157
+
1158
+ type RequestCaptureScopeState = {
1159
+ requestRid: string;
1160
+ transport: 'http' | 'kafka' | 'background';
1161
+ backendRequestCount: number;
1162
+ traceBatchCount: number;
1163
+ dbChangeCount: number;
1164
+ emailEventCount: number;
1165
+ };
1166
+
1167
+ function createRequestCaptureScope(
1168
+ requestRid: string,
1169
+ transport: RequestCaptureScopeState['transport'],
1170
+ ): RequestCaptureScopeState {
1171
+ return {
1172
+ requestRid,
1173
+ transport,
1174
+ backendRequestCount: 0,
1175
+ traceBatchCount: 0,
1176
+ dbChangeCount: 0,
1177
+ emailEventCount: 0,
1178
+ };
1179
+ }
1180
+
1181
+ function buildRequestCaptureManifestPayload(
1182
+ scope: RequestCaptureScopeState,
1183
+ traceBatchTotal: number,
1184
+ ): Record<string, any> {
1185
+ const expectedTraceBatches = Math.max(0, Math.trunc(traceBatchTotal));
1186
+ return {
1187
+ scopeId: `req:${scope.requestRid}`,
1188
+ requestRid: scope.requestRid,
1189
+ transport: scope.transport,
1190
+ expected: {
1191
+ backendRequest: scope.backendRequestCount,
1192
+ traceBatch: expectedTraceBatches,
1193
+ dbChange: scope.dbChangeCount,
1194
+ emailEvent: scope.emailEventCount,
1195
+ },
1196
+ traceBatch:
1197
+ expectedTraceBatches > 0
1198
+ ? {
1199
+ from: 0,
1200
+ to: expectedTraceBatches - 1,
1201
+ }
1202
+ : undefined,
1203
+ closedAt: alignedNow(),
1204
+ };
1205
+ }
1206
+
1156
1207
  const als = new AsyncLocalStorage<Ctx>();
1157
1208
  const getCtx = () => als.getStore() || {};
1158
1209
 
@@ -4747,6 +4798,7 @@ export function reproMiddleware(cfg: ReproMiddlewareConfig) {
4747
4798
  const clockSkewMs = headerTs !== null ? headerTs - requestStartRaw : 0;
4748
4799
  const requestEpochMs = headerTs !== null ? headerTs : requestStartRaw + clockSkewMs;
4749
4800
  const rid = nextRequestId(requestEpochMs);
4801
+ const captureScope = createRequestCaptureScope(rid, 'http');
4750
4802
  const t0 = requestStartRaw;
4751
4803
  const url = (req as any).originalUrl || req.url || '/';
4752
4804
  const urlPathOnly = (url || '/').split('?')[0] || '/';
@@ -4784,7 +4836,7 @@ export function reproMiddleware(cfg: ReproMiddlewareConfig) {
4784
4836
  return fn();
4785
4837
  };
4786
4838
 
4787
- runInTrace(() => als.run({ sid, aid, rid, clockSkewMs, excludedSpanIds: new Set<string>(), maskReq }, () => {
4839
+ runInTrace(() => als.run({ sid, aid, rid, clockSkewMs, excludedSpanIds: new Set<string>(), maskReq, captureScope }, () => {
4788
4840
  const events: PendingTraceEventRecord[] = [];
4789
4841
  let endpointTrace: EndpointTraceInfo | null = null;
4790
4842
  let preferredAppTrace: EndpointTraceInfo | null = null;
@@ -5086,6 +5138,7 @@ export function reproMiddleware(cfg: ReproMiddlewareConfig) {
5086
5138
  t: requestEpochMs,
5087
5139
  }]
5088
5140
  });
5141
+ captureScope.backendRequestCount += 1;
5089
5142
  } catch {
5090
5143
  // never break user code
5091
5144
  }
@@ -5209,6 +5262,7 @@ export function reproMiddleware(cfg: ReproMiddlewareConfig) {
5209
5262
  );
5210
5263
 
5211
5264
  if (traceBatches.length) {
5265
+ captureScope.traceBatchCount = traceBatches.length;
5212
5266
  for (let i = 0; i < traceBatches.length; i++) {
5213
5267
  const batch = traceBatches[i];
5214
5268
  const traceValues = collectBatchTraceValueEntries(batch, i);
@@ -5227,7 +5281,21 @@ export function reproMiddleware(cfg: ReproMiddlewareConfig) {
5227
5281
  }],
5228
5282
  });
5229
5283
  }
5284
+ } else {
5285
+ captureScope.traceBatchCount = 0;
5230
5286
  }
5287
+
5288
+ post(cfg, sid, {
5289
+ entries: [{
5290
+ actionId: aid,
5291
+ requestRid: rid,
5292
+ requestCaptureManifest: buildRequestCaptureManifestPayload(
5293
+ captureScope,
5294
+ traceBatches.length,
5295
+ ),
5296
+ t: alignedNow(),
5297
+ }],
5298
+ });
5231
5299
  } catch {
5232
5300
  // never break user code
5233
5301
  }
@@ -5697,6 +5765,11 @@ function dehydrateComplexValue(value: any) {
5697
5765
 
5698
5766
  function emitDbQuery(cfg: any, sid?: string, aid?: string, payload?: any) {
5699
5767
  const ctx = getCtx() as Ctx;
5768
+ const spanContext = payload?.spanContext ?? captureSpanContextFromTracer();
5769
+ if (!shouldCaptureDbSpan(spanContext)) return;
5770
+ if (ctx.captureScope) {
5771
+ ctx.captureScope.dbChangeCount += 1;
5772
+ }
5700
5773
  const runCtx: Ctx = {
5701
5774
  sid: ctx.sid,
5702
5775
  aid: ctx.aid,
@@ -5704,6 +5777,7 @@ function emitDbQuery(cfg: any, sid?: string, aid?: string, payload?: any) {
5704
5777
  clockSkewMs: ctx.clockSkewMs,
5705
5778
  maskReq: ctx.maskReq,
5706
5779
  excludedSpanIds: ctx.excludedSpanIds ? new Set(ctx.excludedSpanIds) : undefined,
5780
+ captureScope: ctx.captureScope,
5707
5781
  };
5708
5782
  scheduleSdkBackgroundWork(async () => {
5709
5783
  await als.run(runCtx, async () => {
@@ -6588,9 +6662,10 @@ function scheduleKafkaTraceFlush(
6588
6662
  requestRid: string,
6589
6663
  rawTraceEvents: any[],
6590
6664
  maskReq: MaskRequestContext,
6665
+ captureScope?: RequestCaptureScopeState,
6591
6666
  ): void {
6592
6667
  const sid = kafkaCtx.sid;
6593
- if (!sid || !rawTraceEvents.length) return;
6668
+ if (!sid) return;
6594
6669
  const rawEvents = rawTraceEvents.slice();
6595
6670
 
6596
6671
  scheduleSdkBackgroundWork(async () => {
@@ -6611,9 +6686,25 @@ function scheduleKafkaTraceFlush(
6611
6686
  resolvePrivacy: () => getRuntimePrivacyState(cfg).policy ?? null,
6612
6687
  });
6613
6688
  const entries = buildKafkaTraceEntries(actionId, requestRid, materializedEvents);
6689
+ if (captureScope) {
6690
+ captureScope.traceBatchCount = entries.length;
6691
+ }
6614
6692
  if (entries.length) {
6615
6693
  post(cfg, sid, { entries });
6616
6694
  }
6695
+ if (captureScope) {
6696
+ post(cfg, sid, {
6697
+ entries: [{
6698
+ actionId: actionId ?? null,
6699
+ requestRid,
6700
+ requestCaptureManifest: buildRequestCaptureManifestPayload(
6701
+ captureScope,
6702
+ entries.length,
6703
+ ),
6704
+ t: alignedNow(),
6705
+ }],
6706
+ });
6707
+ }
6617
6708
  });
6618
6709
  }, { priority: 'high' });
6619
6710
  }
@@ -6631,6 +6722,7 @@ function patchKafkaProducerInstance(producer: any, cfg: KafkaJsPatchConfig) {
6631
6722
  const aid = ctx.aid ?? fallback.aid ?? null;
6632
6723
  const span = captureSpanContextFromTracer();
6633
6724
  const publishRid = nextRequestId(alignedNow());
6725
+ const captureScope = createRequestCaptureScope(publishRid, 'kafka');
6634
6726
  const payloadObj = payload && typeof payload === 'object' ? payload : {};
6635
6727
  const topic = sanitizeKafkaTopic((payloadObj as any).topic);
6636
6728
  const rawMessages = Array.isArray((payloadObj as any).messages) ? (payloadObj as any).messages : [];
@@ -6719,6 +6811,18 @@ function patchKafkaProducerInstance(producer: any, cfg: KafkaJsPatchConfig) {
6719
6811
  },
6720
6812
  ],
6721
6813
  });
6814
+ captureScope.backendRequestCount += 1;
6815
+ post(cfg, sid, {
6816
+ entries: [{
6817
+ actionId: aid ?? null,
6818
+ requestRid: publishRid,
6819
+ requestCaptureManifest: buildRequestCaptureManifestPayload(
6820
+ captureScope,
6821
+ 0,
6822
+ ),
6823
+ t: alignedNow(),
6824
+ }],
6825
+ });
6722
6826
  }
6723
6827
  };
6724
6828
  }
@@ -6732,6 +6836,7 @@ function patchKafkaProducerInstance(producer: any, cfg: KafkaJsPatchConfig) {
6732
6836
  const aid = ctx.aid ?? fallback.aid ?? null;
6733
6837
  const span = captureSpanContextFromTracer();
6734
6838
  const publishRid = nextRequestId(alignedNow());
6839
+ const captureScope = createRequestCaptureScope(publishRid, 'kafka');
6735
6840
 
6736
6841
  const payloadObj = payload && typeof payload === 'object' ? payload : {};
6737
6842
  const topicMessages = Array.isArray((payloadObj as any).topicMessages)
@@ -6854,6 +6959,18 @@ function patchKafkaProducerInstance(producer: any, cfg: KafkaJsPatchConfig) {
6854
6959
  },
6855
6960
  ],
6856
6961
  });
6962
+ captureScope.backendRequestCount += 1;
6963
+ post(cfg, sid, {
6964
+ entries: [{
6965
+ actionId: aid ?? null,
6966
+ requestRid: publishRid,
6967
+ requestCaptureManifest: buildRequestCaptureManifestPayload(
6968
+ captureScope,
6969
+ 0,
6970
+ ),
6971
+ t: alignedNow(),
6972
+ }],
6973
+ });
6857
6974
  }
6858
6975
  };
6859
6976
  }
@@ -6869,6 +6986,7 @@ function wrapKafkaEachMessageHandler(eachMessage: any, cfg: KafkaJsPatchConfig,
6869
6986
  const aid = runtime.aid;
6870
6987
  const consumeRid = nextRequestId(`${topic}-${message?.offset ?? alignedNow()}`);
6871
6988
  const traceId = consumeRid;
6989
+ const captureScope = createRequestCaptureScope(consumeRid, 'kafka');
6872
6990
  const rawTraceEvents: any[] = [];
6873
6991
  const maskReq: MaskRequestContext = {
6874
6992
  method: 'KAFKA_CONSUME',
@@ -6883,6 +7001,7 @@ function wrapKafkaEachMessageHandler(eachMessage: any, cfg: KafkaJsPatchConfig,
6883
7001
  excludedSpanIds: new Set<string>(),
6884
7002
  maskReq,
6885
7003
  privacyTasks: new Set<Promise<void>>(),
7004
+ captureScope,
6886
7005
  };
6887
7006
  let unsubscribe: undefined | (() => void);
6888
7007
 
@@ -6960,7 +7079,8 @@ function wrapKafkaEachMessageHandler(eachMessage: any, cfg: KafkaJsPatchConfig,
6960
7079
  t: alignedNow(),
6961
7080
  }],
6962
7081
  });
6963
- scheduleKafkaTraceFlush(cfg, kafkaCtx, aid, consumeRid, rawTraceEvents, maskReq);
7082
+ captureScope.backendRequestCount += 1;
7083
+ scheduleKafkaTraceFlush(cfg, kafkaCtx, aid, consumeRid, rawTraceEvents, maskReq, captureScope);
6964
7084
  }
6965
7085
  };
6966
7086
  }
@@ -6976,6 +7096,7 @@ function wrapKafkaEachBatchHandler(eachBatch: any, cfg: KafkaJsPatchConfig, cons
6976
7096
  const aid = runtime.aid;
6977
7097
  const consumeRid = nextRequestId(`${topic}-batch-${alignedNow()}`);
6978
7098
  const traceId = consumeRid;
7099
+ const captureScope = createRequestCaptureScope(consumeRid, 'kafka');
6979
7100
  const rawTraceEvents: any[] = [];
6980
7101
  const maskReq: MaskRequestContext = {
6981
7102
  method: 'KAFKA_CONSUME_BATCH',
@@ -6990,6 +7111,7 @@ function wrapKafkaEachBatchHandler(eachBatch: any, cfg: KafkaJsPatchConfig, cons
6990
7111
  excludedSpanIds: new Set<string>(),
6991
7112
  maskReq,
6992
7113
  privacyTasks: new Set<Promise<void>>(),
7114
+ captureScope,
6993
7115
  };
6994
7116
  let unsubscribe: undefined | (() => void);
6995
7117
 
@@ -7065,7 +7187,8 @@ function wrapKafkaEachBatchHandler(eachBatch: any, cfg: KafkaJsPatchConfig, cons
7065
7187
  t: alignedNow(),
7066
7188
  }],
7067
7189
  });
7068
- scheduleKafkaTraceFlush(cfg, kafkaCtx, aid, consumeRid, rawTraceEvents, maskReq);
7190
+ captureScope.backendRequestCount += 1;
7191
+ scheduleKafkaTraceFlush(cfg, kafkaCtx, aid, consumeRid, rawTraceEvents, maskReq, captureScope);
7069
7192
  }
7070
7193
  };
7071
7194
  }
@@ -7761,11 +7884,15 @@ function patchSendgridFromModuleExports(sgMail: any, cfg: SendgridPatchConfig) {
7761
7884
  const sid = ctx.sid ?? cfg.resolveContext?.()?.sid;
7762
7885
  const aid = ctx.aid ?? cfg.resolveContext?.()?.aid;
7763
7886
  if (!sid) return;
7887
+ if (ctx.captureScope) {
7888
+ ctx.captureScope.emailEventCount += 1;
7889
+ }
7764
7890
 
7765
7891
  const norm = normalizeSendgridMessage(rawMsg);
7766
7892
  post(cfg, sid, {
7767
7893
  entries: [{
7768
7894
  actionId: aid ?? null,
7895
+ requestRid: ctx.rid ?? null,
7769
7896
  email: {
7770
7897
  provider: 'sendgrid',
7771
7898
  kind,
@@ -7,6 +7,8 @@ const toIso = (timestamp: unknown): string => {
7
7
  };
8
8
 
9
9
  const inferEventType = (entry: LegacyEntry): string => {
10
+ if (entry.requestCaptureManifest !== undefined) return 'request_capture_manifest';
11
+ if (entry.sessionCaptureManifest !== undefined) return 'session_capture_manifest';
10
12
  if (entry.request !== undefined) return 'backend_request';
11
13
  if (entry.db !== undefined) return 'db_change';
12
14
  if (entry.trace !== undefined) return 'trace_batch';
@@ -18,6 +18,8 @@ export interface LegacyEntry {
18
18
  requestRid?: string | null;
19
19
  request?: unknown;
20
20
  requestValues?: unknown[];
21
+ requestCaptureManifest?: unknown;
22
+ sessionCaptureManifest?: unknown;
21
23
  db?: unknown;
22
24
  dbValues?: unknown[];
23
25
  trace?: unknown[];
@@ -109,6 +109,11 @@ async function main() {
109
109
 
110
110
  assert.strictEqual(countEvents(capturedBodies, 'backend_request'), 1, JSON.stringify(capturedBodies));
111
111
  assert(countEvents(capturedBodies, 'trace_batch') >= 1, JSON.stringify(capturedBodies));
112
+ assert.strictEqual(
113
+ countEvents(capturedBodies, 'request_capture_manifest'),
114
+ 1,
115
+ JSON.stringify(capturedBodies),
116
+ );
112
117
 
113
118
  console.log('request flush timing OK');
114
119
  } finally {