feat(metrics): Log `entrypoint` to the metrics.

* Add the FxDesktopRelier that imports `entrypoint` and `context` from the URL.
* Relier extended to import `service`, `redirectTo`, `client_id`, and `state`
* Initialize either the FxDesktopRelier or normal Relier on startup.
* Instead of Metrics importing values directly from the URL, they are fetched from the Relier and passed in on creation.

fixes #1568
This commit is contained in:
Shane Tomlinson 2014-09-10 13:06:59 +01:00
Родитель 559516ed8b
Коммит 9ecf71bb51
11 изменённых файлов: 159 добавлений и 21 удалений

Просмотреть файл

@ -32,7 +32,9 @@ define([
'lib/fxa-client',
'lib/assertion',
'lib/profile',
'models/reliers/relier'
'lib/constants',
'models/reliers/relier',
'models/reliers/fx-desktop'
],
function (
_,
@ -49,7 +51,9 @@ function (
FxaClient,
Assertion,
Profile,
Relier
Constants,
Relier,
FxDesktopRelier
) {
function isMetricsCollectionEnabled (sampleRate) {
@ -91,10 +95,13 @@ function (
.then(_.bind(this.useConfig, this))
// both the metrics and router depend on the language
// fetched from config.
.then(_.bind(this.initializeMetrics, this))
.then(_.bind(this.initializeRelier, this))
// fxaClient depends on the relier.
.then(_.bind(this.initializeFxaClient, this))
// profileClient dependsd on fxaClient.
.then(_.bind(this.initializeProfileClient, this))
// metrics depends on the relier.
.then(_.bind(this.initializeMetrics, this))
// router depends on all of the above
.then(_.bind(this.initializeRouter, this));
},
@ -112,14 +119,32 @@ function (
initializeMetrics: function () {
this._metrics = createMetrics(this._config.metricsSampleRate, {
lang: this._config.language
lang: this._config.language,
service: this._relier.get('service'),
context: this._relier.get('context'),
entrypoint: this._relier.get('entrypoint')
});
this._metrics.init();
},
initializeRelier: function () {
this._relier = new Relier();
return this._relier.fetch();
if (! this._relier) {
if (this._isFxDesktop()) {
this._relier = new FxDesktopRelier({
window: this._window
});
} else {
this._relier = new Relier({
window: this._window
});
}
return this._relier.fetch();
}
},
_isFxDesktop: function () {
return this._searchParam('context') === Constants.FX_DESKTOP_CONTEXT;
},
initializeFxaClient: function () {

Просмотреть файл

@ -37,6 +37,7 @@ define([
'timers',
'events',
'context',
'entrypoint',
'service',
'lang',
'marketingLink',
@ -65,10 +66,9 @@ define([
this._window = options.window || window;
this._lang = options.lang || 'unknown';
var searchParams = this._window.location.search;
this._context = Url.searchParam('context', searchParams) || 'web';
this._service = Url.searchParam('service', searchParams) || 'none';
this._context = options.context || 'web';
this._entrypoint = options.entrypoint || 'none';
this._service = options.service || 'none';
this._inactivityFlushMs = options.inactivityFlushMs || TEN_MINS_MS;
}
@ -136,6 +136,7 @@ define([
context: this._context,
service: this._service,
lang: this._lang,
entrypoint: this._entrypoint,
marketingType: this._marketingType || 'none',
marketingLink: this._marketingLink || 'none',
marketingClicked: this._marketingClicked || false

Просмотреть файл

@ -0,0 +1,38 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/**
* The FxDesktop for Sync relier. In addition to the fields available on
* `Relier`, provides the following:
*
* - context
* - entrypoint
*/
'use strict';
define([
'backbone',
'underscore',
'models/reliers/relier'
], function (Backbone, _, Relier) {
var FxDesktopRelier = Relier.extend({
defaults: _.extend({
context: null,
entrypoint: null
}, Relier.prototype.defaults),
fetch: function () {
var self = this;
return Relier.prototype.fetch.call(self)
.then(function () {
self.importSearchParam('context');
self.importSearchParam('entrypoint');
});
}
});
return FxDesktopRelier;
});

Просмотреть файл

@ -39,15 +39,23 @@ define([
* });
* }
*/
fetch: function (options) {
fetch: function () {
var self = this;
return p()
.then(function () {
self._setFromSearchParam('preVerifyToken');
self.importSearchParam('preVerifyToken');
});
},
_setFromSearchParam: function (paramName, modelName) {
/**
* Set a value based on a value in window.location.search. Only updates
* model if parameter exists in window.location.search.
*
* @param {String} paramName - name of the search parameter
* @param {String} [modelName] - name to set in model. If not specified,
* use the same value as `paramName`
*/
importSearchParam: function (paramName, modelName) {
modelName = modelName || paramName;
var value = Url.searchParam(paramName, this._window.location.search);

Просмотреть файл

@ -109,6 +109,17 @@ define([
return isEventLogged(metrics, eventName);
}
function toSearchString(obj) {
var searchString = '?';
var pairs = [];
for (var key in obj) {
pairs.push(key + '=' + encodeURIComponent(obj[key]));
}
return searchString + pairs.join('&');
}
return {
requiresFocus: requiresFocus,
addFxaClientSpy: addFxaClientSpy,
@ -119,6 +130,7 @@ define([
emailToUser: emailToUser,
isEventLogged: isEventLogged,
isErrorLogged: isErrorLogged,
isScreenLogged: isScreenLogged
isScreenLogged: isScreenLogged,
toSearchString: toSearchString
};
});

Просмотреть файл

@ -24,10 +24,12 @@ function (chai, $, Metrics, AuthErrors, WindowMock, TestHelpers) {
beforeEach(function () {
windowMock = new WindowMock();
windowMock.location.search = '?service=sync&context=fxa_desktop_v1';
metrics = new Metrics({
window: windowMock,
lang: 'db_LB'
lang: 'db_LB',
service: 'sync',
context: 'fxa_desktop_v1',
entrypoint: 'menupanel'
});
metrics.init();
});
@ -57,6 +59,7 @@ function (chai, $, Metrics, AuthErrors, WindowMock, TestHelpers) {
assert.isTrue(filteredData.hasOwnProperty('context'));
assert.isTrue(filteredData.hasOwnProperty('service'));
assert.isTrue(filteredData.hasOwnProperty('lang'));
assert.isTrue(filteredData.hasOwnProperty('entrypoint'));
assert.equal(filteredData.screen.width, window.screen.width);
assert.equal(filteredData.screen.height, window.screen.height);
});

Просмотреть файл

@ -0,0 +1,42 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
'use strict';
define([
'chai',
'models/reliers/fx-desktop',
'../../../mocks/window',
'../../../lib/helpers'
], function (chai, Relier, WindowMock, TestHelpers) {
var assert = chai.assert;
describe('reliers/reliers/fx-desktop', function () {
describe('fetch', function () {
var relier, windowMock;
beforeEach(function () {
windowMock = new WindowMock();
relier = new Relier({
window: windowMock
});
});
it('populates context & entrypoint from the search parameters', function () {
windowMock.location.search = TestHelpers.toSearchString({
context: 'fx_desktop_v1',
entrypoint: 'menupanel'
});
return relier.fetch()
.then(function () {
assert.equal(relier.get('context'), 'fx_desktop_v1');
assert.equal(relier.get('entrypoint'), 'menupanel');
});
});
});
});
});

Просмотреть файл

@ -7,8 +7,9 @@
define([
'chai',
'models/reliers/relier',
'../../../mocks/window'
], function (chai, Relier, WindowMock) {
'../../../mocks/window',
'../../../lib/helpers'
], function (chai, Relier, WindowMock, TestHelpers) {
var assert = chai.assert;
describe('reliers/reliers/relier', function () {
@ -23,12 +24,16 @@ define([
});
});
it('populates the preVerifyToken from the search parameters', function () {
windowMock.location.search = '?preVerifyToken=abigtoken';
it('populates expected fields from the search parameters, unexpected search parameters are ignored', function () {
windowMock.location.search = TestHelpers.toSearchString({
preVerifyToken: 'abigtoken',
ignored: 'ignored'
});
return relier.fetch()
.then(function () {
assert.equal(relier.get('preVerifyToken'), 'abigtoken');
assert.isUndefined(relier.get('ignored'));
});
});
});

Просмотреть файл

@ -68,7 +68,8 @@ function (Translator, Session, FxaClientWrapper) {
'../tests/spec/views/mixins/floating-placeholder-mixin',
'../tests/spec/views/mixins/timer-mixin',
'../tests/spec/views/mixins/service-mixin',
'../tests/spec/models/reliers/relier'
'../tests/spec/models/reliers/relier',
'../tests/spec/models/reliers/fx-desktop'
];
/*global mocha */

Просмотреть файл

@ -100,6 +100,7 @@ function toLoggableEvent(event) {
'agent',
'duration',
'context',
'entrypoint',
'service',
'marketingLink',
'marketingType',

Просмотреть файл

@ -65,6 +65,7 @@ define([
assert.equal(loggedMetrics['screen.width'], 1680);
assert.equal(loggedMetrics['screen.height'], 1050);
assert.equal(loggedMetrics.entrypoint, 'menupanel');
});
metricsCollector.write({
@ -87,6 +88,7 @@ define([
lang: 'db_LB',
service: 'sync',
context: 'fx_desktop_v1',
entrypoint: 'menupanel',
marketingType: 'survey',
marketingLink: 'http://mzl.la/1oV7jUy',
marketingClicked: false,