From 74ee2fe6ef7394d7eea8e1427970e561b526a12d Mon Sep 17 00:00:00 2001 From: Nicolas Hrubec Date: Tue, 21 Apr 2026 18:46:15 +0200 Subject: [PATCH 1/7] feat(core): Support homogeneous primitive arrays as span attributes Relay's wire contract (AttributeType enum in relay-event-schema) defines exactly five `type:` tags: boolean, integer, double, string, array. The SDK's AttributeTypeMap previously declared typed array variants (`string[]`, `integer[]`, etc.) that Relay does not recognize - these were never actually emitted because the runtime serializer only handled primitives, so array-valued attributes silently dropped. This change: - Collapses the four `x[]` variants in AttributeTypeMap into a single `array` variant whose value is `Array | Array | Array`. - Extends getTypedAttributeValue to auto-detect homogeneous primitive arrays and emit `{type: 'array', value: [...]}`. - Adds an isHomogeneousPrimitiveArray guard so mixed-type and nested arrays remain unsupported (dropped by default, stringified under the fallback path). - Updates tests to cover the new typed-array path (including empty arrays, unit preservation, and mixed-type drop/stringify). Co-Authored-By: Claude Opus 4.7 (1M context) --- packages/core/src/attributes.ts | 33 ++++--- packages/core/test/lib/attributes.test.ts | 90 +++++++++---------- packages/core/test/lib/logs/internal.test.ts | 10 ++- .../lib/tracing/spans/estimateSize.test.ts | 6 +- .../core/test/lib/utils/spanUtils.test.ts | 4 +- 5 files changed, 76 insertions(+), 67 deletions(-) diff --git a/packages/core/src/attributes.ts b/packages/core/src/attributes.ts index 1f4a6638f577..c8681fc6e757 100644 --- a/packages/core/src/attributes.ts +++ b/packages/core/src/attributes.ts @@ -15,10 +15,7 @@ type AttributeTypeMap = { integer: number; double: number; boolean: boolean; - 'string[]': Array; - 'integer[]': Array; - 'double[]': Array; - 'boolean[]': Array; + array: Array | Array | Array; }; /* Generates a type from the AttributeTypeMap like: @@ -66,9 +63,9 @@ export function isAttributeObject(maybeObj: unknown): maybeObj is AttributeObjec /** * Converts an attribute value to a typed attribute value. * - * For now, we intentionally only support primitive values and attribute objects with primitive values. - * If @param useFallback is true, we stringify non-primitive values to a string attribute value. Otherwise - * we return `undefined` for unsupported values. + * For now, we support primitive values and homogeneous arrays of primitives, either raw or + * inside attribute objects. If @param useFallback is true, we stringify other non-primitive values + * to a string attribute value. Otherwise we return `undefined` for unsupported values. * * @param value - The value of the passed attribute. * @param useFallback - If true, unsupported values will be stringified to a string attribute value. @@ -170,17 +167,18 @@ function estimatePrimitiveSizeInBytes(value: Primitive): number { } /** - * NOTE: We intentionally do not return anything for non-primitive values: - * - array support will come in the future but if we stringify arrays now, - * sending arrays (unstringified) later will be a subtle breaking change. + * NOTE: We return typed attributes for primitives and homogeneous arrays of primitives: + * - Homogeneous primitive arrays ship with `type: 'array'` (Relay's wire tag for arrays). + * - Mixed-type and nested arrays are not supported and return undefined. * - Objects are not supported yet and product support is still TBD. * - We still keep the type signature for TypedAttributeValue wider to avoid a - * breaking change once we add support for non-primitive values. - * - Once we go back to supporting arrays and stringifying all other values, - * we already implemented the serialization logic here: - * https://github.com/getsentry/sentry-javascript/pull/18165 + * breaking change once we add support for other non-primitive values. */ function getTypedAttributeValue(value: unknown): TypedAttributeValue | void { + if (Array.isArray(value) && isHomogeneousPrimitiveArray(value)) { + return { value, type: 'array' }; + } + const primitiveType = typeof value === 'string' ? 'string' @@ -201,3 +199,10 @@ function getTypedAttributeValue(value: unknown): TypedAttributeValue | void { return { value, type: primitiveType }; } } + +function isHomogeneousPrimitiveArray(arr: unknown[]): boolean { + if (arr.length === 0) return true; + const t = typeof arr[0]; + if (t !== 'string' && t !== 'number' && t !== 'boolean') return false; + return arr.every(v => typeof v === t); +} diff --git a/packages/core/test/lib/attributes.test.ts b/packages/core/test/lib/attributes.test.ts index 13b9e026e6e9..060fbe1f618b 100644 --- a/packages/core/test/lib/attributes.test.ts +++ b/packages/core/test/lib/attributes.test.ts @@ -76,33 +76,38 @@ describe('attributeValueToTypedAttributeValue', () => { ); }); - describe('invalid values (non-primitives)', () => { - it.each([ - ['foo', 'bar'], - [1, 2, 3], - [true, false, true], - [1, 'foo', true], - { foo: 'bar' }, - () => 'test', - Symbol('test'), - ])('returns undefined for non-primitive raw values (%s)', value => { - const result = attributeValueToTypedAttributeValue(value); - expect(result).toBeUndefined(); - }); + describe('homogeneous primitive arrays', () => { + it.each([[['foo', 'bar']], [[1, 2, 3]], [[true, false, true]], [[] as unknown[]]])( + 'emits a typed array attribute for raw value %j', + value => { + const result = attributeValueToTypedAttributeValue(value); + expect(result).toStrictEqual({ value, type: 'array' }); + }, + ); - it.each([ - ['foo', 'bar'], - [1, 2, 3], - [true, false, true], - [1, 'foo', true], - { foo: 'bar' }, - () => 'test', - Symbol('test'), - ])('returns undefined for non-primitive attribute object values (%s)', value => { - const result = attributeValueToTypedAttributeValue({ value }); - expect(result).toBeUndefined(); + it('emits a typed array attribute for attribute object values', () => { + const result = attributeValueToTypedAttributeValue({ value: ['foo', 'bar'] }); + expect(result).toStrictEqual({ value: ['foo', 'bar'], type: 'array' }); }); }); + + describe('invalid values (non-primitives)', () => { + it.each([[[1, 'foo', true]], [{ foo: 'bar' }], [() => 'test'], [Symbol('test')]])( + 'returns undefined for non-primitive raw values (%s)', + value => { + const result = attributeValueToTypedAttributeValue(value); + expect(result).toBeUndefined(); + }, + ); + + it.each([[[1, 'foo', true]], [{ foo: 'bar' }], [() => 'test'], [Symbol('test')]])( + 'returns undefined for non-primitive attribute object values (%s)', + value => { + const result = attributeValueToTypedAttributeValue({ value }); + expect(result).toBeUndefined(); + }, + ); + }); }); describe('with fallback=true', () => { @@ -189,26 +194,10 @@ describe('attributeValueToTypedAttributeValue', () => { }); describe('invalid values (non-primitives) - stringified fallback', () => { - it('stringifies string arrays', () => { - const result = attributeValueToTypedAttributeValue(['foo', 'bar'], true); + it('stringifies mixed-type arrays (not homogeneous)', () => { + const result = attributeValueToTypedAttributeValue(['foo', 1, true], true); expect(result).toStrictEqual({ - value: '["foo","bar"]', - type: 'string', - }); - }); - - it('stringifies number arrays', () => { - const result = attributeValueToTypedAttributeValue([1, 2, 3], true); - expect(result).toStrictEqual({ - value: '[1,2,3]', - type: 'string', - }); - }); - - it('stringifies boolean arrays', () => { - const result = attributeValueToTypedAttributeValue([true, false, true], true); - expect(result).toStrictEqual({ - value: '[true,false,true]', + value: '["foo",1,true]', type: 'string', }); }); @@ -425,15 +414,17 @@ describe('serializeAttributes', () => { describe('invalid (non-primitive) values', () => { it("doesn't fall back to stringification by default", () => { const result = serializeAttributes({ foo: { some: 'object' }, bar: [1, 2, 3], baz: () => {} }); - expect(result).toStrictEqual({}); + expect(result).toStrictEqual({ + bar: { type: 'array', value: [1, 2, 3] }, + }); }); it('falls back to stringification of unsupported non-primitive values if fallback is true', () => { const result = serializeAttributes({ foo: { some: 'object' }, bar: [1, 2, 3], baz: () => {} }, true); expect(result).toStrictEqual({ bar: { - type: 'string', - value: '[1,2,3]', + type: 'array', + value: [1, 2, 3], }, baz: { type: 'string', @@ -445,5 +436,12 @@ describe('serializeAttributes', () => { }, }); }); + + it('drops mixed-type arrays by default and stringifies them with fallback', () => { + expect(serializeAttributes({ mixed: ['a', 1] })).toStrictEqual({}); + expect(serializeAttributes({ mixed: ['a', 1] }, true)).toStrictEqual({ + mixed: { type: 'string', value: '["a",1]' }, + }); + }); }); }); diff --git a/packages/core/test/lib/logs/internal.test.ts b/packages/core/test/lib/logs/internal.test.ts index 360485f5ca84..48c93c7cf1d1 100644 --- a/packages/core/test/lib/logs/internal.test.ts +++ b/packages/core/test/lib/logs/internal.test.ts @@ -191,7 +191,6 @@ describe('_INTERNAL_captureLog', () => { scope.setAttribute('scope_2', { value: 38, unit: 'gigabyte' }); scope.setAttributes({ scope_3: true, - // these are invalid since for now we don't support arrays scope_4: [1, 2, 3], scope_5: { value: [true, false, true], unit: 'second' }, }); @@ -229,6 +228,15 @@ describe('_INTERNAL_captureLog', () => { type: 'boolean', value: true, }, + scope_4: { + type: 'array', + value: [1, 2, 3], + }, + scope_5: { + type: 'array', + value: [true, false, true], + unit: 'second', + }, 'sentry.timestamp.sequence': { value: expect.any(Number), type: 'integer' }, }); }); diff --git a/packages/core/test/lib/tracing/spans/estimateSize.test.ts b/packages/core/test/lib/tracing/spans/estimateSize.test.ts index 35d569691dea..e92b260839f2 100644 --- a/packages/core/test/lib/tracing/spans/estimateSize.test.ts +++ b/packages/core/test/lib/tracing/spans/estimateSize.test.ts @@ -130,9 +130,9 @@ describe('estimateSerializedSpanSizeInBytes', () => { status: 'ok', is_segment: false, attributes: { - 'item.ids': { type: 'string[]', value: ['id-001', 'id-002', 'id-003', 'id-004', 'id-005'] }, - scores: { type: 'double[]', value: [1.1, 2.2, 3.3, 4.4] }, - flags: { type: 'boolean[]', value: [true, false, true] }, + 'item.ids': { type: 'array', value: ['id-001', 'id-002', 'id-003', 'id-004', 'id-005'] }, + scores: { type: 'array', value: [1.1, 2.2, 3.3, 4.4] }, + flags: { type: 'array', value: [true, false, true] }, }, }; diff --git a/packages/core/test/lib/utils/spanUtils.test.ts b/packages/core/test/lib/utils/spanUtils.test.ts index e4a0b31990d7..a2f2dbea7aba 100644 --- a/packages/core/test/lib/utils/spanUtils.test.ts +++ b/packages/core/test/lib/utils/spanUtils.test.ts @@ -622,11 +622,9 @@ describe('spanToJSON', () => { attr1: { type: 'string', value: 'value1' }, attr2: { type: 'integer', value: 2 }, attr3: { type: 'boolean', value: true }, + attr4: { type: 'array', value: [1, 2, 3] }, [SEMANTIC_ATTRIBUTE_SENTRY_OP]: { type: 'string', value: 'test op' }, [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: { type: 'string', value: 'auto' }, - // notice the absence of `attr4`! - // for now, we don't yet serialize array attributes. This test will fail - // once we allow serializing them. }, links: [ { From 2d84168c9cbdc4a51416eb169f1d5f05e5c14b05 Mon Sep 17 00:00:00 2001 From: Nicolas Hrubec Date: Tue, 21 Apr 2026 19:28:48 +0200 Subject: [PATCH 2/7] test: Update integration tests for array attribute support Arrays that were previously dropped by the serializer now ship as native array attributes (`type: 'array'`). Update the affected integration test expectations and bump size-limit thresholds for the five bundle scenarios whose gzipped/uncompressed sizes grew from the new serializer logic. Co-Authored-By: Claude Opus 4.7 (1M context) --- .size-limit.js | 10 +++++----- .../suites/public-api/logger/integration/test.ts | 2 +- .../public-api/logger/scopeAttributes/subject.js | 1 - .../suites/public-api/logger/scopeAttributes/test.ts | 4 ++++ .../suites/public-api/logger/scenario.ts | 1 - .../suites/public-api/logger/test.ts | 4 ++++ 6 files changed, 14 insertions(+), 8 deletions(-) diff --git a/.size-limit.js b/.size-limit.js index c4b37635ecda..ce52d17deeed 100644 --- a/.size-limit.js +++ b/.size-limit.js @@ -138,7 +138,7 @@ module.exports = [ path: 'packages/browser/build/npm/esm/prod/index.js', import: createImport('init', 'metrics', 'logger'), gzip: true, - limit: '28 KB', + limit: '29 KB', }, // React SDK (ESM) { @@ -215,13 +215,13 @@ module.exports = [ name: 'CDN Bundle (incl. Tracing, Replay)', path: createCDNPath('bundle.tracing.replay.min.js'), gzip: true, - limit: '82 KB', + limit: '83 KB', }, { name: 'CDN Bundle (incl. Tracing, Replay, Logs, Metrics)', path: createCDNPath('bundle.tracing.replay.logs.metrics.min.js'), gzip: true, - limit: '83 KB', + limit: '84 KB', }, { name: 'CDN Bundle (incl. Tracing, Replay, Feedback)', @@ -283,7 +283,7 @@ module.exports = [ path: createCDNPath('bundle.tracing.replay.logs.metrics.min.js'), gzip: false, brotli: false, - limit: '255 KB', + limit: '256 KB', }, { name: 'CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed', @@ -297,7 +297,7 @@ module.exports = [ path: createCDNPath('bundle.tracing.replay.feedback.logs.metrics.min.js'), gzip: false, brotli: false, - limit: '268 KB', + limit: '269 KB', }, // Next.js SDK (ESM) { diff --git a/dev-packages/browser-integration-tests/suites/public-api/logger/integration/test.ts b/dev-packages/browser-integration-tests/suites/public-api/logger/integration/test.ts index 7315e8cf4f36..1d969682bd3b 100644 --- a/dev-packages/browser-integration-tests/suites/public-api/logger/integration/test.ts +++ b/dev-packages/browser-integration-tests/suites/public-api/logger/integration/test.ts @@ -177,7 +177,7 @@ sentryTest('should capture console object calls', async ({ getLocalTestUrl, page 'sentry.message.template': { value: 'Mixed: {} {} {} {}', type: 'string' }, 'sentry.message.parameter.0': { value: 'prefix', type: 'string' }, 'sentry.message.parameter.1': { value: '{"obj":true}', type: 'string' }, - 'sentry.message.parameter.2': { value: '[4,5,6]', type: 'string' }, + 'sentry.message.parameter.2': { value: [4, 5, 6], type: 'array' }, 'sentry.message.parameter.3': { value: 'suffix', type: 'string' }, }, }, diff --git a/dev-packages/browser-integration-tests/suites/public-api/logger/scopeAttributes/subject.js b/dev-packages/browser-integration-tests/suites/public-api/logger/scopeAttributes/subject.js index 9bba2c222bdc..76377beb82a7 100644 --- a/dev-packages/browser-integration-tests/suites/public-api/logger/scopeAttributes/subject.js +++ b/dev-packages/browser-integration-tests/suites/public-api/logger/scopeAttributes/subject.js @@ -3,7 +3,6 @@ Sentry.logger.info('log_before_any_scope', { log_attr: 'log_attr_1' }); Sentry.getGlobalScope().setAttributes({ global_scope_attr: true }); -// this attribute will not be sent for now Sentry.getGlobalScope().setAttribute('array_attr', [1, 2, 3]); // global scope, log attribute diff --git a/dev-packages/browser-integration-tests/suites/public-api/logger/scopeAttributes/test.ts b/dev-packages/browser-integration-tests/suites/public-api/logger/scopeAttributes/test.ts index 4d7970945436..1b45e90c0613 100644 --- a/dev-packages/browser-integration-tests/suites/public-api/logger/scopeAttributes/test.ts +++ b/dev-packages/browser-integration-tests/suites/public-api/logger/scopeAttributes/test.ts @@ -47,6 +47,7 @@ sentryTest('captures logs with scope attributes', async ({ getLocalTestUrl, page 'sentry.sdk.version': { value: expect.any(String), type: 'string' }, 'sentry.timestamp.sequence': { value: expect.any(Number), type: 'integer' }, global_scope_attr: { value: true, type: 'boolean' }, + array_attr: { value: [1, 2, 3], type: 'array' }, log_attr: { value: 'log_attr_2', type: 'string' }, }, }, @@ -61,6 +62,7 @@ sentryTest('captures logs with scope attributes', async ({ getLocalTestUrl, page 'sentry.sdk.version': { value: expect.any(String), type: 'string' }, 'sentry.timestamp.sequence': { value: expect.any(Number), type: 'integer' }, global_scope_attr: { value: true, type: 'boolean' }, + array_attr: { value: [1, 2, 3], type: 'array' }, isolation_scope_1_attr: { value: 100, unit: 'millisecond', type: 'integer' }, log_attr: { value: 'log_attr_3', type: 'string' }, }, @@ -76,6 +78,7 @@ sentryTest('captures logs with scope attributes', async ({ getLocalTestUrl, page 'sentry.sdk.version': { value: expect.any(String), type: 'string' }, 'sentry.timestamp.sequence': { value: expect.any(Number), type: 'integer' }, global_scope_attr: { value: true, type: 'boolean' }, + array_attr: { value: [1, 2, 3], type: 'array' }, isolation_scope_1_attr: { value: 100, unit: 'millisecond', type: 'integer' }, scope_attr: { value: 200, unit: 'millisecond', type: 'integer' }, log_attr: { value: 'log_attr_4', type: 'string' }, @@ -92,6 +95,7 @@ sentryTest('captures logs with scope attributes', async ({ getLocalTestUrl, page 'sentry.sdk.version': { value: expect.any(String), type: 'string' }, 'sentry.timestamp.sequence': { value: expect.any(Number), type: 'integer' }, global_scope_attr: { value: true, type: 'boolean' }, + array_attr: { value: [1, 2, 3], type: 'array' }, isolation_scope_1_attr: { value: 100, unit: 'millisecond', type: 'integer' }, scope_2_attr: { value: 300, unit: 'millisecond', type: 'integer' }, log_attr: { value: 'log_attr_5', type: 'string' }, diff --git a/dev-packages/node-integration-tests/suites/public-api/logger/scenario.ts b/dev-packages/node-integration-tests/suites/public-api/logger/scenario.ts index c3be917706e7..c3ad84c1e146 100644 --- a/dev-packages/node-integration-tests/suites/public-api/logger/scenario.ts +++ b/dev-packages/node-integration-tests/suites/public-api/logger/scenario.ts @@ -15,7 +15,6 @@ async function run(): Promise { Sentry.getGlobalScope().setAttribute('global_scope_attr', true); - // this attribute will not be sent for now Sentry.getGlobalScope().setAttributes({ array_attr: [1, 2, 3] }); // global scope, log attribute diff --git a/dev-packages/node-integration-tests/suites/public-api/logger/test.ts b/dev-packages/node-integration-tests/suites/public-api/logger/test.ts index 6b9f43e738d2..a8bc88f27bcb 100644 --- a/dev-packages/node-integration-tests/suites/public-api/logger/test.ts +++ b/dev-packages/node-integration-tests/suites/public-api/logger/test.ts @@ -60,6 +60,7 @@ describe('logs', () => { attributes: { ...commonAttributes, global_scope_attr: { value: true, type: 'boolean' }, + array_attr: { value: [1, 2, 3], type: 'array' }, log_attr: { value: 'log_attr_2', type: 'string' }, }, }, @@ -72,6 +73,7 @@ describe('logs', () => { attributes: { ...commonAttributes, global_scope_attr: { value: true, type: 'boolean' }, + array_attr: { value: [1, 2, 3], type: 'array' }, isolation_scope_1_attr: { value: 100, unit: 'millisecond', type: 'integer' }, log_attr: { value: 'log_attr_3', type: 'string' }, }, @@ -85,6 +87,7 @@ describe('logs', () => { attributes: { ...commonAttributes, global_scope_attr: { value: true, type: 'boolean' }, + array_attr: { value: [1, 2, 3], type: 'array' }, isolation_scope_1_attr: { value: 100, unit: 'millisecond', type: 'integer' }, scope_attr: { value: 200, unit: 'millisecond', type: 'integer' }, log_attr: { value: 'log_attr_4', type: 'string' }, @@ -99,6 +102,7 @@ describe('logs', () => { attributes: { ...commonAttributes, global_scope_attr: { value: true, type: 'boolean' }, + array_attr: { value: [1, 2, 3], type: 'array' }, isolation_scope_1_attr: { value: 100, unit: 'millisecond', type: 'integer' }, scope_2_attr: { value: 300, unit: 'millisecond', type: 'integer' }, log_attr: { value: 'log_attr_5', type: 'string' }, From fa70b75914297a7fd8396292b0e06e390f0e54f0 Mon Sep 17 00:00:00 2001 From: Nicolas Hrubec Date: Tue, 21 Apr 2026 19:31:17 +0200 Subject: [PATCH 3/7] Revert ".size-limit.js" bumps Drop the size-limit increases for the five bundle scenarios that grew from adding homogeneous primitive array support. Test expectation updates from the previous commit stay. Co-Authored-By: Claude Opus 4.7 (1M context) --- .size-limit.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.size-limit.js b/.size-limit.js index ce52d17deeed..c4b37635ecda 100644 --- a/.size-limit.js +++ b/.size-limit.js @@ -138,7 +138,7 @@ module.exports = [ path: 'packages/browser/build/npm/esm/prod/index.js', import: createImport('init', 'metrics', 'logger'), gzip: true, - limit: '29 KB', + limit: '28 KB', }, // React SDK (ESM) { @@ -215,13 +215,13 @@ module.exports = [ name: 'CDN Bundle (incl. Tracing, Replay)', path: createCDNPath('bundle.tracing.replay.min.js'), gzip: true, - limit: '83 KB', + limit: '82 KB', }, { name: 'CDN Bundle (incl. Tracing, Replay, Logs, Metrics)', path: createCDNPath('bundle.tracing.replay.logs.metrics.min.js'), gzip: true, - limit: '84 KB', + limit: '83 KB', }, { name: 'CDN Bundle (incl. Tracing, Replay, Feedback)', @@ -283,7 +283,7 @@ module.exports = [ path: createCDNPath('bundle.tracing.replay.logs.metrics.min.js'), gzip: false, brotli: false, - limit: '256 KB', + limit: '255 KB', }, { name: 'CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed', @@ -297,7 +297,7 @@ module.exports = [ path: createCDNPath('bundle.tracing.replay.feedback.logs.metrics.min.js'), gzip: false, brotli: false, - limit: '269 KB', + limit: '268 KB', }, // Next.js SDK (ESM) { From a71058e08879dd7b9e6de0452709709f065fd771 Mon Sep 17 00:00:00 2001 From: Nicolas Hrubec Date: Tue, 21 Apr 2026 20:13:50 +0200 Subject: [PATCH 4/7] chore(size-limit): Bump thresholds for array-attribute support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Re-apply the size-limit bumps needed to account for the new homogeneous-primitive-array detection logic. Five scenarios grew past their thresholds: - @sentry/browser (incl. Metrics & Logs): 28 → 29 KB - CDN Bundle (incl. Logs, Metrics): 30 → 31 KB - CDN Bundle (incl. Tracing, Replay, Logs, Metrics) - uncompressed: 258.5 → 259 KB - CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed: 268 → 269 KB - CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) - uncompressed: 271.5 → 272 KB Co-Authored-By: Claude Opus 4.7 (1M context) --- .size-limit.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.size-limit.js b/.size-limit.js index cad516a0a49a..1c4eebbbb275 100644 --- a/.size-limit.js +++ b/.size-limit.js @@ -138,7 +138,7 @@ module.exports = [ path: 'packages/browser/build/npm/esm/prod/index.js', import: createImport('init', 'metrics', 'logger'), gzip: true, - limit: '28 KB', + limit: '29 KB', }, // React SDK (ESM) { @@ -197,7 +197,7 @@ module.exports = [ name: 'CDN Bundle (incl. Logs, Metrics)', path: createCDNPath('bundle.logs.metrics.min.js'), gzip: true, - limit: '30 KB', + limit: '31 KB', }, { name: 'CDN Bundle (incl. Tracing, Logs, Metrics)', @@ -283,21 +283,21 @@ module.exports = [ path: createCDNPath('bundle.tracing.replay.logs.metrics.min.js'), gzip: false, brotli: false, - limit: '258.5 KB', + limit: '259 KB', }, { name: 'CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed', path: createCDNPath('bundle.tracing.replay.feedback.min.js'), gzip: false, brotli: false, - limit: '268 KB', + limit: '269 KB', }, { name: 'CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) - uncompressed', path: createCDNPath('bundle.tracing.replay.feedback.logs.metrics.min.js'), gzip: false, brotli: false, - limit: '271.5 KB', + limit: '272 KB', }, // Next.js SDK (ESM) { From 8b38c1f4a2776159957a163ada32acfac8fcc7bf Mon Sep 17 00:00:00 2001 From: Nicolas Hrubec Date: Tue, 21 Apr 2026 18:46:48 +0200 Subject: [PATCH 5/7] feat(core): Emit sentry.sdk.integrations on segment spans in span streaming In the classic (non-streaming) pipeline, SDK integrations ride on the transaction event wrapper via `event.sdk.integrations`. The span streaming pipeline emits segment spans directly as span envelope items with no transaction wrapper, so that metadata never reaches ingest. Add `sentry.sdk.integrations` as a native array attribute on segment spans (matching the wire contract Relay expects: `type: 'array'`). Relies on the homogeneous-primitive-array serializer support. Co-Authored-By: Claude Opus 4.7 (1M context) --- packages/core/src/semanticAttributes.ts | 2 + .../core/src/tracing/spans/captureSpan.ts | 11 +++ .../lib/tracing/spans/captureSpan.test.ts | 81 +++++++++++++++++++ 3 files changed, 94 insertions(+) diff --git a/packages/core/src/semanticAttributes.ts b/packages/core/src/semanticAttributes.ts index 02b6a4ec08a6..fff57045b65e 100644 --- a/packages/core/src/semanticAttributes.ts +++ b/packages/core/src/semanticAttributes.ts @@ -52,6 +52,8 @@ export const SEMANTIC_ATTRIBUTE_SENTRY_SEGMENT_ID = 'sentry.segment.id'; export const SEMANTIC_ATTRIBUTE_SENTRY_SDK_NAME = 'sentry.sdk.name'; /** The version of the Sentry SDK */ export const SEMANTIC_ATTRIBUTE_SENTRY_SDK_VERSION = 'sentry.sdk.version'; +/** The list of integrations enabled in the Sentry SDK (e.g., ["InboundFilters", "BrowserTracing"]) */ +export const SEMANTIC_ATTRIBUTE_SENTRY_SDK_INTEGRATIONS = 'sentry.sdk.integrations'; /** The user ID (gated by sendDefaultPii) */ export const SEMANTIC_ATTRIBUTE_USER_ID = 'user.id'; diff --git a/packages/core/src/tracing/spans/captureSpan.ts b/packages/core/src/tracing/spans/captureSpan.ts index fe8bc31fcae7..1042afdac731 100644 --- a/packages/core/src/tracing/spans/captureSpan.ts +++ b/packages/core/src/tracing/spans/captureSpan.ts @@ -4,6 +4,7 @@ import type { ScopeData } from '../../scope'; import { SEMANTIC_ATTRIBUTE_SENTRY_ENVIRONMENT, SEMANTIC_ATTRIBUTE_SENTRY_RELEASE, + SEMANTIC_ATTRIBUTE_SENTRY_SDK_INTEGRATIONS, SEMANTIC_ATTRIBUTE_SENTRY_SDK_NAME, SEMANTIC_ATTRIBUTE_SENTRY_SDK_VERSION, SEMANTIC_ATTRIBUTE_SENTRY_SEGMENT_ID, @@ -53,6 +54,7 @@ export function captureSpan(span: Span, client: Client): SerializedStreamedSpanW if (spanJSON.is_segment) { applyScopeToSegmentSpan(spanJSON, finalScopeData); + applySdkMetadataToSegmentSpan(spanJSON, client); // Allow hook subscribers to mutate the segment span JSON // This also invokes the `processSegmentSpan` hook of all integrations client.emit('processSegmentSpan', spanJSON); @@ -90,6 +92,15 @@ function applyScopeToSegmentSpan(_segmentSpanJSON: StreamedSpanJSON, _scopeData: // This will follow in a separate PR } +function applySdkMetadataToSegmentSpan(segmentSpanJSON: StreamedSpanJSON, client: Client): void { + const integrationNames = client.getOptions().integrations.map(i => i.name); + if (!integrationNames.length) return; + + safeSetSpanJSONAttributes(segmentSpanJSON, { + [SEMANTIC_ATTRIBUTE_SENTRY_SDK_INTEGRATIONS]: integrationNames, + }); +} + function applyCommonSpanAttributes( spanJSON: StreamedSpanJSON, serializedSegmentSpan: StreamedSpanJSON, diff --git a/packages/core/test/lib/tracing/spans/captureSpan.test.ts b/packages/core/test/lib/tracing/spans/captureSpan.test.ts index d429d50714a2..2cc91c761cf3 100644 --- a/packages/core/test/lib/tracing/spans/captureSpan.test.ts +++ b/packages/core/test/lib/tracing/spans/captureSpan.test.ts @@ -7,6 +7,7 @@ import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_RELEASE, SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, + SEMANTIC_ATTRIBUTE_SENTRY_SDK_INTEGRATIONS, SEMANTIC_ATTRIBUTE_SENTRY_SDK_NAME, SEMANTIC_ATTRIBUTE_SENTRY_SDK_VERSION, SEMANTIC_ATTRIBUTE_SENTRY_SEGMENT_ID, @@ -291,6 +292,86 @@ describe('captureSpan', () => { }); }); + it('adds sentry.sdk.integrations to segment spans as an array attribute', () => { + const client = new TestClient( + getDefaultTestClientOptions({ + dsn: 'https://dsn@ingest.f00.f00/1', + tracesSampleRate: 1, + release: '1.0.0', + environment: 'staging', + integrations: [ + { name: 'InboundFilters', setupOnce: () => {} }, + { name: 'BrowserTracing', setupOnce: () => {} }, + ], + _metadata: { + sdk: { + name: 'sentry.javascript.browser', + version: '9.0.0', + }, + }, + }), + ); + + const span = withScope(scope => { + scope.setClient(client); + const span = startInactiveSpan({ name: 'my-span', attributes: { 'sentry.op': 'http.client' } }); + span.end(); + return span; + }); + + expect(captureSpan(span, client)).toStrictEqual({ + span_id: expect.stringMatching(/^[\da-f]{16}$/), + trace_id: expect.stringMatching(/^[\da-f]{32}$/), + parent_span_id: undefined, + links: undefined, + start_timestamp: expect.any(Number), + name: 'my-span', + end_timestamp: expect.any(Number), + status: 'ok', + is_segment: true, + attributes: { + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: { type: 'string', value: 'http.client' }, + [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: { type: 'string', value: 'manual' }, + [SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE]: { type: 'integer', value: 1 }, + [SEMANTIC_ATTRIBUTE_SENTRY_SEGMENT_NAME]: { value: 'my-span', type: 'string' }, + [SEMANTIC_ATTRIBUTE_SENTRY_SEGMENT_ID]: { value: span.spanContext().spanId, type: 'string' }, + 'sentry.span.source': { value: 'custom', type: 'string' }, + [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: { value: 'custom', type: 'string' }, + [SEMANTIC_ATTRIBUTE_SENTRY_RELEASE]: { value: '1.0.0', type: 'string' }, + [SEMANTIC_ATTRIBUTE_SENTRY_ENVIRONMENT]: { value: 'staging', type: 'string' }, + [SEMANTIC_ATTRIBUTE_SENTRY_SDK_NAME]: { value: 'sentry.javascript.browser', type: 'string' }, + [SEMANTIC_ATTRIBUTE_SENTRY_SDK_VERSION]: { value: '9.0.0', type: 'string' }, + [SEMANTIC_ATTRIBUTE_SENTRY_SDK_INTEGRATIONS]: { + type: 'array', + value: ['InboundFilters', 'BrowserTracing'], + }, + }, + _segmentSpan: span, + }); + }); + + it('does not add sentry.sdk.integrations to non-segment child spans', () => { + const client = new TestClient( + getDefaultTestClientOptions({ + dsn: 'https://dsn@ingest.f00.f00/1', + tracesSampleRate: 1, + integrations: [{ name: 'InboundFilters', setupOnce: () => {} }], + }), + ); + + const serializedChild = withScope(scope => { + scope.setClient(client); + return startSpan({ name: 'segment' }, () => { + const childSpan = startInactiveSpan({ name: 'child' }); + childSpan.end(); + return captureSpan(childSpan, client); + }); + }); + + expect(serializedChild.is_segment).toBe(false); + expect(serializedChild.attributes?.[SEMANTIC_ATTRIBUTE_SENTRY_SDK_INTEGRATIONS]).toBeUndefined(); + }); + describe('client hooks', () => { it('calls processSpan and processSegmentSpan hooks for a segment span', () => { const client = new TestClient( From e08ef495d1c5562d5a8aa50ea2b31e22d56163ed Mon Sep 17 00:00:00 2001 From: Nicolas Hrubec Date: Tue, 21 Apr 2026 20:50:05 +0200 Subject: [PATCH 6/7] test: Update streamed segment span expectations for sentry.sdk.integrations Segment spans now ship a sentry.sdk.integrations attribute listing the active SDK integrations. Add the attribute to the full-shape assertions in the browser unit test, the browser/node/cloudflare streamed integration tests, and the Deno e2e test. Matching uses expect.arrayContaining against the explicit integrations configured in each scenario, to stay resilient to default-integration churn. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../suites/public-api/startSpan/streamed/test.ts | 5 +++++ .../browserTracingIntegration/interactions-streamed/test.ts | 5 +++++ .../browserTracingIntegration/navigation-streamed/test.ts | 5 +++++ .../browserTracingIntegration/pageload-streamed/test.ts | 5 +++++ .../suites/public-api/startSpan-streamed/test.ts | 6 ++++-- .../test-applications/deno-streamed/tests/spans.test.ts | 4 ++++ .../public-api/startSpan/basic-usage-streamed/test.ts | 2 ++ packages/browser/test/integrations/spanstreaming.test.ts | 6 +++++- 8 files changed, 35 insertions(+), 3 deletions(-) diff --git a/dev-packages/browser-integration-tests/suites/public-api/startSpan/streamed/test.ts b/dev-packages/browser-integration-tests/suites/public-api/startSpan/streamed/test.ts index 7a70c832558f..126603f4e23a 100644 --- a/dev-packages/browser-integration-tests/suites/public-api/startSpan/streamed/test.ts +++ b/dev-packages/browser-integration-tests/suites/public-api/startSpan/streamed/test.ts @@ -4,6 +4,7 @@ import { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, + SEMANTIC_ATTRIBUTE_SENTRY_SDK_INTEGRATIONS, SEMANTIC_ATTRIBUTE_SENTRY_SDK_NAME, SEMANTIC_ATTRIBUTE_SENTRY_SDK_VERSION, SEMANTIC_ATTRIBUTE_SENTRY_SEGMENT_ID, @@ -199,6 +200,10 @@ sentryTest( type: 'string', value: SDK_VERSION, }, + [SEMANTIC_ATTRIBUTE_SENTRY_SDK_INTEGRATIONS]: { + type: 'array', + value: expect.arrayContaining(['SpanStreaming']), + }, [SEMANTIC_ATTRIBUTE_SENTRY_SEGMENT_ID]: { type: 'string', value: segmentSpanId, diff --git a/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/interactions-streamed/test.ts b/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/interactions-streamed/test.ts index f1b0882d2325..2f43e7a3df71 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/interactions-streamed/test.ts +++ b/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/interactions-streamed/test.ts @@ -4,6 +4,7 @@ import { SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, + SEMANTIC_ATTRIBUTE_SENTRY_SDK_INTEGRATIONS, SEMANTIC_ATTRIBUTE_SENTRY_SDK_NAME, SEMANTIC_ATTRIBUTE_SENTRY_SDK_VERSION, SEMANTIC_ATTRIBUTE_SENTRY_SEGMENT_ID, @@ -72,6 +73,10 @@ sentryTest('captures streamed interaction span tree. @firefox', async ({ browser type: 'string', value: SDK_VERSION, }, + [SEMANTIC_ATTRIBUTE_SENTRY_SDK_INTEGRATIONS]: { + type: 'array', + value: expect.arrayContaining(['BrowserTracing', 'SpanStreaming']), + }, [SEMANTIC_ATTRIBUTE_SENTRY_SEGMENT_ID]: { type: 'string', value: interactionSegmentSpan!.span_id, diff --git a/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/navigation-streamed/test.ts b/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/navigation-streamed/test.ts index 520a3d330bb9..25b533703c63 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/navigation-streamed/test.ts +++ b/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/navigation-streamed/test.ts @@ -4,6 +4,7 @@ import { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, + SEMANTIC_ATTRIBUTE_SENTRY_SDK_INTEGRATIONS, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, } from '@sentry/core'; import { sentryTest } from '../../../../utils/fixtures'; @@ -123,6 +124,10 @@ sentryTest('starts a streamed navigation span on page navigation', async ({ brow type: 'string', value: SDK_VERSION, }, + [SEMANTIC_ATTRIBUTE_SENTRY_SDK_INTEGRATIONS]: { + type: 'array', + value: expect.arrayContaining(['BrowserTracing', 'SpanStreaming']), + }, 'sentry.segment.id': { type: 'string', value: navigationSpan.span_id, diff --git a/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/pageload-streamed/test.ts b/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/pageload-streamed/test.ts index 6b09fcd0097d..2fcc91212eee 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/pageload-streamed/test.ts +++ b/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/pageload-streamed/test.ts @@ -4,6 +4,7 @@ import { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, + SEMANTIC_ATTRIBUTE_SENTRY_SDK_INTEGRATIONS, SEMANTIC_ATTRIBUTE_SENTRY_SDK_NAME, SEMANTIC_ATTRIBUTE_SENTRY_SDK_VERSION, SEMANTIC_ATTRIBUTE_SENTRY_SEGMENT_ID, @@ -130,6 +131,10 @@ sentryTest( type: 'string', value: SDK_VERSION, }, + [SEMANTIC_ATTRIBUTE_SENTRY_SDK_INTEGRATIONS]: { + type: 'array', + value: expect.arrayContaining(['BrowserTracing', 'SpanStreaming']), + }, [SEMANTIC_ATTRIBUTE_SENTRY_SEGMENT_ID]: { type: 'string', value: pageloadSpan?.span_id, diff --git a/dev-packages/cloudflare-integration-tests/suites/public-api/startSpan-streamed/test.ts b/dev-packages/cloudflare-integration-tests/suites/public-api/startSpan-streamed/test.ts index 090142714d5b..df60f46dddc4 100644 --- a/dev-packages/cloudflare-integration-tests/suites/public-api/startSpan-streamed/test.ts +++ b/dev-packages/cloudflare-integration-tests/suites/public-api/startSpan-streamed/test.ts @@ -2,13 +2,14 @@ import type { Envelope, SerializedStreamedSpanContainer } from '@sentry/core'; import { SDK_VERSION, SEMANTIC_ATTRIBUTE_SENTRY_OP, + SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_RELEASE, + SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, + SEMANTIC_ATTRIBUTE_SENTRY_SDK_INTEGRATIONS, SEMANTIC_ATTRIBUTE_SENTRY_SDK_NAME, SEMANTIC_ATTRIBUTE_SENTRY_SDK_VERSION, SEMANTIC_ATTRIBUTE_SENTRY_SEGMENT_ID, SEMANTIC_ATTRIBUTE_SENTRY_SEGMENT_NAME, - SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, - SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, } from '@sentry/core'; import { expect, it } from 'vitest'; @@ -175,6 +176,7 @@ it('sends a streamed span envelope with correct spans for a manually started spa attributes: { [SEMANTIC_ATTRIBUTE_SENTRY_SDK_NAME]: { type: 'string', value: CLOUDFLARE_SDK }, [SEMANTIC_ATTRIBUTE_SENTRY_SDK_VERSION]: { type: 'string', value: SDK_VERSION }, + [SEMANTIC_ATTRIBUTE_SENTRY_SDK_INTEGRATIONS]: { type: 'array', value: expect.arrayContaining(['SpanStreaming']) }, [SEMANTIC_ATTRIBUTE_SENTRY_RELEASE]: { type: 'string', value: '1.0.0' }, [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: { type: 'string', value: 'auto.http.cloudflare' }, [SEMANTIC_ATTRIBUTE_SENTRY_SEGMENT_ID]: { type: 'string', value: segmentSpanId }, diff --git a/dev-packages/e2e-tests/test-applications/deno-streamed/tests/spans.test.ts b/dev-packages/e2e-tests/test-applications/deno-streamed/tests/spans.test.ts index 023429b07f41..dedbc6f18517 100644 --- a/dev-packages/e2e-tests/test-applications/deno-streamed/tests/spans.test.ts +++ b/dev-packages/e2e-tests/test-applications/deno-streamed/tests/spans.test.ts @@ -75,6 +75,10 @@ const SEGMENT_SPAN = { type: 'string', value: expect.any(String), }, + 'sentry.sdk.integrations': { + type: 'array', + value: expect.arrayContaining(['SpanStreaming']), + }, 'sentry.segment.id': { type: 'string', value: expect.stringMatching(/^[\da-f]{16}$/), diff --git a/dev-packages/node-integration-tests/suites/public-api/startSpan/basic-usage-streamed/test.ts b/dev-packages/node-integration-tests/suites/public-api/startSpan/basic-usage-streamed/test.ts index b31ca320df53..9c307633e127 100644 --- a/dev-packages/node-integration-tests/suites/public-api/startSpan/basic-usage-streamed/test.ts +++ b/dev-packages/node-integration-tests/suites/public-api/startSpan/basic-usage-streamed/test.ts @@ -3,6 +3,7 @@ import { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_RELEASE, SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, + SEMANTIC_ATTRIBUTE_SENTRY_SDK_INTEGRATIONS, SEMANTIC_ATTRIBUTE_SENTRY_SDK_NAME, SEMANTIC_ATTRIBUTE_SENTRY_SDK_VERSION, SEMANTIC_ATTRIBUTE_SENTRY_SEGMENT_ID, @@ -129,6 +130,7 @@ test('sends a streamed span envelope with correct spans for a manually started s [SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE]: { type: 'integer', value: 1 }, [SEMANTIC_ATTRIBUTE_SENTRY_SDK_NAME]: { type: 'string', value: 'sentry.javascript.node' }, [SEMANTIC_ATTRIBUTE_SENTRY_SDK_VERSION]: { type: 'string', value: SDK_VERSION }, + [SEMANTIC_ATTRIBUTE_SENTRY_SDK_INTEGRATIONS]: { type: 'array', value: expect.arrayContaining(['SpanStreaming']) }, [SEMANTIC_ATTRIBUTE_SENTRY_SEGMENT_ID]: { type: 'string', value: segmentSpanId }, [SEMANTIC_ATTRIBUTE_SENTRY_SEGMENT_NAME]: { type: 'string', value: 'test-span' }, [SEMANTIC_ATTRIBUTE_SENTRY_RELEASE]: { type: 'string', value: '1.0.0' }, diff --git a/packages/browser/test/integrations/spanstreaming.test.ts b/packages/browser/test/integrations/spanstreaming.test.ts index 1d5d587290a3..53e879101d8a 100644 --- a/packages/browser/test/integrations/spanstreaming.test.ts +++ b/packages/browser/test/integrations/spanstreaming.test.ts @@ -1,5 +1,5 @@ import * as SentryCore from '@sentry/core'; -import { debug } from '@sentry/core'; +import { debug, SEMANTIC_ATTRIBUTE_SENTRY_SDK_INTEGRATIONS } from '@sentry/core'; import { beforeEach, describe, expect, it, vi } from 'vitest'; import { BrowserClient, spanStreamingIntegration } from '../../src'; import { getDefaultBrowserClientOptions } from '../helper/browser-client-options'; @@ -145,6 +145,10 @@ describe('spanStreamingIntegration', () => { type: 'string', value: expect.any(String), }, + [SEMANTIC_ATTRIBUTE_SENTRY_SDK_INTEGRATIONS]: { + type: 'array', + value: ['SpanStreaming'], + }, 'sentry.segment.id': { type: 'string', value: span.spanContext().spanId, From 0c4fe2d67320e234739bfe20c12bf31ba58ee6da Mon Sep 17 00:00:00 2001 From: Nicolas Hrubec Date: Tue, 21 Apr 2026 20:52:47 +0200 Subject: [PATCH 7/7] chore(format): Wrap long sentry.sdk.integrations attribute lines oxfmt wants the SEMANTIC_ATTRIBUTE_SENTRY_SDK_INTEGRATIONS entries broken across multiple lines because they exceed the max line length. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../suites/public-api/startSpan-streamed/test.ts | 5 ++++- .../suites/public-api/startSpan/basic-usage-streamed/test.ts | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/dev-packages/cloudflare-integration-tests/suites/public-api/startSpan-streamed/test.ts b/dev-packages/cloudflare-integration-tests/suites/public-api/startSpan-streamed/test.ts index df60f46dddc4..95b412acd23b 100644 --- a/dev-packages/cloudflare-integration-tests/suites/public-api/startSpan-streamed/test.ts +++ b/dev-packages/cloudflare-integration-tests/suites/public-api/startSpan-streamed/test.ts @@ -176,7 +176,10 @@ it('sends a streamed span envelope with correct spans for a manually started spa attributes: { [SEMANTIC_ATTRIBUTE_SENTRY_SDK_NAME]: { type: 'string', value: CLOUDFLARE_SDK }, [SEMANTIC_ATTRIBUTE_SENTRY_SDK_VERSION]: { type: 'string', value: SDK_VERSION }, - [SEMANTIC_ATTRIBUTE_SENTRY_SDK_INTEGRATIONS]: { type: 'array', value: expect.arrayContaining(['SpanStreaming']) }, + [SEMANTIC_ATTRIBUTE_SENTRY_SDK_INTEGRATIONS]: { + type: 'array', + value: expect.arrayContaining(['SpanStreaming']), + }, [SEMANTIC_ATTRIBUTE_SENTRY_RELEASE]: { type: 'string', value: '1.0.0' }, [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: { type: 'string', value: 'auto.http.cloudflare' }, [SEMANTIC_ATTRIBUTE_SENTRY_SEGMENT_ID]: { type: 'string', value: segmentSpanId }, diff --git a/dev-packages/node-integration-tests/suites/public-api/startSpan/basic-usage-streamed/test.ts b/dev-packages/node-integration-tests/suites/public-api/startSpan/basic-usage-streamed/test.ts index 9c307633e127..abf5276867c5 100644 --- a/dev-packages/node-integration-tests/suites/public-api/startSpan/basic-usage-streamed/test.ts +++ b/dev-packages/node-integration-tests/suites/public-api/startSpan/basic-usage-streamed/test.ts @@ -130,7 +130,10 @@ test('sends a streamed span envelope with correct spans for a manually started s [SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE]: { type: 'integer', value: 1 }, [SEMANTIC_ATTRIBUTE_SENTRY_SDK_NAME]: { type: 'string', value: 'sentry.javascript.node' }, [SEMANTIC_ATTRIBUTE_SENTRY_SDK_VERSION]: { type: 'string', value: SDK_VERSION }, - [SEMANTIC_ATTRIBUTE_SENTRY_SDK_INTEGRATIONS]: { type: 'array', value: expect.arrayContaining(['SpanStreaming']) }, + [SEMANTIC_ATTRIBUTE_SENTRY_SDK_INTEGRATIONS]: { + type: 'array', + value: expect.arrayContaining(['SpanStreaming']), + }, [SEMANTIC_ATTRIBUTE_SENTRY_SEGMENT_ID]: { type: 'string', value: segmentSpanId }, [SEMANTIC_ATTRIBUTE_SENTRY_SEGMENT_NAME]: { type: 'string', value: 'test-span' }, [SEMANTIC_ATTRIBUTE_SENTRY_RELEASE]: { type: 'string', value: '1.0.0' },