Automatic
Instrumenting JavaScript

Adding Instrumentation to Browser Applications

For JavaScript applications running in the browser, adding instrumentation is a matter of integrating the appropriate OpenTelemetry libraries into your codebase. Unlike server-side instrumentation—where a Kubernetes annotation might suffice—browser instrumentation is implemented directly in your JavaScript bundle.

Signals

By default, the OpenTelemetry browser instrumentation collects traces from common browser events such as:

  • Page Loads: Captured via the Document Load Instrumentation.
  • User Interactions: Captured with the User Interaction Instrumentation.
  • Network Requests: Captured automatically when using the fetch API or XMLHttpRequest.

These signals provide insights into how users interact with your application, and no additional configuration is required to capture these events.

Instrumentation for JavaScript Browser Applications

Installation

Ensure that you have installed the necessary OpenTelemetry packages:

npm install --save @opentelemetry/api \
  @opentelemetry/sdk-trace-web \
  @opentelemetry/instrumentation-document-load \
  @opentelemetry/exporter-trace-otlp-http \
  @opentelemetry/resources \
  @opentelemetry/instrumentation-fetch
 
# For Metrics Instrumentation
  npm install --save @opentelemetry/exporter-metrics-otlp-http \
      @opentelemetry/sdk-metrics
 
# For Logs Instrumentation
  npm install --save @opentelemetry/exporter-logs-otlp-http \
      @opentelemetry/sdk-logs \
      @opentelemetry/api-logs

To enable browser instrumentation, add the following code snippet to your client-side JavaScript. This snippet initializes the tracer provider, sets up the required instrumentations, and includes custom resource attributes such as your service name. Before setting up Traces, Metrics, and Logs, we define a common resource object and initialize the OpenTelemetry provider with standard configurations.

Defining Resource Attributes

import { defaultResource, resourceFromAttributes } from '@opentelemetry/resources';
import { ATTR_SERVICE_NAME } from '@opentelemetry/semantic-conventions';
 
const resource = defaultResource().merge(
  resourceFromAttributes({
    [ATTR_SERVICE_NAME]: '<your_service_name>',
     'service.domain': '<your_host_name>',
  }),
);

Traces Instrumentation

Note: This module provides a trace-exporter for OTLP (http/json) using protocol version v0.20.0.

import { DocumentLoadInstrumentation } from '@opentelemetry/instrumentation-document-load';
import { registerInstrumentations } from '@opentelemetry/instrumentation';
import {
  BatchSpanProcessor,
  SimpleSpanProcessor,
  ConsoleSpanExporter,
  WebTracerProvider,
} from '@opentelemetry/sdk-trace-web';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
import { FetchInstrumentation } from '@opentelemetry/instrumentation-fetch';
 
const fetchInstrumentation = new FetchInstrumentation();
const collectorOptions = {
  url: '<your_collector_host_name>/v1/traces',
  headers: {},  // an optional object containing custom headers to be sent with each request
  concurrencyLimit: 10, // an optional limit on pending requests
};
 
const exporter = new OTLPTraceExporter(collectorOptions);
const provider = new WebTracerProvider({
  resource: resource,
  spanProcessors: [
    new SimpleSpanProcessor(new ConsoleSpanExporter()),
    new BatchSpanProcessor(exporter, {
      // The maximum queue size. After the size is reached spans are dropped.
      maxQueueSize: 100,
      // The maximum batch size of every export. It must be smaller or equal to maxQueueSize.
      maxExportBatchSize: 10,
      // The interval between two consecutive exports
      scheduledDelayMillis: 500,
      // How long the export can run before it is cancelled
      exportTimeoutMillis: 30000,
    }),
  ]
});
 
provider.register();
 
registerInstrumentations({
  instrumentations: [new DocumentLoadInstrumentation(),
  fetchInstrumentation,],
});
 
fetchInstrumentation.setTracerProvider(provider);

Metrics Instrumentation

Note: This module provides a metrics-exporter for OTLP (http/json) using protocol version v0.20.0.

import { MeterProvider, PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics';
import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-http';
 
const collectorOptions = {
  url: '<your_collector_host_name>/v1/metrics',
  headers: {}, // an optional object containing custom headers to be sent with each request
  concurrencyLimit: 1, // an optional limit on pending requests
};
 
const metricExporter = new OTLPMetricExporter(collectorOptions);
const meterProvider = new MeterProvider({
  resource: resource,
  readers: [
    new PeriodicExportingMetricReader({
      exporter: metricExporter,
      exportIntervalMillis: 10000,
    }),
  ],
});
 
// Start recording data
const meter = meterProvider.getMeter('example-meter');
const counter = meter.createCounter('example-counter');
counter.add(10, { key: 'value' });

Logs Instrumentation

Note: This module provides a logs-exporter for OTLP (http/json) using protocol version v0.20.0

import { SeverityNumber } from '@opentelemetry/api-logs';
import {
  LoggerProvider,
  BatchLogRecordProcessor,
} from '@opentelemetry/sdk-logs';
import { OTLPLogExporter } from '@opentelemetry/exporter-logs-otlp-http';
 
// exporter options. see all options in OTLPExporterConfigBase
const collectorOptions = {
  url: '<your_collector_host_name>/v1/logs',
  headers: {}, // an optional object containing custom headers to be sent with each request
  concurrencyLimit: 1, // an optional limit on pending requests
};
 
const logExporter = new OTLPLogExporter(collectorOptions);
const loggerProvider = new LoggerProvider({ resource: resource });
 
loggerProvider.addLogRecordProcessor(new BatchLogRecordProcessor(logExporter));
 
const logger = loggerProvider.getLogger('default', '1.0.0');
 
logger.emit({
  severityNumber: SeverityNumber.INFO,
  severityText: 'info',
  body: 'this is a log body',
  attributes: { 'log.type': 'custom' },
});

Adding Ingress for the Gateway Collector

TBD