cordova-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From omef...@apache.org
Subject [2/6] cordova-cli git commit: Telemetry: The Foundational work
Date Thu, 12 May 2016 19:48:46 GMT
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 <omefire@gmail.com>
Authored: Fri Apr 29 12:05:40 2016 -0700
Committer: Omar Mefire <omefire@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


Mime
View raw message