@opentelemetry/browser-instrumentation
Note: This is an experimental package under active development. New releases may include breaking changes. See VERSIONING.md.
OpenTelemetry browser instrumentations, available as subpath exports under ./experimental/*.
Moving from opentelemetry-js or opentelemetry-js-contrib? See the migration guide for import paths, behavior changes, and remaining gaps.
Installation
npm install @opentelemetry/browser-instrumentation
Instrumentations
- Navigation — automatic instrumentation for browser navigations (initial load and SPA route changes)
- Navigation Timing — automatic instrumentation for navigation timing
- Resource Timing — automatic instrumentation for resource timing
- User Action — automatic instrumentation for user actions (clicks)
- Web Vitals — automatic instrumentation for Core Web Vitals
- Console — automatic instrumentation for console API calls (log, warn, error, info, debug)
- Errors — automatic instrumentation for unhandled errors and promise rejections
- Fetch — automatic instrumentation for request using the
fetchAPI
Usage
import { logs } from '@opentelemetry/api-logs';
import {
ConsoleLogRecordExporter,
LoggerProvider,
SimpleLogRecordProcessor,
} from '@opentelemetry/sdk-logs';
import { registerInstrumentations } from '@opentelemetry/instrumentation';
import { ErrorsInstrumentation } from '@opentelemetry/browser-instrumentation/experimental/errors';
import { NavigationInstrumentation } from '@opentelemetry/browser-instrumentation/experimental/navigation';
import { NavigationTimingInstrumentation } from '@opentelemetry/browser-instrumentation/experimental/navigation-timing';
import { ResourceTimingInstrumentation } from '@opentelemetry/browser-instrumentation/experimental/resource-timing';
import { UserActionInstrumentation } from '@opentelemetry/browser-instrumentation/experimental/user-action';
import { WebVitalsInstrumentation } from '@opentelemetry/browser-instrumentation/experimental/web-vitals';
const logProvider = new LoggerProvider({
processors: [
new SimpleLogRecordProcessor(new ConsoleLogRecordExporter()),
],
});
logs.setGlobalLoggerProvider(logProvider);
registerInstrumentations({
instrumentations: [
new ErrorsInstrumentation(),
new NavigationInstrumentation(),
new NavigationTimingInstrumentation(),
new ResourceTimingInstrumentation(),
new UserActionInstrumentation(),
new WebVitalsInstrumentation(),
],
});
Navigation
import { NavigationInstrumentation } from '@opentelemetry/browser-instrumentation/experimental/navigation';
Emits a browser.navigation event for the initial page load (hard navigation) and for subsequent in-page navigations (soft navigations), including history.pushState, history.replaceState, popstate, and hash changes. When enabled via config, the Navigation API is used in preference to patching history.
Configuration
import {
NavigationInstrumentation,
defaultSanitizeUrl,
} from '@opentelemetry/browser-instrumentation/experimental/navigation';
new NavigationInstrumentation({
// Use window.navigation (Navigation API) when available instead of
// patching history.pushState / history.replaceState. Default: false.
useNavigationApiIfAvailable: true,
// Rewrite the captured URL before it is emitted. Useful for stripping
// path segments, query parameters, or tokens that should not be exported.
sanitizeUrl: (url) => defaultSanitizeUrl(url),
// Mutate the log record before it is emitted (e.g. attach custom attributes).
applyCustomLogRecordData: (logRecord) => {
logRecord.attributes = {
...logRecord.attributes,
'app.route.id': '...',
};
},
});
| Option | Type | Default | Description |
|---|---|---|---|
useNavigationApiIfAvailable |
boolean |
false |
When true, subscribes to the Navigation API (currententrychange) instead of patching history.pushState / history.replaceState. Falls back to history patching when the Navigation API is unavailable. |
sanitizeUrl |
(url: string) => string |
— | Called before the URL is written to url.full. |
applyCustomLogRecordData |
(logRecord: LogRecord) => void |
— | Hook to modify log records before they are emitted. Errors thrown from this hook are caught and logged via the instrumentation diag logger. |
defaultSanitizeUrl is exported for composition — it redacts user:password@ credentials and a set of common sensitive query parameters (api_key, token, password, etc.).
Captured Attributes
Each browser.navigation event includes:
| Attribute | Description |
|---|---|
url.full |
The destination URL (after sanitizeUrl if configured). |
browser.navigation.same_document |
true for SPA route changes; false for full-page loads. |
browser.navigation.hash_change |
true when the navigation only adds or changes the URL fragment. |
browser.navigation.type |
One of push, replace, reload, traverse (omitted for the initial hard navigation). |
Navigation Timing
import { NavigationTimingInstrumentation } from '@opentelemetry/browser-instrumentation/experimental/navigation-timing';
Provides automatic instrumentation for Navigation Timing in web applications.
Resource Timing
import { ResourceTimingInstrumentation } from '@opentelemetry/browser-instrumentation/experimental/resource-timing';
Provides automatic instrumentation for Resource Timing in web applications, capturing performance metrics for all resources loaded by the browser (scripts, stylesheets, images, fonts, XHR/fetch requests, etc.).
- Uses
requestIdleCallbackto avoid blocking the main thread (with automaticsetTimeoutfallback for Safari) - Processes resources in configurable batches
- Captures historical resources loaded before instrumentation was enabled via buffered mode
- Flushes pending entries on visibility change to prevent data loss
Configuration
new ResourceTimingInstrumentation({
// Process 100 resources per batch (default: 50)
batchSize: 100,
// Wait max 2 seconds for idle time before forcing processing (default: 1000)
forceProcessingAfter: 2000,
// Spend max 100ms processing per idle callback (default: 50)
maxProcessingTime: 100,
// Maximum queue size before forcing immediate flush (default: 1000)
maxQueueSize: 2000,
});
| Option | Type | Default | Description |
|---|---|---|---|
batchSize |
number |
50 |
Number of resources to process per batch. |
forceProcessingAfter |
number |
1000 |
Maximum time (ms) to wait for an idle callback before forcing processing. |
maxProcessingTime |
number |
50 |
Maximum time (ms) to spend processing resources per idle callback. |
maxQueueSize |
number |
1000 |
Maximum number of resources to queue before forcing immediate flush. |
Captured Data
Each resource timing event includes:
- URL and Initiator Type (script, css, img, xmlhttprequest, fetch, etc.)
- Duration — total resource load time
- Timing Phases — DNS lookup, TCP connection, TLS handshake, request, response
- Size Metrics — transfer size, encoded size, decoded size
- Protocol — HTTP version (h1, h2, h3)
- Redirect Info — redirect timing if applicable
- Service Worker — worker start time if intercepted
- Render Blocking — whether the resource blocked rendering (Chromium only)
User Action
import { UserActionInstrumentation } from '@opentelemetry/browser-instrumentation/experimental/user-action';
Provides automatic instrumentation for user actions in web applications.
Compatible with OpenTelemetry JS API and SDK 1.0+.
Configuration
By default the instrumentation captures click events. Middle clicks are captured through auxclick and right clicks through contextmenu, since native context menus can consume the mouse release before auxclick fires. Only button 2 context menus are recorded, so keyboard menu events are ignored. Right-button auxclick events are ignored to avoid duplicate records. You can configure which events to capture by passing an options object:
new UserActionInstrumentation({
// Array of actions to automatically capture. Default: ['click'].
autoCapturedActions: [],
// Mutate the log record before it is emitted (e.g. attach custom attributes).
applyCustomLogRecordData: (logRecord) => {
logRecord.attributes = {
...logRecord.attributes,
'app.user.role': 'admin',
};
},
});
| Option | Type | Default | Description |
|---|---|---|---|
autoCapturedActions |
AutoCapturedUserAction[] |
['click'] |
Array of actions to automatically capture. |
applyCustomLogRecordData |
(logRecord: LogRecord) => void |
— | Hook to modify log records before they are emitted. Errors thrown from this hook are caught and logged via the instrumentation diag logger. |
Additional Attributes
Data attributes with the prefix data-otel- on the target element will be added as additional attributes to the generated log record. For example:
<button id="btn1" data-otel-user-id="12345" data-otel-feature="signup">
Sign Up
</button>
Web Vitals
import { WebVitalsInstrumentation } from '@opentelemetry/browser-instrumentation/experimental/web-vitals';
Provides automatic instrumentation for Core Web Vitals using the web-vitals library.
Configuration
| Option | Type | Default | Description |
|---|---|---|---|
includeRawAttribution |
boolean |
false |
When true, sets the log record body to the JSON-stringified web-vitals attribution object. |
applyCustomLogRecordData |
(logRecord: LogRecord) => void |
— | Hook to modify log records before they are emitted. |
reportAllChanges |
boolean |
false |
Passed through to web-vitals. When true, reports metric updates according to web-vitals reporting behavior, with delta carrying the change since its previous report. Set before listeners are first registered, later config changes do not replace existing listeners. |
Console
import { ConsoleInstrumentation } from '@opentelemetry/browser-instrumentation/experimental/console';
Provides automatic instrumentation for browser console API calls. By default captures log, warn, error, info, and debug methods.
Configuration
new ConsoleInstrumentation({
// Specify which console methods to capture (default: log, warn, error, info, debug)
logMethods: ['error', 'warn'],
});
Captured Attributes
Each browser.console event includes the following attributes:
| Attribute | Description | Example |
|---|---|---|
browser.console.method |
The console method that was called | error, warn, log, info, debug |
Errors
import { ErrorsInstrumentation } from '@opentelemetry/browser-instrumentation/experimental/errors';
Emits an exception event for every uncaught error (window.addEventListener('error', ...)) and unhandled promise rejection (window.addEventListener('unhandledrejection', ...)).
Configuration
new ErrorsInstrumentation({
// Return extra attributes to attach to the emitted log record.
applyCustomAttributes: (error) => ({
'app.error.severity':
error instanceof Error && error.name === 'ValidationError'
? 'warning'
: 'error',
}),
});
| Option | Type | Default | Description |
|---|---|---|---|
applyCustomAttributes |
(error: Error | string) => Attributes |
— | Returns extra attributes to merge onto the emitted log record. Errors thrown from this hook are caught and logged via the instrumentation diag logger. |
Captured Attributes
Each exception event includes:
| Attribute | Description |
|---|---|
exception.type |
The error's name (omitted when the thrown value is a string). |
exception.message |
The error's message, or the thrown string itself. |
exception.stacktrace |
The error's stack (omitted when the thrown value is a string). |
Fetch
import { FetchInstrumentation } from '@opentelemetry/browser-instrumentation/experimental/fetch';
Emits a Span for every HTTP request made using the window.fetch browser API. This instrumentation also propagates the context for distributed traces.
Configuration
new FetchInstrumentation({
ignoreUrls: ['https://example.com/api'],
propagateTraceHeaderCorsUrls: [/domain.com\/api.*/],
measureRequestSize: true,
applyCustomAttributesOnSpan: (span, request, result) => {
span.setAttribute('foo', 'bar');
},
});
| Option | Type | Default | Description |
|---|---|---|---|
ignoreUrls |
Array<string | RegExp> |
— | List of URLs that we do not want its requests instrumented. You can use strings for a single match or regular expressions to match many. |
propagateTraceHeaderCorsUrls |
Array<string | RegExp> |
— | List of cross origin URLs to appens trace context headers. You can use strings for a single match or regular expressions to match many. |
measureRequestSize |
boolean |
— | Set it to true to add the request size as a Span attribute. |
sanitizeUrl |
(url: string) => string |
— | Returns the given URL with sensitive fields REDACTED. |
requestHook |
(span: Span, request: Request) => void |
— | Function that allows you to interact with the Span and the Request object before the request starts. |
applyCustomAttributesOnSpan |
(span: Span, request: Request, result: Response | FetchError) => void |
— | Function that allows you to interact with the Span once the request is finished. |
Captured Attributes
Each fetch Span includes:
| Attribute | Description |
|---|---|
http.request.method |
The method of the request in uppercase (GET, POST, PUT, PATCH, QUERY). |
http.request.method_original |
Original HTTP method sent by the client in the request line.. |
url.full |
Absolute URL describing a network resource according to RFC3986 (sanitized if passing sanitizeUrl config option). |
server.address |
The hostmane of the request's URL. |
server.port |
The port of the request's URL. |
http.response.status_code |
HTTP response status code. |
error.type |
If request failed. Describes a class of error the operation ended with. |
XHR (XmlHttpRequest)
import { XhrInstrumentation } from '@opentelemetry/browser-instrumentation/experimental/xhr';
Emits a Span for every HTTP request made using the window.XmlHttpRequest browser API. This instrumentation also propagates the context for distributed traces.
Configuration
new XhrInstrumentation({
ignoreUrls: ['https://example.com/api'],
propagateTraceHeaderCorsUrls: [/domain.com\/api.*/],
measureRequestSize: true,
applyCustomAttributesOnSpan: (span, xhr) => {
span.setAttribute('foo', 'bar');
},
});
| Option | Type | Default | Description |
|---|---|---|---|
ignoreUrls |
Array<string | RegExp> |
— | List of URLs that we do not want its requests instrumented. You can use strings for a single match or regular expressions to match many. |
propagateTraceHeaderCorsUrls |
Array<string | RegExp> |
— | List of cross origin URLs to appens trace context headers. You can use strings for a single match or regular expressions to match many. |
measureRequestSize |
boolean |
— | Set it to true to add the request size as a Span attribute. |
sanitizeUrl |
(url: string) => string |
— | Returns the given URL with sensitive fields REDACTED. |
applyCustomAttributesOnSpan |
(span: Span, request: Request, result: Response | FetchError) => void |
— | Function that allows you to interact with the Span once the request is finished. |
Captured Attributes
Each fetch Span includes:
| Attribute | Description |
|---|---|
http.request.method |
The method of the request in uppercase (GET, POST, PUT, PATCH, QUERY). |
http.request.method_original |
Original HTTP method sent by the client in the request line.. |
url.full |
Absolute URL describing a network resource according to RFC3986 (sanitized if passing sanitizeUrl config option). |
server.address |
The hostmane of the request's URL. |
server.port |
The port of the request's URL. |
http.response.status_code |
HTTP response status code. |
error.type |
If request failed. Describes a class of error the operation ended with. |
Useful links
- For more information on OpenTelemetry, visit: https://opentelemetry.io/
- For more about OpenTelemetry Browser: https://github.com/open-telemetry/opentelemetry-browser
- For help or feedback on this project, join us in GitHub Discussions
License
Apache 2.0 - See LICENSE for more information.