feat(core): Support array attributes for spans, logs and metrics#20427
feat(core): Support array attributes for spans, logs and metrics#20427nicohrubec wants to merge 24 commits intodevelopfrom
Conversation
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<string> | Array<number> | Array<boolean>`.
- 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) <[email protected]>
size-limit report 📦
|
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) <[email protected]>
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) <[email protected]>
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) <[email protected]>
…72 KB Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
| } | ||
| } | ||
|
|
||
| function isHomogeneousPrimitiveArray(arr: unknown): arr is Array<string> | Array<number> | Array<boolean> { |
There was a problem hiding this comment.
q: Was it previously decided that SDKs have to guarantee homogeneity? Just wondering if we really have to iterate over the entire array for every array.
There was a problem hiding this comment.
Jap fair question, we are still discussing that one 😅
There was a problem hiding this comment.
Talked to ingest: We don't need any SDK-side runtime validation.
|
Converting back to draft until we have a definitive answer for SDK validation. |
|
@chargome @mydea I talked to Ingest last week and the outcome was that we don't need any SDK-side runtime validation for user-set arrays on attributes. Relay will just drop any attributes with non-conforming arrays set as values. Based on that I simplified the PR, should be good for another look. The frontend still doesn't display these properly yet though. I will make sure to properly test this e2e before merging after the FE is ready. |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit f896f3a. Configure here.
| */ | ||
| function getTypedAttributeValue(value: unknown): TypedAttributeValue | void { | ||
| if (Array.isArray(value) && value.length !== 0) { | ||
| return { value, type: 'array' }; |
There was a problem hiding this comment.
Mixed-type array console parameters silently dropped by Relay
Medium Severity
The getTypedAttributeValue function now converts all non-empty arrays to { type: 'array' } before the stringify fallback path is reached. This means SDK-internal sentry.message.parameter.X attributes created by createConsoleTemplateAttributes from mixed-type console args (e.g. console.log('Array:', [1, 2, 3, 'string'])) are now sent as array attributes instead of being stringified. Since Relay drops non-homogeneous arrays, these template parameters will be silently lost — a regression from the previous behavior where they were preserved as stringified values. The body text is unaffected, but structured template parameter data is lost for mixed-type arrays.
Reviewed by Cursor Bugbot for commit f896f3a. Configure here.
There was a problem hiding this comment.
this is basically what I described in the PR description, we can discuss it but I think this is a tradeoff we have to make. don't think we can really solve this unless we do runtime inspection of the types of elements in arrays
| export type Attributes = Record<string, TypedAttributeValue>; | ||
|
|
||
| export type AttributeValueType = string | number | boolean | Array<string> | Array<number> | Array<boolean>; | ||
| export type AttributeValueType = string | number | boolean | Array<unknown>; |
There was a problem hiding this comment.
h: Do we really want Array<unknown>? Every change that follows would be breaking from here on.
There was a problem hiding this comment.
Narrowed it down again
| value: expect.any(Number), | ||
| }, | ||
| // TODO: 'device.archs' is set but arrays are not yet serialized in span attributes | ||
| 'device.archs': { |
There was a problem hiding this comment.
Thanks for pulling this one in.



Adds array attribute support for spans, logs, and metrics. Relay only supports primitive homogeneous arrays (all elements have the same primitive type). However, any attributes with non-conforming arrays will be dropped by Relay, so there is no need for runtime validation on the SDK end.
This change as is comes with a behavioral change for user-defined logs and metrics. If users previously set array attributes for logs/metrics then these were previously sent to Sentry stringified, now these will be sent as arrays. I noted this in the changelog. I am aware that this could technically be interpreted as breaking, so if someone feels strongly we should keep this behavior for now then we can definitely find a way to work around this.
Note: the Sentry frontend doesn't render array attributes correctly yet, but that's expected to land soon.
Blocks #20428
Closes #20651
Closes #20438