Start · Sprachen · JavaScript · Referenz · InterventionReport

InterventionReport

Schnittstelle

Das Wörterbuch <code>InterventionReport</code> der Reporting API beschreibt einen Bericht darüber, dass der Browser eine Anfrage der Seite blockiert oder verändert hat.

seit JavaScript Chromium 69+ (Chrome, Edge, Opera); nicht in Firef Kategorie: webapi

Signatur

interface InterventionReport

Beschreibung

Ein Interventionsbericht entsteht, wenn der Browser absichtlich nicht das tut, was der Code verlangt. Meist geht es dabei um Sicherheit, Leistung oder Nutzerfreundlichkeit. Typische Fälle sind ein preventDefault() in einem passiven touchstart-Listener, den der Browser ignoriert, ein per document.write() eingefügtes Cross-Origin-Skript, das bei langsamer Verbindung blockiert wird, oder ein navigator.vibrate() ohne vorherige Nutzeraktion.

Ein InterventionReport ist kein Objekt, das man selbst erzeugt. Man bekommt es über einen ReportingObserver, der mit types: ["intervention"] angelegt wurde. Alternativ schickt der Browser den Bericht als JSON per POST an einen Endpunkt, den der HTTP-Header Reporting-Endpoints festlegt (Name default).

Das Wörterbuch hat drei Eigenschaften:

  • type: immer der String "intervention".
  • url: die URL des Dokuments, in dem der Eingriff passiert ist.
  • body: ein InterventionReportBody mit den Feldern id, message, sourceFile, lineNumber und columnNumber, außerdem der Methode toJSON().

Die Berichte sind vor allem für Monitoring im Produktivbetrieb nützlich. So sieht man, an welchen Stellen echter Nutzer der Browser eingreift und der Code sich deshalb anders verhält als geplant.

Parameter

Name Typ Default Beschreibung
$type Pflicht string "intervention" Art des Berichts. Bei Interventionsberichten immer "intervention".
$url Pflicht string URL des Dokuments, das den Bericht ausgelöst hat.
$body Pflicht InterventionReportBody Details zum Eingriff: id (Kennung des Eingriffs, z. B. "NavigatorVibrate"), message (lesbare Beschreibung), sourceFile, lineNumber, columnNumber (Fundstelle, sonst null).

Rückgabewert

Typ
InterventionReport
Beschreibung
Ein Berichtsobjekt, das an den Callback eines ReportingObserver übergeben wird oder das takeRecords() zurückgibt.

Beispiele

Interventionen mit ReportingObserver abfangen

const observer = new ReportingObserver((reports) => {
  for (const report of reports) {
    const { id, message, sourceFile, lineNumber, columnNumber } = report.body;
    console.log(`[${report.type}] ${id}: ${message}`);
    console.log(`Fundstelle: ${sourceFile}:${lineNumber}:${columnNumber}`);
  }
}, { types: ['intervention'], buffered: true });

observer.observe();

// Löst ohne vorherige Nutzeraktion eine Intervention aus
navigator.vibrate?.(200);
[intervention] NavigatorVibrate: Blocked call to navigator.vibrate because user hasn't tapped on the frame or any embedded frame yet. Fundstelle: https://example.com/app.js:11:12

Berichte an ein eigenes Monitoring senden

const sendReports = (reports) => {
  const payload = reports.map((r) => ({
    type: r.type,
    url: r.url,
    body: r.body.toJSON()
  }));
  navigator.sendBeacon('/api/reports', JSON.stringify(payload));
};

const observer = new ReportingObserver(sendReports, { types: ['intervention'] });
observer.observe();

// Beim Verlassen der Seite noch nicht zugestellte Berichte mitnehmen
addEventListener('pagehide', () => {
  const pending = observer.takeRecords();
  if (pending.length) sendReports(pending);
});

Serverseitiger Endpunkt (Node.js/Express) über Reporting-Endpoints

import express from 'express';

const app = express();

// Browser schickt Interventionsberichte an den Endpunkt "default"
app.use((req, res, next) => {
  res.set('Reporting-Endpoints', 'default="https://example.com/reports"');
  next();
});

app.post('/reports', express.json({ type: 'application/reports+json' }), (req, res) => {
  for (const report of req.body) {
    if (report.type === 'intervention') {
      console.log('Intervention:', report.body.id, '-', report.body.message);
    }
  }
  res.sendStatus(204);
});

app.listen(3000);
Intervention: NavigatorVibrate - Blocked call to navigator.vibrate ...

// Wichtig · Fallstricke

  • Kompatibilität: Interventionsberichte liefern nur Chromium-basierte Browser. Firefox und Safari unterstützen ReportingObserver teilweise, erzeugen aber keine Berichte vom Typ intervention. Vor der Nutzung mit 'ReportingObserver' in window prüfen.
  • Die Werte von body.id und der Text von message sind nicht standardisiert und können sich zwischen Browserversionen ändern. Man sollte sich also nicht fest auf bestimmte Strings verlassen.
  • sourceFile, lineNumber und columnNumber können null sein, etwa bei Eingriffen ohne eindeutige Codestelle.
  • Ohne buffered: true kommen nur Berichte an, die nach observe() entstehen. Frühere Eingriffe beim Laden der Seite gehen sonst verloren.
  • Berichte werden gebündelt und verzögert zugestellt, nicht sofort beim Eingriff. Vor dem Verlassen der Seite deshalb takeRecords() aufrufen.
  • Datenschutz: Die gemeldete url kann Abfrageparameter mit personenbezogenen Daten enthalten. Vor dem Speichern bereinigen.
  • Der ältere Header Report-To ist veraltet. Stattdessen Reporting-Endpoints verwenden.