JavaScript Browser
This guide provides instructions for setting up custom instrumentation for JavaScript browser applications using the OpenTelemetry JavaScript SDK.
Overview​
This guide demonstrates how to:
- Set up OpenTelemetry custom instrumentation for JavaScript browser applications
- Export telemetry data to Scout
Note: Auto instrumentation does not support metrics. To collect meaningful metrics, you need to implement them manually.
Prerequisites​
- Node.js 16+
- JavaScript browser application setup
- Scout Collector setup
Required Packages​
Install the following packages:
npm install @opentelemetry/api
npm install @opentelemetry/sdk-trace-web
npm install @opentelemetry/sdk-metrics
npm install @opentelemetry/sdk-logs
npm install @opentelemetry/context-zone
npm install @opentelemetry/exporter-trace-otlp-http
npm install @opentelemetry/exporter-metrics-otlp-http
npm install @opentelemetry/resources
Custom Instrumentation Setup (telemetry.js
)​
// src/telemetry.js
import { WebTracerProvider } from "@opentelemetry/sdk-trace-web";
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
import { BatchSpanProcessor } from "@opentelemetry/sdk-trace-base";
import { Resource } from "@opentelemetry/resources";
import { SemanticResourceAttributes } from "@opentelemetry/semantic-conventions";
import { ZoneContextManager } from "@opentelemetry/context-zone";
import {
MeterProvider,
PeriodicExportingMetricReader,
} from "@opentelemetry/sdk-metrics";
import { OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-http";
import {
LoggerProvider,
SimpleLogRecordProcessor,
} from "@opentelemetry/sdk-logs";
import { OTLPLogExporter } from "@opentelemetry/exporter-logs-otlp-http";
import * as logsAPI from "@opentelemetry/api-logs";
import * as api from "@opentelemetry/api";
import { ZoneContextManager } from "@opentelemetry/context-zone";
export const setupTelemetry = () => {
const resource = new Resource({
[SemanticResourceAttributes.SERVICE_NAME]: "react-service",
[SemanticResourceAttributes.SERVICE_VERSION]: "1.0.0",
});
// Trace setup
const traceExporter = new OTLPTraceExporter({
url: "http://<scout-collector-endpoint>:4318/v1/traces",
});
const traceProvider = new WebTracerProvider({ resource });
traceProvider.addSpanProcessor(new BatchSpanProcessor(traceExporter));
traceProvider.register({ contextManager: new ZoneContextManager() });
// Metric setup
const metricExporter = new OTLPMetricExporter({
url: "http://<scout-collector-endpoint>:4318/v1/metrics",
});
const meterProvider = new MeterProvider({
resource,
readers: [
new PeriodicExportingMetricReader({
exporter: metricExporter,
exportIntervalMillis: 10000,
}),
],
});
api.metrics.setGlobalMeterProvider(meterProvider);
// Log setup
const logExporter = new OTLPLogExporter({
url: "http://<scout-collector-endpoint>:4318/v1/logs",
});
const loggerProvider = new LoggerProvider({
resource,
processors: [new SimpleLogRecordProcessor(logExporter)],
});
logsAPI.logs.setGlobalLoggerProvider(loggerProvider);
};
Initialize in index.js​
// src/index.js
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import { setupTelemetry } from "./telemetry";
setupTelemetry();
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById("root"),
);
Custom Tracing Example​
import { trace } from "@opentelemetry/api";
async function checkServiceHealth() {
// Get the tracer from the global tracer provider set in the setupTelemetry function
const tracer = trace.getTracer("health-service");
const span = tracer.startSpan("checkServiceHealth");
try {
span.setAttribute("health.check", "ping");
const res = await fetch("/ping");
const data = await res.json();
return data;
} catch (error) {
//handle error
throw error;
} finally {
span.end();
}
}
Custom Metrics Example​
import { metrics } from "@opentelemetry/api";
//Gets the meter from the global meter provider set in the setupTelemetry function
const meter = metrics.getMeter("react-app");
const renderCount = meter.createCounter("component.render.count");
function TrackedComponent() {
useEffect(() => {
renderCount.add(1, { component: "TrackedComponent" });
}, []);
return <div>Tracked!</div>;
}
Configuration​
CORS Headers for Otel Collector​
Add the following CORS headers to the Otel Collector configuration:
receivers:
otlp:
protocols:
http:
endpoint: 0.0.0.0:4318
cors:
allowed_origins:
- "https://example.com"
View these traces in Scout Grafana dashboards.
References​
Sample react application with OTel instrumentation
Related Guides​
- Docker Compose Setup - Set up collector for local development
- React Auto-Instrumentation - Auto-instrumentation for React applications
- Kubernetes Helm Setup - Production deployment