Skip to content

feat(core): Support homogeneous primitive arrays as span/metric/log attributes#20427

Draft
nicohrubec wants to merge 12 commits intodevelopfrom
nh/array-attribute-support
Draft

feat(core): Support homogeneous primitive arrays as span/metric/log attributes#20427
nicohrubec wants to merge 12 commits intodevelopfrom
nh/array-attribute-support

Conversation

@nicohrubec
Copy link
Copy Markdown
Member

@nicohrubec nicohrubec commented Apr 21, 2026

Relay and EAP now accept homogeneous arrays alongside primitive types (spec). In the SDK we currently drop any non-primitives during serialization for spans/logs/metrics. This PR adds homogeneous array support to align with the spec:

  • Collapses the four typed x[] variants in AttributeTypeMap into a single array variant, matching Relay's wire contract.
  • Extends getTypedAttributeValue to detect homogeneous primitive arrays and emit { type: 'array', value: [...] }. Mixed-type and nested arrays remain unsupported (dropped by default, stringified under the fallback path).
  • We already had good test coverage for this, so I just updated all the preexisting tests to reflect the new behavior.

Note: the Sentry frontend doesn't render array attributes correctly yet, but that's expected to land soon and this is not necessarily blocking for this PR.

Blocks #20428

Should we call this out in the changelog?

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) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 21, 2026

size-limit report 📦

⚠️ Warning: Base artifact is not the latest one, because the latest workflow run is not done yet. This may lead to incorrect results. Try to re-run all tests to get up to date results.

Path Size % Change Change
@sentry/browser 26.16 kB - -
@sentry/browser - with treeshaking flags 24.63 kB - -
@sentry/browser (incl. Tracing) 44.11 kB - -
@sentry/browser (incl. Tracing + Span Streaming) 46.22 kB +0.14% +63 B 🔺
@sentry/browser (incl. Tracing, Profiling) 49.06 kB - -
@sentry/browser (incl. Tracing, Replay) 83.46 kB - -
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags 72.94 kB - -
@sentry/browser (incl. Tracing, Replay with Canvas) 88.14 kB - -
@sentry/browser (incl. Tracing, Replay, Feedback) 100.79 kB - -
@sentry/browser (incl. Feedback) 43.4 kB - -
@sentry/browser (incl. sendFeedback) 30.96 kB - -
@sentry/browser (incl. FeedbackAsync) 36.14 kB - -
@sentry/browser (incl. Metrics) 27.51 kB +0.25% +66 B 🔺
@sentry/browser (incl. Logs) 27.66 kB +0.25% +67 B 🔺
@sentry/browser (incl. Metrics & Logs) 28.34 kB +0.22% +61 B 🔺
@sentry/react 27.9 kB - -
@sentry/react (incl. Tracing) 46.35 kB - -
@sentry/vue 31.03 kB - -
@sentry/vue (incl. Tracing) 45.95 kB - -
@sentry/svelte 26.18 kB - -
CDN Bundle 28.9 kB +0.23% +65 B 🔺
CDN Bundle (incl. Tracing) 46.77 kB +0.14% +65 B 🔺
CDN Bundle (incl. Logs, Metrics) 30.32 kB +0.22% +64 B 🔺
CDN Bundle (incl. Tracing, Logs, Metrics) 47.86 kB +0.14% +66 B 🔺
CDN Bundle (incl. Replay, Logs, Metrics) 69.41 kB +0.1% +66 B 🔺
CDN Bundle (incl. Tracing, Replay) 83.94 kB +0.08% +60 B 🔺
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) 85 kB +0.08% +64 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback) 89.75 kB +0.08% +65 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) 90.85 kB +0.08% +68 B 🔺
CDN Bundle - uncompressed 84.79 kB +0.29% +238 B 🔺
CDN Bundle (incl. Tracing) - uncompressed 139.92 kB +0.18% +238 B 🔺
CDN Bundle (incl. Logs, Metrics) - uncompressed 88.99 kB +0.27% +238 B 🔺
CDN Bundle (incl. Tracing, Logs, Metrics) - uncompressed 143.38 kB +0.17% +238 B 🔺
CDN Bundle (incl. Replay, Logs, Metrics) - uncompressed 212.95 kB +0.12% +238 B 🔺
CDN Bundle (incl. Tracing, Replay) - uncompressed 257.72 kB +0.1% +238 B 🔺
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) - uncompressed 261.17 kB +0.1% +238 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed 271.42 kB +0.09% +238 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) - uncompressed 274.86 kB +0.09% +238 B 🔺
@sentry/nextjs (client) 48.84 kB - -
@sentry/sveltekit (client) 44.56 kB - -
@sentry/node-core 59.07 kB +0.14% +82 B 🔺
@sentry/node 170.17 kB +0.05% +71 B 🔺
@sentry/node - without tracing 97.88 kB +0.09% +85 B 🔺
@sentry/aws-serverless 114.6 kB +0.11% +120 B 🔺
@sentry/cloudflare (withSentry) - minified 164.41 kB +0.17% +273 B 🔺
@sentry/cloudflare (withSentry) 415.66 kB +0.12% +460 B 🔺

View base workflow run

nicohrubec and others added 8 commits April 21, 2026 19:28
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) <noreply@anthropic.com>
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) <noreply@anthropic.com>
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) <noreply@anthropic.com>
@nicohrubec nicohrubec marked this pull request as ready for review April 28, 2026 11:16
@nicohrubec nicohrubec marked this pull request as draft April 28, 2026 11:16
@nicohrubec nicohrubec changed the title feat(core): Support homogeneous primitive arrays as span attributes feat(core): Support homogeneous primitive arrays as span/metric/log attributes Apr 28, 2026
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit e852120. Configure here.

Comment thread packages/core/src/attributes.ts
…72 KB

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
}
}

function isHomogeneousPrimitiveArray(arr: unknown): arr is Array<string> | Array<number> | Array<boolean> {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Jap fair question, we are still discussing that one 😅

@nicohrubec
Copy link
Copy Markdown
Member Author

Converting back to draft until we have a definitive answer for SDK validation.

@nicohrubec nicohrubec marked this pull request as draft April 29, 2026 07:46

function isHomogeneousPrimitiveArray(arr: unknown): arr is Array<string> | Array<number> | Array<boolean> {
if (!Array.isArray(arr)) return false;
if (arr.length === 0) return true;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

q: Do we even want to send empty ones?

if (!Array.isArray(arr)) return false;
if (arr.length === 0) return true;
const t = typeof arr[0];
if (t !== 'string' && t !== 'number' && t !== 'boolean') return false;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In otel, null is allowed - we should check this with ingest

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants