@reproapp/node-sdk 0.0.46 → 0.0.47
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 +10 -2
- package/dist/index.js +235 -123
- package/dist/ingest/client.js +11 -0
- package/dist/privacy.d.ts +1 -0
- package/dist/privacy.js +306 -7
- package/package.json +3 -3
- package/src/index.ts +355 -108
- package/src/ingest/client.ts +13 -0
- package/src/privacy.ts +409 -7
- package/test/ingest-high-priority-fairness.test.js +76 -0
- package/test/policy-capture-attestation.test.js +234 -0
- package/test/policy-session-completion.testcontainers.test.js +271 -0
- package/test/privacy-policy-index.test.js +194 -0
- package/test/sdk-background-timeout-isolation.test.js +39 -0
- package/test/trace-batch-size.test.js +4 -0
package/src/index.ts
CHANGED
|
@@ -379,7 +379,11 @@ type PendingTraceEventRecord = TraceEventRecord & {
|
|
|
379
379
|
};
|
|
380
380
|
|
|
381
381
|
type TraceValueCaptureRef = {
|
|
382
|
-
status:
|
|
382
|
+
status:
|
|
383
|
+
| 'stored'
|
|
384
|
+
| 'truncated-for-storage'
|
|
385
|
+
| 'skipped-non-meaningful'
|
|
386
|
+
| 'failed-policy';
|
|
383
387
|
valueId?: string;
|
|
384
388
|
projectedKind?: string;
|
|
385
389
|
};
|
|
@@ -1212,22 +1216,70 @@ type RequestCaptureScopeState = {
|
|
|
1212
1216
|
traceBatchCount: number;
|
|
1213
1217
|
dbChangeCount: number;
|
|
1214
1218
|
emailEventCount: number;
|
|
1219
|
+
captureFailures: Array<{
|
|
1220
|
+
stage: string;
|
|
1221
|
+
target: string;
|
|
1222
|
+
reason: string;
|
|
1223
|
+
}>;
|
|
1224
|
+
privacyMode: 'policy' | 'fallback' | 'raw';
|
|
1225
|
+
privacyPolicyFingerprint?: string;
|
|
1226
|
+
privacyStatementCount: number;
|
|
1215
1227
|
};
|
|
1216
1228
|
|
|
1217
1229
|
function createRequestCaptureScope(
|
|
1218
1230
|
requestRid: string,
|
|
1219
1231
|
transport: RequestCaptureScopeState['transport'],
|
|
1232
|
+
cfg?: ReproMiddlewareConfig,
|
|
1220
1233
|
): RequestCaptureScopeState {
|
|
1234
|
+
const privacy = cfg ? getRuntimePrivacyState(cfg).policy ?? null : null;
|
|
1235
|
+
const privacyMode =
|
|
1236
|
+
cfg && shouldCapturePrivacyRaw(cfg)
|
|
1237
|
+
? 'raw'
|
|
1238
|
+
: privacy
|
|
1239
|
+
? 'policy'
|
|
1240
|
+
: 'fallback';
|
|
1221
1241
|
return {
|
|
1222
1242
|
requestRid,
|
|
1223
1243
|
transport,
|
|
1224
|
-
|
|
1244
|
+
// Every scope represents one captured transport request. This is an
|
|
1245
|
+
// observed expectation, not a count of successful enqueue operations.
|
|
1246
|
+
backendRequestCount: 1,
|
|
1225
1247
|
traceBatchCount: 0,
|
|
1226
1248
|
dbChangeCount: 0,
|
|
1227
1249
|
emailEventCount: 0,
|
|
1250
|
+
captureFailures: [],
|
|
1251
|
+
privacyMode,
|
|
1252
|
+
privacyPolicyFingerprint: privacy?.fingerprint,
|
|
1253
|
+
privacyStatementCount: privacy?.statements.length ?? 0,
|
|
1228
1254
|
};
|
|
1229
1255
|
}
|
|
1230
1256
|
|
|
1257
|
+
function recordRequestCaptureFailure(
|
|
1258
|
+
scope: RequestCaptureScopeState | null | undefined,
|
|
1259
|
+
stage: string,
|
|
1260
|
+
target: string,
|
|
1261
|
+
reason: string,
|
|
1262
|
+
): void {
|
|
1263
|
+
if (!scope) return;
|
|
1264
|
+
const normalized = {
|
|
1265
|
+
stage: String(stage || 'capture').slice(0, 80),
|
|
1266
|
+
target: String(target || 'unknown').slice(0, 120),
|
|
1267
|
+
reason: String(reason || 'capture_failed').slice(0, 120),
|
|
1268
|
+
};
|
|
1269
|
+
if (
|
|
1270
|
+
scope.captureFailures.some((failure) =>
|
|
1271
|
+
failure.stage === normalized.stage &&
|
|
1272
|
+
failure.target === normalized.target &&
|
|
1273
|
+
failure.reason === normalized.reason,
|
|
1274
|
+
)
|
|
1275
|
+
) {
|
|
1276
|
+
return;
|
|
1277
|
+
}
|
|
1278
|
+
if (scope.captureFailures.length < 25) {
|
|
1279
|
+
scope.captureFailures.push(normalized);
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1282
|
+
|
|
1231
1283
|
function buildRequestCaptureManifestPayload(
|
|
1232
1284
|
scope: RequestCaptureScopeState,
|
|
1233
1285
|
traceBatchTotal: number,
|
|
@@ -1255,6 +1307,20 @@ function buildRequestCaptureManifestPayload(
|
|
|
1255
1307
|
to: expectedTraceBatches - 1,
|
|
1256
1308
|
}
|
|
1257
1309
|
: undefined,
|
|
1310
|
+
privacy: {
|
|
1311
|
+
mode: scope.privacyMode,
|
|
1312
|
+
status:
|
|
1313
|
+
scope.captureFailures.length > 0
|
|
1314
|
+
? 'failed'
|
|
1315
|
+
: scope.privacyMode === 'raw'
|
|
1316
|
+
? 'bypassed'
|
|
1317
|
+
: 'applied',
|
|
1318
|
+
policyFingerprint: scope.privacyPolicyFingerprint,
|
|
1319
|
+
statementCount: scope.privacyStatementCount,
|
|
1320
|
+
},
|
|
1321
|
+
captureFailures: scope.captureFailures.length
|
|
1322
|
+
? scope.captureFailures.map((failure) => ({ ...failure }))
|
|
1323
|
+
: undefined,
|
|
1258
1324
|
closedAt,
|
|
1259
1325
|
};
|
|
1260
1326
|
}
|
|
@@ -1439,12 +1505,6 @@ const SDK_BACKGROUND_MAX_DEFER_MS = (() => {
|
|
|
1439
1505
|
return Number.POSITIVE_INFINITY;
|
|
1440
1506
|
})();
|
|
1441
1507
|
|
|
1442
|
-
const SDK_BACKGROUND_WORK_TIMEOUT_MS = (() => {
|
|
1443
|
-
const env = Number(process.env.REPRO_SDK_BACKGROUND_WORK_TIMEOUT_MS);
|
|
1444
|
-
if (Number.isFinite(env) && env >= 0) return Math.trunc(env);
|
|
1445
|
-
return 20000;
|
|
1446
|
-
})();
|
|
1447
|
-
|
|
1448
1508
|
const TRACE_MATERIALIZE_OFFTHREAD_ENABLED = (() => {
|
|
1449
1509
|
const env = String(process.env.REPRO_TRACE_MATERIALIZE_OFFTHREAD || '').trim().toLowerCase();
|
|
1450
1510
|
if (!env) return true;
|
|
@@ -1774,24 +1834,9 @@ function scheduleSdkBackgroundDrain(delayMs = 0): void {
|
|
|
1774
1834
|
}
|
|
1775
1835
|
|
|
1776
1836
|
async function runSdkBackgroundWork(work: () => Promise<void> | void): Promise<void> {
|
|
1777
|
-
|
|
1778
|
-
await work();
|
|
1779
|
-
return;
|
|
1780
|
-
}
|
|
1781
|
-
|
|
1782
|
-
let timeout: NodeJS.Timeout | null = null;
|
|
1783
|
-
const workPromise = Promise.resolve()
|
|
1837
|
+
await Promise.resolve()
|
|
1784
1838
|
.then(work)
|
|
1785
1839
|
.catch(() => undefined);
|
|
1786
|
-
const timeoutPromise = new Promise<void>((resolve) => {
|
|
1787
|
-
timeout = setTimeout(resolve, SDK_BACKGROUND_WORK_TIMEOUT_MS);
|
|
1788
|
-
try { (timeout as any).unref?.(); } catch {}
|
|
1789
|
-
});
|
|
1790
|
-
|
|
1791
|
-
await Promise.race([workPromise, timeoutPromise]);
|
|
1792
|
-
if (timeout) {
|
|
1793
|
-
try { clearTimeout(timeout); } catch {}
|
|
1794
|
-
}
|
|
1795
1840
|
}
|
|
1796
1841
|
|
|
1797
1842
|
async function drainQueuedIngestBeforeBackgroundWork(): Promise<void> {
|
|
@@ -2783,7 +2828,7 @@ const TRACE_MAX_EVENTS_PER_REQUEST = (() => {
|
|
|
2783
2828
|
const TRACE_MAX_BATCHES_PER_REQUEST = (() => {
|
|
2784
2829
|
const env = Number(process.env.REPRO_TRACE_MAX_BATCHES_PER_REQUEST);
|
|
2785
2830
|
if (Number.isFinite(env) && env > 0) return Math.trunc(env);
|
|
2786
|
-
return
|
|
2831
|
+
return Math.ceil(TRACE_MAX_EVENTS_PER_REQUEST / TRACE_BATCH_SIZE);
|
|
2787
2832
|
})();
|
|
2788
2833
|
const TRACE_FLUSH_DELAY_MS = 20;
|
|
2789
2834
|
// Choose how to order trace events in payloads.
|
|
@@ -3357,6 +3402,7 @@ async function materializePendingTraceEvents(
|
|
|
3357
3402
|
maskReq: MaskRequestContext;
|
|
3358
3403
|
masking: NormalizedMaskingConfig | null;
|
|
3359
3404
|
resolvePrivacy: () => NormalizedRuntimePrivacyPolicy | null;
|
|
3405
|
+
captureScope?: RequestCaptureScopeState | null;
|
|
3360
3406
|
},
|
|
3361
3407
|
): Promise<TraceEventRecord[]> {
|
|
3362
3408
|
for (const evt of events) {
|
|
@@ -3403,7 +3449,7 @@ async function materializePendingTraceEvents(
|
|
|
3403
3449
|
previewValue: evt.args,
|
|
3404
3450
|
capture: captureContext,
|
|
3405
3451
|
metadata: traceValueMetadata,
|
|
3406
|
-
});
|
|
3452
|
+
}, params.captureScope);
|
|
3407
3453
|
if (argsValueCapture?.entry) {
|
|
3408
3454
|
attachTraceValueEntry(evt, argsValueCapture.entry);
|
|
3409
3455
|
}
|
|
@@ -3432,7 +3478,7 @@ async function materializePendingTraceEvents(
|
|
|
3432
3478
|
previewValue: evt.returnValue,
|
|
3433
3479
|
capture: captureContext,
|
|
3434
3480
|
metadata: traceValueMetadata,
|
|
3435
|
-
});
|
|
3481
|
+
}, params.captureScope);
|
|
3436
3482
|
if (returnValueCapture?.entry) {
|
|
3437
3483
|
attachTraceValueEntry(evt, returnValueCapture.entry);
|
|
3438
3484
|
}
|
|
@@ -3461,7 +3507,7 @@ async function materializePendingTraceEvents(
|
|
|
3461
3507
|
previewValue: evt.error,
|
|
3462
3508
|
capture: captureContext,
|
|
3463
3509
|
metadata: traceValueMetadata,
|
|
3464
|
-
});
|
|
3510
|
+
}, params.captureScope);
|
|
3465
3511
|
if (errorValueCapture?.entry) {
|
|
3466
3512
|
attachTraceValueEntry(evt, errorValueCapture.entry);
|
|
3467
3513
|
}
|
|
@@ -3479,7 +3525,20 @@ function stripPendingTraceValues(
|
|
|
3479
3525
|
reason: string,
|
|
3480
3526
|
): TraceEventRecord[] {
|
|
3481
3527
|
for (const evt of events) {
|
|
3482
|
-
|
|
3528
|
+
const pending = evt.__reproPending;
|
|
3529
|
+
if (!pending) continue;
|
|
3530
|
+
if (pending.argsRaw !== undefined) {
|
|
3531
|
+
evt.args = makeOmittedValue(reason);
|
|
3532
|
+
evt.argsValueCapture = { status: 'failed-policy' };
|
|
3533
|
+
}
|
|
3534
|
+
if (pending.returnValueRaw !== undefined) {
|
|
3535
|
+
evt.returnValue = makeOmittedValue(reason);
|
|
3536
|
+
evt.returnValueCapture = { status: 'failed-policy' };
|
|
3537
|
+
}
|
|
3538
|
+
if (pending.errorRaw !== undefined) {
|
|
3539
|
+
evt.error = makeOmittedValue(reason);
|
|
3540
|
+
evt.errorValueCapture = { status: 'failed-policy' };
|
|
3541
|
+
}
|
|
3483
3542
|
delete evt.__reproPending;
|
|
3484
3543
|
}
|
|
3485
3544
|
return events;
|
|
@@ -3496,6 +3555,7 @@ async function materializePendingTraceEventsAsync(
|
|
|
3496
3555
|
maskReq: MaskRequestContext;
|
|
3497
3556
|
masking: NormalizedMaskingConfig | null;
|
|
3498
3557
|
resolvePrivacy: () => NormalizedRuntimePrivacyPolicy | null;
|
|
3558
|
+
captureScope?: RequestCaptureScopeState | null;
|
|
3499
3559
|
},
|
|
3500
3560
|
): Promise<TraceEventRecord[]> {
|
|
3501
3561
|
if (!events.some((evt) => evt.__reproPending)) {
|
|
@@ -3510,6 +3570,12 @@ async function materializePendingTraceEventsAsync(
|
|
|
3510
3570
|
resolvePrivacy: () => privacy,
|
|
3511
3571
|
});
|
|
3512
3572
|
} catch {
|
|
3573
|
+
recordRequestCaptureFailure(
|
|
3574
|
+
params.captureScope ?? getCtx().captureScope,
|
|
3575
|
+
'privacy.trace',
|
|
3576
|
+
'trace.values',
|
|
3577
|
+
'main_thread_materialization_failed',
|
|
3578
|
+
);
|
|
3513
3579
|
return stripPendingTraceValues(events, 'main_thread_failed');
|
|
3514
3580
|
}
|
|
3515
3581
|
}
|
|
@@ -3528,16 +3594,24 @@ async function materializePendingTraceEventsAsync(
|
|
|
3528
3594
|
fullValueCaptureEnabled: __FULL_VALUE_CAPTURE_ENABLED,
|
|
3529
3595
|
});
|
|
3530
3596
|
} catch (err) {
|
|
3531
|
-
if (isTraceMaterializerTimeoutError(err)) {
|
|
3532
|
-
return stripPendingTraceValues(events, 'worker_timeout');
|
|
3533
|
-
}
|
|
3534
3597
|
try {
|
|
3535
3598
|
return await materializePendingTraceEvents(events, {
|
|
3536
3599
|
...params,
|
|
3537
3600
|
resolvePrivacy: () => privacy,
|
|
3538
3601
|
});
|
|
3539
3602
|
} catch {
|
|
3540
|
-
|
|
3603
|
+
recordRequestCaptureFailure(
|
|
3604
|
+
params.captureScope ?? getCtx().captureScope,
|
|
3605
|
+
'privacy.trace',
|
|
3606
|
+
'trace.values',
|
|
3607
|
+
isTraceMaterializerTimeoutError(err)
|
|
3608
|
+
? 'worker_timeout_fallback_failed'
|
|
3609
|
+
: 'worker_and_fallback_failed',
|
|
3610
|
+
);
|
|
3611
|
+
return stripPendingTraceValues(
|
|
3612
|
+
events,
|
|
3613
|
+
isTraceMaterializerTimeoutError(err) ? 'worker_timeout_fallback_failed' : 'worker_failed',
|
|
3614
|
+
);
|
|
3541
3615
|
}
|
|
3542
3616
|
}
|
|
3543
3617
|
}
|
|
@@ -4137,6 +4211,7 @@ function materializeInlinePrivacyValue(
|
|
|
4137
4211
|
masking: NormalizedMaskingConfig | null,
|
|
4138
4212
|
privacy: NormalizedRuntimePrivacyPolicy | null,
|
|
4139
4213
|
db?: RuntimePrivacyDbContext | null,
|
|
4214
|
+
captureScope?: RequestCaptureScopeState | null,
|
|
4140
4215
|
): InlinePrivacyMaterializationResult {
|
|
4141
4216
|
if (value === undefined) {
|
|
4142
4217
|
return { value };
|
|
@@ -4149,6 +4224,12 @@ function materializeInlinePrivacyValue(
|
|
|
4149
4224
|
const valueAfterPrivacy = applyPrivacyThenMask(target, value, cfg, req, trace, masking, privacy, db);
|
|
4150
4225
|
return { value: valueAfterPrivacy };
|
|
4151
4226
|
} catch {
|
|
4227
|
+
recordRequestCaptureFailure(
|
|
4228
|
+
captureScope ?? getCtx().captureScope,
|
|
4229
|
+
'privacy.inline',
|
|
4230
|
+
target,
|
|
4231
|
+
'privacy_transform_failed',
|
|
4232
|
+
);
|
|
4152
4233
|
return {
|
|
4153
4234
|
value: undefined,
|
|
4154
4235
|
skipped: {
|
|
@@ -4169,6 +4250,7 @@ async function materializeInlinePrivacyValueAsync(
|
|
|
4169
4250
|
masking: NormalizedMaskingConfig | null,
|
|
4170
4251
|
privacy: NormalizedRuntimePrivacyPolicy | null,
|
|
4171
4252
|
db?: RuntimePrivacyDbContext | null,
|
|
4253
|
+
captureScope?: RequestCaptureScopeState | null,
|
|
4172
4254
|
): Promise<InlinePrivacyMaterializationResult> {
|
|
4173
4255
|
if (value === undefined) {
|
|
4174
4256
|
return { value };
|
|
@@ -4181,6 +4263,12 @@ async function materializeInlinePrivacyValueAsync(
|
|
|
4181
4263
|
const valueAfterPrivacy = await applyPrivacyThenMaskAsync(target, value, cfg, req, trace, masking, privacy, db);
|
|
4182
4264
|
return { value: valueAfterPrivacy };
|
|
4183
4265
|
} catch {
|
|
4266
|
+
recordRequestCaptureFailure(
|
|
4267
|
+
captureScope ?? getCtx().captureScope,
|
|
4268
|
+
'privacy.inline',
|
|
4269
|
+
target,
|
|
4270
|
+
'privacy_transform_failed',
|
|
4271
|
+
);
|
|
4184
4272
|
return {
|
|
4185
4273
|
value: undefined,
|
|
4186
4274
|
skipped: {
|
|
@@ -5185,6 +5273,13 @@ function chunkTraceEventsForTransport(
|
|
|
5185
5273
|
if (sizedBatches.length >= TRACE_MAX_BATCHES_PER_REQUEST) {
|
|
5186
5274
|
break;
|
|
5187
5275
|
}
|
|
5276
|
+
if (current.length >= TRACE_BATCH_SIZE) {
|
|
5277
|
+
sizedBatches.push(current);
|
|
5278
|
+
current = [];
|
|
5279
|
+
if (sizedBatches.length >= TRACE_MAX_BATCHES_PER_REQUEST) {
|
|
5280
|
+
break;
|
|
5281
|
+
}
|
|
5282
|
+
}
|
|
5188
5283
|
const candidate = current.concat(event);
|
|
5189
5284
|
const batchIndex = sizedBatches.length;
|
|
5190
5285
|
const estimatedBytes = estimateTraceBatchSerializedBytes(
|
|
@@ -5416,8 +5511,20 @@ async function maybeCaptureRequestValueAsync(
|
|
|
5416
5511
|
capture: FullValueCaptureContext;
|
|
5417
5512
|
},
|
|
5418
5513
|
sink: TraceValueBatchEntry[],
|
|
5514
|
+
captureScope?: RequestCaptureScopeState | null,
|
|
5419
5515
|
): Promise<TraceValueCaptureRef | undefined> {
|
|
5420
|
-
|
|
5516
|
+
let result: Awaited<ReturnType<typeof createCapturedValueEntryAsync>>;
|
|
5517
|
+
try {
|
|
5518
|
+
result = await createCapturedValueEntryAsync(params);
|
|
5519
|
+
} catch {
|
|
5520
|
+
recordRequestCaptureFailure(
|
|
5521
|
+
captureScope ?? getCtx().captureScope,
|
|
5522
|
+
'privacy.full_value',
|
|
5523
|
+
params.target,
|
|
5524
|
+
'privacy_transform_failed',
|
|
5525
|
+
);
|
|
5526
|
+
return { status: 'failed-policy' };
|
|
5527
|
+
}
|
|
5421
5528
|
if (!result) return undefined;
|
|
5422
5529
|
if (result.entry) {
|
|
5423
5530
|
sink.push(result.entry);
|
|
@@ -5445,8 +5552,19 @@ async function maybeCaptureTraceValueAsync(
|
|
|
5445
5552
|
capture: FullValueCaptureContext;
|
|
5446
5553
|
metadata?: Partial<TraceValueBatchEntry>;
|
|
5447
5554
|
},
|
|
5555
|
+
captureScope?: RequestCaptureScopeState | null,
|
|
5448
5556
|
): Promise<{ captureRef: TraceValueCaptureRef; entry?: TraceValueBatchEntry } | undefined> {
|
|
5449
|
-
|
|
5557
|
+
try {
|
|
5558
|
+
return await createCapturedValueEntryAsync(params);
|
|
5559
|
+
} catch {
|
|
5560
|
+
recordRequestCaptureFailure(
|
|
5561
|
+
captureScope ?? getCtx().captureScope,
|
|
5562
|
+
'privacy.full_value',
|
|
5563
|
+
params.target,
|
|
5564
|
+
'privacy_transform_failed',
|
|
5565
|
+
);
|
|
5566
|
+
return { captureRef: { status: 'failed-policy' } };
|
|
5567
|
+
}
|
|
5450
5568
|
}
|
|
5451
5569
|
|
|
5452
5570
|
function maybeCaptureDbValue(
|
|
@@ -5474,8 +5592,20 @@ async function maybeCaptureDbValueAsync(
|
|
|
5474
5592
|
capture: FullValueCaptureContext;
|
|
5475
5593
|
},
|
|
5476
5594
|
sink: TraceValueBatchEntry[],
|
|
5595
|
+
captureScope?: RequestCaptureScopeState | null,
|
|
5477
5596
|
): Promise<TraceValueCaptureRef | undefined> {
|
|
5478
|
-
|
|
5597
|
+
let result: Awaited<ReturnType<typeof createCapturedValueEntryAsync>>;
|
|
5598
|
+
try {
|
|
5599
|
+
result = await createCapturedValueEntryAsync(params);
|
|
5600
|
+
} catch {
|
|
5601
|
+
recordRequestCaptureFailure(
|
|
5602
|
+
captureScope ?? getCtx().captureScope,
|
|
5603
|
+
'privacy.full_value',
|
|
5604
|
+
params.target,
|
|
5605
|
+
'privacy_transform_failed',
|
|
5606
|
+
);
|
|
5607
|
+
return { status: 'failed-policy' };
|
|
5608
|
+
}
|
|
5479
5609
|
if (!result) return undefined;
|
|
5480
5610
|
if (result.entry) {
|
|
5481
5611
|
sink.push(result.entry);
|
|
@@ -5511,15 +5641,27 @@ async function maybeCaptureDbValueFromCandidatesAsync(
|
|
|
5511
5641
|
capture: FullValueCaptureContext;
|
|
5512
5642
|
},
|
|
5513
5643
|
sink: TraceValueBatchEntry[],
|
|
5644
|
+
captureScope?: RequestCaptureScopeState | null,
|
|
5514
5645
|
): Promise<TraceValueCaptureRef | undefined> {
|
|
5515
5646
|
let skippedRef: TraceValueCaptureRef | undefined;
|
|
5516
5647
|
for (const rawValue of params.rawValues) {
|
|
5517
|
-
|
|
5518
|
-
|
|
5519
|
-
|
|
5520
|
-
|
|
5521
|
-
|
|
5522
|
-
|
|
5648
|
+
let result: Awaited<ReturnType<typeof createCapturedValueEntryAsync>>;
|
|
5649
|
+
try {
|
|
5650
|
+
result = await createCapturedValueEntryAsync({
|
|
5651
|
+
target: params.target,
|
|
5652
|
+
rawValue,
|
|
5653
|
+
previewValue: params.previewValue,
|
|
5654
|
+
capture: params.capture,
|
|
5655
|
+
});
|
|
5656
|
+
} catch {
|
|
5657
|
+
recordRequestCaptureFailure(
|
|
5658
|
+
captureScope ?? getCtx().captureScope,
|
|
5659
|
+
'privacy.full_value',
|
|
5660
|
+
params.target,
|
|
5661
|
+
'privacy_transform_failed',
|
|
5662
|
+
);
|
|
5663
|
+
return { status: 'failed-policy' };
|
|
5664
|
+
}
|
|
5523
5665
|
if (!result) continue;
|
|
5524
5666
|
if (result.entry) {
|
|
5525
5667
|
sink.push(result.entry);
|
|
@@ -5827,7 +5969,7 @@ export function reproMiddleware(cfg: ReproMiddlewareConfig) {
|
|
|
5827
5969
|
|
|
5828
5970
|
const clockSkewMs = headerTs !== null ? headerTs - requestStartRaw : 0;
|
|
5829
5971
|
const rid = nextRequestId(requestEpochMs);
|
|
5830
|
-
const captureScope = createRequestCaptureScope(rid, 'http');
|
|
5972
|
+
const captureScope = createRequestCaptureScope(rid, 'http', captureCfg);
|
|
5831
5973
|
emitRequestCaptureStart(captureCfg, sid, aid, captureScope, requestEpochMs);
|
|
5832
5974
|
const t0 = requestStartRaw;
|
|
5833
5975
|
const url = (req as any).originalUrl || req.url || '/';
|
|
@@ -6029,9 +6171,11 @@ export function reproMiddleware(cfg: ReproMiddlewareConfig) {
|
|
|
6029
6171
|
endpointTraceCtx,
|
|
6030
6172
|
masking,
|
|
6031
6173
|
activePrivacy,
|
|
6174
|
+
undefined,
|
|
6175
|
+
captureScope,
|
|
6032
6176
|
);
|
|
6033
6177
|
const requestBody = requestBodyMaterialization.value;
|
|
6034
|
-
const
|
|
6178
|
+
const requestParamsMaterialization = await materializeInlinePrivacyValueAsync(
|
|
6035
6179
|
'request.params',
|
|
6036
6180
|
sanitizeRequestSnapshot((req as any).params),
|
|
6037
6181
|
captureCfg,
|
|
@@ -6039,8 +6183,11 @@ export function reproMiddleware(cfg: ReproMiddlewareConfig) {
|
|
|
6039
6183
|
endpointTraceCtx,
|
|
6040
6184
|
masking,
|
|
6041
6185
|
activePrivacy,
|
|
6186
|
+
undefined,
|
|
6187
|
+
captureScope,
|
|
6042
6188
|
);
|
|
6043
|
-
const
|
|
6189
|
+
const requestParams = requestParamsMaterialization.value;
|
|
6190
|
+
const requestQueryMaterialization = await materializeInlinePrivacyValueAsync(
|
|
6044
6191
|
'request.query',
|
|
6045
6192
|
sanitizeRequestSnapshot((req as any).query),
|
|
6046
6193
|
captureCfg,
|
|
@@ -6048,8 +6195,11 @@ export function reproMiddleware(cfg: ReproMiddlewareConfig) {
|
|
|
6048
6195
|
endpointTraceCtx,
|
|
6049
6196
|
masking,
|
|
6050
6197
|
activePrivacy,
|
|
6198
|
+
undefined,
|
|
6199
|
+
captureScope,
|
|
6051
6200
|
);
|
|
6052
|
-
const
|
|
6201
|
+
const requestQuery = requestQueryMaterialization.value;
|
|
6202
|
+
const requestHeadersMaterialization = await materializeInlinePrivacyValueAsync(
|
|
6053
6203
|
'request.headers',
|
|
6054
6204
|
requestHeaders,
|
|
6055
6205
|
captureCfg,
|
|
@@ -6057,7 +6207,10 @@ export function reproMiddleware(cfg: ReproMiddlewareConfig) {
|
|
|
6057
6207
|
endpointTraceCtx,
|
|
6058
6208
|
masking,
|
|
6059
6209
|
activePrivacy,
|
|
6210
|
+
undefined,
|
|
6211
|
+
captureScope,
|
|
6060
6212
|
);
|
|
6213
|
+
const maskedHeaders = requestHeadersMaterialization.value;
|
|
6061
6214
|
const responseBodyMaterialization = capturedBody === undefined
|
|
6062
6215
|
? { value: undefined }
|
|
6063
6216
|
: limitRawInlinePrivacyValue('response.body', capturedBody)
|
|
@@ -6069,6 +6222,8 @@ export function reproMiddleware(cfg: ReproMiddlewareConfig) {
|
|
|
6069
6222
|
endpointTraceCtx,
|
|
6070
6223
|
masking,
|
|
6071
6224
|
activePrivacy,
|
|
6225
|
+
undefined,
|
|
6226
|
+
captureScope,
|
|
6072
6227
|
);
|
|
6073
6228
|
const responseBody = responseBodyMaterialization.value;
|
|
6074
6229
|
const requestValueEntries: TraceValueBatchEntry[] = [];
|
|
@@ -6086,7 +6241,7 @@ export function reproMiddleware(cfg: ReproMiddlewareConfig) {
|
|
|
6086
6241
|
masking,
|
|
6087
6242
|
privacy: activePrivacy,
|
|
6088
6243
|
},
|
|
6089
|
-
}, requestValueEntries);
|
|
6244
|
+
}, requestValueEntries, captureScope);
|
|
6090
6245
|
const paramsValueCapture = await maybeCaptureRequestValueAsync({
|
|
6091
6246
|
target: 'request.params',
|
|
6092
6247
|
rawValue: (req as any).params,
|
|
@@ -6099,7 +6254,7 @@ export function reproMiddleware(cfg: ReproMiddlewareConfig) {
|
|
|
6099
6254
|
masking,
|
|
6100
6255
|
privacy: activePrivacy,
|
|
6101
6256
|
},
|
|
6102
|
-
}, requestValueEntries);
|
|
6257
|
+
}, requestValueEntries, captureScope);
|
|
6103
6258
|
const queryValueCapture = await maybeCaptureRequestValueAsync({
|
|
6104
6259
|
target: 'request.query',
|
|
6105
6260
|
rawValue: (req as any).query,
|
|
@@ -6112,7 +6267,7 @@ export function reproMiddleware(cfg: ReproMiddlewareConfig) {
|
|
|
6112
6267
|
masking,
|
|
6113
6268
|
privacy: activePrivacy,
|
|
6114
6269
|
},
|
|
6115
|
-
}, requestValueEntries);
|
|
6270
|
+
}, requestValueEntries, captureScope);
|
|
6116
6271
|
const headersValueCapture = await maybeCaptureRequestValueAsync({
|
|
6117
6272
|
target: 'request.headers',
|
|
6118
6273
|
rawValue: req.headers,
|
|
@@ -6125,7 +6280,7 @@ export function reproMiddleware(cfg: ReproMiddlewareConfig) {
|
|
|
6125
6280
|
masking,
|
|
6126
6281
|
privacy: activePrivacy,
|
|
6127
6282
|
},
|
|
6128
|
-
}, requestValueEntries);
|
|
6283
|
+
}, requestValueEntries, captureScope);
|
|
6129
6284
|
const respBodyValueCapture = capturedBody === undefined
|
|
6130
6285
|
? undefined
|
|
6131
6286
|
: await maybeCaptureRequestValueAsync({
|
|
@@ -6140,7 +6295,7 @@ export function reproMiddleware(cfg: ReproMiddlewareConfig) {
|
|
|
6140
6295
|
masking,
|
|
6141
6296
|
privacy: activePrivacy,
|
|
6142
6297
|
},
|
|
6143
|
-
}, requestValueEntries);
|
|
6298
|
+
}, requestValueEntries, captureScope);
|
|
6144
6299
|
|
|
6145
6300
|
const responseDurationMs =
|
|
6146
6301
|
finishedAt !== null && Number.isFinite(finishedAt)
|
|
@@ -6201,9 +6356,43 @@ export function reproMiddleware(cfg: ReproMiddlewareConfig) {
|
|
|
6201
6356
|
t: requestEpochMs,
|
|
6202
6357
|
}]
|
|
6203
6358
|
});
|
|
6204
|
-
captureScope.backendRequestCount += 1;
|
|
6205
6359
|
} catch {
|
|
6206
|
-
|
|
6360
|
+
recordRequestCaptureFailure(
|
|
6361
|
+
captureScope,
|
|
6362
|
+
'request.capture',
|
|
6363
|
+
'backend_request',
|
|
6364
|
+
'request_materialization_failed',
|
|
6365
|
+
);
|
|
6366
|
+
// Preserve non-sensitive request metadata so the manifest cannot
|
|
6367
|
+
// silently turn a failed policy capture into a zero-request scope.
|
|
6368
|
+
post(captureCfg, sid, {
|
|
6369
|
+
entries: [{
|
|
6370
|
+
actionId: aid,
|
|
6371
|
+
request: {
|
|
6372
|
+
rid,
|
|
6373
|
+
method: req.method,
|
|
6374
|
+
url,
|
|
6375
|
+
path,
|
|
6376
|
+
status: res.statusCode,
|
|
6377
|
+
durMs:
|
|
6378
|
+
finishedAt !== null && Number.isFinite(finishedAt)
|
|
6379
|
+
? Math.max(0, finishedAt - t0)
|
|
6380
|
+
: Date.now() - t0,
|
|
6381
|
+
key,
|
|
6382
|
+
bodyMaterialization: {
|
|
6383
|
+
status: 'skipped',
|
|
6384
|
+
reason: 'request_materialization_failed',
|
|
6385
|
+
target: 'request.body',
|
|
6386
|
+
},
|
|
6387
|
+
respBodyMaterialization: {
|
|
6388
|
+
status: 'skipped',
|
|
6389
|
+
reason: 'request_materialization_failed',
|
|
6390
|
+
target: 'response.body',
|
|
6391
|
+
},
|
|
6392
|
+
},
|
|
6393
|
+
t: requestEpochMs,
|
|
6394
|
+
}],
|
|
6395
|
+
});
|
|
6207
6396
|
}
|
|
6208
6397
|
};
|
|
6209
6398
|
|
|
@@ -6326,6 +6515,7 @@ export function reproMiddleware(cfg: ReproMiddlewareConfig) {
|
|
|
6326
6515
|
maskReq,
|
|
6327
6516
|
masking,
|
|
6328
6517
|
resolvePrivacy,
|
|
6518
|
+
captureScope,
|
|
6329
6519
|
});
|
|
6330
6520
|
const baseEvents = balanceTraceEvents(materializedEvents.slice());
|
|
6331
6521
|
const orderedEvents = TRACE_ORDER_MODE === 'tree'
|
|
@@ -6344,12 +6534,21 @@ export function reproMiddleware(cfg: ReproMiddlewareConfig) {
|
|
|
6344
6534
|
}
|
|
6345
6535
|
|
|
6346
6536
|
} catch {
|
|
6537
|
+
recordRequestCaptureFailure(
|
|
6538
|
+
captureScope,
|
|
6539
|
+
'trace.capture',
|
|
6540
|
+
'trace.batches',
|
|
6541
|
+
'trace_capture_failed',
|
|
6542
|
+
);
|
|
6347
6543
|
captureScope.traceBatchCount = 0;
|
|
6348
6544
|
traceBatches = [];
|
|
6349
|
-
} finally {
|
|
6350
|
-
emitRequestCaptureManifest(traceBatches.length);
|
|
6351
6545
|
}
|
|
6352
6546
|
|
|
6547
|
+
// Finalize policy/materialization status before publishing the
|
|
6548
|
+
// high-priority manifest. The manifest must lead its evidence
|
|
6549
|
+
// on the wire so a large trace queue cannot starve completion.
|
|
6550
|
+
emitRequestCaptureManifest(traceBatches.length);
|
|
6551
|
+
|
|
6353
6552
|
try {
|
|
6354
6553
|
for (let i = 0; i < traceBatches.length; i++) {
|
|
6355
6554
|
const batch = traceBatches[i];
|
|
@@ -6370,7 +6569,12 @@ export function reproMiddleware(cfg: ReproMiddlewareConfig) {
|
|
|
6370
6569
|
});
|
|
6371
6570
|
}
|
|
6372
6571
|
} catch {
|
|
6373
|
-
|
|
6572
|
+
recordRequestCaptureFailure(
|
|
6573
|
+
captureScope,
|
|
6574
|
+
'trace.enqueue',
|
|
6575
|
+
'trace.batches',
|
|
6576
|
+
'trace_enqueue_failed',
|
|
6577
|
+
);
|
|
6374
6578
|
}
|
|
6375
6579
|
};
|
|
6376
6580
|
}
|
|
@@ -6971,6 +7175,11 @@ function emitDbQuery(cfg: any, sid?: string, aid?: string, payload?: any) {
|
|
|
6971
7175
|
const ctx = getCtx() as Ctx;
|
|
6972
7176
|
const spanContext = payload?.spanContext ?? captureSpanContextFromTracer();
|
|
6973
7177
|
if (!shouldCaptureDbSpan(spanContext)) return;
|
|
7178
|
+
if (sid && ctx.captureScope) {
|
|
7179
|
+
// Count the observed database operation before asynchronous privacy
|
|
7180
|
+
// materialization. A later failure must remain visible to completeness.
|
|
7181
|
+
ctx.captureScope.dbChangeCount += 1;
|
|
7182
|
+
}
|
|
6974
7183
|
const runCtx: Ctx = {
|
|
6975
7184
|
sid: ctx.sid,
|
|
6976
7185
|
aid: ctx.aid,
|
|
@@ -6982,7 +7191,14 @@ function emitDbQuery(cfg: any, sid?: string, aid?: string, payload?: any) {
|
|
|
6982
7191
|
};
|
|
6983
7192
|
scheduleSdkBackgroundWork(async () => {
|
|
6984
7193
|
await als.run(runCtx, async () => {
|
|
6985
|
-
await emitDbQueryAsync(cfg, sid, aid, payload).catch(() =>
|
|
7194
|
+
await emitDbQueryAsync(cfg, sid, aid, payload).catch(() => {
|
|
7195
|
+
recordRequestCaptureFailure(
|
|
7196
|
+
runCtx.captureScope,
|
|
7197
|
+
'db.capture',
|
|
7198
|
+
'db.change',
|
|
7199
|
+
'db_capture_failed',
|
|
7200
|
+
);
|
|
7201
|
+
});
|
|
6986
7202
|
});
|
|
6987
7203
|
}, { priority: 'high' });
|
|
6988
7204
|
}
|
|
@@ -7097,8 +7313,13 @@ async function emitDbQueryAsync(cfg: any, sid?: string, aid?: string, payload?:
|
|
|
7097
7313
|
t: payload.t,
|
|
7098
7314
|
}]
|
|
7099
7315
|
});
|
|
7100
|
-
if (enqueued
|
|
7101
|
-
|
|
7316
|
+
if (!enqueued) {
|
|
7317
|
+
recordRequestCaptureFailure(
|
|
7318
|
+
ctx.captureScope,
|
|
7319
|
+
'db.enqueue',
|
|
7320
|
+
'db.change',
|
|
7321
|
+
'db_enqueue_failed',
|
|
7322
|
+
);
|
|
7102
7323
|
}
|
|
7103
7324
|
}
|
|
7104
7325
|
|
|
@@ -7534,6 +7755,7 @@ async function materializeKafkaRequestBody(
|
|
|
7534
7755
|
cfg: ReproMiddlewareConfig,
|
|
7535
7756
|
maskReq: MaskRequestContext,
|
|
7536
7757
|
body: Record<string, any>,
|
|
7758
|
+
captureScope?: RequestCaptureScopeState | null,
|
|
7537
7759
|
): Promise<InlinePrivacyMaterializationResult> {
|
|
7538
7760
|
return materializeInlinePrivacyValueAsync(
|
|
7539
7761
|
'request.body',
|
|
@@ -7543,6 +7765,8 @@ async function materializeKafkaRequestBody(
|
|
|
7543
7765
|
null,
|
|
7544
7766
|
normalizeMaskingConfig(cfg.masking),
|
|
7545
7767
|
getRuntimePrivacyState(cfg).policy ?? null,
|
|
7768
|
+
undefined,
|
|
7769
|
+
captureScope,
|
|
7546
7770
|
);
|
|
7547
7771
|
}
|
|
7548
7772
|
|
|
@@ -7882,22 +8106,31 @@ function scheduleKafkaTraceFlush(
|
|
|
7882
8106
|
const evt = buildPendingKafkaTraceEvent(rawTraceEvent);
|
|
7883
8107
|
if (evt) pendingEvents.push(evt);
|
|
7884
8108
|
}
|
|
7885
|
-
|
|
7886
|
-
|
|
7887
|
-
|
|
7888
|
-
|
|
7889
|
-
|
|
7890
|
-
|
|
7891
|
-
|
|
7892
|
-
|
|
7893
|
-
|
|
7894
|
-
|
|
8109
|
+
let entries: LegacyEntry[] = [];
|
|
8110
|
+
try {
|
|
8111
|
+
if (pendingEvents.length) {
|
|
8112
|
+
const masking = normalizeMaskingConfig(cfg.masking);
|
|
8113
|
+
const preparedEvents = preparePendingTraceEventsForFlush(pendingEvents);
|
|
8114
|
+
const materializedEvents = await materializePendingTraceEventsAsync(preparedEvents, {
|
|
8115
|
+
cfg,
|
|
8116
|
+
maskReq,
|
|
8117
|
+
masking,
|
|
8118
|
+
resolvePrivacy: () => getRuntimePrivacyState(cfg).policy ?? null,
|
|
8119
|
+
captureScope,
|
|
8120
|
+
});
|
|
8121
|
+
entries = buildKafkaTraceEntries(actionId, requestRid, materializedEvents);
|
|
8122
|
+
}
|
|
8123
|
+
} catch {
|
|
8124
|
+
recordRequestCaptureFailure(
|
|
8125
|
+
captureScope,
|
|
8126
|
+
'trace.capture',
|
|
8127
|
+
'trace.batches',
|
|
8128
|
+
'trace_capture_failed',
|
|
8129
|
+
);
|
|
8130
|
+
}
|
|
7895
8131
|
if (captureScope) {
|
|
7896
8132
|
captureScope.traceBatchCount = entries.length;
|
|
7897
8133
|
}
|
|
7898
|
-
if (entries.length) {
|
|
7899
|
-
post(cfg, sid, { entries });
|
|
7900
|
-
}
|
|
7901
8134
|
if (captureScope) {
|
|
7902
8135
|
post(cfg, sid, {
|
|
7903
8136
|
entries: [{
|
|
@@ -7909,7 +8142,10 @@ function scheduleKafkaTraceFlush(
|
|
|
7909
8142
|
),
|
|
7910
8143
|
t: alignedNow(),
|
|
7911
8144
|
}],
|
|
7912
|
-
});
|
|
8145
|
+
}, { priority: 'high' });
|
|
8146
|
+
}
|
|
8147
|
+
if (entries.length) {
|
|
8148
|
+
post(cfg, sid, { entries });
|
|
7913
8149
|
}
|
|
7914
8150
|
});
|
|
7915
8151
|
}, { priority: 'high' });
|
|
@@ -7928,7 +8164,7 @@ function patchKafkaProducerInstance(producer: any, cfg: KafkaJsPatchConfig) {
|
|
|
7928
8164
|
const aid = ctx.aid ?? fallback.aid ?? null;
|
|
7929
8165
|
const span = captureSpanContextFromTracer();
|
|
7930
8166
|
const publishRid = nextRequestId(alignedNow());
|
|
7931
|
-
const captureScope = createRequestCaptureScope(publishRid, 'kafka');
|
|
8167
|
+
const captureScope = createRequestCaptureScope(publishRid, 'kafka', cfg);
|
|
7932
8168
|
emitRequestCaptureStart(cfg, sid, aid, captureScope);
|
|
7933
8169
|
const payloadObj = payload && typeof payload === 'object' ? payload : {};
|
|
7934
8170
|
const topic = sanitizeKafkaTopic((payloadObj as any).topic);
|
|
@@ -7987,7 +8223,7 @@ function patchKafkaProducerInstance(producer: any, cfg: KafkaJsPatchConfig) {
|
|
|
7987
8223
|
traceId: span?.traceId ?? null,
|
|
7988
8224
|
spanId: span?.spanId ?? null,
|
|
7989
8225
|
parentSpanId: span?.parentSpanId ?? null,
|
|
7990
|
-
});
|
|
8226
|
+
}, captureScope);
|
|
7991
8227
|
|
|
7992
8228
|
const requestPayload: Record<string, any> = {
|
|
7993
8229
|
rid: publishRid,
|
|
@@ -8018,7 +8254,6 @@ function patchKafkaProducerInstance(producer: any, cfg: KafkaJsPatchConfig) {
|
|
|
8018
8254
|
},
|
|
8019
8255
|
],
|
|
8020
8256
|
});
|
|
8021
|
-
captureScope.backendRequestCount += 1;
|
|
8022
8257
|
post(cfg, sid, {
|
|
8023
8258
|
entries: [{
|
|
8024
8259
|
actionId: aid ?? null,
|
|
@@ -8043,7 +8278,7 @@ function patchKafkaProducerInstance(producer: any, cfg: KafkaJsPatchConfig) {
|
|
|
8043
8278
|
const aid = ctx.aid ?? fallback.aid ?? null;
|
|
8044
8279
|
const span = captureSpanContextFromTracer();
|
|
8045
8280
|
const publishRid = nextRequestId(alignedNow());
|
|
8046
|
-
const captureScope = createRequestCaptureScope(publishRid, 'kafka');
|
|
8281
|
+
const captureScope = createRequestCaptureScope(publishRid, 'kafka', cfg);
|
|
8047
8282
|
emitRequestCaptureStart(cfg, sid, aid, captureScope);
|
|
8048
8283
|
|
|
8049
8284
|
const payloadObj = payload && typeof payload === 'object' ? payload : {};
|
|
@@ -8137,7 +8372,7 @@ function patchKafkaProducerInstance(producer: any, cfg: KafkaJsPatchConfig) {
|
|
|
8137
8372
|
traceId: span?.traceId ?? null,
|
|
8138
8373
|
spanId: span?.spanId ?? null,
|
|
8139
8374
|
parentSpanId: span?.parentSpanId ?? null,
|
|
8140
|
-
});
|
|
8375
|
+
}, captureScope);
|
|
8141
8376
|
const requestPayload: Record<string, any> = {
|
|
8142
8377
|
rid: publishRid,
|
|
8143
8378
|
method: 'KAFKA_PUBLISH_BATCH',
|
|
@@ -8167,7 +8402,6 @@ function patchKafkaProducerInstance(producer: any, cfg: KafkaJsPatchConfig) {
|
|
|
8167
8402
|
},
|
|
8168
8403
|
],
|
|
8169
8404
|
});
|
|
8170
|
-
captureScope.backendRequestCount += 1;
|
|
8171
8405
|
post(cfg, sid, {
|
|
8172
8406
|
entries: [{
|
|
8173
8407
|
actionId: aid ?? null,
|
|
@@ -8194,7 +8428,7 @@ function wrapKafkaEachMessageHandler(eachMessage: any, cfg: KafkaJsPatchConfig,
|
|
|
8194
8428
|
const aid = runtime.aid;
|
|
8195
8429
|
const consumeRid = nextRequestId(`${topic}-${message?.offset ?? alignedNow()}`);
|
|
8196
8430
|
const traceId = consumeRid;
|
|
8197
|
-
const captureScope = createRequestCaptureScope(consumeRid, 'kafka');
|
|
8431
|
+
const captureScope = createRequestCaptureScope(consumeRid, 'kafka', cfg);
|
|
8198
8432
|
emitRequestCaptureStart(cfg, sid, aid, captureScope);
|
|
8199
8433
|
const rawTraceEvents: any[] = [];
|
|
8200
8434
|
const maskReq: MaskRequestContext = {
|
|
@@ -8266,7 +8500,7 @@ function wrapKafkaEachMessageHandler(eachMessage: any, cfg: KafkaJsPatchConfig,
|
|
|
8266
8500
|
valueEncoding: messagePayload.valueEncoding,
|
|
8267
8501
|
valueBytes: messagePayload.valueBytes,
|
|
8268
8502
|
message: messagePayload,
|
|
8269
|
-
});
|
|
8503
|
+
}, captureScope);
|
|
8270
8504
|
const requestPayload: Record<string, any> = {
|
|
8271
8505
|
rid: consumeRid,
|
|
8272
8506
|
method: 'KAFKA_CONSUME',
|
|
@@ -8288,7 +8522,6 @@ function wrapKafkaEachMessageHandler(eachMessage: any, cfg: KafkaJsPatchConfig,
|
|
|
8288
8522
|
t: alignedNow(),
|
|
8289
8523
|
}],
|
|
8290
8524
|
});
|
|
8291
|
-
captureScope.backendRequestCount += 1;
|
|
8292
8525
|
scheduleKafkaTraceFlush(cfg, kafkaCtx, aid, consumeRid, rawTraceEvents, maskReq, captureScope);
|
|
8293
8526
|
}
|
|
8294
8527
|
};
|
|
@@ -8305,7 +8538,7 @@ function wrapKafkaEachBatchHandler(eachBatch: any, cfg: KafkaJsPatchConfig, cons
|
|
|
8305
8538
|
const aid = runtime.aid;
|
|
8306
8539
|
const consumeRid = nextRequestId(`${topic}-batch-${alignedNow()}`);
|
|
8307
8540
|
const traceId = consumeRid;
|
|
8308
|
-
const captureScope = createRequestCaptureScope(consumeRid, 'kafka');
|
|
8541
|
+
const captureScope = createRequestCaptureScope(consumeRid, 'kafka', cfg);
|
|
8309
8542
|
emitRequestCaptureStart(cfg, sid, aid, captureScope);
|
|
8310
8543
|
const rawTraceEvents: any[] = [];
|
|
8311
8544
|
const maskReq: MaskRequestContext = {
|
|
@@ -8375,7 +8608,7 @@ function wrapKafkaEachBatchHandler(eachBatch: any, cfg: KafkaJsPatchConfig, cons
|
|
|
8375
8608
|
parentSpanId: runtime.parentSpanId,
|
|
8376
8609
|
firstMessageKey: firstMessagePayload?.key ?? null,
|
|
8377
8610
|
messages: messages.map((message: any) => buildKafkaMessagePayload(message)),
|
|
8378
|
-
});
|
|
8611
|
+
}, captureScope);
|
|
8379
8612
|
const requestPayload: Record<string, any> = {
|
|
8380
8613
|
rid: consumeRid,
|
|
8381
8614
|
method: 'KAFKA_CONSUME_BATCH',
|
|
@@ -8397,7 +8630,6 @@ function wrapKafkaEachBatchHandler(eachBatch: any, cfg: KafkaJsPatchConfig, cons
|
|
|
8397
8630
|
t: alignedNow(),
|
|
8398
8631
|
}],
|
|
8399
8632
|
});
|
|
8400
|
-
captureScope.backendRequestCount += 1;
|
|
8401
8633
|
scheduleKafkaTraceFlush(cfg, kafkaCtx, aid, consumeRid, rawTraceEvents, maskReq, captureScope);
|
|
8402
8634
|
}
|
|
8403
8635
|
};
|
|
@@ -8820,24 +9052,28 @@ function scheduleAmqpTraceFlush(
|
|
|
8820
9052
|
}
|
|
8821
9053
|
|
|
8822
9054
|
let entries: LegacyEntry[] = [];
|
|
8823
|
-
|
|
8824
|
-
|
|
8825
|
-
|
|
8826
|
-
|
|
8827
|
-
|
|
8828
|
-
|
|
8829
|
-
|
|
8830
|
-
|
|
8831
|
-
|
|
8832
|
-
|
|
8833
|
-
|
|
8834
|
-
|
|
8835
|
-
post(cfg, sid, { entries });
|
|
9055
|
+
try {
|
|
9056
|
+
if (pendingEvents.length) {
|
|
9057
|
+
const masking = normalizeMaskingConfig(cfg.masking);
|
|
9058
|
+
const preparedEvents = preparePendingTraceEventsForFlush(pendingEvents);
|
|
9059
|
+
const materializedEvents = await materializePendingTraceEventsAsync(preparedEvents, {
|
|
9060
|
+
cfg,
|
|
9061
|
+
maskReq,
|
|
9062
|
+
masking,
|
|
9063
|
+
resolvePrivacy: () => getRuntimePrivacyState(cfg).policy ?? null,
|
|
9064
|
+
captureScope,
|
|
9065
|
+
});
|
|
9066
|
+
entries = buildAmqpTraceEntries(actionId, requestRid, materializedEvents);
|
|
8836
9067
|
}
|
|
8837
|
-
}
|
|
8838
|
-
|
|
9068
|
+
} catch {
|
|
9069
|
+
recordRequestCaptureFailure(
|
|
9070
|
+
captureScope,
|
|
9071
|
+
'trace.capture',
|
|
9072
|
+
'trace.batches',
|
|
9073
|
+
'trace_capture_failed',
|
|
9074
|
+
);
|
|
8839
9075
|
}
|
|
8840
|
-
|
|
9076
|
+
captureScope.traceBatchCount = entries.length;
|
|
8841
9077
|
post(cfg, sid, {
|
|
8842
9078
|
entries: [{
|
|
8843
9079
|
actionId: actionId ?? null,
|
|
@@ -8848,7 +9084,10 @@ function scheduleAmqpTraceFlush(
|
|
|
8848
9084
|
),
|
|
8849
9085
|
t: alignedNow(),
|
|
8850
9086
|
}],
|
|
8851
|
-
});
|
|
9087
|
+
}, { priority: 'high' });
|
|
9088
|
+
if (entries.length) {
|
|
9089
|
+
post(cfg, sid, { entries });
|
|
9090
|
+
}
|
|
8852
9091
|
});
|
|
8853
9092
|
}, { priority: 'high' });
|
|
8854
9093
|
}
|
|
@@ -8920,7 +9159,12 @@ function scheduleAmqpPublishCapture(params: {
|
|
|
8920
9159
|
};
|
|
8921
9160
|
|
|
8922
9161
|
scheduleSdkBackgroundWork(async () => {
|
|
8923
|
-
const bodyMaterialization = await materializeKafkaRequestBody(
|
|
9162
|
+
const bodyMaterialization = await materializeKafkaRequestBody(
|
|
9163
|
+
params.cfg,
|
|
9164
|
+
maskReq,
|
|
9165
|
+
body,
|
|
9166
|
+
params.captureScope,
|
|
9167
|
+
);
|
|
8924
9168
|
const requestPayload: Record<string, any> = {
|
|
8925
9169
|
rid: params.publishRid,
|
|
8926
9170
|
method: params.method,
|
|
@@ -8951,7 +9195,6 @@ function scheduleAmqpPublishCapture(params: {
|
|
|
8951
9195
|
t: alignedNow(),
|
|
8952
9196
|
}],
|
|
8953
9197
|
});
|
|
8954
|
-
params.captureScope.backendRequestCount += 1;
|
|
8955
9198
|
post(params.cfg, params.sid!, {
|
|
8956
9199
|
entries: [{
|
|
8957
9200
|
actionId: params.aid ?? null,
|
|
@@ -9013,7 +9256,7 @@ function patchAmqplibPublishMethod(
|
|
|
9013
9256
|
: `amqp://queue/${queue}`;
|
|
9014
9257
|
const key = `${method} ${methodName === 'publish' ? `${exchange || 'default'}/${routingKey}` : queue}`;
|
|
9015
9258
|
const content = methodName === 'publish' ? args[2] : args[1];
|
|
9016
|
-
const captureScope = createRequestCaptureScope(publishRid, 'amqp');
|
|
9259
|
+
const captureScope = createRequestCaptureScope(publishRid, 'amqp', cfg);
|
|
9017
9260
|
emitRequestCaptureStart(cfg, sid, aid, captureScope);
|
|
9018
9261
|
const t0 = Date.now();
|
|
9019
9262
|
let finished = false;
|
|
@@ -9103,7 +9346,7 @@ function wrapAmqplibConsumeHandler(onMessage: any, cfg: AmqplibPatchConfig, queu
|
|
|
9103
9346
|
const deliveryTag = message?.fields?.deliveryTag ?? alignedNow();
|
|
9104
9347
|
const consumeRid = nextRequestId(`${queueName}-${deliveryTag}`);
|
|
9105
9348
|
const traceId = consumeRid;
|
|
9106
|
-
const captureScope = createRequestCaptureScope(consumeRid, 'amqp');
|
|
9349
|
+
const captureScope = createRequestCaptureScope(consumeRid, 'amqp', cfg);
|
|
9107
9350
|
emitRequestCaptureStart(cfg, sid, aid, captureScope);
|
|
9108
9351
|
const rawTraceEvents: any[] = [];
|
|
9109
9352
|
const maskReq: MaskRequestContext = {
|
|
@@ -9188,7 +9431,12 @@ function wrapAmqplibConsumeHandler(onMessage: any, cfg: AmqplibPatchConfig, queu
|
|
|
9188
9431
|
};
|
|
9189
9432
|
|
|
9190
9433
|
scheduleSdkBackgroundWork(async () => {
|
|
9191
|
-
const bodyMaterialization = await materializeKafkaRequestBody(
|
|
9434
|
+
const bodyMaterialization = await materializeKafkaRequestBody(
|
|
9435
|
+
cfg,
|
|
9436
|
+
maskReq,
|
|
9437
|
+
body,
|
|
9438
|
+
captureScope,
|
|
9439
|
+
);
|
|
9192
9440
|
const requestPayload: Record<string, any> = {
|
|
9193
9441
|
rid: consumeRid,
|
|
9194
9442
|
method: 'AMQP_CONSUME',
|
|
@@ -9210,7 +9458,6 @@ function wrapAmqplibConsumeHandler(onMessage: any, cfg: AmqplibPatchConfig, queu
|
|
|
9210
9458
|
t: alignedNow(),
|
|
9211
9459
|
}],
|
|
9212
9460
|
});
|
|
9213
|
-
captureScope.backendRequestCount += 1;
|
|
9214
9461
|
scheduleAmqpTraceFlush(cfg, amqpCtx, aid, consumeRid, rawTraceEvents, maskReq, captureScope);
|
|
9215
9462
|
}, { priority: 'high' });
|
|
9216
9463
|
};
|