@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 +100 -5
- package/dist/ingest/mapper.js +4 -0
- package/dist/ingest/types.d.ts +2 -0
- package/package.json +1 -1
- package/src/index.ts +131 -4
- package/src/ingest/mapper.ts +2 -0
- package/src/ingest/types.ts +2 -0
- package/test/request-flush-timing.test.js +5 -0
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
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
package/dist/ingest/mapper.js
CHANGED
|
@@ -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)
|
package/dist/ingest/types.d.ts
CHANGED
package/package.json
CHANGED
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
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
package/src/ingest/mapper.ts
CHANGED
|
@@ -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';
|
package/src/ingest/types.ts
CHANGED
|
@@ -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 {
|