This repository has been archived by the owner on Dec 11, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 975
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #6267 from brave/telemetry
Telemetry
- Loading branch information
Showing
4 changed files
with
238 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
/* 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 Immutable = require('immutable') | ||
const _ = require('underscore') | ||
const Channel = require('./channel') | ||
const request = require('request') | ||
|
||
var telemetry = Immutable.Map() | ||
var eventList = Immutable.List() | ||
var enabled = false | ||
const params = {} | ||
const DEBUG = !!process.env.TELEMETRY_DEBUG | ||
|
||
var platforms = { | ||
'darwin': 'osx', | ||
'win32x64': 'winx64', | ||
'win32ia32': 'winia32', | ||
'linux': 'linux' | ||
} | ||
|
||
// Configure default payload for Telemetry calls | ||
if (params.platform === 'win32') { | ||
params.platform = platforms[params.platform + process.arch] | ||
} else { | ||
params.platform = platforms[process.platform] | ||
} | ||
params.version = process.env.TELEMETRY_VERSION || require('electron').app.getVersion() | ||
params.channel = Channel.channel() | ||
params.machine = process.env.TELEMETRY_MACHINE | ||
|
||
// determine if fully configured | ||
if (!!process.env.TELEMETRY_URL && | ||
!!process.env.TELEMETRY_TOKEN && | ||
params.platform && | ||
params.version && | ||
params.channel && | ||
!!params.machine) { | ||
console.log('Telemetry enabled: ' + process.env.TELEMETRY_URL) | ||
enabled = true | ||
} | ||
|
||
/** | ||
* Set a checkpoint to current timestamp | ||
* @param checkpoint {String} - name of checkpoint | ||
* @param ts {Number} - epoch timestamp [optional] | ||
*/ | ||
function setCheckpoint (checkpoint, ts) { | ||
ts = ts || (new Date()).getTime() | ||
var delta = 0 | ||
|
||
telemetry = telemetry.set(checkpoint, ts) | ||
|
||
if (eventList.size > 0) { | ||
delta = ts - eventList.get(eventList.size - 1)[1] | ||
} | ||
eventList = eventList.push([checkpoint, ts, delta / 1000]) | ||
if (DEBUG) console.log(events()) | ||
} | ||
|
||
/** | ||
* Return array containing timing info for all calls to setCheckpoint | ||
*/ | ||
function events () { | ||
return eventList.toJS() | ||
} | ||
|
||
/** | ||
* Clear a checkpoint | ||
* @param checkpoint {String} - name of checkpoint | ||
*/ | ||
function clearCheckpoint (checkpoint) { | ||
telemetry = telemetry.delete(checkpoint) | ||
} | ||
|
||
/** | ||
* Find the difference between the timestamps of two checkpoints | ||
* @param checkpoint1 {String} - name of earlier checkpoint | ||
* @param checkpoint2 {String} - name of later checkpoint | ||
*/ | ||
function deltaBetween (checkpoint1, checkpoint2) { | ||
var ts1 = telemetry.get(checkpoint1) | ||
var ts2 = telemetry.get(checkpoint2) | ||
if (_.isNumber(ts1) && _.isNumber(ts2)) { | ||
return Math.abs(ts2 - ts1) | ||
} else { | ||
return | ||
} | ||
} | ||
|
||
/** | ||
* Set a checkpoint and report telemetry if configured | ||
* @param checkpoint {String} - name checkpoint | ||
* @param initialCheckpoint {String} - name of earlier checkpoint | ||
* @param extra {Object} - object passed to telemetry [optional] | ||
* @param ts {Number] - epoch timestamp for checkpoint | ||
*/ | ||
function setCheckpointAndReport (checkpoint, initialCheckpoint, extra, ts) { | ||
initialCheckpoint = initialCheckpoint || 'init' | ||
extra = extra || {} | ||
|
||
setCheckpoint(checkpoint, ts) | ||
return sendTelemetry( | ||
checkpoint, | ||
deltaBetween(initialCheckpoint, checkpoint), | ||
extra | ||
) | ||
} | ||
|
||
// Build payload object and send telemetry if configured | ||
var sendTelemetry = (measure, value, extra) => { | ||
var payload = _.extend(params, { | ||
measure: measure, | ||
value: value / 1000, | ||
ts: (new Date()).getTime(), | ||
extra: extra | ||
}) | ||
if (enabled) { | ||
if (DEBUG) console.log(payload) | ||
request({ | ||
method: 'POST', | ||
url: process.env.TELEMETRY_URL, | ||
form: params, | ||
headers: { | ||
Authorization: 'Bearer ' + process.env.TELEMETRY_TOKEN | ||
} | ||
}, | ||
function (err, response, body) { | ||
if (err) console.log(err) | ||
if (DEBUG) console.log(body) | ||
}) | ||
} | ||
return payload | ||
} | ||
|
||
setCheckpoint('__baseline__') | ||
|
||
module.exports = { | ||
events: events, | ||
setCheckpoint: setCheckpoint, | ||
clearCheckpoint: clearCheckpoint, | ||
deltaBetween: deltaBetween, | ||
setCheckpointAndReport: setCheckpointAndReport | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
# Overview | ||
|
||
The telemetry is used to (optionally) send timing information to a [vault-collector](https://github.com/brave/vault-collector) instance. Typically this will be used in a C.I. system to identify performance regressions. | ||
|
||
## Setup | ||
|
||
Quick setup: To record telemetry without sending to the collector, start browser with the `TELEMETRY_DEBUG` environment variables set to `1`. | ||
|
||
`TELEMETRY_DEBUG=1 npm start` | ||
|
||
The following environment variables must be set for the complete telemetry system to be enabled: | ||
|
||
1. TELEMETRY_URL - url to [vault-collector](https://github.com/brave/vault-collector) endpoint | ||
2. TELEMETRY_MACHINE - string identifier of the machine (i.e. MacBookPro) | ||
3. TELEMETRY_TOKEN - string used to authenticate POST to [vault-collector](https://github.com/brave/vault-collector) | ||
|
||
The following environment variables may be set if desired: | ||
|
||
1. TELEMETRY_DEBUG - turn on logging to console of telemetry info | ||
2. TELEMETRY_VERSION - string in format X.X.X used to override version number | ||
|
||
## Usage | ||
|
||
The browser will automatically create an `init` checkpoint before it begins its startup sequence. | ||
|
||
Use the `setCheckpointAndReport` function to send telemetry information. | ||
|
||
`telemetry.setCheckpointAndReport('startup-complete')` | ||
|
||
This will issue a telemetry POST with the `measure` set to `startup-complete` and the `value` set to the amount of time since the `init` checkpoint was set. | ||
|
||
## API | ||
|
||
* `setCheckpoint(checkpoint, [ts])` - set a checkpoint without sending telemetry | ||
|
||
* `clearCheckpoint(checkpoint)` - clear a previously set checkpoint | ||
|
||
* `deltaBetween(checkpoint1, checkpoint2)` - return timing difference between two checkpoints | ||
|
||
* `setCheckpointAndReport(checkpoint, [initialCheckpoint], [extra], [ts])` - set a checkpoint and send telemetry | ||
|
||
* `events()` - returns an array containing timing info for each recorded event | ||
|
||
## Extra | ||
|
||
Each telemetry POST may contain an object with `extra` information. This should be passed as the third parameter to the `setCheckpointAndReport` function. | ||
|
||
`setCheckpointAndReport('ready', 'init', { lastCommit: 'a3e5fa3' })` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
/* global describe, it */ | ||
const assert = require('assert') | ||
|
||
process.env.TELEMETRY_TOKEN = 'token' | ||
process.env.TELEMETRY_VERSION = '1.2.3' | ||
process.env.TELEMETRY_MACHINE = 'mbp' | ||
|
||
const telemetry = require('../../../../app/telemetry') | ||
|
||
describe('telemetry', function () { | ||
it('records checkpoints', function () { | ||
telemetry.setCheckpoint('foo', 1000) | ||
telemetry.setCheckpoint('bar', 2000) | ||
|
||
assert.equal(telemetry.deltaBetween('foo', 'bar'), 1000, 'has correct delta calculation') | ||
|
||
telemetry.clearCheckpoint('bar') | ||
telemetry.setCheckpoint('bar', 3000) | ||
assert.equal(telemetry.deltaBetween('foo', 'bar'), 2000, 'clears checkpoints') | ||
}) | ||
it('formats and sends telemetry object correctly', function () { | ||
var payload = telemetry.setCheckpointAndReport('baz', 'foo', { attrib: 'value' }, 5000) | ||
var expected = { | ||
platform: payload.platform, | ||
version: '1.2.3', | ||
channel: payload.channel, | ||
machine: 'mbp', | ||
measure: 'baz', | ||
value: 4, | ||
ts: payload.ts, | ||
extra: { attrib: 'value' } | ||
} | ||
assert.deepEqual(payload, expected, 'payload is correct') | ||
}) | ||
it('records events correctly', function () { | ||
assert.equal(telemetry.events().length, 5, 'correct number of events') | ||
}) | ||
}) |