Signatur
Beschreibung
ReportingObserver gehört zur Reporting API. Der Browser erzeugt Berichte, zum Beispiel wenn eine veraltete API aufgerufen wird ("deprecation"), wenn er selbst eingreift und etwa ein Werbe-iframe blockiert ("intervention") oder wenn gegen die Content Security Policy verstoßen wird ("csp-violation"). Diese Berichte kannst du direkt in JavaScript abfangen. Normalerweise würden sie nur in der Entwicklerkonsole stehen oder über den HTTP-Header Reporting-Endpoints an einen Server gehen.
Die Schnittstelle funktioniert wie andere Observer (MutationObserver, IntersectionObserver). Du erzeugst mit new ReportingObserver(callback, options) eine Instanz und startest die Beobachtung mit observe(). Neue Berichte übergibt der Browser gebündelt und asynchron an den Callback. Mit takeRecords() holst du Berichte ab, die noch nicht zugestellt wurden. disconnect() beendet die Beobachtung.
observe(): startet das Sammeln von Berichten.takeRecords(): gibt die Berichte in der Warteschlange als Array zurück und leert die Warteschlange.disconnect(): beendet die Beobachtung.
Jeder Bericht ist ein Report-Objekt mit den Eigenschaften type, url und body. Wie body aufgebaut ist, hängt vom Typ ab. Ein DeprecationReportBody enthält zum Beispiel id, message, sourceFile, lineNumber und anticipatedRemoval. Typische Einsatzfälle sind Überwachung im Produktivbetrieb (Real User Monitoring), das frühzeitige Aufspüren veralteter APIs vor Browser-Updates und das Protokollieren von CSP-Verstößen im eigenen Analyse-Werkzeug.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $callback Pflicht | (reports: Report[], observer: ReportingObserver) => void | Wird asynchron mit einem Array neuer Report-Objekte und dem Observer selbst aufgerufen. |
|
| $options | object | {} | Optionales Konfigurationsobjekt für den Konstruktor. |
| $options.types | string[] | alle unterstützten Typen | Filtert nach Berichtstypen, z. B. ["deprecation", "intervention", "csp-violation"]. "crash"-Berichte kann ein Observer grundsätzlich nicht empfangen. |
| $options.buffered | boolean | false | Bei true werden auch Berichte zugestellt, die vor der Erzeugung des Observers entstanden sind. |
Rückgabewert
ReportingObserver-Instanz. Sie sammelt erst nach dem Aufruf von observe() Berichte.Beispiele
Observer erzeugen und Deprecation-Berichte protokollieren
const observer = new ReportingObserver((reports, obs) => {
for (const report of reports) {
const { id, message, sourceFile, lineNumber } = report.body;
console.warn(`[${report.type}] ${id}: ${message} (${sourceFile}:${lineNumber})`);
}
}, { types: ['deprecation'], buffered: true });
observer.observe();
// Eine veraltete API auslösen (in Chromium z. B. synchrones XHR im Hauptthread)
const xhr = new XMLHttpRequest();
xhr.open('GET', location.href, false);
xhr.send();
Berichte gesammelt an einen Analyse-Endpunkt senden
const queue = [];
const observer = new ReportingObserver((reports) => {
queue.push(...reports.map((r) => r.toJSON()));
}, { types: ['deprecation', 'intervention', 'csp-violation'], buffered: true });
observer.observe();
// Beim Verlassen der Seite: ausstehende Berichte abholen und versenden
document.addEventListener('visibilitychange', () => {
if (document.visibilityState !== 'hidden') return;
queue.push(...observer.takeRecords().map((r) => r.toJSON()));
if (queue.length > 0) {
navigator.sendBeacon('/api/reports', JSON.stringify(queue));
queue.length = 0;
}
});
Feature-Erkennung und Beobachtung wieder beenden
if ('ReportingObserver' in globalThis) {
const observer = new ReportingObserver((reports, obs) => {
console.log(`${reports.length} Bericht(e) erhalten`);
// Nach dem ersten Bündel nicht weiter beobachten
obs.disconnect();
}, { buffered: true });
observer.observe();
} else {
console.info('ReportingObserver wird in diesem Browser nicht unterstützt.');
}
// Wichtig · Fallstricke
- Browser-Unterstützung: Chromium-Browser (Chrome, Edge, Opera) unterstützen die Schnittstelle seit Version 69, Safari seit 16.4. In Firefox ist sie standardmäßig deaktiviert. Prüfe deshalb vorher mit
'ReportingObserver' in globalThis, ob sie vorhanden ist. - Welche Berichtstypen es gibt, ist je nach Browser verschieden.
"crash"-Berichte bekommt ein Observer grundsätzlich nie, weil die Seite dabei ja abstürzt. Solche Berichte gibt es nur über den HeaderReporting-Endpoints. - Der Callback läuft asynchron und gebündelt, nicht sofort bei der Ursache. Ohne
buffered: trueverpasst du Berichte, die vorobserve()entstanden sind. - Berichte, die beim Verlassen der Seite noch in der Warteschlange liegen, gehen verloren. Hole sie mit
takeRecords()ab und versende sie mitnavigator.sendBeacon(). - Datenschutz: Berichte enthalten URLs und Quelltextpositionen, bei CSP-Verstößen auch blockierte URLs. Entferne vor dem Versand an Server von Drittanbietern alle sensiblen Anteile wie Tokens in Abfrageparametern.
- Die Schnittstelle ist in Dokumenten und Web Workern verfügbar. Ein sicherer Kontext (HTTPS) ist laut Spezifikation nicht vorgeschrieben.