Bug 1455724 - add telemetry for legacy PeerConnection getStats API usage draft
authorNico Grunbaum
Mon, 23 Apr 2018 09:49:32 -0700
changeset 790034 d83a5859ffe9176ac48feefa198b2ad954a7ca9c
parent 790006 7ef8450810693ab08e79ab0d4702de6f479e678c
push id108404
push userna-g@nostrum.com
push dateTue, 01 May 2018 04:14:10 +0000
bugs1455724
milestone61.0a1
Bug 1455724 - add telemetry for legacy PeerConnection getStats API usage MozReview-Commit-ID: L17M2whvxpV
dom/media/PeerConnection.js
toolkit/components/telemetry/Scalars.yaml
--- 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