@sentry/browser 10.32.0-alpha.0 → 10.32.1
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/build/npm/cjs/dev/index.js +0 -3
- package/build/npm/cjs/dev/index.js.map +1 -1
- package/build/npm/cjs/dev/integrations/httpcontext.js +1 -27
- package/build/npm/cjs/dev/integrations/httpcontext.js.map +1 -1
- package/build/npm/cjs/dev/tracing/request.js +0 -1
- package/build/npm/cjs/dev/tracing/request.js.map +1 -1
- package/build/npm/cjs/prod/index.js +0 -3
- package/build/npm/cjs/prod/index.js.map +1 -1
- package/build/npm/cjs/prod/integrations/httpcontext.js +1 -27
- package/build/npm/cjs/prod/integrations/httpcontext.js.map +1 -1
- package/build/npm/cjs/prod/tracing/request.js +0 -1
- package/build/npm/cjs/prod/tracing/request.js.map +1 -1
- package/build/npm/esm/dev/index.js +1 -2
- package/build/npm/esm/dev/index.js.map +1 -1
- package/build/npm/esm/dev/integrations/httpcontext.js +2 -28
- package/build/npm/esm/dev/integrations/httpcontext.js.map +1 -1
- package/build/npm/esm/dev/package.json +1 -1
- package/build/npm/esm/dev/tracing/request.js +0 -1
- package/build/npm/esm/dev/tracing/request.js.map +1 -1
- package/build/npm/esm/prod/index.js +1 -2
- package/build/npm/esm/prod/index.js.map +1 -1
- package/build/npm/esm/prod/integrations/httpcontext.js +2 -28
- package/build/npm/esm/prod/integrations/httpcontext.js.map +1 -1
- package/build/npm/esm/prod/package.json +1 -1
- package/build/npm/esm/prod/tracing/request.js +0 -1
- package/build/npm/esm/prod/tracing/request.js.map +1 -1
- package/build/npm/types/index.d.ts +1 -2
- package/build/npm/types/index.d.ts.map +1 -1
- package/build/npm/types/integrations/httpcontext.d.ts.map +1 -1
- package/build/npm/types/tracing/request.d.ts.map +1 -1
- package/build/npm/types-ts3.8/index.d.ts +1 -2
- package/package.json +7 -7
- package/build/npm/cjs/dev/integrations/spanstreaming.js +0 -124
- package/build/npm/cjs/dev/integrations/spanstreaming.js.map +0 -1
- package/build/npm/cjs/prod/integrations/spanstreaming.js +0 -124
- package/build/npm/cjs/prod/integrations/spanstreaming.js.map +0 -1
- package/build/npm/esm/dev/integrations/spanstreaming.js +0 -122
- package/build/npm/esm/dev/integrations/spanstreaming.js.map +0 -1
- package/build/npm/esm/prod/integrations/spanstreaming.js +0 -122
- package/build/npm/esm/prod/integrations/spanstreaming.js.map +0 -1
- package/build/npm/types/integrations/spanstreaming.d.ts +0 -5
- package/build/npm/types/integrations/spanstreaming.d.ts.map +0 -1
- package/build/npm/types-ts3.8/integrations/spanstreaming.d.ts +0 -5
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
-
|
|
3
|
-
const core = require('@sentry/core');
|
|
4
|
-
const debugBuild = require('../debug-build.js');
|
|
5
|
-
|
|
6
|
-
const spanStreamingIntegration = core.defineIntegration(((userOptions) => {
|
|
7
|
-
const validatedUserProvidedBatchLimit =
|
|
8
|
-
userOptions?.batchLimit && userOptions.batchLimit <= 1000 && userOptions.batchLimit >= 1
|
|
9
|
-
? userOptions.batchLimit
|
|
10
|
-
: undefined;
|
|
11
|
-
|
|
12
|
-
if (debugBuild.DEBUG_BUILD && userOptions?.batchLimit && !validatedUserProvidedBatchLimit) {
|
|
13
|
-
core.debug.warn('SpanStreaming batchLimit must be between 1 and 1000, defaulting to 1000');
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const options = {
|
|
17
|
-
...userOptions,
|
|
18
|
-
batchLimit:
|
|
19
|
-
userOptions?.batchLimit && userOptions.batchLimit <= 1000 && userOptions.batchLimit >= 1
|
|
20
|
-
? userOptions.batchLimit
|
|
21
|
-
: 1000,
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
// key: traceId-segmentSpanId
|
|
25
|
-
const spanTreeMap = new Map();
|
|
26
|
-
|
|
27
|
-
return {
|
|
28
|
-
name: 'SpanStreaming',
|
|
29
|
-
setup(client) {
|
|
30
|
-
const clientOptions = client.getOptions();
|
|
31
|
-
const beforeSendSpan = clientOptions.beforeSendSpan;
|
|
32
|
-
|
|
33
|
-
const initialMessage = 'spanStreamingIntegration requires';
|
|
34
|
-
const fallbackMsg = 'Falling back to static trace lifecycle.';
|
|
35
|
-
|
|
36
|
-
if (clientOptions.traceLifecycle !== 'stream') {
|
|
37
|
-
debugBuild.DEBUG_BUILD && core.debug.warn(`${initialMessage} \`traceLifecycle\` to be set to "stream"! ${fallbackMsg}`);
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
if (beforeSendSpan && !core.isV2BeforeSendSpanCallback(beforeSendSpan)) {
|
|
42
|
-
client.getOptions().traceLifecycle = 'static';
|
|
43
|
-
core.debug.warn(`${initialMessage} a beforeSendSpan callback using \`withStreamSpan\`! ${fallbackMsg}`);
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
client.on('enqueueSpan', spanJSON => {
|
|
48
|
-
const spanTreeMapKey = getSpanTreeMapKey(spanJSON);
|
|
49
|
-
const spanBuffer = spanTreeMap.get(spanTreeMapKey);
|
|
50
|
-
if (spanBuffer) {
|
|
51
|
-
spanBuffer.add(spanJSON);
|
|
52
|
-
} else {
|
|
53
|
-
spanTreeMap.set(spanTreeMapKey, new Set([spanJSON]));
|
|
54
|
-
}
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
client.on('afterSpanEnd', span => {
|
|
58
|
-
core.captureSpan(span, client);
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
// For now, we send all spans on local segment (root) span end.
|
|
62
|
-
// TODO: This will change once we have more concrete ideas about a universal SDK data buffer.
|
|
63
|
-
client.on('afterSegmentSpanEnd', segmentSpan => {
|
|
64
|
-
sendSegment(segmentSpan, {
|
|
65
|
-
spanTreeMap,
|
|
66
|
-
client,
|
|
67
|
-
batchLimit: options.batchLimit,
|
|
68
|
-
});
|
|
69
|
-
});
|
|
70
|
-
},
|
|
71
|
-
};
|
|
72
|
-
}) );
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Just the traceid alone isn't enough because there can be multiple span trees with the same traceid.
|
|
76
|
-
*/
|
|
77
|
-
function getSpanTreeMapKey(spanJSON) {
|
|
78
|
-
return `${spanJSON.trace_id}-${spanJSON._segmentSpan?.spanContext().spanId || spanJSON.span_id}`;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
function sendSegment(segmentSpan, { client, spanTreeMap, batchLimit }) {
|
|
82
|
-
const traceId = segmentSpan.spanContext().traceId;
|
|
83
|
-
const segmentSpanId = segmentSpan.spanContext().spanId;
|
|
84
|
-
const spanTreeMapKey = `${traceId}-${segmentSpanId}`;
|
|
85
|
-
const spansOfTrace = spanTreeMap.get(spanTreeMapKey);
|
|
86
|
-
|
|
87
|
-
if (!spansOfTrace?.size) {
|
|
88
|
-
spanTreeMap.delete(spanTreeMapKey);
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// Apply beforeSendSpan callback and clean up segment span references
|
|
93
|
-
const finalSpans = Array.from(spansOfTrace).map(spanJSON => {
|
|
94
|
-
// Remove the segment span reference before processing
|
|
95
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
96
|
-
const { _segmentSpan, ...cleanSpanJSON } = spanJSON;
|
|
97
|
-
return cleanSpanJSON;
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
const batches = [];
|
|
101
|
-
for (let i = 0; i < finalSpans.length; i += batchLimit) {
|
|
102
|
-
batches.push(finalSpans.slice(i, i + batchLimit));
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
debugBuild.DEBUG_BUILD && core.debug.log(`Sending trace ${traceId} in ${batches.length} batch${batches.length === 1 ? '' : 'es'}`);
|
|
106
|
-
|
|
107
|
-
// Compute DSC from the segment span (passed as parameter)
|
|
108
|
-
const dsc = core.getDynamicSamplingContextFromSpan(segmentSpan);
|
|
109
|
-
|
|
110
|
-
for (const batch of batches) {
|
|
111
|
-
const envelope = core.createSpanV2Envelope(batch, dsc, client);
|
|
112
|
-
// no need to handle client reports for network errors,
|
|
113
|
-
// buffer overflows or rate limiting here. All of this is handled
|
|
114
|
-
// by client and transport.
|
|
115
|
-
client.sendEnvelope(envelope).then(null, reason => {
|
|
116
|
-
debugBuild.DEBUG_BUILD && core.debug.error('Error while sending span stream envelope:', reason);
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
spanTreeMap.delete(spanTreeMapKey);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
exports.spanStreamingIntegration = spanStreamingIntegration;
|
|
124
|
-
//# sourceMappingURL=spanstreaming.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"spanstreaming.js","sources":["../../../../../src/integrations/spanstreaming.ts"],"sourcesContent":["import type { Client, IntegrationFn, Span, SpanV2JSON, SpanV2JSONWithSegmentRef } from '@sentry/core';\nimport {\n captureSpan,\n createSpanV2Envelope,\n debug,\n defineIntegration,\n getDynamicSamplingContextFromSpan,\n isV2BeforeSendSpanCallback,\n} from '@sentry/core';\nimport { DEBUG_BUILD } from '../debug-build';\n\nexport interface SpanStreamingOptions {\n batchLimit: number;\n}\n\nexport const spanStreamingIntegration = defineIntegration(((userOptions?: Partial<SpanStreamingOptions>) => {\n const validatedUserProvidedBatchLimit =\n userOptions?.batchLimit && userOptions.batchLimit <= 1000 && userOptions.batchLimit >= 1\n ? userOptions.batchLimit\n : undefined;\n\n if (DEBUG_BUILD && userOptions?.batchLimit && !validatedUserProvidedBatchLimit) {\n debug.warn('SpanStreaming batchLimit must be between 1 and 1000, defaulting to 1000');\n }\n\n const options: SpanStreamingOptions = {\n ...userOptions,\n batchLimit:\n userOptions?.batchLimit && userOptions.batchLimit <= 1000 && userOptions.batchLimit >= 1\n ? userOptions.batchLimit\n : 1000,\n };\n\n // key: traceId-segmentSpanId\n const spanTreeMap = new Map<string, Set<SpanV2JSONWithSegmentRef>>();\n\n return {\n name: 'SpanStreaming',\n setup(client) {\n const clientOptions = client.getOptions();\n const beforeSendSpan = clientOptions.beforeSendSpan;\n\n const initialMessage = 'spanStreamingIntegration requires';\n const fallbackMsg = 'Falling back to static trace lifecycle.';\n\n if (clientOptions.traceLifecycle !== 'stream') {\n DEBUG_BUILD && debug.warn(`${initialMessage} \\`traceLifecycle\\` to be set to \"stream\"! ${fallbackMsg}`);\n return;\n }\n\n if (beforeSendSpan && !isV2BeforeSendSpanCallback(beforeSendSpan)) {\n client.getOptions().traceLifecycle = 'static';\n debug.warn(`${initialMessage} a beforeSendSpan callback using \\`withStreamSpan\\`! ${fallbackMsg}`);\n return;\n }\n\n client.on('enqueueSpan', spanJSON => {\n const spanTreeMapKey = getSpanTreeMapKey(spanJSON);\n const spanBuffer = spanTreeMap.get(spanTreeMapKey);\n if (spanBuffer) {\n spanBuffer.add(spanJSON);\n } else {\n spanTreeMap.set(spanTreeMapKey, new Set([spanJSON]));\n }\n });\n\n client.on('afterSpanEnd', span => {\n captureSpan(span, client);\n });\n\n // For now, we send all spans on local segment (root) span end.\n // TODO: This will change once we have more concrete ideas about a universal SDK data buffer.\n client.on('afterSegmentSpanEnd', segmentSpan => {\n sendSegment(segmentSpan, {\n spanTreeMap,\n client,\n batchLimit: options.batchLimit,\n });\n });\n },\n };\n}) satisfies IntegrationFn);\n\ninterface SpanProcessingOptions {\n client: Client;\n spanTreeMap: Map<string, Set<SpanV2JSONWithSegmentRef>>;\n batchLimit: number;\n}\n\n/**\n * Just the traceid alone isn't enough because there can be multiple span trees with the same traceid.\n */\nfunction getSpanTreeMapKey(spanJSON: SpanV2JSONWithSegmentRef): string {\n return `${spanJSON.trace_id}-${spanJSON._segmentSpan?.spanContext().spanId || spanJSON.span_id}`;\n}\n\nfunction sendSegment(segmentSpan: Span, { client, spanTreeMap, batchLimit }: SpanProcessingOptions): void {\n const traceId = segmentSpan.spanContext().traceId;\n const segmentSpanId = segmentSpan.spanContext().spanId;\n const spanTreeMapKey = `${traceId}-${segmentSpanId}`;\n const spansOfTrace = spanTreeMap.get(spanTreeMapKey);\n\n if (!spansOfTrace?.size) {\n spanTreeMap.delete(spanTreeMapKey);\n return;\n }\n\n // Apply beforeSendSpan callback and clean up segment span references\n const finalSpans = Array.from(spansOfTrace).map(spanJSON => {\n // Remove the segment span reference before processing\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { _segmentSpan, ...cleanSpanJSON } = spanJSON;\n return cleanSpanJSON;\n });\n\n const batches: SpanV2JSON[][] = [];\n for (let i = 0; i < finalSpans.length; i += batchLimit) {\n batches.push(finalSpans.slice(i, i + batchLimit));\n }\n\n DEBUG_BUILD && debug.log(`Sending trace ${traceId} in ${batches.length} batch${batches.length === 1 ? '' : 'es'}`);\n\n // Compute DSC from the segment span (passed as parameter)\n const dsc = getDynamicSamplingContextFromSpan(segmentSpan);\n\n for (const batch of batches) {\n const envelope = createSpanV2Envelope(batch, dsc, client);\n // no need to handle client reports for network errors,\n // buffer overflows or rate limiting here. All of this is handled\n // by client and transport.\n client.sendEnvelope(envelope).then(null, reason => {\n DEBUG_BUILD && debug.error('Error while sending span stream envelope:', reason);\n });\n }\n\n spanTreeMap.delete(spanTreeMapKey);\n}\n"],"names":["defineIntegration","DEBUG_BUILD","debug","isV2BeforeSendSpanCallback","captureSpan","getDynamicSamplingContextFromSpan","createSpanV2Envelope"],"mappings":"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"}
|
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
import { defineIntegration, debug, isV2BeforeSendSpanCallback, captureSpan, getDynamicSamplingContextFromSpan, createSpanV2Envelope } from '@sentry/core';
|
|
2
|
-
import { DEBUG_BUILD } from '../debug-build.js';
|
|
3
|
-
|
|
4
|
-
const spanStreamingIntegration = defineIntegration(((userOptions) => {
|
|
5
|
-
const validatedUserProvidedBatchLimit =
|
|
6
|
-
userOptions?.batchLimit && userOptions.batchLimit <= 1000 && userOptions.batchLimit >= 1
|
|
7
|
-
? userOptions.batchLimit
|
|
8
|
-
: undefined;
|
|
9
|
-
|
|
10
|
-
if (DEBUG_BUILD && userOptions?.batchLimit && !validatedUserProvidedBatchLimit) {
|
|
11
|
-
debug.warn('SpanStreaming batchLimit must be between 1 and 1000, defaulting to 1000');
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const options = {
|
|
15
|
-
...userOptions,
|
|
16
|
-
batchLimit:
|
|
17
|
-
userOptions?.batchLimit && userOptions.batchLimit <= 1000 && userOptions.batchLimit >= 1
|
|
18
|
-
? userOptions.batchLimit
|
|
19
|
-
: 1000,
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
// key: traceId-segmentSpanId
|
|
23
|
-
const spanTreeMap = new Map();
|
|
24
|
-
|
|
25
|
-
return {
|
|
26
|
-
name: 'SpanStreaming',
|
|
27
|
-
setup(client) {
|
|
28
|
-
const clientOptions = client.getOptions();
|
|
29
|
-
const beforeSendSpan = clientOptions.beforeSendSpan;
|
|
30
|
-
|
|
31
|
-
const initialMessage = 'spanStreamingIntegration requires';
|
|
32
|
-
const fallbackMsg = 'Falling back to static trace lifecycle.';
|
|
33
|
-
|
|
34
|
-
if (clientOptions.traceLifecycle !== 'stream') {
|
|
35
|
-
DEBUG_BUILD && debug.warn(`${initialMessage} \`traceLifecycle\` to be set to "stream"! ${fallbackMsg}`);
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
if (beforeSendSpan && !isV2BeforeSendSpanCallback(beforeSendSpan)) {
|
|
40
|
-
client.getOptions().traceLifecycle = 'static';
|
|
41
|
-
debug.warn(`${initialMessage} a beforeSendSpan callback using \`withStreamSpan\`! ${fallbackMsg}`);
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
client.on('enqueueSpan', spanJSON => {
|
|
46
|
-
const spanTreeMapKey = getSpanTreeMapKey(spanJSON);
|
|
47
|
-
const spanBuffer = spanTreeMap.get(spanTreeMapKey);
|
|
48
|
-
if (spanBuffer) {
|
|
49
|
-
spanBuffer.add(spanJSON);
|
|
50
|
-
} else {
|
|
51
|
-
spanTreeMap.set(spanTreeMapKey, new Set([spanJSON]));
|
|
52
|
-
}
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
client.on('afterSpanEnd', span => {
|
|
56
|
-
captureSpan(span, client);
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
// For now, we send all spans on local segment (root) span end.
|
|
60
|
-
// TODO: This will change once we have more concrete ideas about a universal SDK data buffer.
|
|
61
|
-
client.on('afterSegmentSpanEnd', segmentSpan => {
|
|
62
|
-
sendSegment(segmentSpan, {
|
|
63
|
-
spanTreeMap,
|
|
64
|
-
client,
|
|
65
|
-
batchLimit: options.batchLimit,
|
|
66
|
-
});
|
|
67
|
-
});
|
|
68
|
-
},
|
|
69
|
-
};
|
|
70
|
-
}) );
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Just the traceid alone isn't enough because there can be multiple span trees with the same traceid.
|
|
74
|
-
*/
|
|
75
|
-
function getSpanTreeMapKey(spanJSON) {
|
|
76
|
-
return `${spanJSON.trace_id}-${spanJSON._segmentSpan?.spanContext().spanId || spanJSON.span_id}`;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
function sendSegment(segmentSpan, { client, spanTreeMap, batchLimit }) {
|
|
80
|
-
const traceId = segmentSpan.spanContext().traceId;
|
|
81
|
-
const segmentSpanId = segmentSpan.spanContext().spanId;
|
|
82
|
-
const spanTreeMapKey = `${traceId}-${segmentSpanId}`;
|
|
83
|
-
const spansOfTrace = spanTreeMap.get(spanTreeMapKey);
|
|
84
|
-
|
|
85
|
-
if (!spansOfTrace?.size) {
|
|
86
|
-
spanTreeMap.delete(spanTreeMapKey);
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// Apply beforeSendSpan callback and clean up segment span references
|
|
91
|
-
const finalSpans = Array.from(spansOfTrace).map(spanJSON => {
|
|
92
|
-
// Remove the segment span reference before processing
|
|
93
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
94
|
-
const { _segmentSpan, ...cleanSpanJSON } = spanJSON;
|
|
95
|
-
return cleanSpanJSON;
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
const batches = [];
|
|
99
|
-
for (let i = 0; i < finalSpans.length; i += batchLimit) {
|
|
100
|
-
batches.push(finalSpans.slice(i, i + batchLimit));
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
DEBUG_BUILD && debug.log(`Sending trace ${traceId} in ${batches.length} batch${batches.length === 1 ? '' : 'es'}`);
|
|
104
|
-
|
|
105
|
-
// Compute DSC from the segment span (passed as parameter)
|
|
106
|
-
const dsc = getDynamicSamplingContextFromSpan(segmentSpan);
|
|
107
|
-
|
|
108
|
-
for (const batch of batches) {
|
|
109
|
-
const envelope = createSpanV2Envelope(batch, dsc, client);
|
|
110
|
-
// no need to handle client reports for network errors,
|
|
111
|
-
// buffer overflows or rate limiting here. All of this is handled
|
|
112
|
-
// by client and transport.
|
|
113
|
-
client.sendEnvelope(envelope).then(null, reason => {
|
|
114
|
-
DEBUG_BUILD && debug.error('Error while sending span stream envelope:', reason);
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
spanTreeMap.delete(spanTreeMapKey);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
export { spanStreamingIntegration };
|
|
122
|
-
//# sourceMappingURL=spanstreaming.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"spanstreaming.js","sources":["../../../../../src/integrations/spanstreaming.ts"],"sourcesContent":["import type { Client, IntegrationFn, Span, SpanV2JSON, SpanV2JSONWithSegmentRef } from '@sentry/core';\nimport {\n captureSpan,\n createSpanV2Envelope,\n debug,\n defineIntegration,\n getDynamicSamplingContextFromSpan,\n isV2BeforeSendSpanCallback,\n} from '@sentry/core';\nimport { DEBUG_BUILD } from '../debug-build';\n\nexport interface SpanStreamingOptions {\n batchLimit: number;\n}\n\nexport const spanStreamingIntegration = defineIntegration(((userOptions?: Partial<SpanStreamingOptions>) => {\n const validatedUserProvidedBatchLimit =\n userOptions?.batchLimit && userOptions.batchLimit <= 1000 && userOptions.batchLimit >= 1\n ? userOptions.batchLimit\n : undefined;\n\n if (DEBUG_BUILD && userOptions?.batchLimit && !validatedUserProvidedBatchLimit) {\n debug.warn('SpanStreaming batchLimit must be between 1 and 1000, defaulting to 1000');\n }\n\n const options: SpanStreamingOptions = {\n ...userOptions,\n batchLimit:\n userOptions?.batchLimit && userOptions.batchLimit <= 1000 && userOptions.batchLimit >= 1\n ? userOptions.batchLimit\n : 1000,\n };\n\n // key: traceId-segmentSpanId\n const spanTreeMap = new Map<string, Set<SpanV2JSONWithSegmentRef>>();\n\n return {\n name: 'SpanStreaming',\n setup(client) {\n const clientOptions = client.getOptions();\n const beforeSendSpan = clientOptions.beforeSendSpan;\n\n const initialMessage = 'spanStreamingIntegration requires';\n const fallbackMsg = 'Falling back to static trace lifecycle.';\n\n if (clientOptions.traceLifecycle !== 'stream') {\n DEBUG_BUILD && debug.warn(`${initialMessage} \\`traceLifecycle\\` to be set to \"stream\"! ${fallbackMsg}`);\n return;\n }\n\n if (beforeSendSpan && !isV2BeforeSendSpanCallback(beforeSendSpan)) {\n client.getOptions().traceLifecycle = 'static';\n debug.warn(`${initialMessage} a beforeSendSpan callback using \\`withStreamSpan\\`! ${fallbackMsg}`);\n return;\n }\n\n client.on('enqueueSpan', spanJSON => {\n const spanTreeMapKey = getSpanTreeMapKey(spanJSON);\n const spanBuffer = spanTreeMap.get(spanTreeMapKey);\n if (spanBuffer) {\n spanBuffer.add(spanJSON);\n } else {\n spanTreeMap.set(spanTreeMapKey, new Set([spanJSON]));\n }\n });\n\n client.on('afterSpanEnd', span => {\n captureSpan(span, client);\n });\n\n // For now, we send all spans on local segment (root) span end.\n // TODO: This will change once we have more concrete ideas about a universal SDK data buffer.\n client.on('afterSegmentSpanEnd', segmentSpan => {\n sendSegment(segmentSpan, {\n spanTreeMap,\n client,\n batchLimit: options.batchLimit,\n });\n });\n },\n };\n}) satisfies IntegrationFn);\n\ninterface SpanProcessingOptions {\n client: Client;\n spanTreeMap: Map<string, Set<SpanV2JSONWithSegmentRef>>;\n batchLimit: number;\n}\n\n/**\n * Just the traceid alone isn't enough because there can be multiple span trees with the same traceid.\n */\nfunction getSpanTreeMapKey(spanJSON: SpanV2JSONWithSegmentRef): string {\n return `${spanJSON.trace_id}-${spanJSON._segmentSpan?.spanContext().spanId || spanJSON.span_id}`;\n}\n\nfunction sendSegment(segmentSpan: Span, { client, spanTreeMap, batchLimit }: SpanProcessingOptions): void {\n const traceId = segmentSpan.spanContext().traceId;\n const segmentSpanId = segmentSpan.spanContext().spanId;\n const spanTreeMapKey = `${traceId}-${segmentSpanId}`;\n const spansOfTrace = spanTreeMap.get(spanTreeMapKey);\n\n if (!spansOfTrace?.size) {\n spanTreeMap.delete(spanTreeMapKey);\n return;\n }\n\n // Apply beforeSendSpan callback and clean up segment span references\n const finalSpans = Array.from(spansOfTrace).map(spanJSON => {\n // Remove the segment span reference before processing\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { _segmentSpan, ...cleanSpanJSON } = spanJSON;\n return cleanSpanJSON;\n });\n\n const batches: SpanV2JSON[][] = [];\n for (let i = 0; i < finalSpans.length; i += batchLimit) {\n batches.push(finalSpans.slice(i, i + batchLimit));\n }\n\n DEBUG_BUILD && debug.log(`Sending trace ${traceId} in ${batches.length} batch${batches.length === 1 ? '' : 'es'}`);\n\n // Compute DSC from the segment span (passed as parameter)\n const dsc = getDynamicSamplingContextFromSpan(segmentSpan);\n\n for (const batch of batches) {\n const envelope = createSpanV2Envelope(batch, dsc, client);\n // no need to handle client reports for network errors,\n // buffer overflows or rate limiting here. All of this is handled\n // by client and transport.\n client.sendEnvelope(envelope).then(null, reason => {\n DEBUG_BUILD && debug.error('Error while sending span stream envelope:', reason);\n });\n }\n\n spanTreeMap.delete(spanTreeMapKey);\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
import { defineIntegration, debug, isV2BeforeSendSpanCallback, captureSpan, getDynamicSamplingContextFromSpan, createSpanV2Envelope } from '@sentry/core';
|
|
2
|
-
import { DEBUG_BUILD } from '../debug-build.js';
|
|
3
|
-
|
|
4
|
-
const spanStreamingIntegration = defineIntegration(((userOptions) => {
|
|
5
|
-
const validatedUserProvidedBatchLimit =
|
|
6
|
-
userOptions?.batchLimit && userOptions.batchLimit <= 1000 && userOptions.batchLimit >= 1
|
|
7
|
-
? userOptions.batchLimit
|
|
8
|
-
: undefined;
|
|
9
|
-
|
|
10
|
-
if (DEBUG_BUILD && userOptions?.batchLimit && !validatedUserProvidedBatchLimit) {
|
|
11
|
-
debug.warn('SpanStreaming batchLimit must be between 1 and 1000, defaulting to 1000');
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const options = {
|
|
15
|
-
...userOptions,
|
|
16
|
-
batchLimit:
|
|
17
|
-
userOptions?.batchLimit && userOptions.batchLimit <= 1000 && userOptions.batchLimit >= 1
|
|
18
|
-
? userOptions.batchLimit
|
|
19
|
-
: 1000,
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
// key: traceId-segmentSpanId
|
|
23
|
-
const spanTreeMap = new Map();
|
|
24
|
-
|
|
25
|
-
return {
|
|
26
|
-
name: 'SpanStreaming',
|
|
27
|
-
setup(client) {
|
|
28
|
-
const clientOptions = client.getOptions();
|
|
29
|
-
const beforeSendSpan = clientOptions.beforeSendSpan;
|
|
30
|
-
|
|
31
|
-
const initialMessage = 'spanStreamingIntegration requires';
|
|
32
|
-
const fallbackMsg = 'Falling back to static trace lifecycle.';
|
|
33
|
-
|
|
34
|
-
if (clientOptions.traceLifecycle !== 'stream') {
|
|
35
|
-
DEBUG_BUILD && debug.warn(`${initialMessage} \`traceLifecycle\` to be set to "stream"! ${fallbackMsg}`);
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
if (beforeSendSpan && !isV2BeforeSendSpanCallback(beforeSendSpan)) {
|
|
40
|
-
client.getOptions().traceLifecycle = 'static';
|
|
41
|
-
debug.warn(`${initialMessage} a beforeSendSpan callback using \`withStreamSpan\`! ${fallbackMsg}`);
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
client.on('enqueueSpan', spanJSON => {
|
|
46
|
-
const spanTreeMapKey = getSpanTreeMapKey(spanJSON);
|
|
47
|
-
const spanBuffer = spanTreeMap.get(spanTreeMapKey);
|
|
48
|
-
if (spanBuffer) {
|
|
49
|
-
spanBuffer.add(spanJSON);
|
|
50
|
-
} else {
|
|
51
|
-
spanTreeMap.set(spanTreeMapKey, new Set([spanJSON]));
|
|
52
|
-
}
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
client.on('afterSpanEnd', span => {
|
|
56
|
-
captureSpan(span, client);
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
// For now, we send all spans on local segment (root) span end.
|
|
60
|
-
// TODO: This will change once we have more concrete ideas about a universal SDK data buffer.
|
|
61
|
-
client.on('afterSegmentSpanEnd', segmentSpan => {
|
|
62
|
-
sendSegment(segmentSpan, {
|
|
63
|
-
spanTreeMap,
|
|
64
|
-
client,
|
|
65
|
-
batchLimit: options.batchLimit,
|
|
66
|
-
});
|
|
67
|
-
});
|
|
68
|
-
},
|
|
69
|
-
};
|
|
70
|
-
}) );
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Just the traceid alone isn't enough because there can be multiple span trees with the same traceid.
|
|
74
|
-
*/
|
|
75
|
-
function getSpanTreeMapKey(spanJSON) {
|
|
76
|
-
return `${spanJSON.trace_id}-${spanJSON._segmentSpan?.spanContext().spanId || spanJSON.span_id}`;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
function sendSegment(segmentSpan, { client, spanTreeMap, batchLimit }) {
|
|
80
|
-
const traceId = segmentSpan.spanContext().traceId;
|
|
81
|
-
const segmentSpanId = segmentSpan.spanContext().spanId;
|
|
82
|
-
const spanTreeMapKey = `${traceId}-${segmentSpanId}`;
|
|
83
|
-
const spansOfTrace = spanTreeMap.get(spanTreeMapKey);
|
|
84
|
-
|
|
85
|
-
if (!spansOfTrace?.size) {
|
|
86
|
-
spanTreeMap.delete(spanTreeMapKey);
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// Apply beforeSendSpan callback and clean up segment span references
|
|
91
|
-
const finalSpans = Array.from(spansOfTrace).map(spanJSON => {
|
|
92
|
-
// Remove the segment span reference before processing
|
|
93
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
94
|
-
const { _segmentSpan, ...cleanSpanJSON } = spanJSON;
|
|
95
|
-
return cleanSpanJSON;
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
const batches = [];
|
|
99
|
-
for (let i = 0; i < finalSpans.length; i += batchLimit) {
|
|
100
|
-
batches.push(finalSpans.slice(i, i + batchLimit));
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
DEBUG_BUILD && debug.log(`Sending trace ${traceId} in ${batches.length} batch${batches.length === 1 ? '' : 'es'}`);
|
|
104
|
-
|
|
105
|
-
// Compute DSC from the segment span (passed as parameter)
|
|
106
|
-
const dsc = getDynamicSamplingContextFromSpan(segmentSpan);
|
|
107
|
-
|
|
108
|
-
for (const batch of batches) {
|
|
109
|
-
const envelope = createSpanV2Envelope(batch, dsc, client);
|
|
110
|
-
// no need to handle client reports for network errors,
|
|
111
|
-
// buffer overflows or rate limiting here. All of this is handled
|
|
112
|
-
// by client and transport.
|
|
113
|
-
client.sendEnvelope(envelope).then(null, reason => {
|
|
114
|
-
DEBUG_BUILD && debug.error('Error while sending span stream envelope:', reason);
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
spanTreeMap.delete(spanTreeMapKey);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
export { spanStreamingIntegration };
|
|
122
|
-
//# sourceMappingURL=spanstreaming.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"spanstreaming.js","sources":["../../../../../src/integrations/spanstreaming.ts"],"sourcesContent":["import type { Client, IntegrationFn, Span, SpanV2JSON, SpanV2JSONWithSegmentRef } from '@sentry/core';\nimport {\n captureSpan,\n createSpanV2Envelope,\n debug,\n defineIntegration,\n getDynamicSamplingContextFromSpan,\n isV2BeforeSendSpanCallback,\n} from '@sentry/core';\nimport { DEBUG_BUILD } from '../debug-build';\n\nexport interface SpanStreamingOptions {\n batchLimit: number;\n}\n\nexport const spanStreamingIntegration = defineIntegration(((userOptions?: Partial<SpanStreamingOptions>) => {\n const validatedUserProvidedBatchLimit =\n userOptions?.batchLimit && userOptions.batchLimit <= 1000 && userOptions.batchLimit >= 1\n ? userOptions.batchLimit\n : undefined;\n\n if (DEBUG_BUILD && userOptions?.batchLimit && !validatedUserProvidedBatchLimit) {\n debug.warn('SpanStreaming batchLimit must be between 1 and 1000, defaulting to 1000');\n }\n\n const options: SpanStreamingOptions = {\n ...userOptions,\n batchLimit:\n userOptions?.batchLimit && userOptions.batchLimit <= 1000 && userOptions.batchLimit >= 1\n ? userOptions.batchLimit\n : 1000,\n };\n\n // key: traceId-segmentSpanId\n const spanTreeMap = new Map<string, Set<SpanV2JSONWithSegmentRef>>();\n\n return {\n name: 'SpanStreaming',\n setup(client) {\n const clientOptions = client.getOptions();\n const beforeSendSpan = clientOptions.beforeSendSpan;\n\n const initialMessage = 'spanStreamingIntegration requires';\n const fallbackMsg = 'Falling back to static trace lifecycle.';\n\n if (clientOptions.traceLifecycle !== 'stream') {\n DEBUG_BUILD && debug.warn(`${initialMessage} \\`traceLifecycle\\` to be set to \"stream\"! ${fallbackMsg}`);\n return;\n }\n\n if (beforeSendSpan && !isV2BeforeSendSpanCallback(beforeSendSpan)) {\n client.getOptions().traceLifecycle = 'static';\n debug.warn(`${initialMessage} a beforeSendSpan callback using \\`withStreamSpan\\`! ${fallbackMsg}`);\n return;\n }\n\n client.on('enqueueSpan', spanJSON => {\n const spanTreeMapKey = getSpanTreeMapKey(spanJSON);\n const spanBuffer = spanTreeMap.get(spanTreeMapKey);\n if (spanBuffer) {\n spanBuffer.add(spanJSON);\n } else {\n spanTreeMap.set(spanTreeMapKey, new Set([spanJSON]));\n }\n });\n\n client.on('afterSpanEnd', span => {\n captureSpan(span, client);\n });\n\n // For now, we send all spans on local segment (root) span end.\n // TODO: This will change once we have more concrete ideas about a universal SDK data buffer.\n client.on('afterSegmentSpanEnd', segmentSpan => {\n sendSegment(segmentSpan, {\n spanTreeMap,\n client,\n batchLimit: options.batchLimit,\n });\n });\n },\n };\n}) satisfies IntegrationFn);\n\ninterface SpanProcessingOptions {\n client: Client;\n spanTreeMap: Map<string, Set<SpanV2JSONWithSegmentRef>>;\n batchLimit: number;\n}\n\n/**\n * Just the traceid alone isn't enough because there can be multiple span trees with the same traceid.\n */\nfunction getSpanTreeMapKey(spanJSON: SpanV2JSONWithSegmentRef): string {\n return `${spanJSON.trace_id}-${spanJSON._segmentSpan?.spanContext().spanId || spanJSON.span_id}`;\n}\n\nfunction sendSegment(segmentSpan: Span, { client, spanTreeMap, batchLimit }: SpanProcessingOptions): void {\n const traceId = segmentSpan.spanContext().traceId;\n const segmentSpanId = segmentSpan.spanContext().spanId;\n const spanTreeMapKey = `${traceId}-${segmentSpanId}`;\n const spansOfTrace = spanTreeMap.get(spanTreeMapKey);\n\n if (!spansOfTrace?.size) {\n spanTreeMap.delete(spanTreeMapKey);\n return;\n }\n\n // Apply beforeSendSpan callback and clean up segment span references\n const finalSpans = Array.from(spansOfTrace).map(spanJSON => {\n // Remove the segment span reference before processing\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { _segmentSpan, ...cleanSpanJSON } = spanJSON;\n return cleanSpanJSON;\n });\n\n const batches: SpanV2JSON[][] = [];\n for (let i = 0; i < finalSpans.length; i += batchLimit) {\n batches.push(finalSpans.slice(i, i + batchLimit));\n }\n\n DEBUG_BUILD && debug.log(`Sending trace ${traceId} in ${batches.length} batch${batches.length === 1 ? '' : 'es'}`);\n\n // Compute DSC from the segment span (passed as parameter)\n const dsc = getDynamicSamplingContextFromSpan(segmentSpan);\n\n for (const batch of batches) {\n const envelope = createSpanV2Envelope(batch, dsc, client);\n // no need to handle client reports for network errors,\n // buffer overflows or rate limiting here. All of this is handled\n // by client and transport.\n client.sendEnvelope(envelope).then(null, reason => {\n DEBUG_BUILD && debug.error('Error while sending span stream envelope:', reason);\n });\n }\n\n spanTreeMap.delete(spanTreeMapKey);\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"spanstreaming.d.ts","sourceRoot":"","sources":["../../../../src/integrations/spanstreaming.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,wBAAwB,iGAkEV,CAAC"}
|