@sentry/core 10.32.0-alpha.0 → 10.32.0
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/cjs/attributes.js +74 -57
- package/build/cjs/attributes.js.map +1 -1
- package/build/cjs/client.js +6 -11
- package/build/cjs/client.js.map +1 -1
- package/build/cjs/envelope.js +7 -41
- package/build/cjs/envelope.js.map +1 -1
- package/build/cjs/index.js +0 -29
- package/build/cjs/index.js.map +1 -1
- package/build/cjs/integrations/eventFilters.js +1 -1
- package/build/cjs/integrations/eventFilters.js.map +1 -1
- package/build/cjs/integrations/requestdata.js +6 -72
- package/build/cjs/integrations/requestdata.js.map +1 -1
- package/build/cjs/logs/internal.js +8 -54
- package/build/cjs/logs/internal.js.map +1 -1
- package/build/cjs/scope.js +12 -6
- package/build/cjs/scope.js.map +1 -1
- package/build/cjs/semanticAttributes.js +0 -36
- package/build/cjs/semanticAttributes.js.map +1 -1
- package/build/cjs/tracing/sentrySpan.js +0 -31
- package/build/cjs/tracing/sentrySpan.js.map +1 -1
- package/build/cjs/tracing/trace.js +0 -1
- package/build/cjs/tracing/trace.js.map +1 -1
- package/build/cjs/tracing/vercel-ai/index.js +0 -1
- package/build/cjs/tracing/vercel-ai/index.js.map +1 -1
- package/build/cjs/utils/applyScopeDataToEvent.js +1 -4
- package/build/cjs/utils/applyScopeDataToEvent.js.map +1 -1
- package/build/cjs/utils/featureFlags.js +0 -1
- package/build/cjs/utils/featureFlags.js.map +1 -1
- package/build/cjs/utils/should-ignore-span.js +9 -31
- package/build/cjs/utils/should-ignore-span.js.map +1 -1
- package/build/cjs/utils/spanUtils.js +2 -101
- package/build/cjs/utils/spanUtils.js.map +1 -1
- package/build/cjs/utils/version.js +1 -1
- package/build/cjs/utils/version.js.map +1 -1
- package/build/esm/attributes.js +74 -58
- package/build/esm/attributes.js.map +1 -1
- package/build/esm/client.js +1 -6
- package/build/esm/client.js.map +1 -1
- package/build/esm/envelope.js +8 -41
- package/build/esm/envelope.js.map +1 -1
- package/build/esm/index.js +3 -9
- package/build/esm/index.js.map +1 -1
- package/build/esm/integrations/eventFilters.js +1 -1
- package/build/esm/integrations/eventFilters.js.map +1 -1
- package/build/esm/integrations/requestdata.js +6 -72
- package/build/esm/integrations/requestdata.js.map +1 -1
- package/build/esm/logs/internal.js +9 -54
- package/build/esm/logs/internal.js.map +1 -1
- package/build/esm/package.json +1 -1
- package/build/esm/scope.js +12 -6
- package/build/esm/scope.js.map +1 -1
- package/build/esm/semanticAttributes.js +1 -26
- package/build/esm/semanticAttributes.js.map +1 -1
- package/build/esm/tracing/sentrySpan.js +1 -32
- package/build/esm/tracing/sentrySpan.js.map +1 -1
- package/build/esm/tracing/trace.js +0 -1
- package/build/esm/tracing/trace.js.map +1 -1
- package/build/esm/tracing/vercel-ai/index.js +0 -1
- package/build/esm/tracing/vercel-ai/index.js.map +1 -1
- package/build/esm/utils/applyScopeDataToEvent.js +1 -4
- package/build/esm/utils/applyScopeDataToEvent.js.map +1 -1
- package/build/esm/utils/featureFlags.js +0 -1
- package/build/esm/utils/featureFlags.js.map +1 -1
- package/build/esm/utils/should-ignore-span.js +9 -31
- package/build/esm/utils/should-ignore-span.js.map +1 -1
- package/build/esm/utils/spanUtils.js +3 -97
- package/build/esm/utils/spanUtils.js.map +1 -1
- package/build/esm/utils/version.js +1 -1
- package/build/esm/utils/version.js.map +1 -1
- package/build/types/attributes.d.ts +18 -5
- package/build/types/attributes.d.ts.map +1 -1
- package/build/types/client.d.ts +2 -40
- package/build/types/client.d.ts.map +1 -1
- package/build/types/envelope.d.ts +1 -6
- package/build/types/envelope.d.ts.map +1 -1
- package/build/types/index.d.ts +4 -10
- package/build/types/index.d.ts.map +1 -1
- package/build/types/integrations/requestdata.d.ts.map +1 -1
- package/build/types/logs/internal.d.ts +1 -9
- package/build/types/logs/internal.d.ts.map +1 -1
- package/build/types/scope.d.ts +12 -6
- package/build/types/scope.d.ts.map +1 -1
- package/build/types/semanticAttributes.d.ts +0 -21
- package/build/types/semanticAttributes.d.ts.map +1 -1
- package/build/types/tracing/sentrySpan.d.ts +1 -10
- package/build/types/tracing/sentrySpan.d.ts.map +1 -1
- package/build/types/tracing/vercel-ai/index.d.ts.map +1 -1
- package/build/types/types-hoist/envelope.d.ts +2 -22
- package/build/types/types-hoist/envelope.d.ts.map +1 -1
- package/build/types/types-hoist/link.d.ts +2 -2
- package/build/types/types-hoist/link.d.ts.map +1 -1
- package/build/types/types-hoist/log.d.ts +2 -14
- package/build/types/types-hoist/log.d.ts.map +1 -1
- package/build/types/types-hoist/options.d.ts +2 -18
- package/build/types/types-hoist/options.d.ts.map +1 -1
- package/build/types/types-hoist/span.d.ts +0 -27
- package/build/types/types-hoist/span.d.ts.map +1 -1
- package/build/types/utils/applyScopeDataToEvent.d.ts +1 -1
- package/build/types/utils/applyScopeDataToEvent.d.ts.map +1 -1
- package/build/types/utils/featureFlags.d.ts.map +1 -1
- package/build/types/utils/should-ignore-span.d.ts +3 -3
- package/build/types/utils/should-ignore-span.d.ts.map +1 -1
- package/build/types/utils/spanUtils.d.ts +2 -26
- package/build/types/utils/spanUtils.d.ts.map +1 -1
- package/build/types-ts3.8/attributes.d.ts +18 -5
- package/build/types-ts3.8/client.d.ts +2 -40
- package/build/types-ts3.8/envelope.d.ts +1 -6
- package/build/types-ts3.8/index.d.ts +4 -10
- package/build/types-ts3.8/logs/internal.d.ts +1 -9
- package/build/types-ts3.8/scope.d.ts +12 -6
- package/build/types-ts3.8/semanticAttributes.d.ts +0 -21
- package/build/types-ts3.8/tracing/sentrySpan.d.ts +1 -10
- package/build/types-ts3.8/types-hoist/envelope.d.ts +2 -22
- package/build/types-ts3.8/types-hoist/link.d.ts +2 -2
- package/build/types-ts3.8/types-hoist/log.d.ts +2 -14
- package/build/types-ts3.8/types-hoist/options.d.ts +2 -18
- package/build/types-ts3.8/types-hoist/span.d.ts +0 -27
- package/build/types-ts3.8/utils/applyScopeDataToEvent.d.ts +1 -1
- package/build/types-ts3.8/utils/should-ignore-span.d.ts +3 -3
- package/build/types-ts3.8/utils/spanUtils.d.ts +2 -26
- package/package.json +1 -1
- package/build/cjs/integrations/serverSpanStreaming.js +0 -51
- package/build/cjs/integrations/serverSpanStreaming.js.map +0 -1
- package/build/cjs/spans/captureSpan.js +0 -107
- package/build/cjs/spans/captureSpan.js.map +0 -1
- package/build/cjs/spans/spanBuffer.js +0 -117
- package/build/cjs/spans/spanBuffer.js.map +0 -1
- package/build/cjs/spans/spanFirstUtils.js +0 -187
- package/build/cjs/spans/spanFirstUtils.js.map +0 -1
- package/build/cjs/utils/beforeSendSpan.js +0 -36
- package/build/cjs/utils/beforeSendSpan.js.map +0 -1
- package/build/esm/integrations/serverSpanStreaming.js +0 -49
- package/build/esm/integrations/serverSpanStreaming.js.map +0 -1
- package/build/esm/spans/captureSpan.js +0 -105
- package/build/esm/spans/captureSpan.js.map +0 -1
- package/build/esm/spans/spanBuffer.js +0 -115
- package/build/esm/spans/spanBuffer.js.map +0 -1
- package/build/esm/spans/spanFirstUtils.js +0 -183
- package/build/esm/spans/spanFirstUtils.js.map +0 -1
- package/build/esm/utils/beforeSendSpan.js +0 -33
- package/build/esm/utils/beforeSendSpan.js.map +0 -1
- package/build/types/integrations/serverSpanStreaming.d.ts +0 -8
- package/build/types/integrations/serverSpanStreaming.d.ts.map +0 -1
- package/build/types/spans/captureSpan.d.ts +0 -10
- package/build/types/spans/captureSpan.d.ts.map +0 -1
- package/build/types/spans/spanBuffer.d.ts +0 -31
- package/build/types/spans/spanBuffer.d.ts.map +0 -1
- package/build/types/spans/spanFirstUtils.d.ts +0 -20
- package/build/types/spans/spanFirstUtils.d.ts.map +0 -1
- package/build/types/types-hoist/attributes.d.ts +0 -19
- package/build/types/types-hoist/attributes.d.ts.map +0 -1
- package/build/types/utils/beforeSendSpan.d.ts +0 -22
- package/build/types/utils/beforeSendSpan.d.ts.map +0 -1
- package/build/types-ts3.8/integrations/serverSpanStreaming.d.ts +0 -8
- package/build/types-ts3.8/spans/captureSpan.d.ts +0 -10
- package/build/types-ts3.8/spans/spanBuffer.d.ts +0 -31
- package/build/types-ts3.8/spans/spanFirstUtils.d.ts +0 -20
- package/build/types-ts3.8/types-hoist/attributes.d.ts +0 -19
- package/build/types-ts3.8/utils/beforeSendSpan.d.ts +0 -22
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"spanBuffer.js","sources":["../../../src/spans/spanBuffer.ts"],"sourcesContent":["import type { Client } from '../client';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { createSpanV2Envelope } from '../envelope';\nimport { getDynamicSamplingContextFromSpan } from '../tracing/dynamicSamplingContext';\nimport type { SpanV2JSON, SpanV2JSONWithSegmentRef } from '../types-hoist/span';\nimport { debug } from '../utils/debug-logger';\n\nexport interface SpanBufferOptions {\n /** Max spans per trace before auto-flush (default: 1000) */\n maxSpanLimit?: number;\n /** Flush interval in ms (default: 5000) */\n flushInterval?: number;\n}\n\n/**\n * A buffer for span JSON objects that flushes them to Sentry in Span v2 envelopes.\n * Handles interval-based flushing, size thresholds, and graceful shutdown.\n */\nexport class SpanBuffer {\n private _spanTreeMap: Map<string, Set<SpanV2JSONWithSegmentRef>>;\n private _flushIntervalId: ReturnType<typeof setInterval> | null;\n private _client: Client;\n private _maxSpanLimit: number;\n private _flushInterval: number;\n\n public constructor(client: Client, options?: SpanBufferOptions) {\n this._spanTreeMap = new Map();\n this._client = client;\n\n const { maxSpanLimit, flushInterval } = options ?? {};\n\n this._maxSpanLimit = maxSpanLimit && maxSpanLimit > 0 && maxSpanLimit <= 1000 ? maxSpanLimit : 1000;\n this._flushInterval = flushInterval && flushInterval > 0 ? flushInterval : 5_000;\n\n this._flushIntervalId = setInterval(() => {\n this.flush();\n }, this._flushInterval);\n\n this._client.on('flush', () => {\n this.flush();\n });\n }\n\n /**\n * Add a span to the buffer.\n */\n public addSpan(spanJSON: SpanV2JSONWithSegmentRef): void {\n const traceId = spanJSON.trace_id;\n let traceBucket = this._spanTreeMap.get(traceId);\n if (traceBucket) {\n traceBucket.add(spanJSON);\n } else {\n traceBucket = new Set([spanJSON]);\n this._spanTreeMap.set(traceId, traceBucket);\n }\n\n if (traceBucket.size >= this._maxSpanLimit) {\n this._flushTrace(traceId);\n this._debounceFlushInterval();\n }\n }\n\n /**\n * Flush all buffered traces.\n */\n public flush(): void {\n if (!this._spanTreeMap.size) {\n return;\n }\n\n DEBUG_BUILD && debug.log(`Flushing span tree map with ${this._spanTreeMap.size} traces`);\n\n this._spanTreeMap.forEach((_, traceId) => {\n this._flushTrace(traceId);\n });\n this._debounceFlushInterval();\n }\n\n private _flushTrace(traceId: string): void {\n const traceBucket = this._spanTreeMap.get(traceId);\n if (!traceBucket) {\n return;\n }\n\n if (!traceBucket.size) {\n this._spanTreeMap.delete(traceId);\n return;\n }\n\n const firstSpanJSON = traceBucket.values().next().value;\n\n const segmentSpan = firstSpanJSON?._segmentSpan;\n if (!segmentSpan) {\n DEBUG_BUILD && debug.warn('No segment span reference found on span JSON, cannot compute DSC');\n this._spanTreeMap.delete(traceId);\n return;\n }\n\n const dsc = getDynamicSamplingContextFromSpan(segmentSpan);\n\n const cleanedSpans: SpanV2JSON[] = Array.from(traceBucket).map(spanJSON => {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { _segmentSpan, ...cleanSpanJSON } = spanJSON;\n return cleanSpanJSON;\n });\n\n const envelope = createSpanV2Envelope(cleanedSpans, dsc, this._client);\n\n DEBUG_BUILD && debug.log(`Sending span envelope for trace ${traceId} with ${cleanedSpans.length} spans`);\n\n this._client.sendEnvelope(envelope).then(null, reason => {\n DEBUG_BUILD && debug.error('Error while sending span stream envelope:', reason);\n });\n\n this._spanTreeMap.delete(traceId);\n }\n\n private _debounceFlushInterval(): void {\n if (this._flushIntervalId) {\n clearInterval(this._flushIntervalId);\n }\n this._flushIntervalId = setInterval(() => {\n this.flush();\n }, this._flushInterval);\n }\n}\n"],"names":["DEBUG_BUILD","debug","getDynamicSamplingContextFromSpan","envelope","createSpanV2Envelope"],"mappings":"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"}
|
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
-
|
|
3
|
-
const attributes = require('../attributes.js');
|
|
4
|
-
const is = require('../utils/is.js');
|
|
5
|
-
const spanUtils = require('../utils/spanUtils.js');
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Only set a span JSON attribute if it is not already set.
|
|
9
|
-
* This is used to safely set attributes on JSON objects without mutating already-ended span instances.
|
|
10
|
-
*/
|
|
11
|
-
function safeSetSpanJSONAttributes(
|
|
12
|
-
spanJSON,
|
|
13
|
-
newAttributes,
|
|
14
|
-
) {
|
|
15
|
-
if (!spanJSON.attributes) {
|
|
16
|
-
spanJSON.attributes = {};
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const originalAttributes = spanJSON.attributes;
|
|
20
|
-
|
|
21
|
-
Object.keys(newAttributes).forEach(key => {
|
|
22
|
-
if (!originalAttributes?.[key]) {
|
|
23
|
-
setAttributeOnSpanJSONWithMaybeUnit(
|
|
24
|
-
// type-casting here because we ensured above that the attributes object exists
|
|
25
|
-
spanJSON ,
|
|
26
|
-
key,
|
|
27
|
-
newAttributes[key],
|
|
28
|
-
);
|
|
29
|
-
}
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Apply a user-provided beforeSendSpan callback to a span JSON.
|
|
35
|
-
*/
|
|
36
|
-
function applyBeforeSendSpanCallback(
|
|
37
|
-
span,
|
|
38
|
-
beforeSendSpan,
|
|
39
|
-
) {
|
|
40
|
-
const modifedSpan = beforeSendSpan(span);
|
|
41
|
-
if (!modifedSpan) {
|
|
42
|
-
spanUtils.showSpanDropWarning();
|
|
43
|
-
return span;
|
|
44
|
-
}
|
|
45
|
-
return modifedSpan;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
function setAttributeOnSpanJSONWithMaybeUnit(
|
|
49
|
-
spanJSON,
|
|
50
|
-
attributeKey,
|
|
51
|
-
attributeValue,
|
|
52
|
-
) {
|
|
53
|
-
if (attributes.isAttributeObject(attributeValue)) {
|
|
54
|
-
const { value, unit } = attributeValue;
|
|
55
|
-
|
|
56
|
-
if (isSupportedSerializableType(value)) {
|
|
57
|
-
spanJSON.attributes[attributeKey] = attributes.attributeValueToTypedAttributeValue(attributeValue);
|
|
58
|
-
if (unit) {
|
|
59
|
-
spanJSON.attributes[attributeKey].unit = unit;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
} else if (isSupportedSerializableType(attributeValue)) {
|
|
63
|
-
spanJSON.attributes[attributeKey] = attributes.attributeValueToTypedAttributeValue(attributeValue);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
function isSupportedSerializableType(value) {
|
|
68
|
-
return ['string', 'number', 'boolean'].includes(typeof value) || Array.isArray(value);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// map of attributes->context keys for those attributes that don't correspond 1:1 to the context key
|
|
72
|
-
const explicitAttributeToContextMapping = {
|
|
73
|
-
'os.build_id': 'os.build',
|
|
74
|
-
'app.name': 'app.app_name',
|
|
75
|
-
'app.identifier': 'app.app_identifier',
|
|
76
|
-
'app.version': 'app.app_version',
|
|
77
|
-
'app.memory': 'app.app_memory',
|
|
78
|
-
'app.start_time': 'app.app_start_time',
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
const knownContexts = [
|
|
82
|
-
// set by `nodeContextIntegration`
|
|
83
|
-
'app',
|
|
84
|
-
'os',
|
|
85
|
-
'device',
|
|
86
|
-
'culture',
|
|
87
|
-
'cloud_resource',
|
|
88
|
-
'runtime',
|
|
89
|
-
|
|
90
|
-
// TODO: These need more thorough checking if they're all setting expected attributes
|
|
91
|
-
|
|
92
|
-
// set by the `instrumentPostgresJs`
|
|
93
|
-
'postgresjsConnection',
|
|
94
|
-
// set by `ensureIsWrapped`
|
|
95
|
-
'missing_instrumentation',
|
|
96
|
-
// set by `nodeProfilingIntegration`
|
|
97
|
-
'profile',
|
|
98
|
-
// set by angular `init`
|
|
99
|
-
'angular',
|
|
100
|
-
// set by AWS Lambda SDK
|
|
101
|
-
'aws.lambda',
|
|
102
|
-
'aws.cloudwatch.logs',
|
|
103
|
-
// set by `instrumentBunServe`
|
|
104
|
-
'response',
|
|
105
|
-
// set by `trpcMiddleware`
|
|
106
|
-
'trpc',
|
|
107
|
-
// set by `instrumentSupabaseClient`
|
|
108
|
-
'supabase',
|
|
109
|
-
// set by `gcp.function.context`
|
|
110
|
-
'gcp.function.context',
|
|
111
|
-
// set by nextjs SDK
|
|
112
|
-
'nextjs',
|
|
113
|
-
// set by react SDK `captureReactException`, `init`
|
|
114
|
-
'react',
|
|
115
|
-
// set by react SDK `createReduxEnhancer`
|
|
116
|
-
'state',
|
|
117
|
-
// set by `replayIntegration`
|
|
118
|
-
'Replays',
|
|
119
|
-
// Other information:
|
|
120
|
-
// - no need to handler feature flags `flags` context because it's already added to the active span
|
|
121
|
-
];
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Converts a context object to a set of attributes.
|
|
125
|
-
* Only includes attributes that are primitives (for now).
|
|
126
|
-
* @param contexts - The context object to convert.
|
|
127
|
-
* @returns The attributes object.
|
|
128
|
-
*/
|
|
129
|
-
function contextsToAttributes(contexts) {
|
|
130
|
-
function contextToAttribute(context) {
|
|
131
|
-
return Object.keys(context).reduce(
|
|
132
|
-
(acc, key) => {
|
|
133
|
-
if (!is.isPrimitive(context[key])) {
|
|
134
|
-
return acc;
|
|
135
|
-
}
|
|
136
|
-
acc[key] = context[key];
|
|
137
|
-
return acc;
|
|
138
|
-
},
|
|
139
|
-
{} ,
|
|
140
|
-
);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
const contextsWithPrimitiveValues = Object.keys(contexts).reduce((acc, key) => {
|
|
144
|
-
if (!knownContexts.includes(key)) {
|
|
145
|
-
return acc;
|
|
146
|
-
}
|
|
147
|
-
const context = contexts[key];
|
|
148
|
-
if (context) {
|
|
149
|
-
acc[key] = contextToAttribute(context);
|
|
150
|
-
}
|
|
151
|
-
return acc;
|
|
152
|
-
}, {} );
|
|
153
|
-
|
|
154
|
-
const explicitlyMappedAttributes = Object.entries(explicitAttributeToContextMapping).reduce(
|
|
155
|
-
(acc, [attributeKey, contextKey]) => {
|
|
156
|
-
const [contextName, contextValueKey] = contextKey.split('.');
|
|
157
|
-
if (contextName && contextValueKey && contextsWithPrimitiveValues[contextName]?.[contextValueKey]) {
|
|
158
|
-
acc[attributeKey] = contextsWithPrimitiveValues[contextName]?.[contextValueKey];
|
|
159
|
-
// now we delete this key from `contextsWithPrimitiveValues` so we don't include it in the next step
|
|
160
|
-
delete contextsWithPrimitiveValues[contextName]?.[contextValueKey];
|
|
161
|
-
}
|
|
162
|
-
return acc;
|
|
163
|
-
},
|
|
164
|
-
{} ,
|
|
165
|
-
);
|
|
166
|
-
|
|
167
|
-
return {
|
|
168
|
-
...explicitlyMappedAttributes,
|
|
169
|
-
...Object.entries(contextsWithPrimitiveValues).reduce(
|
|
170
|
-
(acc, [contextName, contextObj]) => {
|
|
171
|
-
contextObj &&
|
|
172
|
-
Object.entries(contextObj).forEach(([key, value]) => {
|
|
173
|
-
if (value) {
|
|
174
|
-
acc[`${contextName}.${key}`] = value;
|
|
175
|
-
}
|
|
176
|
-
});
|
|
177
|
-
return acc;
|
|
178
|
-
},
|
|
179
|
-
{} ,
|
|
180
|
-
),
|
|
181
|
-
};
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
exports.applyBeforeSendSpanCallback = applyBeforeSendSpanCallback;
|
|
185
|
-
exports.contextsToAttributes = contextsToAttributes;
|
|
186
|
-
exports.safeSetSpanJSONAttributes = safeSetSpanJSONAttributes;
|
|
187
|
-
//# sourceMappingURL=spanFirstUtils.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"spanFirstUtils.js","sources":["../../../src/spans/spanFirstUtils.ts"],"sourcesContent":["import type { RawAttributes } from '../attributes';\nimport { attributeValueToTypedAttributeValue, isAttributeObject } from '../attributes';\nimport type { Context, Contexts } from '../types-hoist/context';\nimport type { SpanV2JSON } from '../types-hoist/span';\nimport { isPrimitive } from '../utils/is';\nimport { showSpanDropWarning } from '../utils/spanUtils';\n\n/**\n * Only set a span JSON attribute if it is not already set.\n * This is used to safely set attributes on JSON objects without mutating already-ended span instances.\n */\nexport function safeSetSpanJSONAttributes(\n spanJSON: SpanV2JSON,\n newAttributes: RawAttributes<Record<string, unknown>>,\n): void {\n if (!spanJSON.attributes) {\n spanJSON.attributes = {};\n }\n\n const originalAttributes = spanJSON.attributes;\n\n Object.keys(newAttributes).forEach(key => {\n if (!originalAttributes?.[key]) {\n setAttributeOnSpanJSONWithMaybeUnit(\n // type-casting here because we ensured above that the attributes object exists\n spanJSON as SpanV2JSON & Required<Pick<SpanV2JSON, 'attributes'>>,\n key,\n newAttributes[key],\n );\n }\n });\n}\n\n/**\n * Apply a user-provided beforeSendSpan callback to a span JSON.\n */\nexport function applyBeforeSendSpanCallback(\n span: SpanV2JSON,\n beforeSendSpan: (span: SpanV2JSON) => SpanV2JSON,\n): SpanV2JSON {\n const modifedSpan = beforeSendSpan(span);\n if (!modifedSpan) {\n showSpanDropWarning();\n return span;\n }\n return modifedSpan;\n}\n\nfunction setAttributeOnSpanJSONWithMaybeUnit(\n spanJSON: SpanV2JSON & Required<Pick<SpanV2JSON, 'attributes'>>,\n attributeKey: string,\n attributeValue: unknown,\n): void {\n if (isAttributeObject(attributeValue)) {\n const { value, unit } = attributeValue;\n\n if (isSupportedSerializableType(value)) {\n spanJSON.attributes[attributeKey] = attributeValueToTypedAttributeValue(attributeValue);\n if (unit) {\n spanJSON.attributes[attributeKey].unit = unit;\n }\n }\n } else if (isSupportedSerializableType(attributeValue)) {\n spanJSON.attributes[attributeKey] = attributeValueToTypedAttributeValue(attributeValue);\n }\n}\n\nfunction isSupportedSerializableType(value: unknown): boolean {\n return ['string', 'number', 'boolean'].includes(typeof value) || Array.isArray(value);\n}\n\n// map of attributes->context keys for those attributes that don't correspond 1:1 to the context key\nconst explicitAttributeToContextMapping = {\n 'os.build_id': 'os.build',\n 'app.name': 'app.app_name',\n 'app.identifier': 'app.app_identifier',\n 'app.version': 'app.app_version',\n 'app.memory': 'app.app_memory',\n 'app.start_time': 'app.app_start_time',\n};\n\nconst knownContexts = [\n // set by `nodeContextIntegration`\n 'app',\n 'os',\n 'device',\n 'culture',\n 'cloud_resource',\n 'runtime',\n\n // TODO: These need more thorough checking if they're all setting expected attributes\n\n // set by the `instrumentPostgresJs`\n 'postgresjsConnection',\n // set by `ensureIsWrapped`\n 'missing_instrumentation',\n // set by `nodeProfilingIntegration`\n 'profile',\n // set by angular `init`\n 'angular',\n // set by AWS Lambda SDK\n 'aws.lambda',\n 'aws.cloudwatch.logs',\n // set by `instrumentBunServe`\n 'response',\n // set by `trpcMiddleware`\n 'trpc',\n // set by `instrumentSupabaseClient`\n 'supabase',\n // set by `gcp.function.context`\n 'gcp.function.context',\n // set by nextjs SDK\n 'nextjs',\n // set by react SDK `captureReactException`, `init`\n 'react',\n // set by react SDK `createReduxEnhancer`\n 'state',\n // set by `replayIntegration`\n 'Replays',\n // Other information:\n // - no need to handler feature flags `flags` context because it's already added to the active span\n];\n\n/**\n * Converts a context object to a set of attributes.\n * Only includes attributes that are primitives (for now).\n * @param contexts - The context object to convert.\n * @returns The attributes object.\n */\nexport function contextsToAttributes(contexts: Contexts): RawAttributes<Record<string, unknown>> {\n function contextToAttribute(context: Context): Context {\n return Object.keys(context).reduce(\n (acc, key) => {\n if (!isPrimitive(context[key])) {\n return acc;\n }\n acc[key] = context[key];\n return acc;\n },\n {} as Record<string, unknown>,\n );\n }\n\n const contextsWithPrimitiveValues = Object.keys(contexts).reduce((acc, key) => {\n if (!knownContexts.includes(key)) {\n return acc;\n }\n const context = contexts[key];\n if (context) {\n acc[key] = contextToAttribute(context);\n }\n return acc;\n }, {} as Contexts);\n\n const explicitlyMappedAttributes = Object.entries(explicitAttributeToContextMapping).reduce(\n (acc, [attributeKey, contextKey]) => {\n const [contextName, contextValueKey] = contextKey.split('.');\n if (contextName && contextValueKey && contextsWithPrimitiveValues[contextName]?.[contextValueKey]) {\n acc[attributeKey] = contextsWithPrimitiveValues[contextName]?.[contextValueKey];\n // now we delete this key from `contextsWithPrimitiveValues` so we don't include it in the next step\n delete contextsWithPrimitiveValues[contextName]?.[contextValueKey];\n }\n return acc;\n },\n {} as Record<string, unknown>,\n );\n\n return {\n ...explicitlyMappedAttributes,\n ...Object.entries(contextsWithPrimitiveValues).reduce(\n (acc, [contextName, contextObj]) => {\n contextObj &&\n Object.entries(contextObj).forEach(([key, value]) => {\n if (value) {\n acc[`${contextName}.${key}`] = value;\n }\n });\n return acc;\n },\n {} as Record<string, unknown>,\n ),\n };\n}\n"],"names":["showSpanDropWarning","isAttributeObject","attributeValueToTypedAttributeValue","isPrimitive"],"mappings":"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"}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
-
|
|
3
|
-
const object = require('./object.js');
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* A wrapper to use the new span format in your `beforeSendSpan` callback.
|
|
7
|
-
*
|
|
8
|
-
* @example
|
|
9
|
-
*
|
|
10
|
-
* Sentry.init({
|
|
11
|
-
* beforeSendSpan: withStreamSpan((span) => {
|
|
12
|
-
* return span;
|
|
13
|
-
* }),
|
|
14
|
-
* });
|
|
15
|
-
*
|
|
16
|
-
* @param callback
|
|
17
|
-
* @returns
|
|
18
|
-
*/
|
|
19
|
-
function withStreamSpan(callback) {
|
|
20
|
-
object.addNonEnumerableProperty(callback, '_v2', true);
|
|
21
|
-
// type-casting here because TS can't infer the type correctly
|
|
22
|
-
return callback ;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Typesafe check to identify the expected span json format of the `beforeSendSpan` callback.
|
|
27
|
-
*/
|
|
28
|
-
function isV2BeforeSendSpanCallback(
|
|
29
|
-
callback,
|
|
30
|
-
) {
|
|
31
|
-
return !!callback && '_v2' in callback && !!callback._v2;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
exports.isV2BeforeSendSpanCallback = isV2BeforeSendSpanCallback;
|
|
35
|
-
exports.withStreamSpan = withStreamSpan;
|
|
36
|
-
//# sourceMappingURL=beforeSendSpan.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"beforeSendSpan.js","sources":["../../../src/utils/beforeSendSpan.ts"],"sourcesContent":["import type { ClientOptions, SpanV2CompatibleBeforeSendSpanCallback } from '../types-hoist/options';\nimport type { SpanV2JSON } from '../types-hoist/span';\nimport { addNonEnumerableProperty } from './object';\n\n/**\n * A wrapper to use the new span format in your `beforeSendSpan` callback.\n *\n * @example\n *\n * Sentry.init({\n * beforeSendSpan: withStreamSpan((span) => {\n * return span;\n * }),\n * });\n *\n * @param callback\n * @returns\n */\nexport function withStreamSpan(callback: (span: SpanV2JSON) => SpanV2JSON): SpanV2CompatibleBeforeSendSpanCallback {\n addNonEnumerableProperty(callback, '_v2', true);\n // type-casting here because TS can't infer the type correctly\n return callback as SpanV2CompatibleBeforeSendSpanCallback;\n}\n\n/**\n * Typesafe check to identify the expected span json format of the `beforeSendSpan` callback.\n */\nexport function isV2BeforeSendSpanCallback(\n callback: ClientOptions['beforeSendSpan'],\n): callback is SpanV2CompatibleBeforeSendSpanCallback {\n return !!callback && '_v2' in callback && !!callback._v2;\n}\n"],"names":["addNonEnumerableProperty"],"mappings":";;;;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,cAAc,CAAC,QAAQ,EAA4E;AACnH,EAAEA,+BAAwB,CAAC,QAAQ,EAAE,KAAK,EAAE,IAAI,CAAC;AACjD;AACA,EAAE,OAAO,QAAA;AACT;;AAEA;AACA;AACA;AACO,SAAS,0BAA0B;AAC1C,EAAE,QAAQ;AACV,EAAsD;AACtD,EAAE,OAAO,CAAC,CAAC,QAAA,IAAY,KAAA,IAAS,QAAA,IAAY,CAAC,CAAC,QAAQ,CAAC,GAAG;AAC1D;;;;;"}
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import { DEBUG_BUILD } from '../debug-build.js';
|
|
2
|
-
import { defineIntegration } from '../integration.js';
|
|
3
|
-
import { captureSpan } from '../spans/captureSpan.js';
|
|
4
|
-
import { SpanBuffer } from '../spans/spanBuffer.js';
|
|
5
|
-
import { isV2BeforeSendSpanCallback } from '../utils/beforeSendSpan.js';
|
|
6
|
-
import { debug } from '../utils/debug-logger.js';
|
|
7
|
-
|
|
8
|
-
const INTEGRATION_NAME = 'ServerSpanStreaming';
|
|
9
|
-
|
|
10
|
-
const _serverSpanStreamingIntegration = ((options) => {
|
|
11
|
-
return {
|
|
12
|
-
name: INTEGRATION_NAME,
|
|
13
|
-
setup(client) {
|
|
14
|
-
const clientOptions = client.getOptions();
|
|
15
|
-
const beforeSendSpan = clientOptions.beforeSendSpan;
|
|
16
|
-
|
|
17
|
-
const initialMessage = 'serverSpanStreamingIntegration requires';
|
|
18
|
-
const fallbackMsg = 'Falling back to static trace lifecycle.';
|
|
19
|
-
|
|
20
|
-
if (clientOptions.traceLifecycle !== 'stream') {
|
|
21
|
-
client.getOptions().traceLifecycle = 'static';
|
|
22
|
-
DEBUG_BUILD && debug.warn(`${initialMessage} \`traceLifecycle\` to be set to "stream"! ${fallbackMsg}`);
|
|
23
|
-
return;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
if (beforeSendSpan && !isV2BeforeSendSpanCallback(beforeSendSpan)) {
|
|
27
|
-
client.getOptions().traceLifecycle = 'static';
|
|
28
|
-
DEBUG_BUILD &&
|
|
29
|
-
debug.warn(`${initialMessage} a beforeSendSpan callback using \`withStreamSpan\`! ${fallbackMsg}`);
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const buffer = new SpanBuffer(client, options);
|
|
34
|
-
|
|
35
|
-
client.on('enqueueSpan', spanJSON => {
|
|
36
|
-
buffer.addSpan(spanJSON);
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
client.on('afterSpanEnd', span => {
|
|
40
|
-
captureSpan(span, client);
|
|
41
|
-
});
|
|
42
|
-
},
|
|
43
|
-
};
|
|
44
|
-
}) ;
|
|
45
|
-
|
|
46
|
-
const serverSpanStreamingIntegration = defineIntegration(_serverSpanStreamingIntegration);
|
|
47
|
-
|
|
48
|
-
export { serverSpanStreamingIntegration };
|
|
49
|
-
//# sourceMappingURL=serverSpanStreaming.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"serverSpanStreaming.js","sources":["../../../src/integrations/serverSpanStreaming.ts"],"sourcesContent":["import { DEBUG_BUILD } from '../debug-build';\nimport { defineIntegration } from '../integration';\nimport { captureSpan } from '../spans/captureSpan';\nimport { SpanBuffer } from '../spans/spanBuffer';\nimport type { IntegrationFn } from '../types-hoist/integration';\nimport { isV2BeforeSendSpanCallback } from '../utils/beforeSendSpan';\nimport { debug } from '../utils/debug-logger';\n\nexport interface ServerSpanStreamingOptions {\n /** Max spans per envelope batch (default: 1000) */\n maxSpanLimit?: number;\n /** Flush interval in ms (default: 5000) */\n flushInterval?: number;\n}\n\nconst INTEGRATION_NAME = 'ServerSpanStreaming';\n\nconst _serverSpanStreamingIntegration = ((options?: ServerSpanStreamingOptions) => {\n return {\n name: INTEGRATION_NAME,\n setup(client) {\n const clientOptions = client.getOptions();\n const beforeSendSpan = clientOptions.beforeSendSpan;\n\n const initialMessage = 'serverSpanStreamingIntegration requires';\n const fallbackMsg = 'Falling back to static trace lifecycle.';\n\n if (clientOptions.traceLifecycle !== 'stream') {\n client.getOptions().traceLifecycle = 'static';\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_BUILD &&\n debug.warn(`${initialMessage} a beforeSendSpan callback using \\`withStreamSpan\\`! ${fallbackMsg}`);\n return;\n }\n\n const buffer = new SpanBuffer(client, options);\n\n client.on('enqueueSpan', spanJSON => {\n buffer.addSpan(spanJSON);\n });\n\n client.on('afterSpanEnd', span => {\n captureSpan(span, client);\n });\n },\n };\n}) satisfies IntegrationFn;\n\nexport const serverSpanStreamingIntegration = defineIntegration(_serverSpanStreamingIntegration);\n"],"names":[],"mappings":";;;;;;;AAeA,MAAM,gBAAA,GAAmB,qBAAqB;;AAE9C,MAAM,mCAAmC,CAAC,OAAO,KAAkC;AACnF,EAAE,OAAO;AACT,IAAI,IAAI,EAAE,gBAAgB;AAC1B,IAAI,KAAK,CAAC,MAAM,EAAE;AAClB,MAAM,MAAM,aAAA,GAAgB,MAAM,CAAC,UAAU,EAAE;AAC/C,MAAM,MAAM,cAAA,GAAiB,aAAa,CAAC,cAAc;;AAEzD,MAAM,MAAM,cAAA,GAAiB,yCAAyC;AACtE,MAAM,MAAM,WAAA,GAAc,yCAAyC;;AAEnE,MAAM,IAAI,aAAa,CAAC,cAAA,KAAmB,QAAQ,EAAE;AACrD,QAAQ,MAAM,CAAC,UAAU,EAAE,CAAC,cAAA,GAAiB,QAAQ;AACrD,QAAQ,eAAe,KAAK,CAAC,IAAI,CAAC,CAAC,EAAA,cAAA,CAAA,2CAAA,EAAA,WAAA,CAAA,CAAA,CAAA;AACA,QAAA;AACA,MAAA;;AAEA,MAAA,IAAA,cAAA,IAAA,CAAA,0BAAA,CAAA,cAAA,CAAA,EAAA;AACA,QAAA,MAAA,CAAA,UAAA,EAAA,CAAA,cAAA,GAAA,QAAA;AACA,QAAA,WAAA;AACA,UAAA,KAAA,CAAA,IAAA,CAAA,CAAA,EAAA,cAAA,CAAA,qDAAA,EAAA,WAAA,CAAA,CAAA,CAAA;AACA,QAAA;AACA,MAAA;;AAEA,MAAA,MAAA,MAAA,GAAA,IAAA,UAAA,CAAA,MAAA,EAAA,OAAA,CAAA;;AAEA,MAAA,MAAA,CAAA,EAAA,CAAA,aAAA,EAAA,QAAA,IAAA;AACA,QAAA,MAAA,CAAA,OAAA,CAAA,QAAA,CAAA;AACA,MAAA,CAAA,CAAA;;AAEA,MAAA,MAAA,CAAA,EAAA,CAAA,cAAA,EAAA,IAAA,IAAA;AACA,QAAA,WAAA,CAAA,IAAA,EAAA,MAAA,CAAA;AACA,MAAA,CAAA,CAAA;AACA,IAAA,CAAA;AACA,GAAA;AACA,CAAA,CAAA;;AAEA,MAAA,8BAAA,GAAA,iBAAA,CAAA,+BAAA;;;;"}
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
import { getClient, getGlobalScope } from '../currentScopes.js';
|
|
2
|
-
import { DEBUG_BUILD } from '../debug-build.js';
|
|
3
|
-
import { SEMANTIC_ATTRIBUTE_USER_USERNAME, SEMANTIC_ATTRIBUTE_USER_IP_ADDRESS, SEMANTIC_ATTRIBUTE_USER_EMAIL, SEMANTIC_ATTRIBUTE_USER_ID, SEMANTIC_ATTRIBUTE_SENTRY_SDK_VERSION, SEMANTIC_ATTRIBUTE_SENTRY_SDK_NAME, SEMANTIC_ATTRIBUTE_SENTRY_SEGMENT_ID, SEMANTIC_ATTRIBUTE_SENTRY_SEGMENT_NAME, SEMANTIC_ATTRIBUTE_SENTRY_ENVIRONMENT, SEMANTIC_ATTRIBUTE_SENTRY_RELEASE } from '../semanticAttributes.js';
|
|
4
|
-
import { getCapturedScopesOnSpan } from '../tracing/utils.js';
|
|
5
|
-
import { mergeScopeData } from '../utils/applyScopeDataToEvent.js';
|
|
6
|
-
import { isV2BeforeSendSpanCallback } from '../utils/beforeSendSpan.js';
|
|
7
|
-
import { debug } from '../utils/debug-logger.js';
|
|
8
|
-
import { spanToV2JSON, INTERNAL_getSegmentSpan } from '../utils/spanUtils.js';
|
|
9
|
-
import { applyBeforeSendSpanCallback, safeSetSpanJSONAttributes, contextsToAttributes } from './spanFirstUtils.js';
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Captures a span and returns a JSON representation to be enqueued for sending.
|
|
13
|
-
*
|
|
14
|
-
* IMPORTANT: This function converts the span to JSON immediately to avoid writing
|
|
15
|
-
* to an already-ended OTel span instance (which is blocked by the OTel Span class).
|
|
16
|
-
*/
|
|
17
|
-
function captureSpan(span, client = getClient()) {
|
|
18
|
-
if (!client) {
|
|
19
|
-
DEBUG_BUILD && debug.warn('No client available to capture span.');
|
|
20
|
-
return;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
// Convert to JSON FIRST - we cannot write to an already-ended span
|
|
24
|
-
const spanJSON = spanToV2JSON(span);
|
|
25
|
-
|
|
26
|
-
const segmentSpan = INTERNAL_getSegmentSpan(span);
|
|
27
|
-
const serializedSegmentSpan = spanToV2JSON(segmentSpan);
|
|
28
|
-
|
|
29
|
-
const { isolationScope: spanIsolationScope, scope: spanScope } = getCapturedScopesOnSpan(span);
|
|
30
|
-
|
|
31
|
-
const finalScopeData = getFinalScopeData(spanIsolationScope, spanScope);
|
|
32
|
-
|
|
33
|
-
applyCommonSpanAttributes(spanJSON, serializedSegmentSpan, client, finalScopeData);
|
|
34
|
-
|
|
35
|
-
if (span === segmentSpan) {
|
|
36
|
-
applyScopeToSegmentSpan(spanJSON, finalScopeData);
|
|
37
|
-
client.emit('processSegmentSpan', spanJSON, { scopeData: finalScopeData });
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// Allow integrations to add additional data to the span JSON
|
|
41
|
-
client.emit('processSpan', spanJSON, { readOnlySpan: span });
|
|
42
|
-
|
|
43
|
-
const beforeSendSpan = client.getOptions().beforeSendSpan;
|
|
44
|
-
const processedSpan = isV2BeforeSendSpanCallback(beforeSendSpan)
|
|
45
|
-
? applyBeforeSendSpanCallback(spanJSON, beforeSendSpan)
|
|
46
|
-
: spanJSON;
|
|
47
|
-
|
|
48
|
-
const spanWithRef = {
|
|
49
|
-
...processedSpan,
|
|
50
|
-
_segmentSpan: segmentSpan,
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
client.emit('enqueueSpan', spanWithRef);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
function applyScopeToSegmentSpan(segmentSpanJSON, scopeData) {
|
|
57
|
-
// TODO: Apply all scope and request data from auto instrumentation (contexts, request) to segment span
|
|
58
|
-
const { contexts } = scopeData;
|
|
59
|
-
|
|
60
|
-
safeSetSpanJSONAttributes(segmentSpanJSON, contextsToAttributes(contexts));
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
function applyCommonSpanAttributes(
|
|
64
|
-
spanJSON,
|
|
65
|
-
serializedSegmentSpan,
|
|
66
|
-
client,
|
|
67
|
-
scopeData,
|
|
68
|
-
) {
|
|
69
|
-
const sdk = client.getSdkMetadata();
|
|
70
|
-
const { release, environment, sendDefaultPii } = client.getOptions();
|
|
71
|
-
|
|
72
|
-
// avoid overwriting any previously set attributes (from users or potentially our SDK instrumentation)
|
|
73
|
-
safeSetSpanJSONAttributes(spanJSON, {
|
|
74
|
-
[SEMANTIC_ATTRIBUTE_SENTRY_RELEASE]: release,
|
|
75
|
-
[SEMANTIC_ATTRIBUTE_SENTRY_ENVIRONMENT]: environment,
|
|
76
|
-
[SEMANTIC_ATTRIBUTE_SENTRY_SEGMENT_NAME]: serializedSegmentSpan.name,
|
|
77
|
-
[SEMANTIC_ATTRIBUTE_SENTRY_SEGMENT_ID]: serializedSegmentSpan.span_id,
|
|
78
|
-
[SEMANTIC_ATTRIBUTE_SENTRY_SDK_NAME]: sdk?.sdk?.name,
|
|
79
|
-
[SEMANTIC_ATTRIBUTE_SENTRY_SDK_VERSION]: sdk?.sdk?.version,
|
|
80
|
-
...(sendDefaultPii
|
|
81
|
-
? {
|
|
82
|
-
[SEMANTIC_ATTRIBUTE_USER_ID]: scopeData.user?.id,
|
|
83
|
-
[SEMANTIC_ATTRIBUTE_USER_EMAIL]: scopeData.user?.email,
|
|
84
|
-
[SEMANTIC_ATTRIBUTE_USER_IP_ADDRESS]: scopeData.user?.ip_address,
|
|
85
|
-
[SEMANTIC_ATTRIBUTE_USER_USERNAME]: scopeData.user?.username,
|
|
86
|
-
}
|
|
87
|
-
: {}),
|
|
88
|
-
...scopeData.attributes,
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// TODO: Extract this to a helper in core. It's used in multiple places.
|
|
93
|
-
function getFinalScopeData(isolationScope, scope) {
|
|
94
|
-
const finalScopeData = getGlobalScope().getScopeData();
|
|
95
|
-
if (isolationScope) {
|
|
96
|
-
mergeScopeData(finalScopeData, isolationScope.getScopeData());
|
|
97
|
-
}
|
|
98
|
-
if (scope) {
|
|
99
|
-
mergeScopeData(finalScopeData, scope.getScopeData());
|
|
100
|
-
}
|
|
101
|
-
return finalScopeData;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
export { captureSpan };
|
|
105
|
-
//# sourceMappingURL=captureSpan.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"captureSpan.js","sources":["../../../src/spans/captureSpan.ts"],"sourcesContent":["import type { Client } from '../client';\nimport { getClient, getGlobalScope } from '../currentScopes';\nimport { DEBUG_BUILD } from '../debug-build';\nimport type { Scope, ScopeData } from '../scope';\nimport {\n SEMANTIC_ATTRIBUTE_SENTRY_ENVIRONMENT,\n SEMANTIC_ATTRIBUTE_SENTRY_RELEASE,\n SEMANTIC_ATTRIBUTE_SENTRY_SDK_NAME,\n SEMANTIC_ATTRIBUTE_SENTRY_SDK_VERSION,\n SEMANTIC_ATTRIBUTE_SENTRY_SEGMENT_ID,\n SEMANTIC_ATTRIBUTE_SENTRY_SEGMENT_NAME,\n SEMANTIC_ATTRIBUTE_USER_EMAIL,\n SEMANTIC_ATTRIBUTE_USER_ID,\n SEMANTIC_ATTRIBUTE_USER_IP_ADDRESS,\n SEMANTIC_ATTRIBUTE_USER_USERNAME,\n} from '../semanticAttributes';\nimport { getCapturedScopesOnSpan } from '../tracing/utils';\nimport type { Span, SpanV2JSON } from '../types-hoist/span';\nimport { mergeScopeData } from '../utils/applyScopeDataToEvent';\nimport { isV2BeforeSendSpanCallback } from '../utils/beforeSendSpan';\nimport { debug } from '../utils/debug-logger';\nimport { INTERNAL_getSegmentSpan, spanToV2JSON } from '../utils/spanUtils';\nimport { applyBeforeSendSpanCallback, contextsToAttributes, safeSetSpanJSONAttributes } from './spanFirstUtils';\n/**\n * Captures a span and returns a JSON representation to be enqueued for sending.\n *\n * IMPORTANT: This function converts the span to JSON immediately to avoid writing\n * to an already-ended OTel span instance (which is blocked by the OTel Span class).\n */\nexport function captureSpan(span: Span, client = getClient()): void {\n if (!client) {\n DEBUG_BUILD && debug.warn('No client available to capture span.');\n return;\n }\n\n // Convert to JSON FIRST - we cannot write to an already-ended span\n const spanJSON = spanToV2JSON(span);\n\n const segmentSpan = INTERNAL_getSegmentSpan(span);\n const serializedSegmentSpan = spanToV2JSON(segmentSpan);\n\n const { isolationScope: spanIsolationScope, scope: spanScope } = getCapturedScopesOnSpan(span);\n\n const finalScopeData = getFinalScopeData(spanIsolationScope, spanScope);\n\n applyCommonSpanAttributes(spanJSON, serializedSegmentSpan, client, finalScopeData);\n\n if (span === segmentSpan) {\n applyScopeToSegmentSpan(spanJSON, finalScopeData);\n client.emit('processSegmentSpan', spanJSON, { scopeData: finalScopeData });\n }\n\n // Allow integrations to add additional data to the span JSON\n client.emit('processSpan', spanJSON, { readOnlySpan: span });\n\n const beforeSendSpan = client.getOptions().beforeSendSpan;\n const processedSpan = isV2BeforeSendSpanCallback(beforeSendSpan)\n ? applyBeforeSendSpanCallback(spanJSON, beforeSendSpan)\n : spanJSON;\n\n const spanWithRef = {\n ...processedSpan,\n _segmentSpan: segmentSpan,\n };\n\n client.emit('enqueueSpan', spanWithRef);\n}\n\nfunction applyScopeToSegmentSpan(segmentSpanJSON: SpanV2JSON, scopeData: ScopeData): void {\n // TODO: Apply all scope and request data from auto instrumentation (contexts, request) to segment span\n const { contexts } = scopeData;\n\n safeSetSpanJSONAttributes(segmentSpanJSON, contextsToAttributes(contexts));\n}\n\nfunction applyCommonSpanAttributes(\n spanJSON: SpanV2JSON,\n serializedSegmentSpan: SpanV2JSON,\n client: Client,\n scopeData: ScopeData,\n): void {\n const sdk = client.getSdkMetadata();\n const { release, environment, sendDefaultPii } = client.getOptions();\n\n // avoid overwriting any previously set attributes (from users or potentially our SDK instrumentation)\n safeSetSpanJSONAttributes(spanJSON, {\n [SEMANTIC_ATTRIBUTE_SENTRY_RELEASE]: release,\n [SEMANTIC_ATTRIBUTE_SENTRY_ENVIRONMENT]: environment,\n [SEMANTIC_ATTRIBUTE_SENTRY_SEGMENT_NAME]: serializedSegmentSpan.name,\n [SEMANTIC_ATTRIBUTE_SENTRY_SEGMENT_ID]: serializedSegmentSpan.span_id,\n [SEMANTIC_ATTRIBUTE_SENTRY_SDK_NAME]: sdk?.sdk?.name,\n [SEMANTIC_ATTRIBUTE_SENTRY_SDK_VERSION]: sdk?.sdk?.version,\n ...(sendDefaultPii\n ? {\n [SEMANTIC_ATTRIBUTE_USER_ID]: scopeData.user?.id,\n [SEMANTIC_ATTRIBUTE_USER_EMAIL]: scopeData.user?.email,\n [SEMANTIC_ATTRIBUTE_USER_IP_ADDRESS]: scopeData.user?.ip_address,\n [SEMANTIC_ATTRIBUTE_USER_USERNAME]: scopeData.user?.username,\n }\n : {}),\n ...scopeData.attributes,\n });\n}\n\n// TODO: Extract this to a helper in core. It's used in multiple places.\nfunction getFinalScopeData(isolationScope: Scope | undefined, scope: Scope | undefined): ScopeData {\n const finalScopeData = getGlobalScope().getScopeData();\n if (isolationScope) {\n mergeScopeData(finalScopeData, isolationScope.getScopeData());\n }\n if (scope) {\n mergeScopeData(finalScopeData, scope.getScopeData());\n }\n return finalScopeData;\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
import { DEBUG_BUILD } from '../debug-build.js';
|
|
2
|
-
import { createSpanV2Envelope } from '../envelope.js';
|
|
3
|
-
import { getDynamicSamplingContextFromSpan } from '../tracing/dynamicSamplingContext.js';
|
|
4
|
-
import { debug } from '../utils/debug-logger.js';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* A buffer for span JSON objects that flushes them to Sentry in Span v2 envelopes.
|
|
8
|
-
* Handles interval-based flushing, size thresholds, and graceful shutdown.
|
|
9
|
-
*/
|
|
10
|
-
class SpanBuffer {
|
|
11
|
-
|
|
12
|
-
constructor(client, options) {
|
|
13
|
-
this._spanTreeMap = new Map();
|
|
14
|
-
this._client = client;
|
|
15
|
-
|
|
16
|
-
const { maxSpanLimit, flushInterval } = options ?? {};
|
|
17
|
-
|
|
18
|
-
this._maxSpanLimit = maxSpanLimit && maxSpanLimit > 0 && maxSpanLimit <= 1000 ? maxSpanLimit : 1000;
|
|
19
|
-
this._flushInterval = flushInterval && flushInterval > 0 ? flushInterval : 5000;
|
|
20
|
-
|
|
21
|
-
this._flushIntervalId = setInterval(() => {
|
|
22
|
-
this.flush();
|
|
23
|
-
}, this._flushInterval);
|
|
24
|
-
|
|
25
|
-
this._client.on('flush', () => {
|
|
26
|
-
this.flush();
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Add a span to the buffer.
|
|
32
|
-
*/
|
|
33
|
-
addSpan(spanJSON) {
|
|
34
|
-
const traceId = spanJSON.trace_id;
|
|
35
|
-
let traceBucket = this._spanTreeMap.get(traceId);
|
|
36
|
-
if (traceBucket) {
|
|
37
|
-
traceBucket.add(spanJSON);
|
|
38
|
-
} else {
|
|
39
|
-
traceBucket = new Set([spanJSON]);
|
|
40
|
-
this._spanTreeMap.set(traceId, traceBucket);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
if (traceBucket.size >= this._maxSpanLimit) {
|
|
44
|
-
this._flushTrace(traceId);
|
|
45
|
-
this._debounceFlushInterval();
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Flush all buffered traces.
|
|
51
|
-
*/
|
|
52
|
-
flush() {
|
|
53
|
-
if (!this._spanTreeMap.size) {
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
DEBUG_BUILD && debug.log(`Flushing span tree map with ${this._spanTreeMap.size} traces`);
|
|
58
|
-
|
|
59
|
-
this._spanTreeMap.forEach((_, traceId) => {
|
|
60
|
-
this._flushTrace(traceId);
|
|
61
|
-
});
|
|
62
|
-
this._debounceFlushInterval();
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
_flushTrace(traceId) {
|
|
66
|
-
const traceBucket = this._spanTreeMap.get(traceId);
|
|
67
|
-
if (!traceBucket) {
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
if (!traceBucket.size) {
|
|
72
|
-
this._spanTreeMap.delete(traceId);
|
|
73
|
-
return;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
const firstSpanJSON = traceBucket.values().next().value;
|
|
77
|
-
|
|
78
|
-
const segmentSpan = firstSpanJSON?._segmentSpan;
|
|
79
|
-
if (!segmentSpan) {
|
|
80
|
-
DEBUG_BUILD && debug.warn('No segment span reference found on span JSON, cannot compute DSC');
|
|
81
|
-
this._spanTreeMap.delete(traceId);
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
const dsc = getDynamicSamplingContextFromSpan(segmentSpan);
|
|
86
|
-
|
|
87
|
-
const cleanedSpans = Array.from(traceBucket).map(spanJSON => {
|
|
88
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
89
|
-
const { _segmentSpan, ...cleanSpanJSON } = spanJSON;
|
|
90
|
-
return cleanSpanJSON;
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
const envelope = createSpanV2Envelope(cleanedSpans, dsc, this._client);
|
|
94
|
-
|
|
95
|
-
DEBUG_BUILD && debug.log(`Sending span envelope for trace ${traceId} with ${cleanedSpans.length} spans`);
|
|
96
|
-
|
|
97
|
-
this._client.sendEnvelope(envelope).then(null, reason => {
|
|
98
|
-
DEBUG_BUILD && debug.error('Error while sending span stream envelope:', reason);
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
this._spanTreeMap.delete(traceId);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
_debounceFlushInterval() {
|
|
105
|
-
if (this._flushIntervalId) {
|
|
106
|
-
clearInterval(this._flushIntervalId);
|
|
107
|
-
}
|
|
108
|
-
this._flushIntervalId = setInterval(() => {
|
|
109
|
-
this.flush();
|
|
110
|
-
}, this._flushInterval);
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
export { SpanBuffer };
|
|
115
|
-
//# sourceMappingURL=spanBuffer.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"spanBuffer.js","sources":["../../../src/spans/spanBuffer.ts"],"sourcesContent":["import type { Client } from '../client';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { createSpanV2Envelope } from '../envelope';\nimport { getDynamicSamplingContextFromSpan } from '../tracing/dynamicSamplingContext';\nimport type { SpanV2JSON, SpanV2JSONWithSegmentRef } from '../types-hoist/span';\nimport { debug } from '../utils/debug-logger';\n\nexport interface SpanBufferOptions {\n /** Max spans per trace before auto-flush (default: 1000) */\n maxSpanLimit?: number;\n /** Flush interval in ms (default: 5000) */\n flushInterval?: number;\n}\n\n/**\n * A buffer for span JSON objects that flushes them to Sentry in Span v2 envelopes.\n * Handles interval-based flushing, size thresholds, and graceful shutdown.\n */\nexport class SpanBuffer {\n private _spanTreeMap: Map<string, Set<SpanV2JSONWithSegmentRef>>;\n private _flushIntervalId: ReturnType<typeof setInterval> | null;\n private _client: Client;\n private _maxSpanLimit: number;\n private _flushInterval: number;\n\n public constructor(client: Client, options?: SpanBufferOptions) {\n this._spanTreeMap = new Map();\n this._client = client;\n\n const { maxSpanLimit, flushInterval } = options ?? {};\n\n this._maxSpanLimit = maxSpanLimit && maxSpanLimit > 0 && maxSpanLimit <= 1000 ? maxSpanLimit : 1000;\n this._flushInterval = flushInterval && flushInterval > 0 ? flushInterval : 5_000;\n\n this._flushIntervalId = setInterval(() => {\n this.flush();\n }, this._flushInterval);\n\n this._client.on('flush', () => {\n this.flush();\n });\n }\n\n /**\n * Add a span to the buffer.\n */\n public addSpan(spanJSON: SpanV2JSONWithSegmentRef): void {\n const traceId = spanJSON.trace_id;\n let traceBucket = this._spanTreeMap.get(traceId);\n if (traceBucket) {\n traceBucket.add(spanJSON);\n } else {\n traceBucket = new Set([spanJSON]);\n this._spanTreeMap.set(traceId, traceBucket);\n }\n\n if (traceBucket.size >= this._maxSpanLimit) {\n this._flushTrace(traceId);\n this._debounceFlushInterval();\n }\n }\n\n /**\n * Flush all buffered traces.\n */\n public flush(): void {\n if (!this._spanTreeMap.size) {\n return;\n }\n\n DEBUG_BUILD && debug.log(`Flushing span tree map with ${this._spanTreeMap.size} traces`);\n\n this._spanTreeMap.forEach((_, traceId) => {\n this._flushTrace(traceId);\n });\n this._debounceFlushInterval();\n }\n\n private _flushTrace(traceId: string): void {\n const traceBucket = this._spanTreeMap.get(traceId);\n if (!traceBucket) {\n return;\n }\n\n if (!traceBucket.size) {\n this._spanTreeMap.delete(traceId);\n return;\n }\n\n const firstSpanJSON = traceBucket.values().next().value;\n\n const segmentSpan = firstSpanJSON?._segmentSpan;\n if (!segmentSpan) {\n DEBUG_BUILD && debug.warn('No segment span reference found on span JSON, cannot compute DSC');\n this._spanTreeMap.delete(traceId);\n return;\n }\n\n const dsc = getDynamicSamplingContextFromSpan(segmentSpan);\n\n const cleanedSpans: SpanV2JSON[] = Array.from(traceBucket).map(spanJSON => {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { _segmentSpan, ...cleanSpanJSON } = spanJSON;\n return cleanSpanJSON;\n });\n\n const envelope = createSpanV2Envelope(cleanedSpans, dsc, this._client);\n\n DEBUG_BUILD && debug.log(`Sending span envelope for trace ${traceId} with ${cleanedSpans.length} spans`);\n\n this._client.sendEnvelope(envelope).then(null, reason => {\n DEBUG_BUILD && debug.error('Error while sending span stream envelope:', reason);\n });\n\n this._spanTreeMap.delete(traceId);\n }\n\n private _debounceFlushInterval(): void {\n if (this._flushIntervalId) {\n clearInterval(this._flushIntervalId);\n }\n this._flushIntervalId = setInterval(() => {\n this.flush();\n }, this._flushInterval);\n }\n}\n"],"names":[],"mappings":"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"}
|