
OpenTelemetry in einer Vue-App: Was heute funktioniert und was noch experimentell ist (2026)
- vuetelemetry
- Leitfäden
- 9 Min. Lesezeit
OpenTelemetry kann eine Vue-App vom Document Load bis zum Fetch-Aufruf tracen, aber der Browser-Teil ist deutlich weniger gefestigt als der Server-Teil. Welche Pakete stabil sind, was Auto-Instrumentierung wirklich erfasst, die Vue-förmige Lücke, die niemand füllt, und wo die Daten landen.
Deine Vue-App läuft auf dem Rechner von jemand anderem, in einem Netz, das du nicht kontrollierst, in einer Browserversion, die du nicht ausgesucht hast. Serverlogs sagen dir, dass eine Anfrage ankam und eine Antwort rausging; sie sagen dir nichts über die vier Sekunden, die der Nutzer auf einen Spinner gestarrt hat. OpenTelemetry ist der herstellerneutrale Standard, der diese Lücke schließt: ein Weg, Traces, Metriken und Logs zu erzeugen, und jedes Backend, das das Protokoll spricht, kann sie empfangen.
Der Gewinn ist ein einziger Trace, der im Browser beginnt und in deiner Datenbank endet. Ein Document-Load-Span, dann der Fetch, den die Seite auslöst, dann der Server-Span, den dieser Fetch verursacht hat, alles zusammengenäht durch den Trace-Kontext, der in HTTP-Headern weitergereicht wird. Genau das bekommst du weder aus den Vue-Devtools noch aus dem serverseitigen Agenten deines APM allein, und deshalb greift man auf dem Frontend überhaupt zu OpenTelemetry.
Stabiles SDK, unfertiges Bild

Jetzt der ehrliche Teil, der regelmäßig übergangen wird. Das Browser-Tracing-SDK `@opentelemetry/sdk-trace-web` ist im OpenTelemetry-JS-Repository als stabil markiert. Aber die offizielle Dokumentation ist zum Gesamtbild unmissverständlich: „Client instrumentation for the browser is experimental and mostly unspecified." Beide Aussagen sind gleichzeitig wahr und widersprechen sich nicht. Die Klempnerei, die Spans erzeugt und exportiert, steht; die Konventionen dazu, was ein Browser-Span enthalten sollte und welche Signale ein Frontend senden sollte, stehen nicht.
Es gibt außerdem ein neueres Vorhaben, das man kennen sollte, bevor man auf Annahmen baut. Das Repository `open-telemetry/opentelemetry-browser` veröffentlicht `@opentelemetry/browser-instrumentation`, dessen Status als experimentell geführt wird. Sein Ansatz unterscheidet sich von den älteren Paketen: Es sendet strukturierte Log-Records für Browser-Performance und Nutzerinteraktionen, als Ergänzung zu den anderswo gepflegten span-basierten Instrumentierungen. Wer heute anfängt, baut auf dem stabilen Span-Pfad auf und behält den ereignisbasierten im Auge, statt sich darauf zu verlassen.
Die Pakete und die Verkabelung
Der brauchbare Satz Pakete ist klein. `@opentelemetry/api` liefert das Tracer-Interface, `@opentelemetry/sdk-trace-web` den Browser-Provider, `@opentelemetry/sdk-trace-base` die Span-Prozessoren und den Konsolen-Exporter, `@opentelemetry/context-zone` den Context Manager und `@opentelemetry/instrumentation` die Registrierungshilfe. Einzelne Instrumentierungen kommen separat, ebenso die OTLP-Exporter. Nichts davon ist Vue-spezifisch, was schon ein Hinweis auf das Folgende ist.
- `@opentelemetry/sdk-trace-web` ist stabil, aber die offizielle Doku sagt, dass Client-Instrumentierung für den Browser experimentell und größtenteils unspezifiziert ist
- Drei Aufrufe zur Verkabelung: `WebTracerProvider` mit Span-Prozessoren erzeugen, `provider.register()` mit `ZoneContextManager`, dann `registerInstrumentations()`
- Fertige Abdeckung sind Document Load, Nutzerinteraktionen, XHR und Fetch - gebündelt in `@opentelemetry/auto-instrumentations-web`
- Es gibt keine offizielle Vue-Instrumentierung: Komponenten- und Router-Spans sind Code, den du selbst schreibst und pflegst
- `@opentelemetry/browser-instrumentation` (das neuere Repository opentelemetry-browser) ist experimentell und sendet strukturierte Log-Records statt Spans
- `SimpleSpanProcessor` plus Konsole für die Entwicklung, `BatchSpanProcessor` plus OTLP-Exporter für die Produktion
Die Verkabelung sind drei Aufrufe. Du erzeugst den Provider mit seinen Span-Prozessoren, etwa `new WebTracerProvider({ spanProcessors: [new SimpleSpanProcessor(new ConsoleSpanExporter())] })`. Du registrierst ihn mit einem Context Manager, `provider.register({ contextManager: new ZoneContextManager() })`. Dann registrierst du deine Instrumentierungen mit `registerInstrumentations({ instrumentations: [new DocumentLoadInstrumentation()] })`. Konsole und `SimpleSpanProcessor` sind für die Entwicklung; in Produktion willst du `BatchSpanProcessor` und einen OTLP-Exporter, damit Spans in Bündeln rausgehen statt eine Anfrage pro Span.
Was Auto-Instrumentierung erfasst
Was die fertigen Instrumentierungen tatsächlich erfassen, ist schmaler als erwartet. `@opentelemetry/instrumentation-document-load` erzeugt Spans für Document Load und Navigation Timing. `@opentelemetry/instrumentation-user-interaction` tracet Nutzerinteraktionen wie Klicks. `@opentelemetry/instrumentation-xml-http-request` und das Fetch-Pendant decken ausgehende Anfragen ab. `@opentelemetry/auto-instrumentations-web` bündelt sie, sodass du eines statt vier registrierst. Zusammen bekommst du Seitenladen, Klicks und Netzwerkaufrufe: echte Abdeckung, aber Abdeckung des Browsers, nicht deiner Komponenten.
Der Context Manager verdient einen Moment. `ZoneContextManager` existiert, weil sich asynchroner Kontext im Browser nicht von allein fortpflanzt: Ohne ihn verliert ein vor einem await geöffneter Span häufig seinen Elternteil, und dein Trace zerfällt in Waisen. Er stützt sich auf zone.js, was bedeutet, diese Bibliothek im Bundle auszuliefern und auszuführen. Das ist ein realer Preis an Gewicht und gepatchten Globals, und genau die Art Abwägung, die man besser misst als annimmt, gerade in einem Stack, der an seinen Core Web Vitals arbeitet.
Die Vue-förmige Lücke
Nun die Lücke. Eine offizielle Vue-Instrumentierung gibt es nicht. Weder im Kern-Repository noch in den Contrib-Paketen. Was in Blogbeiträgen und Herstellerguides als „Vue-Instrumentierung" kursiert, ist handgeschriebener Code: Spans in Lifecycle-Hooks, Spans um Navigation Guards des Routers, ein Plugin, das pro Komponenten-Render einen Span startet. Das zu bauen ist völlig vernünftig und kann echt nützen, aber man sollte wissen, dass man es selbst schreibt und pflegt, ohne semantische Konventionen, an die man sich halten könnte, und ohne Upstream, von dem man Fixes erbt.
Wohin die Daten gehen, ist die letzte Entscheidung und die, die darüber bestimmt, ob sich das Ganze auszahlt. Der Exporter spricht OTLP über HTTP zu einem Collector oder direkt zu einem Backend; ab da liegt die Werkzeugwahl bei dir, gerade weil der Standard herstellerneutral ist. Fang kleiner an als gedacht: `ConsoleSpanExporter`, bis die Spans in den Devtools stimmig aussehen, dann Document Load und Fetch zu einem echten Backend, dann entscheide, ob Spans auf Komponentenebene ihren Platz verdienen. Am ersten Tag alles zu instrumentieren ist der Weg, auf dem Frontend-Observability-Projekte als Rauschen enden, das niemand liest.



Der Context Manager verdient einen Moment. `ZoneContextManager` existiert, weil sich asynchroner Kontext im Browser nicht von allein fortpflanzt: Ohne ihn verliert ein vor einem await geöffneter Span häufig seinen Elternteil, und dein Trace zerfällt in Waisen. Er stützt sich auf zone.js, was bedeutet, diese Bibliothek im Bundle auszuliefern und auszuführen. Das ist ein realer Preis an Gewicht und gepatchten Globals, und genau die Art Abwägung, die man besser misst als annimmt, gerade in einem Stack, der an seinen Core Web Vitals arbeitet.