Signatur
Beschreibung
Die schreibgeschützte Eigenschaft timestamp eines RTCCertificateStats-Objekts gibt an, wann der Browser den Statistik-Schnappschuss erstellt hat. Der Wert ist ein DOMHighResTimeStamp, also eine Gleitkommazahl in Millisekunden. Laut WebRTC-Statistik-Spezifikation bezieht sie sich auf die UNIX-Epoche (1. Januar 1970, UTC).
Ein RTCCertificateStats-Objekt bekommst du über RTCPeerConnection.getStats(). Im zurückgegebenen RTCStatsReport steht es als Eintrag mit type === "certificate". Er beschreibt ein Zertifikat, das beim DTLS-Handshake benutzt wird, mit Fingerabdruck, Hash-Algorithmus und dem Base64-kodierten DER-Zertifikat. Solche Einträge gibt es erst, wenn der DTLS-Transport steht, also typischerweise nach erfolgreichem ICE- und DTLS-Aufbau.
In der Praxis nutzt du timestamp vor allem für Protokollierung und Diagnose. Du kannst Statistik-Schnappschüsse zeitlich einordnen, veraltete Daten erkennen oder Einträge aus mehreren getStats()-Aufrufen einander zuordnen. Die Eigenschaft wird von RTCStats geerbt. Alle Einträge desselben Berichts haben deshalb meist denselben oder einen sehr ähnlichen Zeitstempel.
Rückgabewert
new Date() übergeben.Beispiele
Zeitstempel der Zertifikats-Statistik auslesen
// pc ist eine bereits verbundene RTCPeerConnection
const logCertificateTimestamps = async (pc) => {
const report = await pc.getStats();
report.forEach((stats) => {
if (stats.type === 'certificate') {
console.log(
`Zertifikat ${stats.fingerprintAlgorithm} erfasst um`,
new Date(stats.timestamp).toISOString()
);
}
});
};
await logCertificateTimestamps(pc);
Vollständige lokale Verbindung mit Zertifikats-Statistik
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);
pc1.createDataChannel('test');
await pc1.setLocalDescription();
await pc2.setRemoteDescription(pc1.localDescription);
await pc2.setLocalDescription();
await pc1.setRemoteDescription(pc2.localDescription);
// Warten, bis DTLS verbunden ist
await new Promise((resolve) => {
pc1.onconnectionstatechange = () =>
pc1.connectionState === 'connected' && resolve();
});
const report = await pc1.getStats();
const certs = [...report.values()].filter((s) => s.type === 'certificate');
certs.forEach(({ id, timestamp }) => console.log(id, timestamp.toFixed(3)));
Veraltete Statistikdaten erkennen
const MAX_AGE_MS = 5000;
const isFresh = (stats) => Date.now() - stats.timestamp < MAX_AGE_MS;
let cachedCert = null;
const getCertificateStats = async (pc) => {
if (cachedCert && isFresh(cachedCert)) return cachedCert;
const report = await pc.getStats();
cachedCert = [...report.values()].find((s) => s.type === 'certificate') ?? null;
return cachedCert;
};
const cert = await getCertificateStats(pc);
console.log(cert ? `Alter: ${Math.round(Date.now() - cert.timestamp)} ms` : 'Kein Zertifikat');
// Wichtig · Fallstricke
- Bezugspunkt: Die Spezifikation legt die UNIX-Epoche fest, nicht
performance.timeOrigin. Ältere Browser-Versionen haben das teilweise anders umgesetzt. Willst du den Wert mitperformance.now()vergleichen, rechne mitperformance.timeOrigin + performance.now(). Prüfe die Plausibilität der Werte am besten einmal im Zielbrowser. - Kein Echtzeitwert: Der Zeitstempel beschreibt den Schnappschuss zum Zeitpunkt von
getStats(). Er ändert sich nicht nachträglich. Für aktuelle Daten musst dugetStats()erneut aufrufen. - Verfügbarkeit: Einträge vom Typ
"certificate"gibt es erst nach dem DTLS-Handshake. Ruft mangetStats()vorher auf, fehlen sie. - Genauigkeit: Aus Datenschutzgründen (Fingerprinting, Timing-Angriffe) können Browser die Auflösung von
DOMHighResTimeStampvergröbern. - Kompatibilität: Chromium-basierte Browser und Safari unterstützen Zertifikats-Statistiken. Firefox liefert sie nicht in allen Versionen. Prüfe deshalb immer, ob ein passender Eintrag vorhanden ist.