feat(metrics): metrics flow for iframeless flow #6227
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,18 +21,23 @@ define(function (require, exports, module) { | |
var flow; | ||
var sentryMetricsMock; | ||
var windowMock; | ||
var metricsMock; | ||
|
||
beforeEach(function () { | ||
sentryMetricsMock = { | ||
captureException: sinon.spy() | ||
}; | ||
metricsMock = { | ||
markEventLogged: sinon.spy() | ||
}; | ||
windowMock = new WindowMock(); | ||
$(windowMock.document.body).removeData('flowId').removeAttr('data-flow-id'); | ||
$(windowMock.document.body).removeData('flowBegin').removeAttr('data-flow-begin'); | ||
}); | ||
|
||
function createFlow () { | ||
flow = new Flow({ | ||
metrics: metricsMock, | ||
sentryMetrics: sentryMetricsMock, | ||
window: windowMock | ||
}); | ||
|
@@ -76,6 +81,27 @@ define(function (require, exports, module) { | |
assert.equal(flow.get('flowBegin'), 42); | ||
}); | ||
|
||
it('fetches from query parameters, if available', function () { | ||
$(windowMock.document.body).attr('data-flow-id', BODY_FLOW_ID); | ||
$(windowMock.document.body).attr('data-flow-begin', '42'); | ||
|
||
const QUERY_FLOW_BEGIN = '55'; | ||
const QUERY_FLOW_ID = 'A1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF103'; | ||
|
||
windowMock.location.search = Url.objToSearchString({ | ||
/*eslint-disable camelcase*/ | ||
flow_begin_time: QUERY_FLOW_BEGIN, | ||
flow_id: QUERY_FLOW_ID | ||
/*eslint-enable camelcase*/ | ||
}); | ||
|
||
createFlow(); | ||
|
||
assert.equal(flow.get('flowId'), QUERY_FLOW_ID); | ||
assert.equal(flow.get('flowBegin'), QUERY_FLOW_BEGIN); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't this test also assert that |
||
assert.ok(metricsMock.markEventLogged.calledOnce); | ||
}); | ||
|
||
it('logs an error when the resume token contains `flowId` but not `flowBegin`', function () { | ||
windowMock.location.search = Url.objToSearchString({ | ||
resume: ResumeToken.stringify({ flowId: RESUME_FLOW_ID }) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
/* 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'; | ||
|
||
const flowMetrics = require('../flow-metrics'); | ||
const logFlowEvent = require('../flow-event').logFlowEvent; | ||
const logger = require('../logging/log')('server.get-metrics-flow'); | ||
|
||
module.exports = function (config) { | ||
const FLOW_ID_KEY = config.get('flow_id_key'); | ||
const FLOW_EVENT_NAME = 'flow.begin'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @philbooth what flow event name should we use here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We'll also need to remove Any places that were mixing it in can mix in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hmmm, We cannot just remove flow-begin from client-side because there are still iframe versions of the flow. So we either not record a begin if there was a query flow sent or some other solution There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh good point, lol. Yeah, maybe add some condition to the begin mixin so it doesn't emit the event if the query params are set? |
||
const ALLOWED_CORS_ORIGINS = config.get('allowed_metrics_flow_cors_origins'); | ||
const CORS_OPTIONS = { | ||
methods: 'GET', | ||
origin: function corsOrigin(origin, callback) { | ||
if (ALLOWED_CORS_ORIGINS.includes(origin)) { | ||
callback(null, true); | ||
} else { | ||
logger.info('request.metrics-flow.bad-origin', origin); | ||
callback(new Error('CORS Error')); | ||
} | ||
}, | ||
preflightContinue: false | ||
}; | ||
|
||
const route = {}; | ||
route.method = 'get'; | ||
route.path = '/metrics-flow'; | ||
route.cors = CORS_OPTIONS; | ||
|
||
route.process = function (req, res) { | ||
const flowEventData = flowMetrics.create(FLOW_ID_KEY, req.headers['user-agent']); | ||
const flowBeingTime = flowEventData.flowBeginTime; | ||
const flowId = flowEventData.flowId; | ||
const metricsData = req.query || {}; | ||
|
||
metricsData.flowId = flowId; | ||
|
||
logFlowEvent({ | ||
flowTime: flowBeingTime, | ||
time: flowBeingTime, | ||
type: FLOW_EVENT_NAME | ||
}, metricsData, req); | ||
|
||
// charset must be set on json responses. | ||
res.charset = 'utf-8'; | ||
res.json({ | ||
flowBeginTime: flowEventData.flowBeginTime, | ||
flowId: flowId | ||
}); | ||
}; | ||
|
||
return route; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should flow_begin_time and flow_id be checked for validity? The schema below is even used when populating from the data attributes.