@reproapp/node-sdk 0.0.46 → 0.0.48
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 +16 -3
- package/dist/index.js +327 -159
- package/dist/ingest/client.js +11 -0
- package/dist/privacy.d.ts +1 -0
- package/dist/privacy.js +306 -7
- package/dist/semantic-serialization.d.ts +9 -0
- package/dist/semantic-serialization.js +171 -0
- package/package.json +3 -3
- package/src/index.ts +513 -144
- package/src/ingest/client.ts +13 -0
- package/src/privacy.ts +409 -7
- package/src/semantic-serialization.ts +182 -0
- package/test/content-addressed-mongodb.testcontainers.test.js +348 -0
- package/test/content-addressed-trace-values.test.js +264 -0
- package/test/fixtures/semantic-serialization-trace-controller.js +85 -0
- package/test/fixtures/semantic-serialization-trace-server.js +19 -0
- 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/semantic-serialization-trace.test.js +152 -0
- package/test/semantic-serialization.test.js +229 -0
- package/test/session-storage-budget.test.js +298 -0
- package/test/trace-batch-size.test.js +37 -0
package/dist/index.js
CHANGED
|
@@ -9,6 +9,7 @@ const path_1 = require("path");
|
|
|
9
9
|
const url_1 = require("url");
|
|
10
10
|
const client_1 = require("./ingest/client");
|
|
11
11
|
const privacy_1 = require("./privacy");
|
|
12
|
+
const semantic_serialization_1 = require("./semantic-serialization");
|
|
12
13
|
/**
|
|
13
14
|
* ============================= IMPORTANT =============================
|
|
14
15
|
* We snapshot Mongoose core methods BEFORE tracer init, then re-apply them
|
|
@@ -817,16 +818,46 @@ function attachSpanContext(target, span) {
|
|
|
817
818
|
}
|
|
818
819
|
return target;
|
|
819
820
|
}
|
|
820
|
-
function createRequestCaptureScope(requestRid, transport) {
|
|
821
|
+
function createRequestCaptureScope(requestRid, transport, cfg) {
|
|
822
|
+
const privacy = cfg ? getRuntimePrivacyState(cfg).policy ?? null : null;
|
|
823
|
+
const privacyMode = cfg && shouldCapturePrivacyRaw(cfg)
|
|
824
|
+
? 'raw'
|
|
825
|
+
: privacy
|
|
826
|
+
? 'policy'
|
|
827
|
+
: 'fallback';
|
|
821
828
|
return {
|
|
822
829
|
requestRid,
|
|
823
830
|
transport,
|
|
824
|
-
|
|
831
|
+
// Every scope represents one captured transport request. This is an
|
|
832
|
+
// observed expectation, not a count of successful enqueue operations.
|
|
833
|
+
backendRequestCount: 1,
|
|
825
834
|
traceBatchCount: 0,
|
|
826
835
|
dbChangeCount: 0,
|
|
827
836
|
emailEventCount: 0,
|
|
837
|
+
captureFailures: [],
|
|
838
|
+
privacyMode,
|
|
839
|
+
privacyPolicyFingerprint: privacy?.fingerprint,
|
|
840
|
+
privacyStatementCount: privacy?.statements.length ?? 0,
|
|
841
|
+
emittedValueDefinitionIds: new Set(),
|
|
828
842
|
};
|
|
829
843
|
}
|
|
844
|
+
function recordRequestCaptureFailure(scope, stage, target, reason) {
|
|
845
|
+
if (!scope)
|
|
846
|
+
return;
|
|
847
|
+
const normalized = {
|
|
848
|
+
stage: String(stage || 'capture').slice(0, 80),
|
|
849
|
+
target: String(target || 'unknown').slice(0, 120),
|
|
850
|
+
reason: String(reason || 'capture_failed').slice(0, 120),
|
|
851
|
+
};
|
|
852
|
+
if (scope.captureFailures.some((failure) => failure.stage === normalized.stage &&
|
|
853
|
+
failure.target === normalized.target &&
|
|
854
|
+
failure.reason === normalized.reason)) {
|
|
855
|
+
return;
|
|
856
|
+
}
|
|
857
|
+
if (scope.captureFailures.length < 25) {
|
|
858
|
+
scope.captureFailures.push(normalized);
|
|
859
|
+
}
|
|
860
|
+
}
|
|
830
861
|
function buildRequestCaptureManifestPayload(scope, traceBatchTotal, closedAtMs) {
|
|
831
862
|
const expectedTraceBatches = Math.max(0, Math.trunc(traceBatchTotal));
|
|
832
863
|
const closedAt = typeof closedAtMs === 'number' && Number.isFinite(closedAtMs)
|
|
@@ -848,6 +879,19 @@ function buildRequestCaptureManifestPayload(scope, traceBatchTotal, closedAtMs)
|
|
|
848
879
|
to: expectedTraceBatches - 1,
|
|
849
880
|
}
|
|
850
881
|
: undefined,
|
|
882
|
+
privacy: {
|
|
883
|
+
mode: scope.privacyMode,
|
|
884
|
+
status: scope.captureFailures.length > 0
|
|
885
|
+
? 'failed'
|
|
886
|
+
: scope.privacyMode === 'raw'
|
|
887
|
+
? 'bypassed'
|
|
888
|
+
: 'applied',
|
|
889
|
+
policyFingerprint: scope.privacyPolicyFingerprint,
|
|
890
|
+
statementCount: scope.privacyStatementCount,
|
|
891
|
+
},
|
|
892
|
+
captureFailures: scope.captureFailures.length
|
|
893
|
+
? scope.captureFailures.map((failure) => ({ ...failure }))
|
|
894
|
+
: undefined,
|
|
851
895
|
closedAt,
|
|
852
896
|
};
|
|
853
897
|
}
|
|
@@ -1024,12 +1068,6 @@ const SDK_BACKGROUND_MAX_DEFER_MS = (() => {
|
|
|
1024
1068
|
return Math.trunc(env);
|
|
1025
1069
|
return Number.POSITIVE_INFINITY;
|
|
1026
1070
|
})();
|
|
1027
|
-
const SDK_BACKGROUND_WORK_TIMEOUT_MS = (() => {
|
|
1028
|
-
const env = Number(process.env.REPRO_SDK_BACKGROUND_WORK_TIMEOUT_MS);
|
|
1029
|
-
if (Number.isFinite(env) && env >= 0)
|
|
1030
|
-
return Math.trunc(env);
|
|
1031
|
-
return 20000;
|
|
1032
|
-
})();
|
|
1033
1071
|
const TRACE_MATERIALIZE_OFFTHREAD_ENABLED = (() => {
|
|
1034
1072
|
const env = String(process.env.REPRO_TRACE_MATERIALIZE_OFFTHREAD || '').trim().toLowerCase();
|
|
1035
1073
|
if (!env)
|
|
@@ -1378,28 +1416,9 @@ function scheduleSdkBackgroundDrain(delayMs = 0) {
|
|
|
1378
1416
|
catch { }
|
|
1379
1417
|
}
|
|
1380
1418
|
async function runSdkBackgroundWork(work) {
|
|
1381
|
-
|
|
1382
|
-
await work();
|
|
1383
|
-
return;
|
|
1384
|
-
}
|
|
1385
|
-
let timeout = null;
|
|
1386
|
-
const workPromise = Promise.resolve()
|
|
1419
|
+
await Promise.resolve()
|
|
1387
1420
|
.then(work)
|
|
1388
1421
|
.catch(() => undefined);
|
|
1389
|
-
const timeoutPromise = new Promise((resolve) => {
|
|
1390
|
-
timeout = setTimeout(resolve, SDK_BACKGROUND_WORK_TIMEOUT_MS);
|
|
1391
|
-
try {
|
|
1392
|
-
timeout.unref?.();
|
|
1393
|
-
}
|
|
1394
|
-
catch { }
|
|
1395
|
-
});
|
|
1396
|
-
await Promise.race([workPromise, timeoutPromise]);
|
|
1397
|
-
if (timeout) {
|
|
1398
|
-
try {
|
|
1399
|
-
clearTimeout(timeout);
|
|
1400
|
-
}
|
|
1401
|
-
catch { }
|
|
1402
|
-
}
|
|
1403
1422
|
}
|
|
1404
1423
|
async function drainQueuedIngestBeforeBackgroundWork() {
|
|
1405
1424
|
(0, client_1.kickIngestQueueDrain)();
|
|
@@ -2258,7 +2277,11 @@ const TRACE_MAX_BATCHES_PER_REQUEST = (() => {
|
|
|
2258
2277
|
const env = Number(process.env.REPRO_TRACE_MAX_BATCHES_PER_REQUEST);
|
|
2259
2278
|
if (Number.isFinite(env) && env > 0)
|
|
2260
2279
|
return Math.trunc(env);
|
|
2261
|
-
|
|
2280
|
+
// Byte-based splitting can legitimately produce one batch per event when
|
|
2281
|
+
// every event owns a distinct large value. The event limit remains the
|
|
2282
|
+
// hard upper bound; deriving this from the count-only batch size silently
|
|
2283
|
+
// dropped otherwise valid events after ten batches.
|
|
2284
|
+
return TRACE_MAX_EVENTS_PER_REQUEST;
|
|
2262
2285
|
})();
|
|
2263
2286
|
const TRACE_FLUSH_DELAY_MS = 20;
|
|
2264
2287
|
// Choose how to order trace events in payloads.
|
|
@@ -2586,6 +2609,10 @@ function sanitizeTraceValue(value, depth = 0, seen = new WeakMap(), options = {}
|
|
|
2586
2609
|
const mongoPlaceholder = describeMongoPlaceholder(value);
|
|
2587
2610
|
if (mongoPlaceholder)
|
|
2588
2611
|
return mongoPlaceholder;
|
|
2612
|
+
const semanticProjection = (0, semantic_serialization_1.projectSemanticInfrastructureValue)(value);
|
|
2613
|
+
if (semanticProjection) {
|
|
2614
|
+
return sanitizeTraceValue(semanticProjection.value, depth, seen, options, valuePath);
|
|
2615
|
+
}
|
|
2589
2616
|
if (isThenable(value)) {
|
|
2590
2617
|
return { __type: 'Promise', state: 'pending' };
|
|
2591
2618
|
}
|
|
@@ -2807,6 +2834,7 @@ async function materializePendingTraceEvents(events, params) {
|
|
|
2807
2834
|
trace: candidate,
|
|
2808
2835
|
masking: params.masking,
|
|
2809
2836
|
privacy: activePrivacy,
|
|
2837
|
+
valueNamespace: params.valueNamespace,
|
|
2810
2838
|
};
|
|
2811
2839
|
const traceValueMetadata = {
|
|
2812
2840
|
fn: evt.fn,
|
|
@@ -2828,7 +2856,7 @@ async function materializePendingTraceEvents(events, params) {
|
|
|
2828
2856
|
previewValue: evt.args,
|
|
2829
2857
|
capture: captureContext,
|
|
2830
2858
|
metadata: traceValueMetadata,
|
|
2831
|
-
});
|
|
2859
|
+
}, params.captureScope);
|
|
2832
2860
|
if (argsValueCapture?.entry) {
|
|
2833
2861
|
attachTraceValueEntry(evt, argsValueCapture.entry);
|
|
2834
2862
|
}
|
|
@@ -2850,7 +2878,7 @@ async function materializePendingTraceEvents(events, params) {
|
|
|
2850
2878
|
previewValue: evt.returnValue,
|
|
2851
2879
|
capture: captureContext,
|
|
2852
2880
|
metadata: traceValueMetadata,
|
|
2853
|
-
});
|
|
2881
|
+
}, params.captureScope);
|
|
2854
2882
|
if (returnValueCapture?.entry) {
|
|
2855
2883
|
attachTraceValueEntry(evt, returnValueCapture.entry);
|
|
2856
2884
|
}
|
|
@@ -2872,7 +2900,7 @@ async function materializePendingTraceEvents(events, params) {
|
|
|
2872
2900
|
previewValue: evt.error,
|
|
2873
2901
|
capture: captureContext,
|
|
2874
2902
|
metadata: traceValueMetadata,
|
|
2875
|
-
});
|
|
2903
|
+
}, params.captureScope);
|
|
2876
2904
|
if (errorValueCapture?.entry) {
|
|
2877
2905
|
attachTraceValueEntry(evt, errorValueCapture.entry);
|
|
2878
2906
|
}
|
|
@@ -2886,8 +2914,21 @@ async function materializePendingTraceEvents(events, params) {
|
|
|
2886
2914
|
}
|
|
2887
2915
|
function stripPendingTraceValues(events, reason) {
|
|
2888
2916
|
for (const evt of events) {
|
|
2889
|
-
|
|
2917
|
+
const pending = evt.__reproPending;
|
|
2918
|
+
if (!pending)
|
|
2890
2919
|
continue;
|
|
2920
|
+
if (pending.argsRaw !== undefined) {
|
|
2921
|
+
evt.args = makeOmittedValue(reason);
|
|
2922
|
+
evt.argsValueCapture = { status: 'failed-policy' };
|
|
2923
|
+
}
|
|
2924
|
+
if (pending.returnValueRaw !== undefined) {
|
|
2925
|
+
evt.returnValue = makeOmittedValue(reason);
|
|
2926
|
+
evt.returnValueCapture = { status: 'failed-policy' };
|
|
2927
|
+
}
|
|
2928
|
+
if (pending.errorRaw !== undefined) {
|
|
2929
|
+
evt.error = makeOmittedValue(reason);
|
|
2930
|
+
evt.errorValueCapture = { status: 'failed-policy' };
|
|
2931
|
+
}
|
|
2891
2932
|
delete evt.__reproPending;
|
|
2892
2933
|
}
|
|
2893
2934
|
return events;
|
|
@@ -2908,6 +2949,7 @@ async function materializePendingTraceEventsAsync(events, params) {
|
|
|
2908
2949
|
});
|
|
2909
2950
|
}
|
|
2910
2951
|
catch {
|
|
2952
|
+
recordRequestCaptureFailure(params.captureScope ?? getCtx().captureScope, 'privacy.trace', 'trace.values', 'main_thread_materialization_failed');
|
|
2911
2953
|
return stripPendingTraceValues(events, 'main_thread_failed');
|
|
2912
2954
|
}
|
|
2913
2955
|
}
|
|
@@ -2915,6 +2957,7 @@ async function materializePendingTraceEventsAsync(events, params) {
|
|
|
2915
2957
|
return await materializePendingTraceEventsOffThread(events, {
|
|
2916
2958
|
events,
|
|
2917
2959
|
cfg: {
|
|
2960
|
+
tenantId: params.cfg.tenantId,
|
|
2918
2961
|
appId: params.cfg.appId,
|
|
2919
2962
|
appSecret: params.cfg.appSecret,
|
|
2920
2963
|
appName: params.cfg.appName,
|
|
@@ -2924,12 +2967,10 @@ async function materializePendingTraceEventsAsync(events, params) {
|
|
|
2924
2967
|
masking: params.masking,
|
|
2925
2968
|
privacy,
|
|
2926
2969
|
fullValueCaptureEnabled: __FULL_VALUE_CAPTURE_ENABLED,
|
|
2970
|
+
valueNamespace: params.valueNamespace,
|
|
2927
2971
|
});
|
|
2928
2972
|
}
|
|
2929
2973
|
catch (err) {
|
|
2930
|
-
if (isTraceMaterializerTimeoutError(err)) {
|
|
2931
|
-
return stripPendingTraceValues(events, 'worker_timeout');
|
|
2932
|
-
}
|
|
2933
2974
|
try {
|
|
2934
2975
|
return await materializePendingTraceEvents(events, {
|
|
2935
2976
|
...params,
|
|
@@ -2937,7 +2978,10 @@ async function materializePendingTraceEventsAsync(events, params) {
|
|
|
2937
2978
|
});
|
|
2938
2979
|
}
|
|
2939
2980
|
catch {
|
|
2940
|
-
|
|
2981
|
+
recordRequestCaptureFailure(params.captureScope ?? getCtx().captureScope, 'privacy.trace', 'trace.values', isTraceMaterializerTimeoutError(err)
|
|
2982
|
+
? 'worker_timeout_fallback_failed'
|
|
2983
|
+
: 'worker_and_fallback_failed');
|
|
2984
|
+
return stripPendingTraceValues(events, isTraceMaterializerTimeoutError(err) ? 'worker_timeout_fallback_failed' : 'worker_failed');
|
|
2941
2985
|
}
|
|
2942
2986
|
}
|
|
2943
2987
|
}
|
|
@@ -2950,6 +2994,7 @@ async function __materializePendingTraceEventsForWorker(payload) {
|
|
|
2950
2994
|
maskReq: payload.maskReq,
|
|
2951
2995
|
masking: payload.masking,
|
|
2952
2996
|
resolvePrivacy: () => payload.privacy,
|
|
2997
|
+
valueNamespace: payload.valueNamespace,
|
|
2953
2998
|
});
|
|
2954
2999
|
return materialized.map((event) => {
|
|
2955
3000
|
const entries = getEventTraceValueEntries(event);
|
|
@@ -3404,7 +3449,7 @@ function limitRawInlinePrivacyValue(target, value) {
|
|
|
3404
3449
|
const limited = limitInlinePrivacyValue(target, value);
|
|
3405
3450
|
return limited.skipped ? limited : null;
|
|
3406
3451
|
}
|
|
3407
|
-
function materializeInlinePrivacyValue(target, value, cfg, req, trace, masking, privacy, db) {
|
|
3452
|
+
function materializeInlinePrivacyValue(target, value, cfg, req, trace, masking, privacy, db, captureScope) {
|
|
3408
3453
|
if (value === undefined) {
|
|
3409
3454
|
return { value };
|
|
3410
3455
|
}
|
|
@@ -3416,6 +3461,7 @@ function materializeInlinePrivacyValue(target, value, cfg, req, trace, masking,
|
|
|
3416
3461
|
return { value: valueAfterPrivacy };
|
|
3417
3462
|
}
|
|
3418
3463
|
catch {
|
|
3464
|
+
recordRequestCaptureFailure(captureScope ?? getCtx().captureScope, 'privacy.inline', target, 'privacy_transform_failed');
|
|
3419
3465
|
return {
|
|
3420
3466
|
value: undefined,
|
|
3421
3467
|
skipped: {
|
|
@@ -3426,7 +3472,7 @@ function materializeInlinePrivacyValue(target, value, cfg, req, trace, masking,
|
|
|
3426
3472
|
};
|
|
3427
3473
|
}
|
|
3428
3474
|
}
|
|
3429
|
-
async function materializeInlinePrivacyValueAsync(target, value, cfg, req, trace, masking, privacy, db) {
|
|
3475
|
+
async function materializeInlinePrivacyValueAsync(target, value, cfg, req, trace, masking, privacy, db, captureScope) {
|
|
3430
3476
|
if (value === undefined) {
|
|
3431
3477
|
return { value };
|
|
3432
3478
|
}
|
|
@@ -3438,6 +3484,7 @@ async function materializeInlinePrivacyValueAsync(target, value, cfg, req, trace
|
|
|
3438
3484
|
return { value: valueAfterPrivacy };
|
|
3439
3485
|
}
|
|
3440
3486
|
catch {
|
|
3487
|
+
recordRequestCaptureFailure(captureScope ?? getCtx().captureScope, 'privacy.inline', target, 'privacy_transform_failed');
|
|
3441
3488
|
return {
|
|
3442
3489
|
value: undefined,
|
|
3443
3490
|
skipped: {
|
|
@@ -3949,6 +3996,10 @@ function cloneFullValueCandidate(value, ctx, limits, depth = 0, seen = new WeakM
|
|
|
3949
3996
|
const mongoPlaceholder = describeMongoPlaceholder(value);
|
|
3950
3997
|
if (mongoPlaceholder)
|
|
3951
3998
|
return undefined;
|
|
3999
|
+
const semanticProjection = (0, semantic_serialization_1.projectSemanticInfrastructureValue)(value);
|
|
4000
|
+
if (semanticProjection) {
|
|
4001
|
+
return cloneFullValueCandidate(semanticProjection.value, ctx, limits, depth, seen, valuePath);
|
|
4002
|
+
}
|
|
3952
4003
|
if (isThenable(value))
|
|
3953
4004
|
return undefined;
|
|
3954
4005
|
if (shouldSkipFullValueObject(value))
|
|
@@ -4133,6 +4184,10 @@ async function cloneFullValueCandidateAsync(value, ctx, limits, depth = 0, seen
|
|
|
4133
4184
|
const mongoPlaceholder = describeMongoPlaceholder(value);
|
|
4134
4185
|
if (mongoPlaceholder)
|
|
4135
4186
|
return undefined;
|
|
4187
|
+
const semanticProjection = (0, semantic_serialization_1.projectSemanticInfrastructureValue)(value);
|
|
4188
|
+
if (semanticProjection) {
|
|
4189
|
+
return cloneFullValueCandidateAsync(semanticProjection.value, ctx, limits, depth, seen, valuePath);
|
|
4190
|
+
}
|
|
4136
4191
|
if (isThenable(value))
|
|
4137
4192
|
return undefined;
|
|
4138
4193
|
if (shouldSkipFullValueObject(value))
|
|
@@ -4281,13 +4336,16 @@ function getEventTraceValueEntries(event) {
|
|
|
4281
4336
|
}
|
|
4282
4337
|
return undefined;
|
|
4283
4338
|
}
|
|
4284
|
-
function collectBatchTraceValueEntries(batch, batchIndex) {
|
|
4339
|
+
function collectBatchTraceValueEntries(batch, batchIndex, emittedValueIds = new Set()) {
|
|
4285
4340
|
const collected = [];
|
|
4286
4341
|
batch.forEach((event, eventIndex) => {
|
|
4287
4342
|
const entries = getEventTraceValueEntries(event);
|
|
4288
4343
|
if (!Array.isArray(entries) || !entries.length)
|
|
4289
4344
|
return;
|
|
4290
4345
|
entries.forEach((entry) => {
|
|
4346
|
+
if (emittedValueIds.has(entry.id))
|
|
4347
|
+
return;
|
|
4348
|
+
emittedValueIds.add(entry.id);
|
|
4291
4349
|
collected.push({
|
|
4292
4350
|
...entry,
|
|
4293
4351
|
batchIndex,
|
|
@@ -4305,8 +4363,25 @@ function serializedByteLength(value) {
|
|
|
4305
4363
|
return Number.MAX_SAFE_INTEGER;
|
|
4306
4364
|
}
|
|
4307
4365
|
}
|
|
4308
|
-
function
|
|
4309
|
-
const
|
|
4366
|
+
function contentAddressedValueId(target, candidateSerialized, capture) {
|
|
4367
|
+
const config = capture.runtimeConfig;
|
|
4368
|
+
const signingKey = String(config.appSecret ||
|
|
4369
|
+
`${config.tenantId || 'tenant'}:${config.appId || 'app'}`);
|
|
4370
|
+
const namespace = String(capture.valueNamespace ||
|
|
4371
|
+
`${config.tenantId || 'tenant'}:${config.appId || 'app'}`);
|
|
4372
|
+
const digest = (0, crypto_1.createHmac)('sha256', signingKey)
|
|
4373
|
+
.update('repro-captured-value-v1\0')
|
|
4374
|
+
.update(namespace)
|
|
4375
|
+
.update('\0')
|
|
4376
|
+
.update(target)
|
|
4377
|
+
.update('\0')
|
|
4378
|
+
.update(candidateSerialized)
|
|
4379
|
+
.digest('hex')
|
|
4380
|
+
.slice(0, 40);
|
|
4381
|
+
return `rv1_${digest}`;
|
|
4382
|
+
}
|
|
4383
|
+
function estimateTraceBatchSerializedBytes(batch, requestRid, actionId, batchIndex, previouslyEmittedValueIds = new Set()) {
|
|
4384
|
+
const traceValues = collectBatchTraceValueEntries(batch, batchIndex, new Set(previouslyEmittedValueIds));
|
|
4310
4385
|
return serializedByteLength({
|
|
4311
4386
|
actionId: actionId ?? null,
|
|
4312
4387
|
trace: batch,
|
|
@@ -4325,19 +4400,32 @@ function chunkTraceEventsForTransport(events, requestRid, actionId) {
|
|
|
4325
4400
|
const boundedEvents = boundTraceEventsForTransport(events);
|
|
4326
4401
|
const countBatches = chunkArray(boundedEvents, TRACE_BATCH_SIZE);
|
|
4327
4402
|
const sizedBatches = [];
|
|
4403
|
+
const emittedValueIds = new Set();
|
|
4328
4404
|
let current = [];
|
|
4405
|
+
const commitCurrent = () => {
|
|
4406
|
+
if (!current.length)
|
|
4407
|
+
return;
|
|
4408
|
+
collectBatchTraceValueEntries(current, sizedBatches.length, emittedValueIds);
|
|
4409
|
+
sizedBatches.push(current);
|
|
4410
|
+
current = [];
|
|
4411
|
+
};
|
|
4329
4412
|
for (const event of countBatches.flat()) {
|
|
4330
4413
|
if (sizedBatches.length >= TRACE_MAX_BATCHES_PER_REQUEST) {
|
|
4331
4414
|
break;
|
|
4332
4415
|
}
|
|
4416
|
+
if (current.length >= TRACE_BATCH_SIZE) {
|
|
4417
|
+
commitCurrent();
|
|
4418
|
+
if (sizedBatches.length >= TRACE_MAX_BATCHES_PER_REQUEST) {
|
|
4419
|
+
break;
|
|
4420
|
+
}
|
|
4421
|
+
}
|
|
4333
4422
|
const candidate = current.concat(event);
|
|
4334
4423
|
const batchIndex = sizedBatches.length;
|
|
4335
|
-
const estimatedBytes = estimateTraceBatchSerializedBytes(candidate, requestRid, actionId, batchIndex);
|
|
4424
|
+
const estimatedBytes = estimateTraceBatchSerializedBytes(candidate, requestRid, actionId, batchIndex, emittedValueIds);
|
|
4336
4425
|
if (current.length > 0 &&
|
|
4337
4426
|
estimatedBytes > TRACE_BATCH_MAX_SERIALIZED_BYTES) {
|
|
4338
|
-
|
|
4427
|
+
commitCurrent();
|
|
4339
4428
|
if (sizedBatches.length >= TRACE_MAX_BATCHES_PER_REQUEST) {
|
|
4340
|
-
current = [];
|
|
4341
4429
|
break;
|
|
4342
4430
|
}
|
|
4343
4431
|
current = [event];
|
|
@@ -4347,7 +4435,7 @@ function chunkTraceEventsForTransport(events, requestRid, actionId) {
|
|
|
4347
4435
|
}
|
|
4348
4436
|
if (current.length > 0 &&
|
|
4349
4437
|
sizedBatches.length < TRACE_MAX_BATCHES_PER_REQUEST) {
|
|
4350
|
-
|
|
4438
|
+
commitCurrent();
|
|
4351
4439
|
}
|
|
4352
4440
|
return sizedBatches;
|
|
4353
4441
|
}
|
|
@@ -4384,7 +4472,7 @@ function createCapturedValueEntry(params) {
|
|
|
4384
4472
|
if (!candidateSerialized || candidateSerialized === previewSerialized) {
|
|
4385
4473
|
return undefined;
|
|
4386
4474
|
}
|
|
4387
|
-
const valueId = (
|
|
4475
|
+
const valueId = contentAddressedValueId(params.target, candidateSerialized, params.capture);
|
|
4388
4476
|
const projectedKind = candidate && typeof candidate === 'object'
|
|
4389
4477
|
? (candidate.__kind || candidate.__type)
|
|
4390
4478
|
: undefined;
|
|
@@ -4431,7 +4519,7 @@ async function createCapturedValueEntryAsync(params) {
|
|
|
4431
4519
|
if (!candidateSerialized || candidateSerialized === previewSerialized) {
|
|
4432
4520
|
return undefined;
|
|
4433
4521
|
}
|
|
4434
|
-
const valueId = (
|
|
4522
|
+
const valueId = contentAddressedValueId(params.target, candidateSerialized, params.capture);
|
|
4435
4523
|
const projectedKind = candidate && typeof candidate === 'object'
|
|
4436
4524
|
? (candidate.__kind || candidate.__type)
|
|
4437
4525
|
: undefined;
|
|
@@ -4452,46 +4540,67 @@ async function createCapturedValueEntryAsync(params) {
|
|
|
4452
4540
|
entry,
|
|
4453
4541
|
};
|
|
4454
4542
|
}
|
|
4543
|
+
function appendCapturedValueDefinition(sink, entry, captureScope) {
|
|
4544
|
+
if (!entry)
|
|
4545
|
+
return;
|
|
4546
|
+
const emitted = captureScope?.emittedValueDefinitionIds;
|
|
4547
|
+
if (emitted?.has(entry.id))
|
|
4548
|
+
return;
|
|
4549
|
+
emitted?.add(entry.id);
|
|
4550
|
+
sink.push(entry);
|
|
4551
|
+
}
|
|
4455
4552
|
function maybeCaptureRequestValue(params, sink) {
|
|
4456
4553
|
const result = createCapturedValueEntry(params);
|
|
4457
4554
|
if (!result)
|
|
4458
4555
|
return undefined;
|
|
4459
|
-
|
|
4460
|
-
sink.push(result.entry);
|
|
4461
|
-
}
|
|
4556
|
+
appendCapturedValueDefinition(sink, result.entry);
|
|
4462
4557
|
return result.captureRef;
|
|
4463
4558
|
}
|
|
4464
|
-
async function maybeCaptureRequestValueAsync(params, sink) {
|
|
4465
|
-
|
|
4559
|
+
async function maybeCaptureRequestValueAsync(params, sink, captureScope) {
|
|
4560
|
+
let result;
|
|
4561
|
+
try {
|
|
4562
|
+
result = await createCapturedValueEntryAsync(params);
|
|
4563
|
+
}
|
|
4564
|
+
catch {
|
|
4565
|
+
recordRequestCaptureFailure(captureScope ?? getCtx().captureScope, 'privacy.full_value', params.target, 'privacy_transform_failed');
|
|
4566
|
+
return { status: 'failed-policy' };
|
|
4567
|
+
}
|
|
4466
4568
|
if (!result)
|
|
4467
4569
|
return undefined;
|
|
4468
|
-
|
|
4469
|
-
sink.push(result.entry);
|
|
4470
|
-
}
|
|
4570
|
+
appendCapturedValueDefinition(sink, result.entry, captureScope);
|
|
4471
4571
|
return result.captureRef;
|
|
4472
4572
|
}
|
|
4473
4573
|
function maybeCaptureTraceValue(params) {
|
|
4474
4574
|
return createCapturedValueEntry(params);
|
|
4475
4575
|
}
|
|
4476
|
-
async function maybeCaptureTraceValueAsync(params) {
|
|
4477
|
-
|
|
4576
|
+
async function maybeCaptureTraceValueAsync(params, captureScope) {
|
|
4577
|
+
try {
|
|
4578
|
+
return await createCapturedValueEntryAsync(params);
|
|
4579
|
+
}
|
|
4580
|
+
catch {
|
|
4581
|
+
recordRequestCaptureFailure(captureScope ?? getCtx().captureScope, 'privacy.full_value', params.target, 'privacy_transform_failed');
|
|
4582
|
+
return { captureRef: { status: 'failed-policy' } };
|
|
4583
|
+
}
|
|
4478
4584
|
}
|
|
4479
4585
|
function maybeCaptureDbValue(params, sink) {
|
|
4480
4586
|
const result = createCapturedValueEntry(params);
|
|
4481
4587
|
if (!result)
|
|
4482
4588
|
return undefined;
|
|
4483
|
-
|
|
4484
|
-
sink.push(result.entry);
|
|
4485
|
-
}
|
|
4589
|
+
appendCapturedValueDefinition(sink, result.entry);
|
|
4486
4590
|
return result.captureRef;
|
|
4487
4591
|
}
|
|
4488
|
-
async function maybeCaptureDbValueAsync(params, sink) {
|
|
4489
|
-
|
|
4592
|
+
async function maybeCaptureDbValueAsync(params, sink, captureScope) {
|
|
4593
|
+
let result;
|
|
4594
|
+
try {
|
|
4595
|
+
result = await createCapturedValueEntryAsync(params);
|
|
4596
|
+
}
|
|
4597
|
+
catch {
|
|
4598
|
+
recordRequestCaptureFailure(captureScope ?? getCtx().captureScope, 'privacy.full_value', params.target, 'privacy_transform_failed');
|
|
4599
|
+
return { status: 'failed-policy' };
|
|
4600
|
+
}
|
|
4490
4601
|
if (!result)
|
|
4491
4602
|
return undefined;
|
|
4492
|
-
|
|
4493
|
-
sink.push(result.entry);
|
|
4494
|
-
}
|
|
4603
|
+
appendCapturedValueDefinition(sink, result.entry, captureScope);
|
|
4495
4604
|
return result.captureRef;
|
|
4496
4605
|
}
|
|
4497
4606
|
function pushUniqueCaptureCandidate(candidates, value) {
|
|
@@ -4512,19 +4621,26 @@ function buildResultMetaFullValueCandidates(resultMetaRaw, resultMetaSource) {
|
|
|
4512
4621
|
pushUniqueCaptureCandidate(candidates, resultMetaSource);
|
|
4513
4622
|
return candidates;
|
|
4514
4623
|
}
|
|
4515
|
-
async function maybeCaptureDbValueFromCandidatesAsync(params, sink) {
|
|
4624
|
+
async function maybeCaptureDbValueFromCandidatesAsync(params, sink, captureScope) {
|
|
4516
4625
|
let skippedRef;
|
|
4517
4626
|
for (const rawValue of params.rawValues) {
|
|
4518
|
-
|
|
4519
|
-
|
|
4520
|
-
|
|
4521
|
-
|
|
4522
|
-
|
|
4523
|
-
|
|
4627
|
+
let result;
|
|
4628
|
+
try {
|
|
4629
|
+
result = await createCapturedValueEntryAsync({
|
|
4630
|
+
target: params.target,
|
|
4631
|
+
rawValue,
|
|
4632
|
+
previewValue: params.previewValue,
|
|
4633
|
+
capture: params.capture,
|
|
4634
|
+
});
|
|
4635
|
+
}
|
|
4636
|
+
catch {
|
|
4637
|
+
recordRequestCaptureFailure(captureScope ?? getCtx().captureScope, 'privacy.full_value', params.target, 'privacy_transform_failed');
|
|
4638
|
+
return { status: 'failed-policy' };
|
|
4639
|
+
}
|
|
4524
4640
|
if (!result)
|
|
4525
4641
|
continue;
|
|
4526
4642
|
if (result.entry) {
|
|
4527
|
-
sink
|
|
4643
|
+
appendCapturedValueDefinition(sink, result.entry, captureScope);
|
|
4528
4644
|
return result.captureRef;
|
|
4529
4645
|
}
|
|
4530
4646
|
if (!skippedRef) {
|
|
@@ -4690,7 +4806,7 @@ function reproMiddleware(cfg) {
|
|
|
4690
4806
|
const resolvePrivacy = () => getRuntimePrivacyState(captureCfg).policy ?? null;
|
|
4691
4807
|
const clockSkewMs = headerTs !== null ? headerTs - requestStartRaw : 0;
|
|
4692
4808
|
const rid = nextRequestId(requestEpochMs);
|
|
4693
|
-
const captureScope = createRequestCaptureScope(rid, 'http');
|
|
4809
|
+
const captureScope = createRequestCaptureScope(rid, 'http', captureCfg);
|
|
4694
4810
|
emitRequestCaptureStart(captureCfg, sid, aid, captureScope, requestEpochMs);
|
|
4695
4811
|
const t0 = requestStartRaw;
|
|
4696
4812
|
const url = req.originalUrl || req.url || '/';
|
|
@@ -4893,15 +5009,18 @@ function reproMiddleware(cfg) {
|
|
|
4893
5009
|
const activePrivacy = resolvePrivacy();
|
|
4894
5010
|
const requestBodyRaw = req.body;
|
|
4895
5011
|
const requestBodyMaterialization = limitRawInlinePrivacyValue('request.body', requestBodyRaw)
|
|
4896
|
-
?? await materializeInlinePrivacyValueAsync('request.body', sanitizeRequestSnapshot(requestBodyRaw), captureCfg, maskReq, endpointTraceCtx, masking, activePrivacy);
|
|
5012
|
+
?? await materializeInlinePrivacyValueAsync('request.body', sanitizeRequestSnapshot(requestBodyRaw), captureCfg, maskReq, endpointTraceCtx, masking, activePrivacy, undefined, captureScope);
|
|
4897
5013
|
const requestBody = requestBodyMaterialization.value;
|
|
4898
|
-
const
|
|
4899
|
-
const
|
|
4900
|
-
const
|
|
5014
|
+
const requestParamsMaterialization = await materializeInlinePrivacyValueAsync('request.params', sanitizeRequestSnapshot(req.params), captureCfg, maskReq, endpointTraceCtx, masking, activePrivacy, undefined, captureScope);
|
|
5015
|
+
const requestParams = requestParamsMaterialization.value;
|
|
5016
|
+
const requestQueryMaterialization = await materializeInlinePrivacyValueAsync('request.query', sanitizeRequestSnapshot(req.query), captureCfg, maskReq, endpointTraceCtx, masking, activePrivacy, undefined, captureScope);
|
|
5017
|
+
const requestQuery = requestQueryMaterialization.value;
|
|
5018
|
+
const requestHeadersMaterialization = await materializeInlinePrivacyValueAsync('request.headers', requestHeaders, captureCfg, maskReq, endpointTraceCtx, masking, activePrivacy, undefined, captureScope);
|
|
5019
|
+
const maskedHeaders = requestHeadersMaterialization.value;
|
|
4901
5020
|
const responseBodyMaterialization = capturedBody === undefined
|
|
4902
5021
|
? { value: undefined }
|
|
4903
5022
|
: limitRawInlinePrivacyValue('response.body', capturedBody)
|
|
4904
|
-
?? await materializeInlinePrivacyValueAsync('response.body', sanitizeRequestSnapshot(capturedBody), captureCfg, maskReq, endpointTraceCtx, masking, activePrivacy);
|
|
5023
|
+
?? await materializeInlinePrivacyValueAsync('response.body', sanitizeRequestSnapshot(capturedBody), captureCfg, maskReq, endpointTraceCtx, masking, activePrivacy, undefined, captureScope);
|
|
4905
5024
|
const responseBody = responseBodyMaterialization.value;
|
|
4906
5025
|
const requestValueEntries = [];
|
|
4907
5026
|
const bodyValueCapture = requestBodyRaw === undefined
|
|
@@ -4917,8 +5036,9 @@ function reproMiddleware(cfg) {
|
|
|
4917
5036
|
trace: endpointTraceCtx,
|
|
4918
5037
|
masking,
|
|
4919
5038
|
privacy: activePrivacy,
|
|
5039
|
+
valueNamespace: sid,
|
|
4920
5040
|
},
|
|
4921
|
-
}, requestValueEntries);
|
|
5041
|
+
}, requestValueEntries, captureScope);
|
|
4922
5042
|
const paramsValueCapture = await maybeCaptureRequestValueAsync({
|
|
4923
5043
|
target: 'request.params',
|
|
4924
5044
|
rawValue: req.params,
|
|
@@ -4930,8 +5050,9 @@ function reproMiddleware(cfg) {
|
|
|
4930
5050
|
trace: endpointTraceCtx,
|
|
4931
5051
|
masking,
|
|
4932
5052
|
privacy: activePrivacy,
|
|
5053
|
+
valueNamespace: sid,
|
|
4933
5054
|
},
|
|
4934
|
-
}, requestValueEntries);
|
|
5055
|
+
}, requestValueEntries, captureScope);
|
|
4935
5056
|
const queryValueCapture = await maybeCaptureRequestValueAsync({
|
|
4936
5057
|
target: 'request.query',
|
|
4937
5058
|
rawValue: req.query,
|
|
@@ -4943,8 +5064,9 @@ function reproMiddleware(cfg) {
|
|
|
4943
5064
|
trace: endpointTraceCtx,
|
|
4944
5065
|
masking,
|
|
4945
5066
|
privacy: activePrivacy,
|
|
5067
|
+
valueNamespace: sid,
|
|
4946
5068
|
},
|
|
4947
|
-
}, requestValueEntries);
|
|
5069
|
+
}, requestValueEntries, captureScope);
|
|
4948
5070
|
const headersValueCapture = await maybeCaptureRequestValueAsync({
|
|
4949
5071
|
target: 'request.headers',
|
|
4950
5072
|
rawValue: req.headers,
|
|
@@ -4956,8 +5078,9 @@ function reproMiddleware(cfg) {
|
|
|
4956
5078
|
trace: endpointTraceCtx,
|
|
4957
5079
|
masking,
|
|
4958
5080
|
privacy: activePrivacy,
|
|
5081
|
+
valueNamespace: sid,
|
|
4959
5082
|
},
|
|
4960
|
-
}, requestValueEntries);
|
|
5083
|
+
}, requestValueEntries, captureScope);
|
|
4961
5084
|
const respBodyValueCapture = capturedBody === undefined
|
|
4962
5085
|
? undefined
|
|
4963
5086
|
: await maybeCaptureRequestValueAsync({
|
|
@@ -4971,8 +5094,9 @@ function reproMiddleware(cfg) {
|
|
|
4971
5094
|
trace: endpointTraceCtx,
|
|
4972
5095
|
masking,
|
|
4973
5096
|
privacy: activePrivacy,
|
|
5097
|
+
valueNamespace: sid,
|
|
4974
5098
|
},
|
|
4975
|
-
}, requestValueEntries);
|
|
5099
|
+
}, requestValueEntries, captureScope);
|
|
4976
5100
|
const responseDurationMs = finishedAt !== null && Number.isFinite(finishedAt)
|
|
4977
5101
|
? Math.max(0, finishedAt - t0)
|
|
4978
5102
|
: Date.now() - t0;
|
|
@@ -5034,10 +5158,38 @@ function reproMiddleware(cfg) {
|
|
|
5034
5158
|
t: requestEpochMs,
|
|
5035
5159
|
}]
|
|
5036
5160
|
});
|
|
5037
|
-
captureScope.backendRequestCount += 1;
|
|
5038
5161
|
}
|
|
5039
5162
|
catch {
|
|
5040
|
-
|
|
5163
|
+
recordRequestCaptureFailure(captureScope, 'request.capture', 'backend_request', 'request_materialization_failed');
|
|
5164
|
+
// Preserve non-sensitive request metadata so the manifest cannot
|
|
5165
|
+
// silently turn a failed policy capture into a zero-request scope.
|
|
5166
|
+
post(captureCfg, sid, {
|
|
5167
|
+
entries: [{
|
|
5168
|
+
actionId: aid,
|
|
5169
|
+
request: {
|
|
5170
|
+
rid,
|
|
5171
|
+
method: req.method,
|
|
5172
|
+
url,
|
|
5173
|
+
path,
|
|
5174
|
+
status: res.statusCode,
|
|
5175
|
+
durMs: finishedAt !== null && Number.isFinite(finishedAt)
|
|
5176
|
+
? Math.max(0, finishedAt - t0)
|
|
5177
|
+
: Date.now() - t0,
|
|
5178
|
+
key,
|
|
5179
|
+
bodyMaterialization: {
|
|
5180
|
+
status: 'skipped',
|
|
5181
|
+
reason: 'request_materialization_failed',
|
|
5182
|
+
target: 'request.body',
|
|
5183
|
+
},
|
|
5184
|
+
respBodyMaterialization: {
|
|
5185
|
+
status: 'skipped',
|
|
5186
|
+
reason: 'request_materialization_failed',
|
|
5187
|
+
target: 'response.body',
|
|
5188
|
+
},
|
|
5189
|
+
},
|
|
5190
|
+
t: requestEpochMs,
|
|
5191
|
+
}],
|
|
5192
|
+
});
|
|
5041
5193
|
}
|
|
5042
5194
|
};
|
|
5043
5195
|
const emitRequestCaptureManifest = (traceBatchTotal) => {
|
|
@@ -5151,6 +5303,8 @@ function reproMiddleware(cfg) {
|
|
|
5151
5303
|
maskReq,
|
|
5152
5304
|
masking,
|
|
5153
5305
|
resolvePrivacy,
|
|
5306
|
+
captureScope,
|
|
5307
|
+
valueNamespace: sid,
|
|
5154
5308
|
});
|
|
5155
5309
|
const baseEvents = balanceTraceEvents(materializedEvents.slice());
|
|
5156
5310
|
const orderedEvents = TRACE_ORDER_MODE === 'tree'
|
|
@@ -5165,16 +5319,19 @@ function reproMiddleware(cfg) {
|
|
|
5165
5319
|
}
|
|
5166
5320
|
}
|
|
5167
5321
|
catch {
|
|
5322
|
+
recordRequestCaptureFailure(captureScope, 'trace.capture', 'trace.batches', 'trace_capture_failed');
|
|
5168
5323
|
captureScope.traceBatchCount = 0;
|
|
5169
5324
|
traceBatches = [];
|
|
5170
5325
|
}
|
|
5171
|
-
|
|
5172
|
-
|
|
5173
|
-
|
|
5326
|
+
// Finalize policy/materialization status before publishing the
|
|
5327
|
+
// high-priority manifest. The manifest must lead its evidence
|
|
5328
|
+
// on the wire so a large trace queue cannot starve completion.
|
|
5329
|
+
emitRequestCaptureManifest(traceBatches.length);
|
|
5174
5330
|
try {
|
|
5331
|
+
const emittedValueIds = new Set();
|
|
5175
5332
|
for (let i = 0; i < traceBatches.length; i++) {
|
|
5176
5333
|
const batch = traceBatches[i];
|
|
5177
|
-
const traceValues = collectBatchTraceValueEntries(batch, i);
|
|
5334
|
+
const traceValues = collectBatchTraceValueEntries(batch, i, emittedValueIds);
|
|
5178
5335
|
post(captureCfg, sid, {
|
|
5179
5336
|
entries: [{
|
|
5180
5337
|
actionId: aid,
|
|
@@ -5191,7 +5348,7 @@ function reproMiddleware(cfg) {
|
|
|
5191
5348
|
}
|
|
5192
5349
|
}
|
|
5193
5350
|
catch {
|
|
5194
|
-
|
|
5351
|
+
recordRequestCaptureFailure(captureScope, 'trace.enqueue', 'trace.batches', 'trace_enqueue_failed');
|
|
5195
5352
|
}
|
|
5196
5353
|
};
|
|
5197
5354
|
}
|
|
@@ -5745,12 +5902,6 @@ function dehydrateComplexValue(value) {
|
|
|
5745
5902
|
}
|
|
5746
5903
|
}
|
|
5747
5904
|
catch { }
|
|
5748
|
-
const ctor = value?.constructor?.name;
|
|
5749
|
-
if (ctor && ctor !== 'Object') {
|
|
5750
|
-
const plain = safeJson(value);
|
|
5751
|
-
if (plain !== undefined)
|
|
5752
|
-
return plain;
|
|
5753
|
-
}
|
|
5754
5905
|
return value;
|
|
5755
5906
|
}
|
|
5756
5907
|
function emitDbQuery(cfg, sid, aid, payload) {
|
|
@@ -5758,6 +5909,11 @@ function emitDbQuery(cfg, sid, aid, payload) {
|
|
|
5758
5909
|
const spanContext = payload?.spanContext ?? captureSpanContextFromTracer();
|
|
5759
5910
|
if (!shouldCaptureDbSpan(spanContext))
|
|
5760
5911
|
return;
|
|
5912
|
+
if (sid && ctx.captureScope) {
|
|
5913
|
+
// Count the observed database operation before asynchronous privacy
|
|
5914
|
+
// materialization. A later failure must remain visible to completeness.
|
|
5915
|
+
ctx.captureScope.dbChangeCount += 1;
|
|
5916
|
+
}
|
|
5761
5917
|
const runCtx = {
|
|
5762
5918
|
sid: ctx.sid,
|
|
5763
5919
|
aid: ctx.aid,
|
|
@@ -5769,7 +5925,9 @@ function emitDbQuery(cfg, sid, aid, payload) {
|
|
|
5769
5925
|
};
|
|
5770
5926
|
scheduleSdkBackgroundWork(async () => {
|
|
5771
5927
|
await als.run(runCtx, async () => {
|
|
5772
|
-
await emitDbQueryAsync(cfg, sid, aid, payload).catch(() =>
|
|
5928
|
+
await emitDbQueryAsync(cfg, sid, aid, payload).catch(() => {
|
|
5929
|
+
recordRequestCaptureFailure(runCtx.captureScope, 'db.capture', 'db.change', 'db_capture_failed');
|
|
5930
|
+
});
|
|
5773
5931
|
});
|
|
5774
5932
|
}, { priority: 'high' });
|
|
5775
5933
|
}
|
|
@@ -5814,6 +5972,7 @@ async function emitDbQueryAsync(cfg, sid, aid, payload) {
|
|
|
5814
5972
|
masking: null,
|
|
5815
5973
|
privacy,
|
|
5816
5974
|
db: dbContext,
|
|
5975
|
+
valueNamespace: sid,
|
|
5817
5976
|
};
|
|
5818
5977
|
const dbValues = [];
|
|
5819
5978
|
const pkValueCapture = pkMaterialization.skipped ? undefined : await maybeCaptureDbValueAsync({
|
|
@@ -5821,37 +5980,37 @@ async function emitDbQueryAsync(cfg, sid, aid, payload) {
|
|
|
5821
5980
|
rawValue: payload.pk,
|
|
5822
5981
|
previewValue: pkPreview,
|
|
5823
5982
|
capture,
|
|
5824
|
-
}, dbValues);
|
|
5983
|
+
}, dbValues, ctx.captureScope);
|
|
5825
5984
|
const beforeValueCapture = beforeMaterialization.skipped ? undefined : await maybeCaptureDbValueAsync({
|
|
5826
5985
|
target: 'db.before',
|
|
5827
5986
|
rawValue: payload.before,
|
|
5828
5987
|
previewValue: beforePreview,
|
|
5829
5988
|
capture,
|
|
5830
|
-
}, dbValues);
|
|
5989
|
+
}, dbValues, ctx.captureScope);
|
|
5831
5990
|
const afterValueCapture = afterMaterialization.skipped ? undefined : await maybeCaptureDbValueAsync({
|
|
5832
5991
|
target: 'db.after',
|
|
5833
5992
|
rawValue: payload.after,
|
|
5834
5993
|
previewValue: afterPreview,
|
|
5835
5994
|
capture,
|
|
5836
|
-
}, dbValues);
|
|
5995
|
+
}, dbValues, ctx.captureScope);
|
|
5837
5996
|
const queryValueCapture = queryMaterialization.skipped ? undefined : await maybeCaptureDbValueAsync({
|
|
5838
5997
|
target: 'db.query',
|
|
5839
5998
|
rawValue: querySource,
|
|
5840
5999
|
previewValue: queryPreview,
|
|
5841
6000
|
capture,
|
|
5842
|
-
}, dbValues);
|
|
6001
|
+
}, dbValues, ctx.captureScope);
|
|
5843
6002
|
const resultMetaValueCapture = resultMetaMaterialization.skipped ? undefined : await maybeCaptureDbValueFromCandidatesAsync({
|
|
5844
6003
|
target: 'db.resultMeta',
|
|
5845
6004
|
rawValues: buildResultMetaFullValueCandidates(payload.resultMetaRaw, resultMetaSource),
|
|
5846
6005
|
previewValue: resultMetaPreview,
|
|
5847
6006
|
capture,
|
|
5848
|
-
}, dbValues);
|
|
6007
|
+
}, dbValues, ctx.captureScope);
|
|
5849
6008
|
const errorValueCapture = errorMaterialization.skipped ? undefined : await maybeCaptureDbValueAsync({
|
|
5850
6009
|
target: 'db.error',
|
|
5851
6010
|
rawValue: payload.error,
|
|
5852
6011
|
previewValue: errorPreview,
|
|
5853
6012
|
capture,
|
|
5854
|
-
}, dbValues);
|
|
6013
|
+
}, dbValues, ctx.captureScope);
|
|
5855
6014
|
const dbEntry = attachSpanContext({
|
|
5856
6015
|
type: payload.type ?? 'mongo',
|
|
5857
6016
|
collection: payload.collection,
|
|
@@ -5885,8 +6044,8 @@ async function emitDbQueryAsync(cfg, sid, aid, payload) {
|
|
|
5885
6044
|
t: payload.t,
|
|
5886
6045
|
}]
|
|
5887
6046
|
});
|
|
5888
|
-
if (enqueued
|
|
5889
|
-
ctx.captureScope.
|
|
6047
|
+
if (!enqueued) {
|
|
6048
|
+
recordRequestCaptureFailure(ctx.captureScope, 'db.enqueue', 'db.change', 'db_enqueue_failed');
|
|
5890
6049
|
}
|
|
5891
6050
|
}
|
|
5892
6051
|
function buildMinimalUpdate(before, after) {
|
|
@@ -6293,8 +6452,8 @@ function cloneKafkaTelemetryValue(value) {
|
|
|
6293
6452
|
return value;
|
|
6294
6453
|
}
|
|
6295
6454
|
}
|
|
6296
|
-
async function materializeKafkaRequestBody(cfg, maskReq, body) {
|
|
6297
|
-
return materializeInlinePrivacyValueAsync('request.body', sanitizeInlinePrivacyValue(body), cfg, maskReq, null, normalizeMaskingConfig(cfg.masking), getRuntimePrivacyState(cfg).policy ?? null);
|
|
6455
|
+
async function materializeKafkaRequestBody(cfg, maskReq, body, captureScope) {
|
|
6456
|
+
return materializeInlinePrivacyValueAsync('request.body', sanitizeInlinePrivacyValue(body), cfg, maskReq, null, normalizeMaskingConfig(cfg.masking), getRuntimePrivacyState(cfg).policy ?? null, undefined, captureScope);
|
|
6298
6457
|
}
|
|
6299
6458
|
function summarizeKafkaError(error) {
|
|
6300
6459
|
const message = typeof error?.message === 'string'
|
|
@@ -6393,6 +6552,7 @@ function recordKafkaTraceEvent(raw, sink, cfg, maskReq) {
|
|
|
6393
6552
|
trace: candidate,
|
|
6394
6553
|
masking,
|
|
6395
6554
|
privacy,
|
|
6555
|
+
valueNamespace: getCtx().sid,
|
|
6396
6556
|
};
|
|
6397
6557
|
const traceValueMetadata = {
|
|
6398
6558
|
fn: evt.fn,
|
|
@@ -6530,6 +6690,7 @@ async function recordKafkaTraceEventAsync(raw, sink, cfg, maskReq) {
|
|
|
6530
6690
|
maskReq,
|
|
6531
6691
|
masking,
|
|
6532
6692
|
resolvePrivacy: () => getRuntimePrivacyState(cfg).policy ?? null,
|
|
6693
|
+
valueNamespace: getCtx().sid,
|
|
6533
6694
|
});
|
|
6534
6695
|
sink.push(...materializedEvents);
|
|
6535
6696
|
}
|
|
@@ -6541,10 +6702,11 @@ function buildKafkaTraceEntries(actionId, requestRid, events) {
|
|
|
6541
6702
|
? reorderTraceEvents(baseEvents)
|
|
6542
6703
|
: sortTraceEventsChronologically(baseEvents);
|
|
6543
6704
|
const batches = chunkTraceEventsForTransport(orderedEvents, requestRid, actionId);
|
|
6705
|
+
const emittedValueIds = new Set();
|
|
6544
6706
|
return batches.map((batch, index) => ({
|
|
6545
6707
|
actionId: actionId ?? null,
|
|
6546
6708
|
trace: batch,
|
|
6547
|
-
traceValues: collectBatchTraceValueEntries(batch, index),
|
|
6709
|
+
traceValues: collectBatchTraceValueEntries(batch, index, emittedValueIds),
|
|
6548
6710
|
traceBatch: {
|
|
6549
6711
|
rid: requestRid,
|
|
6550
6712
|
index,
|
|
@@ -6567,23 +6729,28 @@ function scheduleKafkaTraceFlush(cfg, kafkaCtx, actionId, requestRid, rawTraceEv
|
|
|
6567
6729
|
if (evt)
|
|
6568
6730
|
pendingEvents.push(evt);
|
|
6569
6731
|
}
|
|
6570
|
-
|
|
6571
|
-
|
|
6572
|
-
|
|
6573
|
-
|
|
6574
|
-
|
|
6575
|
-
|
|
6576
|
-
|
|
6577
|
-
|
|
6578
|
-
|
|
6579
|
-
|
|
6580
|
-
|
|
6732
|
+
let entries = [];
|
|
6733
|
+
try {
|
|
6734
|
+
if (pendingEvents.length) {
|
|
6735
|
+
const masking = normalizeMaskingConfig(cfg.masking);
|
|
6736
|
+
const preparedEvents = preparePendingTraceEventsForFlush(pendingEvents);
|
|
6737
|
+
const materializedEvents = await materializePendingTraceEventsAsync(preparedEvents, {
|
|
6738
|
+
cfg,
|
|
6739
|
+
maskReq,
|
|
6740
|
+
masking,
|
|
6741
|
+
resolvePrivacy: () => getRuntimePrivacyState(cfg).policy ?? null,
|
|
6742
|
+
captureScope,
|
|
6743
|
+
valueNamespace: sid,
|
|
6744
|
+
});
|
|
6745
|
+
entries = buildKafkaTraceEntries(actionId, requestRid, materializedEvents);
|
|
6746
|
+
}
|
|
6747
|
+
}
|
|
6748
|
+
catch {
|
|
6749
|
+
recordRequestCaptureFailure(captureScope, 'trace.capture', 'trace.batches', 'trace_capture_failed');
|
|
6750
|
+
}
|
|
6581
6751
|
if (captureScope) {
|
|
6582
6752
|
captureScope.traceBatchCount = entries.length;
|
|
6583
6753
|
}
|
|
6584
|
-
if (entries.length) {
|
|
6585
|
-
post(cfg, sid, { entries });
|
|
6586
|
-
}
|
|
6587
6754
|
if (captureScope) {
|
|
6588
6755
|
post(cfg, sid, {
|
|
6589
6756
|
entries: [{
|
|
@@ -6592,7 +6759,10 @@ function scheduleKafkaTraceFlush(cfg, kafkaCtx, actionId, requestRid, rawTraceEv
|
|
|
6592
6759
|
requestCaptureManifest: buildRequestCaptureManifestPayload(captureScope, entries.length),
|
|
6593
6760
|
t: alignedNow(),
|
|
6594
6761
|
}],
|
|
6595
|
-
});
|
|
6762
|
+
}, { priority: 'high' });
|
|
6763
|
+
}
|
|
6764
|
+
if (entries.length) {
|
|
6765
|
+
post(cfg, sid, { entries });
|
|
6596
6766
|
}
|
|
6597
6767
|
});
|
|
6598
6768
|
}, { priority: 'high' });
|
|
@@ -6610,7 +6780,7 @@ function patchKafkaProducerInstance(producer, cfg) {
|
|
|
6610
6780
|
const aid = ctx.aid ?? fallback.aid ?? null;
|
|
6611
6781
|
const span = captureSpanContextFromTracer();
|
|
6612
6782
|
const publishRid = nextRequestId(alignedNow());
|
|
6613
|
-
const captureScope = createRequestCaptureScope(publishRid, 'kafka');
|
|
6783
|
+
const captureScope = createRequestCaptureScope(publishRid, 'kafka', cfg);
|
|
6614
6784
|
emitRequestCaptureStart(cfg, sid, aid, captureScope);
|
|
6615
6785
|
const payloadObj = payload && typeof payload === 'object' ? payload : {};
|
|
6616
6786
|
const topic = sanitizeKafkaTopic(payloadObj.topic);
|
|
@@ -6669,7 +6839,7 @@ function patchKafkaProducerInstance(producer, cfg) {
|
|
|
6669
6839
|
traceId: span?.traceId ?? null,
|
|
6670
6840
|
spanId: span?.spanId ?? null,
|
|
6671
6841
|
parentSpanId: span?.parentSpanId ?? null,
|
|
6672
|
-
});
|
|
6842
|
+
}, captureScope);
|
|
6673
6843
|
const requestPayload = {
|
|
6674
6844
|
rid: publishRid,
|
|
6675
6845
|
method: 'KAFKA_PUBLISH',
|
|
@@ -6698,7 +6868,6 @@ function patchKafkaProducerInstance(producer, cfg) {
|
|
|
6698
6868
|
},
|
|
6699
6869
|
],
|
|
6700
6870
|
});
|
|
6701
|
-
captureScope.backendRequestCount += 1;
|
|
6702
6871
|
post(cfg, sid, {
|
|
6703
6872
|
entries: [{
|
|
6704
6873
|
actionId: aid ?? null,
|
|
@@ -6719,7 +6888,7 @@ function patchKafkaProducerInstance(producer, cfg) {
|
|
|
6719
6888
|
const aid = ctx.aid ?? fallback.aid ?? null;
|
|
6720
6889
|
const span = captureSpanContextFromTracer();
|
|
6721
6890
|
const publishRid = nextRequestId(alignedNow());
|
|
6722
|
-
const captureScope = createRequestCaptureScope(publishRid, 'kafka');
|
|
6891
|
+
const captureScope = createRequestCaptureScope(publishRid, 'kafka', cfg);
|
|
6723
6892
|
emitRequestCaptureStart(cfg, sid, aid, captureScope);
|
|
6724
6893
|
const payloadObj = payload && typeof payload === 'object' ? payload : {};
|
|
6725
6894
|
const topicMessages = Array.isArray(payloadObj.topicMessages)
|
|
@@ -6809,7 +6978,7 @@ function patchKafkaProducerInstance(producer, cfg) {
|
|
|
6809
6978
|
traceId: span?.traceId ?? null,
|
|
6810
6979
|
spanId: span?.spanId ?? null,
|
|
6811
6980
|
parentSpanId: span?.parentSpanId ?? null,
|
|
6812
|
-
});
|
|
6981
|
+
}, captureScope);
|
|
6813
6982
|
const requestPayload = {
|
|
6814
6983
|
rid: publishRid,
|
|
6815
6984
|
method: 'KAFKA_PUBLISH_BATCH',
|
|
@@ -6838,7 +7007,6 @@ function patchKafkaProducerInstance(producer, cfg) {
|
|
|
6838
7007
|
},
|
|
6839
7008
|
],
|
|
6840
7009
|
});
|
|
6841
|
-
captureScope.backendRequestCount += 1;
|
|
6842
7010
|
post(cfg, sid, {
|
|
6843
7011
|
entries: [{
|
|
6844
7012
|
actionId: aid ?? null,
|
|
@@ -6861,7 +7029,7 @@ function wrapKafkaEachMessageHandler(eachMessage, cfg, consumer) {
|
|
|
6861
7029
|
const aid = runtime.aid;
|
|
6862
7030
|
const consumeRid = nextRequestId(`${topic}-${message?.offset ?? alignedNow()}`);
|
|
6863
7031
|
const traceId = consumeRid;
|
|
6864
|
-
const captureScope = createRequestCaptureScope(consumeRid, 'kafka');
|
|
7032
|
+
const captureScope = createRequestCaptureScope(consumeRid, 'kafka', cfg);
|
|
6865
7033
|
emitRequestCaptureStart(cfg, sid, aid, captureScope);
|
|
6866
7034
|
const rawTraceEvents = [];
|
|
6867
7035
|
const maskReq = {
|
|
@@ -6939,7 +7107,7 @@ function wrapKafkaEachMessageHandler(eachMessage, cfg, consumer) {
|
|
|
6939
7107
|
valueEncoding: messagePayload.valueEncoding,
|
|
6940
7108
|
valueBytes: messagePayload.valueBytes,
|
|
6941
7109
|
message: messagePayload,
|
|
6942
|
-
});
|
|
7110
|
+
}, captureScope);
|
|
6943
7111
|
const requestPayload = {
|
|
6944
7112
|
rid: consumeRid,
|
|
6945
7113
|
method: 'KAFKA_CONSUME',
|
|
@@ -6960,7 +7128,6 @@ function wrapKafkaEachMessageHandler(eachMessage, cfg, consumer) {
|
|
|
6960
7128
|
t: alignedNow(),
|
|
6961
7129
|
}],
|
|
6962
7130
|
});
|
|
6963
|
-
captureScope.backendRequestCount += 1;
|
|
6964
7131
|
scheduleKafkaTraceFlush(cfg, kafkaCtx, aid, consumeRid, rawTraceEvents, maskReq, captureScope);
|
|
6965
7132
|
}
|
|
6966
7133
|
};
|
|
@@ -6976,7 +7143,7 @@ function wrapKafkaEachBatchHandler(eachBatch, cfg, consumer) {
|
|
|
6976
7143
|
const aid = runtime.aid;
|
|
6977
7144
|
const consumeRid = nextRequestId(`${topic}-batch-${alignedNow()}`);
|
|
6978
7145
|
const traceId = consumeRid;
|
|
6979
|
-
const captureScope = createRequestCaptureScope(consumeRid, 'kafka');
|
|
7146
|
+
const captureScope = createRequestCaptureScope(consumeRid, 'kafka', cfg);
|
|
6980
7147
|
emitRequestCaptureStart(cfg, sid, aid, captureScope);
|
|
6981
7148
|
const rawTraceEvents = [];
|
|
6982
7149
|
const maskReq = {
|
|
@@ -7052,7 +7219,7 @@ function wrapKafkaEachBatchHandler(eachBatch, cfg, consumer) {
|
|
|
7052
7219
|
parentSpanId: runtime.parentSpanId,
|
|
7053
7220
|
firstMessageKey: firstMessagePayload?.key ?? null,
|
|
7054
7221
|
messages: messages.map((message) => buildKafkaMessagePayload(message)),
|
|
7055
|
-
});
|
|
7222
|
+
}, captureScope);
|
|
7056
7223
|
const requestPayload = {
|
|
7057
7224
|
rid: consumeRid,
|
|
7058
7225
|
method: 'KAFKA_CONSUME_BATCH',
|
|
@@ -7073,7 +7240,6 @@ function wrapKafkaEachBatchHandler(eachBatch, cfg, consumer) {
|
|
|
7073
7240
|
t: alignedNow(),
|
|
7074
7241
|
}],
|
|
7075
7242
|
});
|
|
7076
|
-
captureScope.backendRequestCount += 1;
|
|
7077
7243
|
scheduleKafkaTraceFlush(cfg, kafkaCtx, aid, consumeRid, rawTraceEvents, maskReq, captureScope);
|
|
7078
7244
|
}
|
|
7079
7245
|
};
|
|
@@ -7453,24 +7619,24 @@ function scheduleAmqpTraceFlush(cfg, amqpCtx, actionId, requestRid, rawTraceEven
|
|
|
7453
7619
|
pendingEvents.push(evt);
|
|
7454
7620
|
}
|
|
7455
7621
|
let entries = [];
|
|
7456
|
-
|
|
7457
|
-
|
|
7458
|
-
|
|
7459
|
-
|
|
7460
|
-
|
|
7461
|
-
|
|
7462
|
-
|
|
7463
|
-
|
|
7464
|
-
|
|
7465
|
-
|
|
7466
|
-
|
|
7467
|
-
|
|
7468
|
-
post(cfg, sid, { entries });
|
|
7622
|
+
try {
|
|
7623
|
+
if (pendingEvents.length) {
|
|
7624
|
+
const masking = normalizeMaskingConfig(cfg.masking);
|
|
7625
|
+
const preparedEvents = preparePendingTraceEventsForFlush(pendingEvents);
|
|
7626
|
+
const materializedEvents = await materializePendingTraceEventsAsync(preparedEvents, {
|
|
7627
|
+
cfg,
|
|
7628
|
+
maskReq,
|
|
7629
|
+
masking,
|
|
7630
|
+
resolvePrivacy: () => getRuntimePrivacyState(cfg).policy ?? null,
|
|
7631
|
+
captureScope,
|
|
7632
|
+
});
|
|
7633
|
+
entries = buildAmqpTraceEntries(actionId, requestRid, materializedEvents);
|
|
7469
7634
|
}
|
|
7470
7635
|
}
|
|
7471
|
-
|
|
7472
|
-
captureScope.
|
|
7636
|
+
catch {
|
|
7637
|
+
recordRequestCaptureFailure(captureScope, 'trace.capture', 'trace.batches', 'trace_capture_failed');
|
|
7473
7638
|
}
|
|
7639
|
+
captureScope.traceBatchCount = entries.length;
|
|
7474
7640
|
post(cfg, sid, {
|
|
7475
7641
|
entries: [{
|
|
7476
7642
|
actionId: actionId ?? null,
|
|
@@ -7478,7 +7644,10 @@ function scheduleAmqpTraceFlush(cfg, amqpCtx, actionId, requestRid, rawTraceEven
|
|
|
7478
7644
|
requestCaptureManifest: buildRequestCaptureManifestPayload(captureScope, entries.length),
|
|
7479
7645
|
t: alignedNow(),
|
|
7480
7646
|
}],
|
|
7481
|
-
});
|
|
7647
|
+
}, { priority: 'high' });
|
|
7648
|
+
if (entries.length) {
|
|
7649
|
+
post(cfg, sid, { entries });
|
|
7650
|
+
}
|
|
7482
7651
|
});
|
|
7483
7652
|
}, { priority: 'high' });
|
|
7484
7653
|
}
|
|
@@ -7524,7 +7693,7 @@ function scheduleAmqpPublishCapture(params) {
|
|
|
7524
7693
|
parentSpanId: params.span?.parentSpanId ?? null,
|
|
7525
7694
|
};
|
|
7526
7695
|
scheduleSdkBackgroundWork(async () => {
|
|
7527
|
-
const bodyMaterialization = await materializeKafkaRequestBody(params.cfg, maskReq, body);
|
|
7696
|
+
const bodyMaterialization = await materializeKafkaRequestBody(params.cfg, maskReq, body, params.captureScope);
|
|
7528
7697
|
const requestPayload = {
|
|
7529
7698
|
rid: params.publishRid,
|
|
7530
7699
|
method: params.method,
|
|
@@ -7554,7 +7723,6 @@ function scheduleAmqpPublishCapture(params) {
|
|
|
7554
7723
|
t: alignedNow(),
|
|
7555
7724
|
}],
|
|
7556
7725
|
});
|
|
7557
|
-
params.captureScope.backendRequestCount += 1;
|
|
7558
7726
|
post(params.cfg, params.sid, {
|
|
7559
7727
|
entries: [{
|
|
7560
7728
|
actionId: params.aid ?? null,
|
|
@@ -7605,7 +7773,7 @@ function patchAmqplibPublishMethod(channel, cfg, methodName) {
|
|
|
7605
7773
|
: `amqp://queue/${queue}`;
|
|
7606
7774
|
const key = `${method} ${methodName === 'publish' ? `${exchange || 'default'}/${routingKey}` : queue}`;
|
|
7607
7775
|
const content = methodName === 'publish' ? args[2] : args[1];
|
|
7608
|
-
const captureScope = createRequestCaptureScope(publishRid, 'amqp');
|
|
7776
|
+
const captureScope = createRequestCaptureScope(publishRid, 'amqp', cfg);
|
|
7609
7777
|
emitRequestCaptureStart(cfg, sid, aid, captureScope);
|
|
7610
7778
|
const t0 = Date.now();
|
|
7611
7779
|
let finished = false;
|
|
@@ -7692,7 +7860,7 @@ function wrapAmqplibConsumeHandler(onMessage, cfg, queue) {
|
|
|
7692
7860
|
const deliveryTag = message?.fields?.deliveryTag ?? alignedNow();
|
|
7693
7861
|
const consumeRid = nextRequestId(`${queueName}-${deliveryTag}`);
|
|
7694
7862
|
const traceId = consumeRid;
|
|
7695
|
-
const captureScope = createRequestCaptureScope(consumeRid, 'amqp');
|
|
7863
|
+
const captureScope = createRequestCaptureScope(consumeRid, 'amqp', cfg);
|
|
7696
7864
|
emitRequestCaptureStart(cfg, sid, aid, captureScope);
|
|
7697
7865
|
const rawTraceEvents = [];
|
|
7698
7866
|
const maskReq = {
|
|
@@ -7782,7 +7950,7 @@ function wrapAmqplibConsumeHandler(onMessage, cfg, queue) {
|
|
|
7782
7950
|
properties: buildAmqpMessagePropertiesPayload(properties),
|
|
7783
7951
|
};
|
|
7784
7952
|
scheduleSdkBackgroundWork(async () => {
|
|
7785
|
-
const bodyMaterialization = await materializeKafkaRequestBody(cfg, maskReq, body);
|
|
7953
|
+
const bodyMaterialization = await materializeKafkaRequestBody(cfg, maskReq, body, captureScope);
|
|
7786
7954
|
const requestPayload = {
|
|
7787
7955
|
rid: consumeRid,
|
|
7788
7956
|
method: 'AMQP_CONSUME',
|
|
@@ -7803,7 +7971,6 @@ function wrapAmqplibConsumeHandler(onMessage, cfg, queue) {
|
|
|
7803
7971
|
t: alignedNow(),
|
|
7804
7972
|
}],
|
|
7805
7973
|
});
|
|
7806
|
-
captureScope.backendRequestCount += 1;
|
|
7807
7974
|
scheduleAmqpTraceFlush(cfg, amqpCtx, aid, consumeRid, rawTraceEvents, maskReq, captureScope);
|
|
7808
7975
|
}, { priority: 'high' });
|
|
7809
7976
|
};
|
|
@@ -9978,5 +10145,6 @@ exports.__reproTestHooks = {
|
|
|
9978
10145
|
estimateTraceBatchSerializedBytesForTest: estimateTraceBatchSerializedBytes,
|
|
9979
10146
|
sanitizeTraceValueForPrivacyForTest: sanitizeTraceValueForPrivacy,
|
|
9980
10147
|
sanitizeMaterializedTraceValueForTest: sanitizeMaterializedTraceValue,
|
|
10148
|
+
projectSemanticInfrastructureValueForTest: semantic_serialization_1.projectSemanticInfrastructureValue,
|
|
9981
10149
|
getEventTraceValueEntriesForTest: getEventTraceValueEntries,
|
|
9982
10150
|
};
|