Skip to content
Permalink
Browse files

feat(metrics): pass selected sync engines to amplitude

  • Loading branch information...
philbooth committed Jun 4, 2019
1 parent b08178e commit 6c8c051847e4845c6614619a04ee653f6f4cf26c
@@ -56,6 +56,7 @@ const ALLOWED_FIELDS = [
'referrer',
'screen',
'service',
'syncEngines',
'startTime',
'timers',
'uid',
@@ -149,6 +150,7 @@ function Metrics (options = {}) {
// if navigationTiming is supported, the baseTime will be from
// navigationTiming.navigationStart, otherwise Date.now().
this._startTime = options.startTime || this._speedTrap.baseTime;
this._syncEngines = options.syncEngines || [];
this._uid = options.uid || NOT_REPORTED_VALUE;
this._uniqueUserId = options.uniqueUserId || NOT_REPORTED_VALUE;
this._utmCampaign = options.utmCampaign || NOT_REPORTED_VALUE;
@@ -188,6 +190,7 @@ _.extend(Metrics.prototype, Backbone.Events, {
'flow.initialize': '_initializeFlowModel',
'flow.event': '_logFlowEvent',
'set-email-domain': '_setEmailDomain',
'set-sync-engines': '_setSyncEngines',
'set-uid': '_setUid',
'clear-uid': '_clearUid',
'once!view-shown': '_setInitialView'
@@ -376,6 +379,7 @@ _.extend(Metrics.prototype, Backbone.Events, {
},
service: this._service,
startTime: this._startTime,
syncEngines: this._syncEngines,
uid: this._uid,
uniqueUserId: this._uniqueUserId,
utm_campaign: this._utmCampaign, //eslint-disable-line camelcase
@@ -693,6 +697,12 @@ _.extend(Metrics.prototype, Backbone.Events, {
}
},

_setSyncEngines (engines) {
if (engines) {
this._syncEngines = engines;
}
},

_setUid (uid) {
if (uid) {
this._uid = uid;
@@ -92,7 +92,10 @@ const View = FormView.extend({
});

return this.user.setAccount(account)
.then(this.onSubmitComplete);
.then(account => {
this.notifier.trigger('set-sync-engines', offeredSyncEngines);
return this.onSubmitComplete(account);
});
},

/**
@@ -73,11 +73,12 @@ describe('lib/metrics', function () {
});

it('has the expected notifications', () => {
assert.lengthOf(Object.keys(metrics.notifications), 6);
assert.lengthOf(Object.keys(metrics.notifications), 7);

assert.isTrue('flow.initialize' in metrics.notifications);
assert.isTrue('flow.event' in metrics.notifications);
assert.isTrue('set-email-domain' in metrics.notifications);
assert.isTrue('set-sync-engines' in metrics.notifications);
assert.isTrue('set-uid' in metrics.notifications);
assert.isTrue('clear-uid' in metrics.notifications);
assert.isTrue('once!view-shown' in metrics.notifications);
@@ -207,6 +208,7 @@ describe('lib/metrics', function () {
assert.equal(filteredData.screen.devicePixelRatio, 2);
assert.equal(filteredData.screen.clientWidth, 1033);
assert.equal(filteredData.screen.clientHeight, 966);
assert.deepEqual(filteredData.syncEngines, []);

assert.isTrue(filteredData.isSampledUser);

@@ -336,7 +338,7 @@ describe('lib/metrics', function () {
assert.equal(windowMock.navigator.sendBeacon.getCall(0).args[0], '/metrics');

var data = JSON.parse(windowMock.navigator.sendBeacon.getCall(0).args[1]);
assert.lengthOf(Object.keys(data), 32);
assert.lengthOf(Object.keys(data), 33);
assert.equal(data.broker, 'none');
assert.equal(data.context, Constants.CONTENT_SERVER_CONTEXT);
assert.match(data.deviceId, /^[0-9a-f]{32}$/);
@@ -365,6 +367,7 @@ describe('lib/metrics', function () {
assert.isObject(data.screen);
assert.equal(data.service, 'none');
assert.isDefined(data.startTime);
assert.deepEqual(data.syncEngines, []);
assert.isDefined(data.flushTime);
assert.isObject(data.timers);
assert.lengthOf(Object.keys(data.timers), 0);
@@ -429,6 +432,19 @@ describe('lib/metrics', function () {
});
});

describe('sendBeacon after set-sync-engines', () => {
beforeEach(() => {
notifier.trigger('set-sync-engines', [ 'foo', 'bar' ]);
sandbox.spy(windowMock.navigator, 'sendBeacon');
return metrics.flush();
});

it('set syncEngines correctly', () => {
const data = JSON.parse(windowMock.navigator.sendBeacon.args[0][1]);
assert.deepEqual(data.syncEngines, [ 'foo', 'bar' ]);
});
});

describe('emit clear-uid then flush', () => {
beforeEach(() => {
sandbox.stub(windowMock.navigator, 'sendBeacon').callsFake(() => true);
@@ -511,7 +527,7 @@ describe('lib/metrics', function () {
assert.equal(settings.contentType, 'application/json');

var data = JSON.parse(settings.data);
assert.lengthOf(Object.keys(data), 31);
assert.lengthOf(Object.keys(data), 32);
assert.match(data.deviceId, /^[0-9a-f]{32}$/);
assert.isArray(data.events);
assert.lengthOf(data.events, 5);
@@ -591,7 +607,7 @@ describe('lib/metrics', function () {
assert.isTrue(metrics._send.getCall(0).args[1]);

var data = metrics._send.getCall(0).args[0];
assert.lengthOf(Object.keys(data), 31);
assert.lengthOf(Object.keys(data), 32);
assert.lengthOf(data.events, 5);
assert.equal(data.events[0].type, 'foo');
assert.equal(data.events[1].type, 'flow.bar');
@@ -616,7 +632,7 @@ describe('lib/metrics', function () {
assert.isTrue(metrics._send.getCall(0).args[1]);

var data = metrics._send.getCall(0).args[0];
assert.lengthOf(Object.keys(data), 31);
assert.lengthOf(Object.keys(data), 32);
assert.lengthOf(data.events, 5);
assert.equal(data.events[0].type, 'foo');
assert.equal(data.events[1].type, 'flow.bar');
@@ -248,6 +248,7 @@ describe('views/choose_what_to_sync', () => {
describe('submit', () => {
beforeEach(() => {
sinon.stub(user, 'setAccount').callsFake(() => Promise.resolve(account));
sinon.spy(notifier, 'trigger');
});

it('updates and saves the account, logs metrics, calls onSubmitComplete', () => {
@@ -266,6 +267,11 @@ describe('views/choose_what_to_sync', () => {

assert.isTrue(user.setAccount.calledWith(account));

assert.equal(notifier.trigger.callCount, 2);
const args = notifier.trigger.args[1];
assert.equal(args[0], 'set-sync-engines');
assert.deepEqual(args[1], DISPLAYED_ENGINE_IDS);

assert.isTrue(view.onSubmitComplete.calledOnce);
assert.instanceOf(view.onSubmitComplete.args[0][0], Account);

Some generated files are not rendered by default. Learn more.

@@ -63,7 +63,7 @@
"fxa-js-client": "1.0.12",
"fxa-mustache-loader": "0.0.2",
"fxa-pairing-channel": "1.0.1",
"fxa-shared": "1.0.24",
"fxa-shared": "1.0.26",
"got": "6.7.1",
"grunt": "1.0.4",
"grunt-babel": "6.0.0",
@@ -37,6 +37,7 @@ const {
OFFSET: OFFSET_TYPE,
REFERRER: REFERRER_TYPE,
STRING: STRING_TYPE,
SYNC_ENGINES: SYNC_ENGINES_TYPE,
TIME: TIME_TYPE,
URL: URL_TYPE,
UTM: UTM_TYPE,
@@ -111,6 +112,7 @@ const BODY_SCHEMA = {
}).required(),
service: STRING_TYPE.regex(SERVICE_PATTERN).required(),
startTime: TIME_TYPE.required(),
syncEngines: SYNC_ENGINES_TYPE.optional(),
timers: joi.object().optional(), // this is never consumed.
uid: HEX32_TYPE.allow('none').required(),
uniqueUserId: STRING_TYPE.regex(UNIQUE_USER_ID_PATTERN).allow('none').required(),
@@ -24,6 +24,7 @@ const PATTERNS = {
FORM_TYPE: /^(email|other)$/,
MIGRATION: /^(sync11|amo|none)$/,
SERVICE: /^(sync|content-server|none|[0-9a-f]{16})$/,
SYNC_ENGINE: /^[a-z]+$/,
UNIQUE_USER_ID: /^[0-9a-z-]{36}$/
};

@@ -42,6 +43,7 @@ const TYPES = {
RESUME: joi.string().regex(PATTERNS.BASE64),
SIGNIN_CODE: joi.string().regex(PATTERNS.BASE64_URL_SAFE).length(8),
STRING: joi.string().max(1024), // 1024 is arbitrary, seems like it should give CSP reports plenty of space.
SYNC_ENGINES: joi.array().items(joi.string().regex(PATTERNS.SYNC_ENGINE)),
TIME: joi.number().integer().min(0),
URL: joi.string().max(2048).uri({ scheme: [ 'http', 'https' ]}), // 2048 is also arbitrary, the same limit we use on the front end.
UTM: joi.string().max(128).regex(/^[\w\/.%-]+$/) // values here can be 'firefox/sync'
@@ -392,6 +392,7 @@ registerSuite('amplitude', {

assert.equal(logger.info.callCount, 1);
assert.equal(logger.info.args[0][1].event_type, 'fxa_reg - cwts_engage');
assert.isUndefined(logger.info.args[0][1].user_properties.sync_engines);
},

'flow.enter-email.engage': () => {
@@ -652,6 +653,7 @@ registerSuite('amplitude', {
assert.equal(logger.info.callCount, 1);
const arg = logger.info.args[0][1];
assert.equal(arg.event_type, 'fxa_reg - cwts_back');
assert.isUndefined(logger.info.args[0][1].user_properties.sync_engines);
},

'flow.signin.forgot-password': () => {
@@ -704,11 +706,13 @@ registerSuite('amplitude', {
}, {
flowBeginTime: 'b',
flowId: 'c',
syncEngines: [ 'wibble', 'blee' ],
uid: 'd'
});

assert.equal(logger.info.callCount, 1);
assert.equal(logger.info.args[0][1].event_type, 'fxa_reg - cwts_submit');
assert.deepEqual(logger.info.args[0][1].user_properties.sync_engines, [ 'wibble', 'blee' ]);
},

'flow.enter-email.submit': () => {
@@ -862,6 +866,7 @@ registerSuite('amplitude', {

assert.equal(logger.info.callCount, 1);
assert.equal(logger.info.args[0][1].event_type, 'fxa_reg - cwts_view');
assert.isUndefined(logger.info.args[0][1].user_properties.sync_engines);
},

'screen.enter-email': () => {
@@ -138,6 +138,7 @@ registerSuite('routes/post-metrics', {
],
isSampledUser: true,
startTime: 10,
syncEngines: [ 'foo', 'bar' ],
flushTime: 20
},
userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:47.0) Gecko/20100101 Firefox/47.0'
@@ -191,7 +192,8 @@ registerSuite('routes/post-metrics', {
],
flushTime: 20,
isSampledUser: true,
startTime: 10
startTime: 10,
syncEngines: [ 'foo', 'bar' ],
});
},

0 comments on commit 6c8c051

Please sign in to comment.
You can’t perform that action at this time.