otel-browser · git:20260721.af56d6c · 2026-07-21 · sha256 0d2bb219e19ef88f

otel-browser git:20260721.af56d6cA

Immutable. This exact content is served forever at /api/v1/blob/0d2bb219e19ef88f.

---
name: otel-browser
description: OpenTelemetry in the browser (Real User Monitoring / RUM) — capturing page loads, Core Web Vitals, route changes, clicks, console output, and JavaScript errors, and connecting frontend telemetry to backend traces. Covers the web tracing SDK (sdk-trace-web, context-zone), the experimental browser-sdk, and event- and span-based browser instrumentations. Use when adding, reviewing, or configuring OpenTelemetry in a web app (SPA/MPA). Triggers on "browser otel", "RUM", "real user monitoring", "frontend observability", "web vitals", "core web vitals", "sdk-trace-web", "WebTracerProvider", "browser-sdk", "browser-instrumentation", "instrument the frontend", "page load tracing", "session", or any browser/web OTel question.
---

# OpenTelemetry in the Browser (RUM)

Entry point for OpenTelemetry mechanics in web apps. Load a reference below based on the task;
each reference is self-contained.

> **Stability**: Browser/RUM is one of the **newest and most experimental** areas of OpenTelemetry.
> Within the RUM packages covered here, the web *tracing* primitives
> (`@opentelemetry/sdk-trace-web`, `@opentelemetry/context-zone`) and the JS API are **stable** today.
> The Browser SDK (`@opentelemetry/browser-sdk`) and the event-based instrumentations are
> experimental and may break between minor versions — pin exact versions. Verify current status
> via the Sources of Truth below.

## References

| File | Use when |
|---|---|
| [`references/setup-sdk.md`](references/setup-sdk.md) | Wiring up the SDK: the direct providers (`WebTracerProvider` + `ZoneContextManager` for spans; `LoggerProvider` for events) vs the experimental `browser-sdk`, sessions, frontend→backend `traceparent`/CORS propagation, and why a Collector sits in front. |
| [`references/instrumentation.md`](references/instrumentation.md) | Choosing and configuring instrumentations: the event-based catalog (navigation, web vitals, console, errors, …), the span-based catalog (fetch, XHR, document-load, long-task, …), per-instrumentation options, and what each captures. |
| [`references/performance.md`](references/performance.md) | Keeping it cheap, fast, and private: bundle size, bounded main-thread work, page-lifecycle flushing, telemetry volume/cost, and PII vectors. |

## Two telemetry models — read first

The experimental Browser SDK currently models browser telemetry as **spans** and **events**; it
does not include metrics. The general JS `MeterProvider` and OTLP/HTTP metrics exporter do support
browser builds, but metrics are outside this RUM catalog. Picking the right model for the signals
covered here is the first decision:

| Model | Signal | For | Examples |
|---|---|---|---|
| **Events** | Logs API → `LogRecord` | point-in-time facts (no duration/children) | web vitals, navigation, console, errors, user action |
| **Spans** | Trace API | operations with a duration and parent/child | `fetch`, XHR, document load, long task |

## Verify attributes against released semantic conventions before hand-rolling

Not every browser signal has a released convention yet — e.g. `browser.web_vital` is a released
**development**-stability event, but `browser.navigation` and `browser.resource_timing` have no
released convention under the `browser` group, and `exception` is a released **stable** group of
its own (not under `browser`). Check coverage per signal rather than assuming it; before emitting a
hand-written span or `LogRecord` with custom attributes:

1. Prefer a catalog instrumentation from [`references/instrumentation.md`](references/instrumentation.md), then verify its
   released output shape against the convention; experimental implementations can lag a merged
   convention (the released Web Vitals package currently does).
2. Check whether a released convention covers the signal: use the `otel-semantic-conventions`
   skill to query the relevant group (e.g. `browser` for `event.browser.web_vital`, `exceptions`
   for `exception.type`), or WebFetch the matching page under
   `https://opentelemetry.io/docs/specs/semconv/browser/`.
3. If one exists, use its event, body-field, and attribute names verbatim (e.g. the
   `browser.web_vital` event's required map body has `name`, `value`, `delta`, and `id`), even at
   development stability. If none exists, define bounded, low-cardinality custom attributes under
   a stable namespace instead of guessing at a released-looking name.

## The browser package ecosystem — three repositories

Browser packages are spread across three upstream repos. The
[`opentelemetry-browser` README "Browser Packages" tables](https://github.com/open-telemetry/opentelemetry-browser#browser-packages)
are the authoritative, current map. Summary:

| Package | Repo | Model | Stability |
|---|---|---|---|
| `@opentelemetry/sdk-trace-web` | opentelemetry-js | SDK (spans) | **stable** |
| `@opentelemetry/context-zone` | opentelemetry-js | context | **stable** |
| `@opentelemetry/instrumentation-fetch` | opentelemetry-js | spans | experimental |
| `@opentelemetry/instrumentation-xml-http-request` | opentelemetry-js | spans | experimental |
| `@opentelemetry/opentelemetry-browser-detector` | opentelemetry-js | resource | experimental |
| `@opentelemetry/browser-instrumentation` | opentelemetry-browser | events | experimental |
| `@opentelemetry/browser-sdk` | opentelemetry-browser | SDK | experimental (0.x) |
| `@opentelemetry/auto-instrumentations-web` | opentelemetry-js-contrib | bundle | experimental |
| `instrumentation-document-load` / `-long-task` / `-user-interaction` | opentelemetry-js-contrib | spans | experimental |
| `instrumentation-browser-navigation` / `-web-exception` | opentelemetry-js-contrib | events | experimental |
| `plugin-react-load` | opentelemetry-js-contrib | spans | **unmaintained** |

`opentelemetry-browser` is the home of the event-based instrumentations and the experimental Browser
SDK; the span-based packages still live in `opentelemetry-js` / `opentelemetry-js-contrib`.

## Why browser RUM is different

These constraints drive most design decisions (detailed in the references):

- **The process disappears** — no graceful shutdown. Flush on `visibilitychange`/`pagehide`;
  browser exporters use `keepalive` when limits allow it. Do not rely on `unload`.
- **No gRPC** — export is **OTLP/HTTP** only (protobuf or JSON).
- **Cross-origin propagation is opt-in** — `traceparent` is not sent to other origins unless you set
  `propagateTraceHeaderCorsUrls` **and** the server allows the header via `Access-Control-Allow-Headers`.
- **The client is untrusted and chatty** — put a **Collector (or vendor edge)** between browsers and
  your backend for CORS termination, sampling, redaction, and rate limiting.
- **PII is everywhere** — URLs, console output, form fields, and click targets routinely carry it.

## Sources of Truth

Browser packages move fast while experimental — fetch current versions and status rather than
relying on these notes.

| Fact | Fetch |
|---|---|
| `opentelemetry-browser` package versions / status | `gh api repos/open-telemetry/opentelemetry-browser/releases -q '.[].tag_name'` |
| Latest `@opentelemetry/browser-instrumentation` | `npm view @opentelemetry/browser-instrumentation version` |
| Latest `@opentelemetry/browser-sdk` (0.x, published) | `npm view @opentelemetry/browser-sdk version` |
| Latest `@opentelemetry/sdk-trace-web` | `npm view @opentelemetry/sdk-trace-web version` |
| Latest `@opentelemetry/auto-instrumentations-web` | `npm view @opentelemetry/auto-instrumentations-web version` |
| Authoritative browser package map | `WebFetch https://github.com/open-telemetry/opentelemetry-browser#browser-packages` |
| `browser-instrumentation` README / config | `WebFetch https://raw.githubusercontent.com/open-telemetry/opentelemetry-browser/main/packages/instrumentation/README.md` |
| `browser.*` event semantic-convention status | `WebFetch https://opentelemetry.io/docs/specs/semconv/browser/` |

## Cross-References

- Shared JS API and Node.js SDK (the browser builds on the same API): `otel-js` skill.
- Schema-level facts for declarative YAML config: `otel-declarative-config` skill.
- Semantic conventions lookup (`browser.*`, `session.*`, `exception`): `otel-semantic-conventions` skill — use it before hand-rolling any event/span attributes (see above).
- Edge sampling / redaction / rate limiting in front of browsers: `otel-collector` skill.
- SDK version selection across languages: `otel-sdk-versions` skill.