build(analytics): add support for tracking npm installs
Since the very first npm install is called while node_modules is empty, we need to ignore it, but we can track the start timestamp and record the install even once the installation is completed.
This commit is contained in:
parent
edd4b93589
commit
ae7f76e91f
|
@ -1317,5 +1317,6 @@ process.on('beforeExit', function() {
|
|||
});
|
||||
|
||||
|
||||
gulp.on('task_stop', (e) => { analytics.build('gulp ' + e.task, e.duration*1000)});
|
||||
gulp.on('task_err', (e) => { analytics.build('gulp ' + e.task + ' (errored)', e.duration*1000)});
|
||||
gulp.on('task_start', (e) => { analytics.buildStart('gulp ' + e.task)});
|
||||
gulp.on('task_stop', (e) => { analytics.buildSuccess('gulp ' + e.task, e.duration*1000)});
|
||||
gulp.on('task_err', (e) => { analytics.buildError('gulp ' + e.task, e.duration*1000)});
|
||||
|
|
|
@ -23,8 +23,8 @@
|
|||
"url": "https://github.com/angular/angular.git"
|
||||
},
|
||||
"scripts": {
|
||||
"preinstall": "node tools/npm/check-node-modules --purge",
|
||||
"postinstall": "node tools/npm/copy-npm-shrinkwrap && node tools/chromedriverpatch.js && webdriver-manager update && bower install && gulp pubget.dart && tsd reinstall --overwrite --clean --config modules/angular2/tsd.json && tsd reinstall --overwrite --clean --config tools/tsd.json && tsd reinstall --overwrite --config modules/angular1_router/tsd.json",
|
||||
"preinstall": "node tools/analytics/build-analytics start install npm-install; node tools/analytics/build-analytics start install npm-preinstall; node tools/npm/check-node-modules --purge; node tools/analytics/build-analytics success install npm-preinstall; node tools/analytics/build-analytics start install npm-install-net",
|
||||
"postinstall": "node tools/analytics/build-analytics success install npm-install-net; node tools/analytics/build-analytics start install npm-postinstall; node tools/npm/copy-npm-shrinkwrap && node tools/chromedriverpatch.js && webdriver-manager update && bower install && gulp pubget.dart && tsd reinstall --overwrite --clean --config modules/angular2/tsd.json && tsd reinstall --overwrite --clean --config tools/tsd.json && tsd reinstall --overwrite --config modules/angular1_router/tsd.json; node tools/analytics/build-analytics success install npm-postinstall; node tools/analytics/build-analytics success install npm-install",
|
||||
"test": "gulp test.all.js && gulp test.all.dart"
|
||||
},
|
||||
"dependencies": {
|
||||
|
|
|
@ -4,7 +4,13 @@ let execSync = require('child_process').execSync;
|
|||
let fs = require('fs');
|
||||
let path = require('path');
|
||||
let os = require('os');
|
||||
let ua = require('universal-analytics');
|
||||
let ua;
|
||||
|
||||
try {
|
||||
ua = require('universal-analytics');
|
||||
} catch(e) {
|
||||
// ignore errors due to invoking analytics before the first npm install
|
||||
}
|
||||
|
||||
const analyticsFile = path.resolve(path.join(__dirname, '..', '..', '.build-analytics'));
|
||||
const analyticsId = "UA-8594346-17"; // Owned by the Angular account
|
||||
|
@ -16,6 +22,7 @@ const analyticsOptions = {
|
|||
let cid = fs.existsSync(analyticsFile) ? fs.readFileSync(analyticsFile, 'utf-8') : null;
|
||||
let visitor;
|
||||
|
||||
if (ua) {
|
||||
if (cid) {
|
||||
visitor = ua(analyticsId, cid, analyticsOptions);
|
||||
} else {
|
||||
|
@ -23,7 +30,7 @@ if (cid) {
|
|||
cid = visitor.cid;
|
||||
fs.writeFileSync(analyticsFile, cid, 'utf-8');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters
|
||||
let customParams = {
|
||||
|
@ -80,28 +87,74 @@ function getDartVersion() {
|
|||
}
|
||||
|
||||
|
||||
function recordEvent(eventType, actionCategory, actionName, duration) {
|
||||
// if universal-analytics is not yet installed, don't bother doing anything (e.g. when tracking initial npm install)
|
||||
// build-analytics will however store the starting timestamp, so at least we can record the success/error event with duration
|
||||
if (!ua) return;
|
||||
|
||||
if (duration) {
|
||||
duration = Math.round(duration);
|
||||
}
|
||||
|
||||
switch (eventType) {
|
||||
case 'start':
|
||||
visitor.
|
||||
event(actionCategory, actionName + ' (start)', 'testLabel', null, customParams).
|
||||
send();
|
||||
break;
|
||||
case 'success':
|
||||
visitor.
|
||||
event(actionCategory, actionName, 'testLabel', duration, customParams).
|
||||
timing(actionCategory, actionName, duration, customParams).
|
||||
send();
|
||||
break;
|
||||
case 'error':
|
||||
visitor.
|
||||
event(actionCategory, actionName + ' (errored)', 'testLabel', duration, customParams).
|
||||
timing(actionCategory, actionName, duration, customParams).
|
||||
send();
|
||||
break;
|
||||
default:
|
||||
throw new Error(`unknown event type "${eventType}"`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module.exports = {
|
||||
install: (actionName, duration) => {
|
||||
duration = Math.round(duration);
|
||||
visitor.
|
||||
event('install', actionName, 'testLabel', duration, customParams).
|
||||
timing('install', actionName, duration, customParams).
|
||||
send();
|
||||
|
||||
installStart: (actionName) => {
|
||||
recordEvent('start', 'install', actionName);
|
||||
},
|
||||
|
||||
build: (actionName, duration) => {
|
||||
duration = Math.round(duration);
|
||||
visitor.
|
||||
event('build', actionName, 'testLabel', duration, customParams).
|
||||
timing('build', actionName, duration, customParams).
|
||||
send();
|
||||
installSuccess: (actionName, duration) => {
|
||||
recordEvent('success', 'install', actionName, duration);
|
||||
},
|
||||
|
||||
test: (actionName, duration) => {
|
||||
duration = Math.round(duration);
|
||||
visitor.
|
||||
event('test', actionName, 'testLabel', duration, customParams).
|
||||
timing('test', actionName, duration, customParams).
|
||||
send();
|
||||
installError: (actionName, duration) => {
|
||||
recordEvent('error', 'install', actionName, duration);
|
||||
},
|
||||
|
||||
buildStart: (actionName) => {
|
||||
recordEvent('start', 'build', actionName);
|
||||
},
|
||||
|
||||
buildSuccess: (actionName, duration) => {
|
||||
recordEvent('success', 'build', actionName, duration);
|
||||
},
|
||||
|
||||
buildError: (actionName, duration) => {
|
||||
recordEvent('error', 'build', actionName, duration);
|
||||
},
|
||||
|
||||
ciStart: (actionName) => {
|
||||
recordEvent('start', 'ci', actionName);
|
||||
},
|
||||
|
||||
ciSuccess: (actionName, duration) => {
|
||||
recordEvent('success', 'ci', actionName, duration);
|
||||
},
|
||||
|
||||
ciError: (actionName, duration) => {
|
||||
recordEvent('success', 'ci', actionName, duration);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
'use strict';
|
||||
|
||||
|
||||
var analytics = require('./analytics');
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
|
||||
var eventType = process.argv[2];
|
||||
var actionCategory = process.argv[3];
|
||||
var actionName = process.argv[4];
|
||||
|
||||
|
||||
if (!analytics[actionCategory + 'Start']) {
|
||||
throw new Error('Unknown build-analytics actionCategory "' + actionCategory + '"');
|
||||
}
|
||||
|
||||
if (eventType != 'start' && eventType != 'success' && eventType != 'error') {
|
||||
throw new Error('Unknown build-analytics eventType "' + eventType + '"');
|
||||
}
|
||||
|
||||
|
||||
var startTimestampFilePath = path.resolve(path.join(__dirname, '..', '..', 'tmp', 'analytics', actionCategory + '-' + actionName));
|
||||
var analyticsDirPath = path.dirname(startTimestampFilePath);
|
||||
var tmpDirPath = path.dirname(analyticsDirPath);
|
||||
|
||||
|
||||
if (!fs.existsSync(tmpDirPath)) {
|
||||
fs.mkdirSync(tmpDirPath);
|
||||
}
|
||||
if (!fs.existsSync(analyticsDirPath)) {
|
||||
fs.mkdirSync(analyticsDirPath);
|
||||
}
|
||||
|
||||
|
||||
switch (eventType) {
|
||||
case 'start':
|
||||
analytics[actionCategory + 'Start'](actionName);
|
||||
fs.writeFileSync(startTimestampFilePath, Date.now(), 'utf-8');
|
||||
break;
|
||||
case 'success':
|
||||
var startTime = fs.readFileSync(startTimestampFilePath, 'utf-8');
|
||||
analytics[actionCategory + 'Success'](actionName, Date.now() - startTime);
|
||||
fs.unlinkSync(startTimestampFilePath);
|
||||
break;
|
||||
case 'error':
|
||||
var startTime = fs.readFileSync(startTimestampFilePath, 'utf-8');
|
||||
analytics[actionCategory + 'Error'](actionName, Date.now() - startTime);
|
||||
fs.unlinkSync(startTimestampFilePath);
|
||||
}
|
Loading…
Reference in New Issue