Skip to content

Instantly share code, notes, and snippets.

@jessitron
Last active March 26, 2023 21:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jessitron/7be742d32408497c8ac6194954be6f5b to your computer and use it in GitHub Desktop.
Save jessitron/7be742d32408497c8ac6194954be6f5b to your computer and use it in GitHub Desktop.
OpenTelemetry instrumentation for JavaScript in the Browser: it sends a trace with a span for each CWV (Core Web Vitals) metric. By Purvi Kanal
import { onFID, onLCP, onCLS, onINP, onTTFB } from 'web-vitals'; // you'll need to install this
import { InstrumentationBase, InstrumentationModuleDefinition } from '@opentelemetry/instrumentation';
import { trace, context } from '@opentelemetry/api';
import { hrTime } from '@opentelemetry/core';
export class WebVitalsInstrumentation extends InstrumentationBase {
constructor() {
super('web-vitals-instrumentation', 'v0.1.0');
}
protected init(): void | InstrumentationModuleDefinition<any> | InstrumentationModuleDefinition<any>[] {
}
private enabled: boolean = false;
onReport(metric, parentSpanContext) {
const now = hrTime();
const webVitalsSpan = this.tracer.startSpan(metric.name, { startTime: now }, parentSpanContext);
webVitalsSpan.setAttributes({
[`webvitals.${metric.name}.name`]: metric.name,
[`webvitals.${metric.name}.id`]: metric.id,
[`webvitals.${metric.name}.navigationType`]: metric.navigationType,
[`webvitals.${metric.name}.delta`]: metric.delta,
[`webvitals.${metric.name}.rating`]: metric.rating,
[`webvitals.${metric.name}.value`]: metric.value,
// can expand these into their own attributes!
[`webvitals.${metric.name}.entries`]: JSON.stringify(metric.entries),
});
webVitalsSpan.end();
}
enable() {
if (this.enabled) {
return;
}
this.enabled = true;
// create a parent span that will have all web vitals spans as children
const parentSpan = this.tracer.startSpan('web-vitals');
const ctx = trace.setSpan(context.active(), parentSpan);
parentSpan.end();
onFID(metric => {
this.onReport(metric, ctx);
});
onCLS(metric => {
this.onReport(metric, ctx);
});
onLCP(metric => {
this.onReport(metric, ctx);
});
onINP(metric => {
this.onReport(metric, ctx);
});
onTTFB(metric => {
this.onReport(metric, ctx);
});
}
}
// where you're registering instrumentations, add this one:
registerInstrumentations({
tracerProvider: provider,
instrumentations: [
new WebVitalsInstrumentation()
]});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment