Signatur
Beschreibung
Die schreibgeschützte Eigenschaft timestamp gibt es in jedem RTCDataChannelStats-Objekt, also in jedem Eintrag vom Typ "data-channel" im RTCStatsReport, den RTCPeerConnection.getStats() zurückgibt. Sie enthält einen DOMHighResTimeStamp, also eine Zeit in Millisekunden (mit Nachkommastellen), zu der der Browser die Werte des Eintrags erfasst hat.
Laut Spezifikation wird die Zeit ab der UNIX-Epoche (1. Januar 1970, UTC) gemessen. Sie lässt sich deshalb ungefähr mit Date.now() oder performance.timeOrigin + performance.now() vergleichen. Wirklich wichtig ist die Eigenschaft aber für Differenzen: Aus zwei Messungen desselben Kanals berechnet man mit timestamp das genaue Zeitintervall. Daraus ergeben sich Kennzahlen wie Bytes pro Sekunde oder Nachrichten pro Sekunde.
Nehmen Sie für solche Rechnungen immer timestamp und nicht die eigene Wartezeit zwischen zwei getStats()-Aufrufen. Der Browser kann Statistiken zwischenspeichern oder verzögert erfassen. Nur timestamp sagt zuverlässig, zu welchem Zeitpunkt die Zähler wie bytesSent, bytesReceived, messagesSent und messagesReceived gemessen wurden.
Rückgabewert
Beispiele
Zeitstempel der Datenkanal-Statistik auslesen
// Lokale Verbindung mit sich selbst (Loopback) zum Ausprobieren
const pc1 = new RTCPeerConnection();
const pc2 = new RTCPeerConnection();
pc1.onicecandidate = (e) => e.candidate && pc2.addIceCandidate(e.candidate);
pc2.onicecandidate = (e) => e.candidate && pc1.addIceCandidate(e.candidate);
const channel = pc1.createDataChannel('chat');
await pc1.setLocalDescription();
await pc2.setRemoteDescription(pc1.localDescription);
await pc2.setLocalDescription();
await pc1.setRemoteDescription(pc2.localDescription);
channel.onopen = async () => {
channel.send('Hallo');
const report = await pc1.getStats();
report.forEach((stats) => {
if (stats.type === 'data-channel') {
console.log(stats.label, new Date(stats.timestamp).toISOString());
}
});
};
Durchsatz eines Datenkanals mit timestamp-Differenzen berechnen
const getChannelStats = async (pc, label) => {
const report = await pc.getStats();
for (const stats of report.values()) {
if (stats.type === 'data-channel' && stats.label === label) return stats;
}
return null;
};
const measureThroughput = async (pc, label, intervalMs = 1000) => {
const before = await getChannelStats(pc, label);
await new Promise((r) => setTimeout(r, intervalMs));
const after = await getChannelStats(pc, label);
if (!before || !after) return null;
// Genaues Intervall aus den Zeitstempeln, nicht aus intervalMs
const seconds = (after.timestamp - before.timestamp) / 1000;
const bytesPerSecond = (after.bytesSent - before.bytesSent) / seconds;
return Math.round(bytesPerSecond);
};
// Nutzung: const bps = await measureThroughput(pc1, 'chat');
// console.log(`${bps} B/s gesendet`);
Alter der Statistikdaten prüfen
const statsAge = async (pc) => {
const report = await pc.getStats();
const now = performance.timeOrigin + performance.now();
return [...report.values()]
.filter((s) => s.type === 'data-channel')
.map((s) => ({ label: s.label, ageMs: Math.round(now - s.timestamp) }));
};
// console.table(await statsAge(pc1));
// Wichtig · Fallstricke
- Nur Differenzen sind wirklich verlässlich: Ältere Browserversionen haben andere Bezugspunkte verwendet, etwa die Zeitbasis von
performance.now(). Wenn Sie absolute Zeiten mitDate.now()vergleichen, kann es darum kleine Abweichungen oder Uhrsprünge geben. Differenzen zwischen zwei Messungen desselben Browsers sind dagegen stabil. - Zwei Statistikobjekte können denselben
timestamphaben, wenn der Browser zwischengespeicherte Werte liefert. Prüfen Sie vor der Division, ob die Differenz0ist, sonst entstehtInfinityoderNaN. - Der Wert ist eine Gleitkommazahl. Aus Datenschutzgründen (Fingerprinting, Timing-Angriffe) können Browser die Genauigkeit absichtlich verringern.
- Einträge vom Typ
"data-channel"erscheinen im Bericht erst, wenn einRTCDataChannelangelegt wurde. Ein geschlossener Kanal kann noch eine Zeit lang im Bericht bleiben. - Kompatibilität: Chromium-Browser, Firefox und Safari stellen
RTCDataChannelStatsübergetStats()bereit. Welche einzelnen Felder verfügbar sind, kann sich je nach Browser unterscheiden.