Bug 1135095: add telemetry for window and tab sharing triggers in Loop. r=Standard8,vladan

This commit is contained in:
Mike de Boer 2015-03-24 11:21:20 +01:00
parent ec7fa2a2c2
commit e5bb1dd175
6 changed files with 198 additions and 13 deletions

View File

@ -639,6 +639,13 @@ function injectLoopAPI(targetWindow) {
}
},
SHARING_STATE_CHANGE: {
enumerable: true,
get: function() {
return Cu.cloneInto(SHARING_STATE_CHANGE, targetWindow);
}
},
fxAEnabled: {
enumerable: true,
get: function() {

View File

@ -29,6 +29,19 @@ const TWO_WAY_MEDIA_CONN_LENGTH = {
MORE_THAN_5M: "MORE_THAN_5M",
};
/**
* Buckets that we segment sharing state change telemetry probes into.
*
* @type {{WINDOW_ENABLED: String, WINDOW_DISABLED: String,
* BROWSER_ENABLED: String, BROWSER_DISABLED: String}}
*/
const SHARING_STATE_CHANGE = {
WINDOW_ENABLED: "WINDOW_ENABLED",
WINDOW_DISABLED: "WINDOW_DISABLED",
BROWSER_ENABLED: "BROWSER_ENABLED",
BROWSER_DISABLED: "BROWSER_DISABLED"
};
// See LOG_LEVELS in Console.jsm. Common examples: "All", "Info", "Warn", & "Error".
const PREF_LOG_LEVEL = "loop.debug.loglevel";
@ -42,7 +55,8 @@ Cu.import("resource://gre/modules/FxAccountsOAuthClient.jsm");
Cu.importGlobalProperties(["URL"]);
this.EXPORTED_SYMBOLS = ["MozLoopService", "LOOP_SESSION_TYPE", "TWO_WAY_MEDIA_CONN_LENGTH"];
this.EXPORTED_SYMBOLS = ["MozLoopService", "LOOP_SESSION_TYPE",
"TWO_WAY_MEDIA_CONN_LENGTH", "SHARING_STATE_CHANGE"];
XPCOMUtils.defineLazyModuleGetter(this, "injectLoopAPI",
"resource:///modules/loop/MozLoopAPI.jsm");

View File

@ -165,6 +165,8 @@ loop.OTSdkDriver = (function() {
config);
this.screenshare.on("accessAllowed", this._onScreenShareGranted.bind(this));
this.screenshare.on("accessDenied", this._onScreenShareDenied.bind(this));
this._noteSharingState(options.videoSource, true);
},
/**
@ -196,6 +198,7 @@ loop.OTSdkDriver = (function() {
this.screenshare.off("accessAllowed accessDenied");
this.screenshare.destroy();
delete this.screenshare;
this._noteSharingState(this._windowId ? "browser" : "window", false);
delete this._windowId;
return true;
},
@ -648,15 +651,15 @@ loop.OTSdkDriver = (function() {
* @private
*/
_noteConnectionLength: function(callLengthSeconds) {
var buckets = this.mozLoop.TWO_WAY_MEDIA_CONN_LENGTH;
var bucket = this.mozLoop.TWO_WAY_MEDIA_CONN_LENGTH.SHORTER_THAN_10S;
var bucket = buckets.SHORTER_THAN_10S;
if (callLengthSeconds >= 10 && callLengthSeconds <= 30) {
bucket = this.mozLoop.TWO_WAY_MEDIA_CONN_LENGTH.BETWEEN_10S_AND_30S;
bucket = buckets.BETWEEN_10S_AND_30S;
} else if (callLengthSeconds > 30 && callLengthSeconds <= 300) {
bucket = this.mozLoop.TWO_WAY_MEDIA_CONN_LENGTH.BETWEEN_30S_AND_5M;
bucket = buckets.BETWEEN_30S_AND_5M;
} else if (callLengthSeconds > 300) {
bucket = this.mozLoop.TWO_WAY_MEDIA_CONN_LENGTH.MORE_THAN_5M;
bucket = buckets.MORE_THAN_5M;
}
this.mozLoop.telemetryAddKeyedValue("LOOP_TWO_WAY_MEDIA_CONN_LENGTH",
@ -705,7 +708,32 @@ loop.OTSdkDriver = (function() {
* If set to true, make it easy to test/verify 2-way media connection
* telemetry code operation by viewing the logs.
*/
_debugTwoWayMediaTelemetry: false
_debugTwoWayMediaTelemetry: false,
/**
* Note the sharing state. If this.mozLoop is not defined, we're assumed to
* be running in the standalone client and return immediately.
*
* @param {String} type Type of sharing that was flipped. May be 'window'
* or 'tab'.
* @param {Boolean} enabled Flag that tells us if the feature was flipped on
* or off.
* @private
*/
_noteSharingState: function(type, enabled) {
if (!this.mozLoop) {
return;
}
var bucket = this.mozLoop.SHARING_STATE_CHANGE[type.toUpperCase() + "_" +
(enabled ? "ENABLED" : "DISABLED")];
if (!bucket) {
console.error("No sharing state bucket found for '" + type + "'");
return;
}
this.mozLoop.telemetryAddKeyedValue("LOOP_SHARING_STATE_CHANGE", bucket);
}
};
return OTSdkDriver;

View File

@ -47,3 +47,29 @@ add_task(function* test_mozLoop_telemetryAdd_buckets() {
is(snapshot["BETWEEN_30S_AND_5M"].sum, 3, "TWO_WAY_MEDIA_CONN_LENGTH.BETWEEN_30S_AND_5M");
is(snapshot["MORE_THAN_5M"].sum, 4, "TWO_WAY_MEDIA_CONN_LENGTH.MORE_THAN_5M");
});
add_task(function* test_mozLoop_telemetryAdd_sharing_buckets() {
let histogramId = "LOOP_SHARING_STATE_CHANGE";
let histogram = Services.telemetry.getKeyedHistogramById(histogramId);
const SHARING_STATES = gMozLoopAPI.SHARING_STATE_CHANGE;
histogram.clear();
for (let value of [SHARING_STATES.WINDOW_ENABLED,
SHARING_STATES.WINDOW_DISABLED,
SHARING_STATES.WINDOW_DISABLED,
SHARING_STATES.BROWSER_ENABLED,
SHARING_STATES.BROWSER_ENABLED,
SHARING_STATES.BROWSER_ENABLED,
SHARING_STATES.BROWSER_DISABLED,
SHARING_STATES.BROWSER_DISABLED,
SHARING_STATES.BROWSER_DISABLED,
SHARING_STATES.BROWSER_DISABLED]) {
gMozLoopAPI.telemetryAddKeyedValue(histogramId, value);
}
let snapshot = histogram.snapshot();
Assert.strictEqual(snapshot["WINDOW_ENABLED"].sum, 1, "SHARING_STATE_CHANGE.WINDOW_ENABLED");
Assert.strictEqual(snapshot["WINDOW_DISABLED"].sum, 2, "SHARING_STATE_CHANGE.WINDOW_DISABLED");
Assert.strictEqual(snapshot["BROWSER_ENABLED"].sum, 3, "SHARING_STATE_CHANGE.BROWSER_ENABLED");
Assert.strictEqual(snapshot["BROWSER_DISABLED"].sum, 4, "SHARING_STATE_CHANGE.BROWSER_DISABLED");
});

View File

@ -71,6 +71,12 @@ describe("loop.OTSdkDriver", function () {
BETWEEN_10S_AND_30S: "BETWEEN_10S_AND_30S",
BETWEEN_30S_AND_5M: "BETWEEN_30S_AND_5M",
MORE_THAN_5M: "MORE_THAN_5M"
},
SHARING_STATE_CHANGE: {
WINDOW_ENABLED: "WINDOW_ENABLED",
WINDOW_DISABLED: "WINDOW_DISABLED",
BROWSER_ENABLED: "BROWSER_ENABLED",
BROWSER_DISABLED: "BROWSER_DISABLED"
}
};
@ -189,6 +195,7 @@ describe("loop.OTSdkDriver", function () {
beforeEach(function() {
sandbox.stub(dispatcher, "dispatch");
sandbox.stub(driver, "_noteSharingState");
fakeElement = {
className: "fakeVideo"
@ -214,6 +221,19 @@ describe("loop.OTSdkDriver", function () {
sinon.assert.calledOnce(sdk.initPublisher);
sinon.assert.calledWithMatch(sdk.initPublisher, fakeElement, options);
});
it("should log a telemetry action", function() {
var options = {
videoSource: "browser",
constraints: {
browserWindow: 42,
scrollWithPage: true
}
};
driver.startScreenShare(options);
sinon.assert.calledWithExactly(driver._noteSharingState, "browser", true);
});
});
describe("#switchAcquiredWindow", function() {
@ -251,26 +271,70 @@ describe("loop.OTSdkDriver", function () {
beforeEach(function() {
driver.getScreenShareElementFunc = function() {};
driver.startScreenShare({
videoSource: "window"
});
sandbox.stub(dispatcher, "dispatch");
driver.session = session;
sandbox.stub(driver, "_noteSharingState");
});
it("should unpublish the share", function() {
driver.startScreenShare({
videoSource: "window"
});
driver.session = session;
driver.endScreenShare(new sharedActions.EndScreenShare());
sinon.assert.calledOnce(session.unpublish);
});
it("should log a telemetry action", function() {
driver.startScreenShare({
videoSource: "window"
});
driver.session = session;
driver.endScreenShare(new sharedActions.EndScreenShare());
sinon.assert.calledWithExactly(driver._noteSharingState, "window", false);
});
it("should destroy the share", function() {
driver.startScreenShare({
videoSource: "window"
});
driver.session = session;
expect(driver.endScreenShare()).to.equal(true);
sinon.assert.calledOnce(publisher.destroy);
});
it("should unpublish the share too when type is 'browser'", function() {
driver.startScreenShare({
videoSource: "browser",
constraints: {
browserWindow: 42
}
});
driver.session = session;
driver.endScreenShare(new sharedActions.EndScreenShare());
sinon.assert.calledOnce(session.unpublish);
});
it("should log a telemetry action too when type is 'browser'", function() {
driver.startScreenShare({
videoSource: "browser",
constraints: {
browserWindow: 42
}
});
driver.session = session;
driver.endScreenShare(new sharedActions.EndScreenShare());
sinon.assert.calledWithExactly(driver._noteSharingState, "browser", false);
});
});
describe("#connectSession", function() {
@ -431,6 +495,44 @@ describe("loop.OTSdkDriver", function () {
});
});
describe("#_noteSharingState", function() {
it("should record enabled sharing states for window", function() {
driver._noteSharingState("window", true);
sinon.assert.calledOnce(mozLoop.telemetryAddKeyedValue);
sinon.assert.calledWithExactly(mozLoop.telemetryAddKeyedValue,
"LOOP_SHARING_STATE_CHANGE",
mozLoop.SHARING_STATE_CHANGE.WINDOW_ENABLED);
});
it("should record enabled sharing states for browser", function() {
driver._noteSharingState("browser", true);
sinon.assert.calledOnce(mozLoop.telemetryAddKeyedValue);
sinon.assert.calledWithExactly(mozLoop.telemetryAddKeyedValue,
"LOOP_SHARING_STATE_CHANGE",
mozLoop.SHARING_STATE_CHANGE.BROWSER_ENABLED);
});
it("should record disabled sharing states for window", function() {
driver._noteSharingState("window", false);
sinon.assert.calledOnce(mozLoop.telemetryAddKeyedValue);
sinon.assert.calledWithExactly(mozLoop.telemetryAddKeyedValue,
"LOOP_SHARING_STATE_CHANGE",
mozLoop.SHARING_STATE_CHANGE.WINDOW_DISABLED);
});
it("should record disabled sharing states for browser", function() {
driver._noteSharingState("browser", false);
sinon.assert.calledOnce(mozLoop.telemetryAddKeyedValue);
sinon.assert.calledWithExactly(mozLoop.telemetryAddKeyedValue,
"LOOP_SHARING_STATE_CHANGE",
mozLoop.SHARING_STATE_CHANGE.BROWSER_DISABLED);
});
});
describe("#forceDisconnectAll", function() {
it("should not disconnect anything when not connected", function() {
driver.session = session;

View File

@ -7287,6 +7287,14 @@
"releaseChannelCollection": "opt-out",
"description": "Connection length for bi-directionally connected media"
},
"LOOP_SHARING_STATE_CHANGE": {
"alert_emails": ["firefox-dev@mozilla.org", "mdeboer@mozilla.com"],
"expires_in_version": "43",
"kind": "count",
"keyed": true,
"releaseChannelCollection": "opt-in",
"description": "Number of times the sharing feature has been enabled and disabled"
},
"E10S_AUTOSTART": {
"expires_in_version": "never",
"kind": "boolean",