Signatur
Beschreibung
RTCDataChannelStats ist ein Wörterbuch (Dictionary), keine instanziierbare Klasse. Du bekommst solche Objekte als Einträge des RTCStatsReport, den RTCPeerConnection.getStats() liefert. Einträge mit type === "data-channel" beschreiben jeweils einen RTCDataChannel der Verbindung.
Neben den geerbten RTCStats-Feldern (id, timestamp, type) stehen dir unter anderem label, protocol, dataChannelIdentifier, state sowie die Zähler messagesSent, bytesSent, messagesReceived und bytesReceived zur Verfügung.
Typische Einsatzfälle sind Monitoring und Diagnose: Durchsatz eines Kanals messen, prüfen, ob überhaupt Daten fließen, oder für Dateiübertragungen per DataChannel eine Fortschrittsanzeige und Übertragungsrate berechnen. Weil die Zähler kumulativ sind, ermittelst du Raten, indem du zwei Momentaufnahmen vergleichst und die Differenz durch die Zeitdifferenz von timestamp teilst.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $id Pflicht | string | Eindeutige Kennung dieses Statistik-Objekts innerhalb des Reports (von RTCStats geerbt). |
|
| $timestamp Pflicht | DOMHighResTimeStamp | Zeitpunkt der Erfassung in Millisekunden (geerbt). | |
| $type Pflicht | string | "data-channel" | Immer "data-channel" für dieses Wörterbuch (geerbt). |
| $label | string | Das Label des Kanals, wie bei createDataChannel(label) angegeben. |
|
| $protocol | string | Unterprotokoll des Kanals (Option protocol), oft leer. |
|
| $dataChannelIdentifier | number | SCTP-Stream-ID des Kanals; entspricht RTCDataChannel.id. |
|
| $state Pflicht | "connecting" | "open" | "closing" | "closed" | Aktueller Zustand, entspricht RTCDataChannel.readyState. |
|
| $messagesSent | number | Anzahl gesendeter Nachrichten (API-Ebene, send()-Aufrufe). |
|
| $bytesSent | number | Gesendete Nutzdaten in Bytes (ohne Protokoll-Overhead). | |
| $messagesReceived | number | Anzahl empfangener message-Ereignisse. |
|
| $bytesReceived | number | Empfangene Nutzdaten in Bytes (ohne Protokoll-Overhead). |
Rückgabewert
RTCStatsReport (einer Map-ähnlichen Struktur), erreichbar über await pc.getStats().Beispiele
Alle DataChannel-Statistiken auslesen
const pc = new RTCPeerConnection();
const channel = pc.createDataChannel('chat');
const logDataChannelStats = async () => {
const report = await pc.getStats();
report.forEach((stats) => {
if (stats.type === 'data-channel') {
console.log(`${stats.label} (${stats.state}): ` +
`${stats.messagesSent} Nachrichten / ${stats.bytesSent} Bytes gesendet`);
}
});
};
await logDataChannelStats();
Übertragungsrate eines Kanals 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 measureRate = 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;
const seconds = (after.timestamp - before.timestamp) / 1000;
const kbps = ((after.bytesSent - before.bytesSent) * 8) / 1000 / seconds;
return kbps.toFixed(1);
};
// Annahme: pc ist eine verbundene RTCPeerConnection mit Kanal 'file'
console.log(`Senderate: ${await measureRate(pc, 'file')} kbit/s`);
Statistik-Objekt einem konkreten RTCDataChannel zuordnen
const findStatsFor = async (pc, channel) => {
const report = await pc.getStats();
return [...report.values()].find(
(s) => s.type === 'data-channel' && s.dataChannelIdentifier === channel.id
);
};
channel.addEventListener('open', async () => {
const stats = await findStatsFor(pc, channel);
console.log(stats?.state, stats?.dataChannelIdentifier);
});
// Wichtig · Fallstricke
- Kein Konstruktor:
RTCDataChannelStatsist ein Dictionary; es gibt keinnew RTCDataChannelStats()und kein globales Objekt dieses Namens. - Kein Selektor:
getStats(selector)akzeptiert nur eineMediaStreamTrack. Für DataChannels immer den Gesamtreport abrufen und nachtype === "data-channel"filtern. - Labels sind nicht eindeutig: Mehrere Kanäle können dasselbe Label tragen. Zur sicheren Zuordnung
dataChannelIdentifiermitRTCDataChannel.idvergleichen (die ID ist erst nach der Aushandlung gesetzt, vorher ggf.null). - Kumulative Zähler: Bytes- und Nachrichtenzähler steigen nur an. Raten immer über Differenzen zweier Messungen berechnen und
timestampstatt eigener Uhrzeit verwenden. - Nur Nutzdaten:
bytesSent/bytesReceivedenthalten keinen SCTP-/DTLS-Overhead; für den tatsächlichen NetzwerkverbrauchRTCTransportStatsheranziehen. - Kompatibilität: Alle modernen Browser liefern
data-channel-Einträge, einzelne Felder können aber fehlen (z. B. ältere Firefox- oder Safari-Versionen). Darum vor der Verwendung aufundefinedprüfen. Geschlossene Kanäle können nach einiger Zeit aus dem Report verschwinden. - Performance:
getStats()ist asynchron und nicht kostenlos, also nicht in sehr kurzen Abständen abfragen (üblich sind 1 s oder mehr).