Dash0 acquires Polar Signals
Opentelemetry-js is OpenTelemetry's official set of SDKs for instrumentation within web browsers
This integration is based on the official OpenTelemetry browser JavaScript instrumentation. While widely used, it is still officially marked as experimental.
Opentelemetry-js is OpenTelemetry's official set of SDKs for the instrumentation of javascript applications running in web browsers. This SDK allows you to observe end-user page loads, sessions, fetch requests, errors, and asset retrievals.
Instrumenting web applications with opentelemetry-js sdks will emit trace signals, which will be available in dash0's tracing product area. If you want to make use of dash0's website monitoring, please consider using the Dash0 web sdk instead.
Want AI to set this up for you? Install the Dash0 Agent Skills to let Claude Code, Cursor, or Windsurf instrument your application automatically with OpenTelemetry best practices.
The OpenTelemetry Browser JavaScript SDK is available as many fine-grained NPM packages under the OpenTelemetry organization. This guide will walk you through a basic setup using Rollup as a bundler. You don't need to use Rollup, though. You can also import the packages with your existing Next.js, Webpack, Parcel, and Vite builds.
To start, let's grab all the necessary dependencies:
npm install --save \
@opentelemetry/api \
@opentelemetry/context-zone \
@opentelemetry/exporter-trace-otlp-http \
@opentelemetry/instrumentation \
@opentelemetry/auto-instrumentations-web \
@opentelemetry/sdk-trace-web \
@opentelemetry/semantic-conventionsNow, let's initialize this SDK within your application code as early as possible so that the instrumentation can observe
all interactions. Place the following code into a file called instrumentation.js (of course, you may also use
TypeScript – the packages come with type definitions).
import { BatchSpanProcessor, WebTracerProvider } from "@opentelemetry/sdk-trace-web";
import { ZoneContextManager } from "@opentelemetry/context-zone";
import { registerInstrumentations } from "@opentelemetry/instrumentation";
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
import { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION } from "@opentelemetry/semantic-conventions";
import { ATTR_DEPLOYMENT_ENVIRONMENT_NAME } from "@opentelemetry/semantic-conventions/incubating";
import { getWebAutoInstrumentations } from "@opentelemetry/auto-instrumentations-web";
const tracerProvider = new WebTracerProvider({
resource: {
attributes: {
// TODO update these values with ones that make sense for your application
[ATTR_DEPLOYMENT_ENVIRONMENT_NAME]: "production",
[ATTR_SERVICE_NAME]: "my-website",
[ATTR_SERVICE_VERSION]: "1.0.0",
},
},
spanProcessors: [
new BatchSpanProcessor(
new OTLPTraceExporter({
url: "{{endpoint_otlp_http}}/v1/traces",
headers: {
// TODO we **highly** recommend that you use an auth token with restricted permissions for
// in-browser telemetry collection. Within the auth token settings screen, you can restrict
// an auth token to a single dataset and **only ingesting** permissions.
Authorization: "Bearer {{token}}",
},
}),
{
maxQueueSize: 100, // The maximum queue size. After the size is reached, spans are dropped.
maxExportBatchSize: 10, // The maximum batch size of every export. It must be smaller or equal to maxQueueSize.
scheduledDelayMillis: 500, // The interval between two consecutive exports
exportTimeoutMillis: 30000, // How long the export can run before it is cancelled
}
),
],
});
tracerProvider.register({
// Changing default context manager to use ZoneContextManager. This one supports tracking of asynchronous operations.
// Optional, but recommended for better correlation.
contextManager: new ZoneContextManager(),
});
// Registering instrumentations
registerInstrumentations({
instrumentations: [
// You can configure all the auto-instrumentations via this function's parameter.
// Learn more via this documentation: https://www.npmjs.com/package/@opentelemetry/auto-instrumentations-web
getWebAutoInstrumentations(),
],
});Next, make sure this file is loaded within your application, for example, by importing it into your application's code.
In a React application, you can consider initializing within a useEffect hook.
We will import the bundled index.js file directly from an index.html HTML file within our minimal example.
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>OTel Browser JavaScript Demo</title>
</head>
<body>
<p>Inspect the network tab for telemetry transmission requests.</p>
<script type="module" src="index.js"></script>
</body>
</html>This is all the configuration being done. You could now open up your application to see traces being generated. If you
follow our example of leveraging Rollup and an index.html, the next step is building the application. To do that,
we need a configuration file for our bundler. Create a file called rollup.config.js with this content.
import nodeResolve from "@rollup/plugin-node-resolve";
import commonjs from "@rollup/plugin-commonjs";
export default {
input: "instrumentation.js",
output: {
file: "index.js",
format: "iife",
},
plugins: [
commonjs(),
nodeResolve({
browser: true,
}),
],
};For the bundling process to work, you need to mark the package as a module by adding "type": "module" to your package.json,
and you will also need a few more development-only dependencies:
npm install --save \
@rollup/plugin-node-resolve \
@rollup/plugin-commonjsAnd at last, we can build our application:
npx rollup --config rollup.config.jsYou can now open up your website to start sending telemetry to Dash0! If you have followed along using Rollup and the
index.html file, you can now open the index.html file in your web browser. The instrumentation will collect
information about page loads and report these as traces to Dash0 (you can see calls to the Dash0 ingestion API in the
network tab)!
Now, this is where the real fun begins: Insights into real-world impact! We also suggest you read the manual instrumentation guidelines to learn how to capture custom data about your application.