Skip to content

feat(o11y): add setAttributes and removeAttributes - #865

Open
abelonogov-ld wants to merge 1 commit into
mainfrom
andrey/global-attributes-web
Open

abelonogov-ld wants to merge 1 commit into
mainfrom
andrey/global-attributes-web

Conversation

@abelonogov-ld

@abelonogov-ld abelonogov-ld commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Adds LDObserve.setAttributes(attributes) / LDObserve.removeAttributes(keys) to the browser SDK (@launchdarkly/o11y, surfaced through @launchdarkly/observability and @launchdarkly/session-replay). This addresses the customer request for app-wide attributes (e.g. UTM parameters) on all telemetry, and matches the RN (#856), Android (#860), iOS (launchdarkly/swift-launchdarkly-observability#290), Flutter (#858), MAUI (#863), Java (#861) and Python (#859) PRs.

  • One in-memory attribute map for the page lifetime, merged by key (immutable snapshot rebuilt only on change). It lives on globalThis under a Symbol.for key so the observability and session-replay bundles, which each bundle their own copy of o11y, share it.
  • Applied to every span via CustomBatchSpanProcessor.onStart (manual, fetch/XHR, error, flag evaluation, track, document load, user interaction), to logs (the launchdarkly.js.log span and its log event), and to every metric data point. Spans take the values current when they start.
  • Precedence: per-call / explicitly set attributes > LD context keys > globals > resource. Globals only fill missing keys.
  • highlight.session_id, session.id and highlight.record are ignored (logged in debug mode), as are invalid attribute values. setAttributes({ k: undefined }) is ignored; use removeAttributes to remove.
  • Calls write straight to the store instead of the pre-init call buffer, so they apply before init or start() with manualStart, including to automatic spans emitted during init. Nothing is persisted; values survive session changes.

README documents the API and how it differs from addSessionProperties.

How did you test this change?

  • New globalAttributes.test.ts (14 tests): merge/remove, reserved keys, invalid values, snapshot immutability, calls before init and with manualStart, the processor path used by automatic spans (values captured at start, later attributes win), manual spans, errors, logs and metrics.
  • Full o11y suite (597 tests), yarn turbo run build test typegen lint for o11y, observability, highlight.run and session-replay, Prettier check, and yarn enforce-size (172.6 kB / 256 kB) pass.

Are there any deployment considerations?

Additive; no behavior change unless the new API is used. Global attributes are added to metric data points, so they increase metric cardinality.


Note

Overview
Adds LDObserve.setAttributes / removeAttributes so apps can attach page-scoped metadata (e.g. tenant, campaign) to all subsequent spans, logs, and metrics, including auto-instrumented telemetry.

A new globalAttributes store merges keys in memory for the page lifetime, shared across observability and session-replay bundles via globalThis. setAttributes / removeAttributes bypass the pre-init call buffer so values apply before init or manualStart. Globals only fill missing keys; explicit span/log/metric attributes and LD context keys win. Reserved keys (highlight.session_id, session.id, highlight.record) and invalid OTel values are dropped.

Wiring: CustomBatchSpanProcessor.onStart applies globals to every span at start; ObserveSDK and the replay Highlight client spread getGlobalAttributes() onto log events and metric data points. README and Observe API types document behavior vs addSessionProperties.

Tests: new globalAttributes.test.ts covers merge/remove, precedence, pre-init usage, and telemetry paths.

Reviewed by Cursor Bugbot for commit bb4b6d7. Bugbot is set up for automated code reviews on this repo. Configure here.

Co-authored-by: Cursor <cursoragent@cursor.com>

This branch has not been deployed

No deployments
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.

2 participants