fix(server): remove redundant metrics context fields
This commit is contained in:
Родитель
ed9ec79565
Коммит
f027f0bda5
|
@ -85,10 +85,7 @@ There are also further flow events
|
|||
that do not correspond to an activity event.
|
||||
In addition to the data that is present on activity events,
|
||||
these events also have a metrics context
|
||||
that includes the `utm_*` parameters and a `flowId`.
|
||||
The flow events respect the `dnt` "Do not track"
|
||||
header and do not send `utm_*` parameters
|
||||
if that header is set to `1`.
|
||||
that includes `flowId` and `flowBeginTime` properties.
|
||||
|
||||
#### Flow event structure
|
||||
|
||||
|
@ -100,15 +97,6 @@ containg the following fields:
|
|||
* `flow_time`
|
||||
* `time`
|
||||
* `userAgent`
|
||||
* `context` (optional)
|
||||
* `entrypoint` (optional)
|
||||
* `migration` (optional)
|
||||
* `service` (optional)
|
||||
* `utm_campaign` (optional)
|
||||
* `utm_content` (optional)
|
||||
* `utm_medium` (optional)
|
||||
* `utm_source` (optional)
|
||||
* `utm_term` (optional)
|
||||
|
||||
##### Example event
|
||||
|
||||
|
@ -118,11 +106,7 @@ containg the following fields:
|
|||
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:50.0) Gecko/20100101 Firefox/50.0",
|
||||
"time": 1471258615891,
|
||||
"flow_id": "1386176a76f4359d30aea806400ebbf8af1fb0040891ff32cd0d5cc5038f6d58",
|
||||
"flow_time": 11948,
|
||||
"uid": "d03249d2af7d4447be3debc674110978",
|
||||
"context": "fx_desktop_v3",
|
||||
"entrypoint": "menupanel",
|
||||
"service": "sync"
|
||||
"flow_time": 11948
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
@ -18,16 +18,7 @@ const FLOW_ID_LENGTH = 64
|
|||
|
||||
const SCHEMA = isA.object({
|
||||
flowId: isA.string().length(64).regex(HEX).optional(),
|
||||
flowBeginTime: isA.number().integer().positive().optional(),
|
||||
context: isA.string().optional(),
|
||||
entrypoint: isA.string().optional(),
|
||||
migration: isA.string().optional(),
|
||||
service: isA.string().optional(),
|
||||
utmCampaign: isA.string().optional(),
|
||||
utmContent: isA.string().optional(),
|
||||
utmMedium: isA.string().optional(),
|
||||
utmSource: isA.string().optional(),
|
||||
utmTerm: isA.string().optional()
|
||||
flowBeginTime: isA.number().integer().positive().optional()
|
||||
}).and('flowId', 'flowBeginTime').optional()
|
||||
|
||||
const NOP = function () {
|
||||
|
@ -40,14 +31,6 @@ const NULL_MEMCACHED = {
|
|||
setAsync: NOP
|
||||
}
|
||||
|
||||
const VALID_PROPERTIES = [
|
||||
{ key: 'context', pattern: /^[0-9a-z_-]+$/ },
|
||||
{ key: 'entrypoint', pattern: /^[\w\.-]+$/ },
|
||||
{ key: 'flowId', pattern: /^[0-9a-f]{64}$/ },
|
||||
{ key: 'migration', pattern: /^(sync11|amo)$/ },
|
||||
{ key: 'service', pattern: /^(sync|content-server|[0-9a-f]{16})$/ }
|
||||
]
|
||||
|
||||
module.exports = function (log, config) {
|
||||
let _memcached
|
||||
|
||||
|
@ -122,7 +105,6 @@ module.exports = function (log, config) {
|
|||
*/
|
||||
function gather (data) {
|
||||
const metadata = this.payload && this.payload.metricsContext
|
||||
const doNotTrack = this.headers && this.headers.dnt === '1'
|
||||
let token
|
||||
|
||||
return P.resolve()
|
||||
|
@ -141,18 +123,6 @@ module.exports = function (log, config) {
|
|||
data.flow_id = metadata.flowId
|
||||
data.flow_time = calculateFlowTime(data.time, metadata.flowBeginTime)
|
||||
data.flowCompleteSignal = metadata.flowCompleteSignal
|
||||
data.context = metadata.context
|
||||
data.entrypoint = metadata.entrypoint
|
||||
data.migration = metadata.migration
|
||||
data.service = metadata.service
|
||||
|
||||
if (! doNotTrack) {
|
||||
data.utm_campaign = metadata.utmCampaign
|
||||
data.utm_content = metadata.utmContent
|
||||
data.utm_medium = metadata.utmMedium
|
||||
data.utm_source = metadata.utmSource
|
||||
data.utm_term = metadata.utmTerm
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(err => log.error({
|
||||
|
@ -225,10 +195,6 @@ module.exports = function (log, config) {
|
|||
return logInvalidContext(this, 'expired flowBeginTime')
|
||||
}
|
||||
|
||||
if (! isValidData(metadata)) {
|
||||
return logInvalidContext(this, 'invalid data')
|
||||
}
|
||||
|
||||
// The first half of the id is random bytes, the second half is a HMAC of
|
||||
// additional contextual information about the request. It's a simple way
|
||||
// to check that the metrics came from the right place, without having to
|
||||
|
@ -314,16 +280,5 @@ function calculateFlowTime (time, flowBeginTime) {
|
|||
return time - flowBeginTime
|
||||
}
|
||||
|
||||
function isValidData (data) {
|
||||
return VALID_PROPERTIES.every(p => {
|
||||
const property = data[p.key]
|
||||
if (property) {
|
||||
return p.pattern.test(property)
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
module.exports.schema = SCHEMA
|
||||
|
||||
|
|
|
@ -102,13 +102,6 @@ module.exports = config => {
|
|||
ClientApi.prototype.accountCreate = function (email, authPW, options) {
|
||||
options = options || {}
|
||||
|
||||
// Default to desktop client context
|
||||
if (!options.metricsContext) {
|
||||
options.metricsContext = {
|
||||
context: 'fx_desktop_v3'
|
||||
}
|
||||
}
|
||||
|
||||
var url = this.baseURL + '/account/create' + getQueryString(options)
|
||||
return this.doRequest(
|
||||
'POST',
|
||||
|
@ -136,13 +129,6 @@ module.exports = config => {
|
|||
opts = { keys: true }
|
||||
}
|
||||
|
||||
// Default to desktop client context
|
||||
if (!opts.metricsContext) {
|
||||
opts.metricsContext = {
|
||||
context: 'fx_desktop_v3'
|
||||
}
|
||||
}
|
||||
|
||||
return this.doRequest(
|
||||
'POST',
|
||||
this.baseURL + '/account/login' + getQueryString(opts),
|
||||
|
|
|
@ -251,9 +251,7 @@ describe('/recovery_email/resend_code', () => {
|
|||
payload: {
|
||||
metricsContext: {
|
||||
flowBeginTime: Date.now(),
|
||||
flowId: 'F1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF103',
|
||||
entrypoint: 'preferences',
|
||||
utmContent: 'some-content-string'
|
||||
flowId: 'F1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF103'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -279,9 +277,7 @@ describe('/recovery_email/resend_code', () => {
|
|||
payload: {
|
||||
metricsContext: {
|
||||
flowBeginTime: Date.now(),
|
||||
flowId: 'F1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF103',
|
||||
entrypoint: 'preferences',
|
||||
utmContent: 'some-content-string'
|
||||
flowId: 'F1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF103'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -730,9 +726,7 @@ describe('/account/create', function () {
|
|||
service: 'sync',
|
||||
metricsContext: {
|
||||
flowBeginTime: Date.now(),
|
||||
flowId: 'F1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF103',
|
||||
entrypoint: 'preferences',
|
||||
utmContent: 'some-content-string'
|
||||
flowId: 'F1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF103'
|
||||
}
|
||||
},
|
||||
query: {
|
||||
|
@ -880,11 +874,8 @@ describe('/account/login', function () {
|
|||
service: 'sync',
|
||||
reason: 'signin',
|
||||
metricsContext: {
|
||||
context: 'fx_desktop_v3',
|
||||
flowBeginTime: Date.now(),
|
||||
flowId: 'F1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF103',
|
||||
entrypoint: 'preferences',
|
||||
utmContent: 'some-content-string'
|
||||
flowId: 'F1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF103'
|
||||
}
|
||||
},
|
||||
query: {
|
||||
|
@ -1774,11 +1765,8 @@ describe('/account/login/send_unblock_code', function () {
|
|||
payload: {
|
||||
email: TEST_EMAIL,
|
||||
metricsContext: {
|
||||
context: 'fx_desktop_v3',
|
||||
flowBeginTime: Date.now(),
|
||||
flowId: 'F1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF103',
|
||||
entrypoint: 'preferences',
|
||||
utmContent: 'some-content-string'
|
||||
flowId: 'F1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF103'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
@ -116,11 +116,8 @@ const mockRequest = mocks.mockRequest({
|
|||
service: 'sync',
|
||||
reason: 'signin',
|
||||
metricsContext: {
|
||||
context: 'fx_desktop_v3',
|
||||
flowBeginTime: Date.now(),
|
||||
flowId: 'F1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF103',
|
||||
entrypoint: 'preferences',
|
||||
utmContent: 'some-content-string'
|
||||
flowId: 'F1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF103'
|
||||
}
|
||||
},
|
||||
query: {
|
||||
|
|
|
@ -205,21 +205,12 @@ describe('metricsConext', () => {
|
|||
}, {}).then(function (result) {
|
||||
assert.equal(typeof result, 'object', 'result is object')
|
||||
assert.notEqual(result, null, 'result is not null')
|
||||
assert.equal(Object.keys(result).length, 13, 'result has 13 properties')
|
||||
assert.equal(Object.keys(result).length, 4, 'result has 4 properties')
|
||||
assert.ok(result.time > time, 'result.time seems correct')
|
||||
assert.equal(result.flow_id, 'mock flow id', 'result.flow_id is correct')
|
||||
assert.ok(result.flow_time > 0, 'result.flow_time is greater than zero')
|
||||
assert.ok(result.flow_time < time, 'result.flow_time is less than the current time')
|
||||
assert.equal(result.flowCompleteSignal, 'mock flow complete signal', 'result.flowCompleteSignal is correct')
|
||||
assert.equal(result.context, 'mock context', 'result.context is correct')
|
||||
assert.equal(result.entrypoint, 'mock entry point', 'result.entrypoint is correct')
|
||||
assert.equal(result.migration, 'mock migration', 'result.migration is correct')
|
||||
assert.equal(result.service, 'mock service', 'result.service is correct')
|
||||
assert.equal(result.utm_campaign, 'mock utm_campaign', 'result.utm_campaign is correct')
|
||||
assert.equal(result.utm_content, 'mock utm_content', 'result.utm_content is correct')
|
||||
assert.equal(result.utm_medium, 'mock utm_medium', 'result.utm_medium is correct')
|
||||
assert.equal(result.utm_source, 'mock utm_source', 'result.utm_source is correct')
|
||||
assert.equal(result.utm_term, 'mock utm_term', 'result.utm_term is correct')
|
||||
|
||||
assert.equal(Memcached.prototype.getAsync.callCount, 0, 'memcached.getAsync was not called')
|
||||
assert.equal(log.error.callCount, 0, 'log.error was not called')
|
||||
|
@ -250,45 +241,6 @@ describe('metricsConext', () => {
|
|||
}
|
||||
)
|
||||
|
||||
it(
|
||||
'metricsContext.gather with DNT header',
|
||||
() => {
|
||||
var time = Date.now() - 1
|
||||
metricsContext.gather.call({
|
||||
headers: {
|
||||
dnt: '1'
|
||||
},
|
||||
payload: {
|
||||
metricsContext: {
|
||||
flowId: 'mock flow id',
|
||||
flowBeginTime: time,
|
||||
flowCompleteSignal: 'mock flow complete signal',
|
||||
context: 'mock context',
|
||||
entrypoint: 'mock entry point',
|
||||
migration: 'mock migration',
|
||||
service: 'mock service',
|
||||
utmCampaign: 'mock utm_campaign',
|
||||
utmContent: 'mock utm_content',
|
||||
utmMedium: 'mock utm_medium',
|
||||
utmSource: 'mock utm_source',
|
||||
utmTerm: 'mock utm_term',
|
||||
ignore: 'mock ignorable property'
|
||||
}
|
||||
}
|
||||
}, {}).then(function (result) {
|
||||
assert.equal(Object.keys(result).length, 8, 'result has 8 properties')
|
||||
assert.equal(result.utm_campaign, undefined, 'result.utm_campaign is undefined')
|
||||
assert.equal(result.utm_content, undefined, 'result.utm_content is undefined')
|
||||
assert.equal(result.utm_medium, undefined, 'result.utm_medium is undefined')
|
||||
assert.equal(result.utm_source, undefined, 'result.utm_source is undefined')
|
||||
assert.equal(result.utm_term, undefined, 'result.utm_term is undefined')
|
||||
|
||||
assert.equal(log.error.callCount, 0, 'log.error was not called')
|
||||
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
it(
|
||||
'metricsContext.gather with token',
|
||||
() => {
|
||||
|
@ -302,17 +254,7 @@ describe('metricsConext', () => {
|
|||
return P.resolve({
|
||||
flowId: 'flowId',
|
||||
flowBeginTime: time,
|
||||
flowCompleteSignal: 'flowCompleteSignal',
|
||||
context: 'context',
|
||||
entrypoint: 'entrypoint',
|
||||
migration: 'migration',
|
||||
service: 'service',
|
||||
utmCampaign: 'utm_campaign',
|
||||
utmContent: 'utm_content',
|
||||
utmMedium: 'utm_medium',
|
||||
utmSource: 'utm_source',
|
||||
utmTerm: 'utm_term',
|
||||
ignore: 'ignore me'
|
||||
flowCompleteSignal: 'flowCompleteSignal'
|
||||
})
|
||||
})
|
||||
metricsContext.gather.call({
|
||||
|
@ -329,21 +271,12 @@ describe('metricsConext', () => {
|
|||
|
||||
assert.equal(typeof result, 'object', 'result is object')
|
||||
assert.notEqual(result, null, 'result is not null')
|
||||
assert.equal(Object.keys(result).length, 13, 'result has 13 properties')
|
||||
assert.equal(Object.keys(result).length, 4, 'result has 4 properties')
|
||||
assert.ok(result.time > time, 'result.time seems correct')
|
||||
assert.equal(result.flow_id, 'flowId', 'result.flow_id is correct')
|
||||
assert.ok(result.flow_time > 0, 'result.flow_time is greater than zero')
|
||||
assert.ok(result.flow_time < time, 'result.flow_time is less than the current time')
|
||||
assert.equal(result.flowCompleteSignal, 'flowCompleteSignal', 'result.flowCompleteSignal is correct')
|
||||
assert.equal(result.context, 'context', 'result.context is correct')
|
||||
assert.equal(result.entrypoint, 'entrypoint', 'result.entry point is correct')
|
||||
assert.equal(result.migration, 'migration', 'result.migration is correct')
|
||||
assert.equal(result.service, 'service', 'result.service is correct')
|
||||
assert.equal(result.utm_campaign, 'utm_campaign', 'result.utm_campaign is correct')
|
||||
assert.equal(result.utm_content, 'utm_content', 'result.utm_content is correct')
|
||||
assert.equal(result.utm_medium, 'utm_medium', 'result.utm_medium is correct')
|
||||
assert.equal(result.utm_source, 'utm_source', 'result.utm_source is correct')
|
||||
assert.equal(result.utm_term, 'utm_term', 'result.utm_term is correct')
|
||||
|
||||
assert.equal(log.error.callCount, 0, 'log.error was not called')
|
||||
|
||||
|
@ -380,7 +313,7 @@ describe('metricsConext', () => {
|
|||
|
||||
assert.equal(typeof result, 'object', 'result is object')
|
||||
assert.notEqual(result, null, 'result is not null')
|
||||
assert.equal(Object.keys(result).length, 13, 'result has 13 properties')
|
||||
assert.equal(Object.keys(result).length, 4, 'result has 4 properties')
|
||||
assert.ok(result.time > time, 'result.time seems correct')
|
||||
assert.equal(result.flow_id, 'flowId', 'result.flow_id is correct')
|
||||
assert.ok(result.flow_time > 0, 'result.flow_time is greater than zero')
|
||||
|
@ -730,12 +663,8 @@ describe('metricsConext', () => {
|
|||
},
|
||||
payload: {
|
||||
metricsContext: {
|
||||
context: 'fx_desktop_v3',
|
||||
entrypoint: 'menupanel',
|
||||
flowId,
|
||||
flowBeginTime,
|
||||
migration: 'sync11',
|
||||
service: 'sync'
|
||||
flowBeginTime
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -809,11 +738,7 @@ describe('metricsConext', () => {
|
|||
},
|
||||
payload: {
|
||||
metricsContext: {
|
||||
context: 'fx_desktop_v3',
|
||||
entrypoint: 'menupanel',
|
||||
flowBeginTime: Date.now() - 1,
|
||||
migration: 'sync11',
|
||||
service: 'sync'
|
||||
flowBeginTime: Date.now() - 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -850,11 +775,7 @@ describe('metricsConext', () => {
|
|||
},
|
||||
payload: {
|
||||
metricsContext: {
|
||||
context: 'fx_desktop_v3',
|
||||
entrypoint: 'menupanel',
|
||||
flowId: 'f1031df1031df1031df1031df1031df1031df1031df1031df1031df1031df103',
|
||||
migration: 'sync11',
|
||||
service: 'sync'
|
||||
flowId: 'f1031df1031df1031df1031df1031df1031df1031df1031df1031df1031df103'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -891,12 +812,8 @@ describe('metricsConext', () => {
|
|||
},
|
||||
payload: {
|
||||
metricsContext: {
|
||||
context: 'fx_desktop_v3',
|
||||
entrypoint: 'menupanel',
|
||||
flowId: 'f1031df1031df1031df1031df1031df1031df1031df1031df1031df1031df103',
|
||||
flowBeginTime: Date.now() - mockConfig.metrics.flow_id_expiry - 1,
|
||||
migration: 'sync11',
|
||||
service: 'sync'
|
||||
flowBeginTime: Date.now() - mockConfig.metrics.flow_id_expiry - 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -917,245 +834,6 @@ describe('metricsConext', () => {
|
|||
}
|
||||
)
|
||||
|
||||
it(
|
||||
'metricsContext.validate with invalid context',
|
||||
() => {
|
||||
const flowBeginTime = 1451566800000
|
||||
const flowId = '1234567890abcdef1234567890abcdef6a7c0469a1e3d6dfa7d9bed7ae209672'
|
||||
sinon.stub(Date, 'now', function() {
|
||||
return flowBeginTime + 59999
|
||||
})
|
||||
const mockLog = mocks.spyLog()
|
||||
const mockConfig = {
|
||||
metrics: {
|
||||
flow_id_expiry: 60000,
|
||||
flow_id_key: 'S3CR37'
|
||||
}
|
||||
}
|
||||
const mockRequest = {
|
||||
headers: {
|
||||
'user-agent': 'test-agent'
|
||||
},
|
||||
payload: {
|
||||
metricsContext: {
|
||||
context: '!',
|
||||
entrypoint: 'menupanel',
|
||||
flowId,
|
||||
flowBeginTime,
|
||||
migration: 'sync11',
|
||||
service: 'sync'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const metricsContext = require('../../lib/metrics/context')(mockLog, mockConfig)
|
||||
const result = metricsContext.validate.call(mockRequest)
|
||||
|
||||
assert.strictEqual(result, false, 'result was false')
|
||||
assert.strictEqual(mockRequest.payload.metricsContext.flowId, undefined, 'invalid flow data was removed')
|
||||
assert.equal(mockLog.info.callCount, 0, 'log.info was not called')
|
||||
assert.equal(mockLog.warn.callCount, 1, 'log.warn was called once')
|
||||
assert.equal(mockLog.warn.args[0].length, 1, 'log.warn was passed one argument')
|
||||
assert.deepEqual(mockLog.warn.args[0][0], {
|
||||
op: 'metrics.context.validate',
|
||||
valid: false,
|
||||
reason: 'invalid data',
|
||||
agent: 'test-agent'
|
||||
}, 'log.warn was passed correct argument')
|
||||
|
||||
Date.now.restore()
|
||||
}
|
||||
)
|
||||
|
||||
it(
|
||||
'metricsContext.validate with invalid entrypoint',
|
||||
() => {
|
||||
const flowBeginTime = 1451566800000
|
||||
const flowId = '1234567890abcdef1234567890abcdef6a7c0469a1e3d6dfa7d9bed7ae209672'
|
||||
sinon.stub(Date, 'now', function() {
|
||||
return flowBeginTime + 59999
|
||||
})
|
||||
const mockLog = mocks.spyLog()
|
||||
const mockConfig = {
|
||||
metrics: {
|
||||
flow_id_expiry: 60000,
|
||||
flow_id_key: 'S3CR37'
|
||||
}
|
||||
}
|
||||
const mockRequest = {
|
||||
headers: {
|
||||
'user-agent': 'test-agent'
|
||||
},
|
||||
payload: {
|
||||
metricsContext: {
|
||||
context: 'fx_desktop_v3',
|
||||
entrypoint: '!',
|
||||
flowId,
|
||||
flowBeginTime,
|
||||
migration: 'sync11',
|
||||
service: 'sync'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const metricsContext = require('../../lib/metrics/context')(mockLog, mockConfig)
|
||||
const result = metricsContext.validate.call(mockRequest)
|
||||
|
||||
assert.strictEqual(result, false, 'result was false')
|
||||
assert.strictEqual(mockRequest.payload.metricsContext.flowId, undefined, 'invalid flow data was removed')
|
||||
assert.equal(mockLog.info.callCount, 0, 'log.info was not called')
|
||||
assert.equal(mockLog.warn.callCount, 1, 'log.warn was called once')
|
||||
assert.equal(mockLog.warn.args[0].length, 1, 'log.warn was passed one argument')
|
||||
assert.deepEqual(mockLog.warn.args[0][0], {
|
||||
op: 'metrics.context.validate',
|
||||
valid: false,
|
||||
reason: 'invalid data',
|
||||
agent: 'test-agent'
|
||||
}, 'log.warn was passed correct argument')
|
||||
|
||||
Date.now.restore()
|
||||
}
|
||||
)
|
||||
|
||||
it(
|
||||
'metricsContext.validate with invalid migration',
|
||||
() => {
|
||||
const flowBeginTime = 1451566800000
|
||||
const flowId = '1234567890abcdef1234567890abcdef6a7c0469a1e3d6dfa7d9bed7ae209672'
|
||||
sinon.stub(Date, 'now', function() {
|
||||
return flowBeginTime + 59999
|
||||
})
|
||||
const mockLog = mocks.spyLog()
|
||||
const mockConfig = {
|
||||
metrics: {
|
||||
flow_id_expiry: 60000,
|
||||
flow_id_key: 'S3CR37'
|
||||
}
|
||||
}
|
||||
const mockRequest = {
|
||||
headers: {
|
||||
'user-agent': 'test-agent'
|
||||
},
|
||||
payload: {
|
||||
metricsContext: {
|
||||
context: 'fx_desktop_v3',
|
||||
entrypoint: 'menupanel',
|
||||
flowId,
|
||||
flowBeginTime,
|
||||
migration: 'sync111',
|
||||
service: 'sync'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const metricsContext = require('../../lib/metrics/context')(mockLog, mockConfig)
|
||||
const result = metricsContext.validate.call(mockRequest)
|
||||
|
||||
assert.strictEqual(result, false, 'result was false')
|
||||
assert.strictEqual(mockRequest.payload.metricsContext.flowId, undefined, 'invalid flow data was removed')
|
||||
assert.equal(mockLog.info.callCount, 0, 'log.info was not called')
|
||||
assert.equal(mockLog.warn.callCount, 1, 'log.warn was called once')
|
||||
assert.equal(mockLog.warn.args[0].length, 1, 'log.warn was passed one argument')
|
||||
assert.deepEqual(mockLog.warn.args[0][0], {
|
||||
op: 'metrics.context.validate',
|
||||
valid: false,
|
||||
reason: 'invalid data',
|
||||
agent: 'test-agent'
|
||||
}, 'log.warn was passed correct argument')
|
||||
|
||||
Date.now.restore()
|
||||
}
|
||||
)
|
||||
|
||||
it(
|
||||
'metricsContext.validate with invalid service',
|
||||
() => {
|
||||
const flowBeginTime = 1451566800000
|
||||
const flowId = '1234567890abcdef1234567890abcdef6a7c0469a1e3d6dfa7d9bed7ae209672'
|
||||
sinon.stub(Date, 'now', function() {
|
||||
return flowBeginTime + 59999
|
||||
})
|
||||
const mockLog = mocks.spyLog()
|
||||
const mockConfig = {
|
||||
metrics: {
|
||||
flow_id_expiry: 60000,
|
||||
flow_id_key: 'S3CR37'
|
||||
}
|
||||
}
|
||||
const mockRequest = {
|
||||
headers: {
|
||||
'user-agent': 'test-agent'
|
||||
},
|
||||
payload: {
|
||||
metricsContext: {
|
||||
context: 'fx_desktop_v3',
|
||||
entrypoint: 'menupanel',
|
||||
flowId,
|
||||
flowBeginTime,
|
||||
migration: 'sync11',
|
||||
service: 'foo'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const metricsContext = require('../../lib/metrics/context')(mockLog, mockConfig)
|
||||
const result = metricsContext.validate.call(mockRequest)
|
||||
|
||||
assert.strictEqual(result, false, 'result was false')
|
||||
assert.strictEqual(mockRequest.payload.metricsContext.flowId, undefined, 'invalid flow data was removed')
|
||||
assert.equal(mockLog.info.callCount, 0, 'log.info was not called')
|
||||
assert.equal(mockLog.warn.callCount, 1, 'log.warn was called once')
|
||||
assert.equal(mockLog.warn.args[0].length, 1, 'log.warn was passed one argument')
|
||||
assert.deepEqual(mockLog.warn.args[0][0], {
|
||||
op: 'metrics.context.validate',
|
||||
valid: false,
|
||||
reason: 'invalid data',
|
||||
agent: 'test-agent'
|
||||
}, 'log.warn was passed correct argument')
|
||||
|
||||
Date.now.restore()
|
||||
}
|
||||
)
|
||||
|
||||
it(
|
||||
'metricsContext.validate without optional data',
|
||||
() => {
|
||||
const flowBeginTime = 1451566800000
|
||||
const flowId = '1234567890abcdef1234567890abcdef6a7c0469a1e3d6dfa7d9bed7ae209672'
|
||||
sinon.stub(Date, 'now', function() {
|
||||
return flowBeginTime + 59999
|
||||
})
|
||||
const mockLog = mocks.spyLog()
|
||||
const mockConfig = {
|
||||
metrics: {
|
||||
flow_id_expiry: 60000,
|
||||
flow_id_key: 'S3CR37'
|
||||
}
|
||||
}
|
||||
const mockRequest = {
|
||||
headers: {
|
||||
'user-agent': 'test-agent'
|
||||
},
|
||||
payload: {
|
||||
metricsContext: {
|
||||
flowId,
|
||||
flowBeginTime
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const metricsContext = require('../../lib/metrics/context')(mockLog, mockConfig)
|
||||
const result = metricsContext.validate.call(mockRequest)
|
||||
|
||||
assert.strictEqual(result, true, 'result was true')
|
||||
assert.equal(mockRequest.payload.metricsContext.flowId, '1234567890abcdef1234567890abcdef6a7c0469a1e3d6dfa7d9bed7ae209672', 'valid flow data was not removed')
|
||||
assert.equal(mockLog.warn.callCount, 0, 'log.warn was not called')
|
||||
assert.equal(mockLog.info.callCount, 1, 'log.info was called')
|
||||
|
||||
Date.now.restore()
|
||||
}
|
||||
)
|
||||
|
||||
it(
|
||||
'metricsContext.validate with an invalid flow signature',
|
||||
() => {
|
||||
|
@ -1172,12 +850,8 @@ describe('metricsConext', () => {
|
|||
},
|
||||
payload: {
|
||||
metricsContext: {
|
||||
context: 'fx_desktop_v3',
|
||||
entrypoint: 'menupanel',
|
||||
flowId: 'f1031df1031df1031df1031df1031df1031df1031df1031df1031df1031df103',
|
||||
flowBeginTime: Date.now() - 1,
|
||||
migration: 'sync11',
|
||||
service: 'sync'
|
||||
flowBeginTime: Date.now() - 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1217,12 +891,8 @@ describe('metricsConext', () => {
|
|||
},
|
||||
payload: {
|
||||
metricsContext: {
|
||||
context: 'fx_desktop_v3',
|
||||
entrypoint: 'menupanel',
|
||||
flowId: expectedSalt + expectedHmac,
|
||||
flowBeginTime: expectedTime,
|
||||
migration: 'sync11',
|
||||
service: 'sync'
|
||||
flowBeginTime: expectedTime
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1269,12 +939,8 @@ describe('metricsConext', () => {
|
|||
},
|
||||
payload: {
|
||||
metricsContext: {
|
||||
context: 'fx_desktop_v3',
|
||||
entrypoint: 'menupanel',
|
||||
flowId: expectedSalt + expectedHmac,
|
||||
flowBeginTime: expectedTime - 1,
|
||||
migration: 'sync11',
|
||||
service: 'sync'
|
||||
flowBeginTime: expectedTime - 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1321,12 +987,8 @@ describe('metricsConext', () => {
|
|||
},
|
||||
payload: {
|
||||
metricsContext: {
|
||||
context: 'fx_desktop_v3',
|
||||
entrypoint: 'menupanel',
|
||||
flowId: expectedSalt + expectedHmac,
|
||||
flowBeginTime: expectedTime,
|
||||
migration: 'sync11',
|
||||
service: 'sync'
|
||||
flowBeginTime: expectedTime
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -412,16 +412,27 @@ describe('remote account create', function() {
|
|||
)
|
||||
|
||||
it(
|
||||
'account creation works with minimal metricsContext metadata',
|
||||
'account creation fails with old metricsContext fields',
|
||||
() => {
|
||||
var email = server.uniqueEmail()
|
||||
return Client.create(config.publicUrl, email, 'foo', {
|
||||
metricsContext: {
|
||||
flowId: 'deadbeefbaadf00ddeadbeefbaadf00ddeadbeefbaadf00ddeadbeefbaadf00d',
|
||||
flowBeginTime: 1
|
||||
flowBeginTime: 1,
|
||||
context: 'foo',
|
||||
entrypoint: 'bar',
|
||||
migration: 'baz',
|
||||
service: 'qux',
|
||||
utmCampaign: 'wibble',
|
||||
utmContent: 'blurgh',
|
||||
utmMedium: 'blee',
|
||||
utmSource: 'fnarr',
|
||||
utmTerm: 'frang'
|
||||
}
|
||||
}).then(function (client) {
|
||||
assert.ok(client, 'created account')
|
||||
}).then(function () {
|
||||
assert(false, 'account creation should have failed')
|
||||
}, function (err) {
|
||||
assert.ok(err, 'account creation failed')
|
||||
})
|
||||
}
|
||||
)
|
||||
|
@ -467,16 +478,7 @@ describe('remote account create', function() {
|
|||
return Client.create(config.publicUrl, email, 'foo', {
|
||||
metricsContext: {
|
||||
flowId: 'deadbeefbaadf00ddeadbeefbaadf00ddeadbeefbaadf00ddeadbeefbaadf00d',
|
||||
flowBeginTime: 1,
|
||||
context: 'foo',
|
||||
entrypoint: 'bar',
|
||||
migration: 'baz',
|
||||
service: 'qux',
|
||||
utmCampaign: 'wibble',
|
||||
utmContent: 'blurgh',
|
||||
utmMedium: 'blee',
|
||||
utmSource: 'fnarr',
|
||||
utmTerm: 'frang'
|
||||
flowBeginTime: 1
|
||||
}
|
||||
}).then(function (client) {
|
||||
assert.ok(client, 'created account')
|
||||
|
|
Загрузка…
Ссылка в новой задаче