Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
74ee2fe
feat(core): Support homogeneous primitive arrays as span attributes
nicohrubec Apr 21, 2026
2d84168
test: Update integration tests for array attribute support
nicohrubec Apr 21, 2026
fa70b75
Revert ".size-limit.js" bumps
nicohrubec Apr 21, 2026
aa3b2b1
Merge branch 'develop' into nh/array-attribute-support
nicohrubec Apr 21, 2026
a71058e
chore(size-limit): Bump thresholds for array-attribute support
nicohrubec Apr 21, 2026
467dfcc
types
nicohrubec Apr 28, 2026
5f62ad7
Merge branch 'develop' into nh/array-attribute-support
nicohrubec Apr 28, 2026
4b05596
formatting
nicohrubec Apr 28, 2026
e852120
Merge branch 'develop' into nh/array-attribute-support
nicohrubec Apr 28, 2026
7cd226a
guard against nan
nicohrubec Apr 28, 2026
735bbe8
chore(size-limit): Bump CDN Tracing+Replay+Feedback uncompressed to 2…
nicohrubec Apr 28, 2026
d9a8974
Merge branch 'develop' into nh/array-attribute-support
nicohrubec Apr 29, 2026
a26bdc0
no runtime validation
nicohrubec May 4, 2026
50bdc74
Merge branch 'develop' into nh/array-attribute-support
nicohrubec May 4, 2026
cb94756
add changelog
nicohrubec May 4, 2026
fa0dbde
update changelog
nicohrubec May 4, 2026
c711703
.
nicohrubec May 4, 2026
ad724e2
.
nicohrubec May 4, 2026
01a6851
fix test
nicohrubec May 4, 2026
20adc34
Merge branch 'develop' into nh/array-attribute-support
nicohrubec May 4, 2026
f896f3a
fix test
nicohrubec May 4, 2026
f76bca2
.
nicohrubec May 4, 2026
1538b0d
.
nicohrubec May 4, 2026
f24852d
.
nicohrubec May 4, 2026
516cb6a
emit empty arrays
nicohrubec May 7, 2026
15ebfc1
Merge branch 'develop' into nh/array-attribute-support
nicohrubec May 7, 2026
6f10a4f
fix(tests): Expect `device.archs` array attribute in streamed span tests
nicohrubec May 7, 2026
da88fee
feat(core): Emit sentry.sdk.integrations on segment spans in span str…
nicohrubec Apr 21, 2026
a153e72
test: Update streamed segment span expectations for sentry.sdk.integr…
nicohrubec Apr 21, 2026
44128b7
chore(format): Wrap long sentry.sdk.integrations attribute lines
nicohrubec Apr 21, 2026
b93294d
test(node-core): Add sentry.sdk.integrations to streamed segment span…
nicohrubec Apr 22, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@

- "You miss 100 percent of the chances you don't take. — Wayne Gretzky" — Michael Scott

- **feat(core): Support array attributes for spans, logs, and metrics ([#20427](https://github.com/getsentry/sentry-javascript/pull/20427))**

Arrays of primitive values (`string`, `number`, `boolean`) are now accepted as attribute values. Arrays containing non-primitive elements will be dropped and won't show up in Sentry. Note that array attributes on logs and metrics were previously stringified in certain cases and will now be sent as arrays instead.

## 10.52.0

### Important Changes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ sentryTest('should capture console object calls', async ({ getLocalTestUrl, page
'sentry.sdk.version': { value: expect.any(String), type: 'string' },
'sentry.timestamp.sequence': { value: expect.any(Number), type: 'integer' },
'sentry.message.template': { value: 'Array: {}', type: 'string' },
'sentry.message.parameter.0': { value: '[1,2,3,"string"]', type: 'string' },
'sentry.message.parameter.0': { value: [1, 2, 3, 'string'], type: 'array' },
},
},
{
Expand All @@ -179,7 +179,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' },
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,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' },
},
},
Expand All @@ -63,6 +64,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' },
},
Expand All @@ -78,6 +80,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' },
Expand All @@ -94,6 +97,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' },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -209,6 +210,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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -80,6 +81,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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -131,6 +132,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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -138,6 +139,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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -175,6 +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_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 },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ const SEGMENT_SPAN = {
type: 'integer',
value: expect.any(Number),
},
// TODO: 'device.archs' is set but arrays are not yet serialized in span attributes
'device.archs': {
type: 'array',
value: expect.any(Array),
},
'device.processor_count': {
type: 'integer',
value: expect.any(Number),
Expand Down Expand Up @@ -92,6 +95,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}$/),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -128,6 +129,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-core' },
[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' },
Expand All @@ -143,8 +148,7 @@ test('sends a streamed span envelope with correct spans for a manually started s
'device.processor_frequency': { type: 'integer', value: expect.any(Number) },
'culture.locale': { type: 'string', value: expect.any(String) },
'culture.timezone': { type: 'string', value: expect.any(String) },
// TODO: device.archs is an array and currently dropped during serialization
// 'device.archs': { type: 'array', value: [expect.any(String)] },
'device.archs': { type: 'array', value: expect.any(Array) },
};

// process.availableMemory is only available in Node 22+
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ test('nodeContextIntegration sets context attributes on segment spans', async ()

// Static attributes
expect(attrs['app.start_time']).toEqual({ type: 'string', value: expect.any(String) });
// TODO: device.archs is an array and currently dropped during serialization
// expect(attrs['device.archs']).toEqual({ type: 'array', value: [expect.any(String)] });
expect(attrs['device.archs']).toEqual({ type: 'array', value: expect.any(Array) });
expect(attrs['device.boot_time']).toEqual({ type: 'string', value: expect.any(String) });
expect(attrs['device.processor_count']).toEqual({ type: 'integer', value: expect.any(Number) });
expect(attrs['device.cpu_description']).toEqual({ type: 'string', value: expect.any(String) });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ async function run(): Promise<void> {

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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,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' },
},
},
Expand All @@ -73,6 +74,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' },
},
Expand All @@ -86,6 +88,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' },
Expand All @@ -100,6 +103,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' },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -128,15 +129,18 @@ 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' },
'process.runtime.engine.name': { type: 'string', value: 'v8' },
'process.runtime.engine.version': { type: 'string', value: expect.any(String) },
'app.start_time': { type: 'string', value: expect.any(String) },
'app.memory': { type: 'integer', value: expect.any(Number) },
// TODO: device.archs is an array and currently dropped during serialization
// 'device.archs': { type: 'array', value: [expect.any(String)] },
'device.archs': { type: 'array', value: expect.any(Array) },
'device.boot_time': { type: 'string', value: expect.any(String) },
'device.memory_size': { type: 'integer', value: expect.any(Number) },
'device.free_memory': { type: 'integer', value: expect.any(Number) },
Expand Down
6 changes: 5 additions & 1 deletion packages/browser/test/integrations/spanstreaming.test.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand Down Expand Up @@ -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,
Expand Down
25 changes: 10 additions & 15 deletions packages/core/src/attributes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,7 @@ type AttributeTypeMap = {
integer: number;
double: number;
boolean: boolean;
'string[]': Array<string>;
'integer[]': Array<number>;
'double[]': Array<number>;
'boolean[]': Array<boolean>;
array: Array<string> | Array<number> | Array<boolean>;
};

/* Generates a type from the AttributeTypeMap like:
Expand Down Expand Up @@ -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 arrays, 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.
Expand Down Expand Up @@ -170,17 +167,15 @@ 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 arrays:
* - Relay currently only supports arrays consisting of primitive values. Attributes with non-conforming arrays are dropped by Relay, so runtime type validation in the SDK is unnecessary.
* - 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
*/
function getTypedAttributeValue(value: unknown): TypedAttributeValue | void {
if (Array.isArray(value)) {
return { value, type: 'array' };
}

const primitiveType =
typeof value === 'string'
? 'string'
Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/semanticAttributes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down
Loading
Loading