Bug 1455724 - add telemetry for legacy PeerConnection getStats API usage
MozReview-Commit-ID: L17M2whvxpV
--- a/dom/media/PeerConnection.js
+++ b/dom/media/PeerConnection.js
@@ -35,16 +35,20 @@ const PC_MANAGER_CID = Components.ID("{7
const PC_STATS_CID = Components.ID("{7fe6e18b-0da3-4056-bf3b-440ef3809e06}");
const PC_STATIC_CID = Components.ID("{0fb47c47-a205-4583-a9fc-cbadf8c95880}");
const PC_SENDER_CID = Components.ID("{4fff5d46-d827-4cd4-a970-8fd53977440e}");
const PC_RECEIVER_CID = Components.ID("{d974b814-8fde-411c-8c45-b86791b81030}");
const PC_TRANSCEIVER_CID = Components.ID("{09475754-103a-41f5-a2d0-e1f27eb0b537}");
const PC_COREQUEST_CID = Components.ID("{74b2122d-65a8-4824-aa9e-3d664cb75dc2}");
const PC_DTMF_SENDER_CID = Components.ID("{3610C242-654E-11E6-8EC0-6D1BE389A607}");
+const TELEMETRY_PC_CONNECTED = "webrtc.peerconnection.connected";
+const TELEMETRY_PC_CALLBACK_GETSTATS = "webrtc.peerconnection.legacy_callback_stats_used";
+const TELEMETRY_PC_PROMISE_GETSTATS = "webrtc.peerconnection.promise_stats_used";
+const TELEMETRY_PC_PROMISE_AND_CALLBACK_GETSTATS = "webrtc.peerconnection.promise_and_callback_stats_used";
function logMsg(msg, file, line, flag, winID) {
let scriptErrorClass = Cc["@mozilla.org/scripterror;1"];
let scriptError = scriptErrorClass.createInstance(Ci.nsIScriptError);
scriptError.initWithWindowID(msg, file, null, line, 0, flag,
"content javascript", winID);
Services.console.logMessage(scriptError);
}
@@ -333,16 +337,42 @@ setupPrototype(RTCStatsReport, {
"inbound-rtp": "inboundrtp",
"outbound-rtp": "outboundrtp",
"candidate-pair": "candidatepair",
"local-candidate": "localcandidate",
"remote-candidate": "remotecandidate"
}
});
+// This is its own class so that it does not need to be exposed to the client.
+class PeerConnectionTelemetry {
+ // Record which style(s) of invocation for getStats are used
+ recordPromiseAndCallbackGetStats(isCallback) {
+ if (!this._hasCallbackStatsBeenUsed && isCallback) {
+ this._hasCallbackStatsBeenUsed = true;
+ Services.telemetry.scalarAdd(TELEMETRY_PC_CALLBACK_GETSTATS, 1);
+ }
+ if (!this._hasPromiseStatsBeenUsed && !isCallback) {
+ this._hasPromiseStatsBeenUsed = true;
+ Services.telemetry.scalarAdd(TELEMETRY_PC_PROMISE_GETSTATS, 1);
+ }
+ if (this._hasCallbackStatsBeenUsed && this._hasPromiseStatsBeenUsed) {
+ Services.telemetry.scalarAdd(
+ TELEMETRY_PC_PROMISE_AND_CALLBACK_GETSTATS, 1);
+ // Everything that can be recorded has been at this point.
+ this.recordPromiseAndCallbackGetStats = () => {};
+ }
+ }
+ // ICE connection state enters connected or completed.
+ recordConnected() {
+ Services.telemetry.scalarAdd(TELEMETRY_PC_CONNECTED, 1);
+ this.recordConnected = () => {};
+ }
+}
+
// Cache for RTPSourceEntries
// Note: each cache is only valid for one JS event loop execution
class RTCRtpSourceCache {
constructor() {
// The time in RTP source time (ms)
this.tsNowInRtpSourceTime = null;
// The time in JS
this.jsTimestamp = null;
@@ -379,16 +409,18 @@ class RTCPeerConnection {
this._iceGatheredRelayCandidates = false;
// Stored webrtc timing information
this._storedRtpSourceReferenceTime = null;
// TODO: Remove legacy API eventually
// see Bug 1328194
this._onGetStatsIsLegacy = false;
// Stores cached RTP sources state
this._rtpSourceCache = new RTCRtpSourceCache();
+ // Records telemetry
+ this._pcTelemetry = new PeerConnectionTelemetry();
}
init(win) {
this._win = win;
}
__init(rtcConfig) {
this._winID = this._win.QueryInterface(Ci.nsIInterfaceRequestor)
@@ -1541,16 +1573,20 @@ class RTCPeerConnection {
this._iceConnectionState = state;
_globalPCList.notifyLifecycleObservers(this, "iceconnectionstatechange");
this.dispatchEvent(new this._win.Event("iceconnectionstatechange"));
}
}
getStats(selector, onSucc, onErr) {
let isLegacy = (typeof onSucc) == "function";
+ if (this._iceConnectionState === "completed" ||
+ this._iceConnectionState === "connected") {
+ this._pcTelemetry.recordPromiseAndCallbackGetStats(isLegacy);
+ }
if (isLegacy &&
this._warnDeprecatedStatsCallbacksNullable.warn) {
this._warnDeprecatedStatsCallbacksNullable.warn();
this._warnDeprecatedStatsCallbacksNullable.warn = null;
}
return this._auto(onSucc, onErr, () => this._getStats(selector, isLegacy));
}
@@ -1746,16 +1782,17 @@ class PeerConnectionObserver {
} else if (iceConnectionState === "failed") {
checking_histogram.add(false);
}
} else if (pc.iceConnectionState === "checking") {
var success_histogram = Services.telemetry.getHistogramById("WEBRTC_ICE_SUCCESS_RATE");
if (iceConnectionState === "completed" ||
iceConnectionState === "connected") {
success_histogram.add(true);
+ pc._pcTelemetry.recordConnected();
} else if (iceConnectionState === "failed") {
success_histogram.add(false);
}
}
if (iceConnectionState === "failed") {
if (!pc._hasStunServer) {
pc.logError("ICE failed, add a STUN server and see about:webrtc for more details");
--- a/toolkit/components/telemetry/Scalars.yaml
+++ b/toolkit/components/telemetry/Scalars.yaml
@@ -616,16 +616,89 @@ preferences:
expires: "62"
kind: boolean
notification_emails:
- yzenevich@mozilla.com
release_channel_collection: opt-out
record_in_processes:
- 'main'
+# The following section contains WebRTC JS API scalars
+# For more information on WebRTC, see https://www.w3.org/TR/webrtc/
+# For more info on ICE, see https://tools.ietf.org/html/rfc5245
+webrtc.peerconnection:
+ connected:
+ bug_numbers:
+ - 1455724
+ description: >
+ The number of RTCPeerConnection objects that established connections.
+ This is incremented the first time a RTCPeerConnection object's
+ iceConnectionState becomes "connected" or "complete".
+ For more information on WebRTC, see https://www.w3.org/TR/webrtc/
+ expires: "65"
+ kind: uint
+ notification_emails:
+ - ngrunbaum@mozilla.com
+ release_channel_collection: opt-in
+ record_in_processes:
+ - 'main'
+ - 'content'
+
+ legacy_callback_stats_used:
+ bug_numbers:
+ - 1455724
+ description: >
+ The number of RTCPeerConnections in which the current statistics
+ API is called. Recorded the first time getStats is called using the
+ deprecated callback based API on a RTCPeerConnection that has an
+ iceConnectionState of "complete" or "connected".
+ expires: "65"
+ kind: uint
+ notification_emails:
+ - ngrunbaum@mozilla.com
+ release_channel_collection: opt-in
+ record_in_processes:
+ - 'main'
+ - 'content'
+
+ promise_stats_used:
+ bug_numbers:
+ - 1455724
+ description: >
+ The number of RTCPeerConnection objects in which the current statistics
+ API is called. This is recorded the first time getStats is called using
+ the promise based API on a RTCPeerConnection that has an
+ iceConnectionState of "complete" or "connected".
+ expires: "65"
+ kind: uint
+ notification_emails:
+ - ngrunbaum@mozilla.com
+ release_channel_collection: opt-in
+ record_in_processes:
+ - 'main'
+ - 'content'
+
+ promise_and_callback_stats_used:
+ bug_numbers:
+ - 1455724
+ description: >
+ The number of RTCPeerConnection objects in which both the legacy callback
+ statistics API and the modern promise statistics API are used. This is
+ recorded once for each RTCPeerConnection after the callback and promise
+ getStats API has been called on a RTCPeerConnection that has an
+ iceConnectionState of "complete" or "connected".
+ expires: "65"
+ kind: uint
+ notification_emails:
+ - ngrunbaum@mozilla.com
+ release_channel_collection: opt-in
+ record_in_processes:
+ - 'main'
+ - 'content'
+
# The following section contains WebRTC nICEr scalars
# For more info on ICE, see https://tools.ietf.org/html/rfc5245
# For more info on STUN, see https://tools.ietf.org/html/rfc5389
# For more info on TURN, see https://tools.ietf.org/html/rfc5766
webrtc.nicer:
stun_retransmits:
bug_numbers:
- 1325536