otel-browser

$npx mdskill add ollygarden/opentelemetry-agent-skills/otel-browser

Configure OpenTelemetry browser RUM for frontend observability.

  • Captures page loads, Core Web Vitals, clicks, errors, and console output.
  • Depends on @opentelemetry/sdk-trace-web, context-zone, and browser-sdk packages.
  • Triggers on keywords like RUM, web vitals, or browser instrumentation.
  • Returns references to setup guides and configuration examples.

SKILL.md

.github/skills/otel-browserView on GitHub ↗
---
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.

More from ollygarden/opentelemetry-agent-skills

SkillDescription
otel-collectorOpenTelemetry Collector component configuration. Use when authoring, reviewing, or debugging Collector YAML for a specific receiver, processor, exporter, connector, or extension — config keys, defaults, validation rules, signal support, stability levels, and component-level gotchas. Triggers on Collector component questions including receivers, processors, exporters, connectors, extensions, component renames, signal support, and pipeline wiring.
otel-collector-builderBuild custom OpenTelemetry Collector distributions with OCB (OpenTelemetry Collector Builder). Use when authoring or debugging a builder manifest (builder.yaml), choosing component and provider versions, building a collector that bundles a custom or out-of-distribution component, setting up CI or Docker builds of a distribution, or troubleshooting OCB build failures. Triggers on "ocb", "collector builder", "custom collector distribution", "builder manifest", "builder-config", and version-mismatch errors from OCB builds.
otel-declarative-configOpenTelemetry declarative YAML configuration for SDK setup. Use when configuring OpenTelemetry SDK providers (tracer, meter, logger), setting up OTLP exporters, defining sampling strategies, or writing otel config files. Triggers on "otel config", "OpenTelemetry YAML", "declarative configuration", "otelconf", "OTEL_CONFIG_FILE", "file_format", "configure tracing/metrics/logs export", or when the user is setting up telemetry pipelines via config files rather than code.
otel-dotnetOpenTelemetry in .NET — DI/builder SDK setup (OpenTelemetry.Extensions.Hosting, AddOpenTelemetry, UseOtlpExporter, OpenTelemetrySdk.Create), native .NET instrumentation APIs (ActivitySource, System.Diagnostics.Metrics Meter) plus logging abstractions (ILogger), zero-code CLR-profiler agent, contrib instrumentation packages, performance tuning, and breaking-change audits. Use when adding, reviewing, or configuring OpenTelemetry in a .NET or ASP.NET Core service. Triggers on "setup otel in dotnet", "dotnet telemetry", ".net tracing", "ASP.NET Core opentelemetry", "AddOpenTelemetry", "UseOtlpExporter", "OpenTelemetrySdk.Create", "ActivitySource", "System.Diagnostics.Metrics Meter", "ILogger opentelemetry", "OpenTelemetry.Extensions.Hosting", "opentelemetry-dotnet-instrumentation", or any C# OTel question.
otel-goOpenTelemetry in Go — SDK setup, API surface, breaking changes, contrib instrumentation libraries (otelhttp, otelgrpc, otelmongo), compile-time zero-code instrumentation (otelc), and performance tuning. Use when adding, reviewing, or configuring OpenTelemetry in a Go service. Triggers on "setup otel in go", "go telemetry", "go tracing", "otelconf go", "otelhttp", "otelgrpc", "TracerProvider go", "MeterProvider go", "otelc", "compile-time instrumentation go", "zero-code go instrumentation", "go build instrumentation", or any Go-related OTel question.
otel-javaOpenTelemetry in Java — Javaagent zero-code instrumentation, Spring Boot Starter, manual autoconfigure SDK, declarative YAML configuration, BOM dependency management, sensitive-data capture and redaction (url.query, headers, request parameters, SQL sanitization). Use when adding, reviewing, or configuring OpenTelemetry in a Java service. Triggers on "setup otel in java", "java telemetry", "javaagent", "Spring Boot otel", "GlobalOpenTelemetry", "AutoConfiguredOpenTelemetrySdk", "TracerProvider java", "url.query redaction", "capture request headers", or any Java-related OTel question.
otel-jsOpenTelemetry in Node.js / JavaScript / TypeScript — NodeSDK, declarative YAML configuration, auto-instrumentations, ESM vs CJS import patterns. Use when adding, reviewing, or configuring OpenTelemetry in a Node.js service. Triggers on "setup otel in node", "js telemetry", "node tracing setup", "NodeSDK", "auto instrumentation node", "TracerProvider node", or any Node.js-related OTel question.
otel-ottlOpenTelemetry Transformation Language (OTTL) expert for writing and debugging telemetry transformations in the OpenTelemetry Collector. Use when authoring or reviewing `transform`, `filter`, `tail_sampling` processor configs or `routing` connector configs, debugging OTTL syntax or semantics, transforming traces, metrics, logs, or profiles, or converting data-processing requirements into OTTL statements.
otel-pythonOpenTelemetry in Python — SDK setup, declarative config, zero-code instrumentation (opentelemetry-instrument, opentelemetry-distro), contrib auto-instrumentation, manual API, performance tuning, breaking changes. Use when configuring or troubleshooting OpenTelemetry in a Python service. Triggers on "setup otel in python", "python telemetry", "python tracing", "opentelemetry-instrument", "opentelemetry-distro", "TracerProvider python", "MeterProvider python", "FastAPI/Flask/Django otel", "python logging bridge".
otel-sdk-versionsOpenTelemetry SDK and package version lookup across languages. Use when choosing the latest compatible released OpenTelemetry SDK or package version and locating setup docs or examples.