You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by om...@apache.org on 2016/05/12 19:48:46 UTC
[2/6] cordova-cli git commit: Telemetry: The Foundational work
Telemetry: The Foundational work
Project: http://git-wip-us.apache.org/repos/asf/cordova-cli/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-cli/commit/eafb8b9a
Tree: http://git-wip-us.apache.org/repos/asf/cordova-cli/tree/eafb8b9a
Diff: http://git-wip-us.apache.org/repos/asf/cordova-cli/diff/eafb8b9a
Branch: refs/heads/master
Commit: eafb8b9af1579b1f31a46bcb4c4e6a0aec8356d9
Parents: f0bb918
Author: Omar Mefire <om...@gmail.com>
Authored: Fri Apr 29 12:05:40 2016 -0700
Committer: Omar Mefire <om...@gmail.com>
Committed: Thu May 12 11:13:57 2016 -0700
----------------------------------------------------------------------
package.json | 3 +-
src/cli.js | 133 ++++++++++++++++++++++++++++++++++++--------------
src/telemetry.js | 93 +++++++++++++++++++++++++++++++++++
3 files changed, 191 insertions(+), 38 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/eafb8b9a/package.json
----------------------------------------------------------------------
diff --git a/package.json b/package.json
index 028fcd8..8a42b53 100644
--- a/package.json
+++ b/package.json
@@ -34,7 +34,8 @@
"q": "1.0.1",
"nopt": "3.0.1",
"underscore": "1.7.0",
- "update-notifier": "^0.5.0"
+ "update-notifier": "^0.5.0",
+ "insight": "~0.8.1"
},
"devDependencies": {
"istanbul": "^0.3.4",
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/eafb8b9a/src/cli.js
----------------------------------------------------------------------
diff --git a/src/cli.js b/src/cli.js
index 301e913..ac12f67 100644
--- a/src/cli.js
+++ b/src/cli.js
@@ -29,7 +29,8 @@ var path = require('path'),
nopt,
_,
updateNotifier,
- pkg = require('../package.json');
+ pkg = require('../package.json'),
+ telemetry = require('./telemetry');
var cordova_lib = require('cordova-lib'),
CordovaError = cordova_lib.CordovaError,
@@ -79,8 +80,20 @@ function checkForUpdates() {
}
}
-module.exports = cli;
-function cli(inputArgs) {
+module.exports = function(inputArgs) {
+ // Telemetry Prompt: only shows up on first run
+ // If the user has not made any decision about telemetry yet,
+ // ... a timed prompt is shown(30 seconds), asking him whether or not he wants to opt-in.
+ // ... If the timeout expires without him having made any decisions, he is considered to have opted out.
+
+ // Note: The timed prompt can be prevented from being shown by setting an environment variable: CORDOVA_TELEMETRY_OPT_OUT
+ // ... This is useful in CI environments.
+ return telemetry.setup().then(function(isUserOptedIntoTelemetry) {
+ return cli(inputArgs, isUserOptedIntoTelemetry);
+ });
+};
+
+function cli(inputArgs, isUserOptedIntoTelemetry) {
// When changing command line arguments, update doc/help.txt accordingly.
var knownOpts =
{ 'verbose' : Boolean
@@ -138,6 +151,10 @@ function cli(inputArgs) {
toPrint += ' (cordova-lib@' + libVersion + ')';
}
console.log(toPrint);
+ if(isUserOptedIntoTelemetry) {
+ var cmd = 'version';
+ telemetry.track(cmd, args.version);
+ }
return;
}
@@ -146,6 +163,8 @@ function cli(inputArgs) {
// are in a verbose mode.
process.on('uncaughtException', function(err) {
logger.error(err);
+ // Test this
+ telemetry.track('uncaughtException', err);
process.exit(1);
});
@@ -186,6 +205,10 @@ function cli(inputArgs) {
if (!args.help && remain[0] == 'help') {
remain.shift();
}
+ if(isUserOptedIntoTelemetry) {
+ telemetry.track(cmd);
+ telemetry.trackEvent('category', cmd);
+ }
return help(remain);
}
@@ -220,12 +243,25 @@ function cli(inputArgs) {
opts.options = args;
opts.options.argv = unparsedArgs;
- if (cmd == 'run' && args.list && cordova.raw.targets) {
- cordova.raw.targets.call(null, opts).done();
- return;
+ if (cmd === 'run' && args.list && cordova.raw.targets) {
+ var result = cordova.raw.targets.call(null, opts);
+ return result.finally(function() {
+ if (isUserOptedIntoTelemetry) {
+ telemetry.track(cmd, result.isFulfilled() ? 'successful' : 'unsuccessful');
+ telemetry.trackEvent('category', cmd);
+ }
+ return result;
+ });
}
- cordova.raw[cmd].call(null, opts).done();
+ var result = cordova.raw[cmd].call(null, opts);
+ return result.finally(function() {
+ if (isUserOptedIntoTelemetry) {
+ telemetry.track(cmd, result.isFulfilled() ? 'successful' : 'unsuccessful');
+ telemetry.trackEvent('category', cmd);
+ }
+ return result;
+ });
} else if (cmd === 'requirements') {
// All options without dashes are assumed to be platform names
opts.platforms = undashed.slice(1);
@@ -235,41 +271,58 @@ function cli(inputArgs) {
throw new CordovaError(msg);
}
- cordova.raw[cmd].call(null, opts.platforms)
- .then(function (platformChecks) {
-
- var someChecksFailed = Object.keys(platformChecks).map(function (platformName) {
- events.emit('log', '\nRequirements check results for ' + platformName + ':');
- var platformCheck = platformChecks[platformName];
- if (platformCheck instanceof CordovaError) {
- events.emit('warn', 'Check failed for ' + platformName + ' due to ' + platformCheck);
- return true;
- }
+ var result = cordova.raw[cmd].call(null, opts.platforms)
+ .then(function(platformChecks) {
- var someChecksFailed = false;
- platformCheck.forEach(function (checkItem) {
- var checkSummary = checkItem.name + ': ' +
- (checkItem.installed ? 'installed ' : 'not installed ') +
- (checkItem.metadata.version || '');
- events.emit('log', checkSummary);
- if (!checkItem.installed) {
- someChecksFailed = true;
- events.emit('warn', checkItem.metadata.reason);
+ var someChecksFailed = Object.keys(platformChecks).map(function(platformName) {
+ events.emit('log', '\nRequirements check results for ' + platformName + ':');
+ var platformCheck = platformChecks[platformName];
+ if (platformCheck instanceof CordovaError) {
+ events.emit('warn', 'Check failed for ' + platformName + ' due to ' + platformCheck);
+ return true;
}
+
+ var someChecksFailed = false;
+ platformCheck.forEach(function(checkItem) {
+ var checkSummary = checkItem.name + ': ' +
+ (checkItem.installed ? 'installed ' : 'not installed ') +
+ (checkItem.metadata.version || '');
+ events.emit('log', checkSummary);
+ if (!checkItem.installed) {
+ someChecksFailed = true;
+ events.emit('warn', checkItem.metadata.reason);
+ }
+ });
+
+ return someChecksFailed;
+ }).some(function(isCheckFailedForPlatform) {
+ return isCheckFailedForPlatform;
});
- return someChecksFailed;
- }).some(function (isCheckFailedForPlatform) {
- return isCheckFailedForPlatform;
+ if (someChecksFailed) throw new CordovaError('Some of requirements check failed');
});
-
- if (someChecksFailed) throw new CordovaError('Some of requirements check failed');
- }).done();
+ return result.finally(function() {
+ if (isUserOptedIntoTelemetry) {
+ telemetry.track(cmd, result.isFulfilled() ? 'successful' : 'unsuccessful');
+ }
+ return result;
+ });
} else if (cmd == 'serve') {
var port = undashed[1];
- cordova.raw.serve(port).done();
+ var result = cordova.raw.serve(port);
+ return result.finally(function() {
+ if(isUserOptedIntoTelemetry) {
+ telemetry.track(cmd, result.isFulfilled() ? 'successful' : 'unsuccessful');
+ }
+ });
} else if (cmd == 'create') {
- create();
+ var result = create();
+ return result.finally(function() {
+ if (isUserOptedIntoTelemetry) {
+ telemetry.track(cmd, result.isFulfilled() ? 'successful' : 'unsuccessful');
+ }
+ return result;
+ });
} else {
// platform/plugins add/rm [target(s)]
subcommand = undashed[1]; // sub-command like "add", "ls", "rm" etc.
@@ -297,7 +350,13 @@ function cli(inputArgs) {
, shrinkwrap: args.shrinkwrap || false
, force: args.force || false
};
- cordova.raw[cmd](subcommand, targets, download_opts).done();
+ var result = cordova.raw[cmd](subcommand, targets, download_opts);
+ return result.finally(function() {
+ if (isUserOptedIntoTelemetry) {
+ telemetry.track(cmd, result.isFulfilled() ? 'successful' : 'unsuccessful');
+ }
+ return result;
+ });
}
function create() {
@@ -339,10 +398,10 @@ function cli(inputArgs) {
}
// create(dir, id, name, cfg)
- cordova.raw.create( undashed[1] // dir to create the project in
+ return cordova.raw.create( undashed[1] // dir to create the project in
, undashed[2] // App id
, undashed[3] // App name
, cfg
- ).done();
+ );
}
}
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/eafb8b9a/src/telemetry.js
----------------------------------------------------------------------
diff --git a/src/telemetry.js b/src/telemetry.js
new file mode 100644
index 0000000..d05b696
--- /dev/null
+++ b/src/telemetry.js
@@ -0,0 +1,93 @@
+/**
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+/* jshint node:true, bitwise:true, undef:true, trailing:true, quotmark:true,
+ indent:4, unused:vars, latedef:nofunc,
+ laxcomma:true
+*/
+
+var path = require('path');
+var Q = require('q');
+
+var GOOGLE_ANALYTICS_TRACKING_ID = 'UA-64283057-7';
+
+var pkg = require('../package.json');
+var Insight = require('insight');
+var insight = new Insight({
+ trackingCode: GOOGLE_ANALYTICS_TRACKING_ID,
+ pkg: pkg
+});
+
+/** Telemetry Prompt:
+ * If the user has not made any decision about telemetry yet,
+ * ... a timed prompt is shown, asking him whether or not he wants to opt-in.
+ * ... If the timeout expires without him having made any decisions, he is considered to have opted out.
+
+ * Note: The timed prompt can be prevented from being shown by setting an environment variable: CORDOVA_TELEMETRY_OPT_OUT
+ * ... This is useful in CI environments.
+
+@returns {Boolean} It returns true if the user has agreed to opt-in to telemetry, false otherwise
+*/
+exports.setup = function setup() {
+ var deferred = Q.defer();
+
+ var isInteractive = !process.env.CORDOVA_TELEMETRY_OPT_OUT && !process.env.CI;
+ if(!isInteractive) {
+ // Update user's config file to make sure telemetry doesn't get collected
+ // This handles the case where user had previously opted-in, then
+ // ... sets up environment variable to signify they want out
+ insight.optOut = true;
+ }
+
+ if (isInteractive && insight.optOut === undefined) {
+
+ // Note: insight.askPermission() won't display the permissions prompt if one of these is true:
+ // - the process is not a TTY
+ // - the process was started with --no-insight flag
+ // - the CI environment variable is set
+ // For further infos, see: https://github.com/yeoman/insight/blob/3a6ac613b7312272f9f10e1188310b199afa4e1d/lib/index.js#L133
+
+ // ToDO: Fix link to privacy-statement
+ var msg = 'Privacy statement: http://docs.cordova.io/privacy-statement.html' + require('os').EOL +
+ 'May cordova anonymously report usage statitics to improve the tool over time ?';
+ insight.askPermission(msg, function(unused, optIn) {
+ track('telemetry-opt-out');
+ deferred.resolve(optIn /* same as !insight.optOut */);
+ }, {
+ optInByDefault: false // If prompt timeout expires, opt the user out of telemetry
+ });
+ } else {
+ deferred.resolve(!insight.optOut);
+ }
+
+ return deferred.promise;
+}
+
+exports.track = function track() {
+ insight.track.apply(insight, arguments);
+}
+
+exports.trackEvent = function trackEvent(category, action, label, value) {
+ insight.trackEvent({
+ category: category,
+ action: action,
+ label: label,
+ value: value
+ });
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org