text: 'use strict';
  
  let execSync = require('child_process').execSync;
  let fs = require('fs');
  let path = require('path');
  let os = require('os');
  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
  const analyticsOptions = {
    https: true,
    debug: false
  };
  
  let cid = fs.existsSync(analyticsFile) ? fs.readFileSync(analyticsFile, 'utf-8') : null;
  let visitor;
  
  if (ua) {
    if (cid) {
      visitor = ua(analyticsId, cid, analyticsOptions);
    } else {
      visitor = ua(analyticsId, analyticsOptions);
      cid = visitor.cid;
      fs.writeFileSync(analyticsFile, cid, 'utf-8');
    }
  }
  
  // https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters
  let customParams = {
    // OS Platform (darwin, win32, linux)
    cd1: os.platform,
    // Node.js Version (v4.1.2)
    cd2: process.version,
    // npm Version (2.14.7)
    cd10: getNpmVersion(),
    // TypeScript Version (1.6.2)
    cd3: getTypeScriptVersion(),
    // Dart Version
    cd11: getDartVersion(),
    // Dev Environment
    cd4: process.env.TRAVIS ? 'Travis CI' : 'Local Dev',
    // Travis - Pull Request?
    cd5: process.env.TRAVIS && process.env.TRAVIS_PULL_REQUEST ? 'true' : 'false',
    // Travis - Branch Name (master)
    cd6: process.env.TRAVIS_BRANCH,
    // Travis - Repo Slug  (angular/angular)
    cd7: process.env.TRAVIS_REPO_SLUG,
    // Travis - Job ID (4.1)
    cd12: process.env.TRAVIS_JOB_NUMBER,
    // HW - CPU Info
    cd8: `${os.cpus().length} x ${os.cpus()[0].model}`,
    // HW - Memory Info
    cd9: `${Math.round(os.totalmem()/1024/1024/1024)}GB`,
  };
  
  
  
  function getTypeScriptVersion() {
    try {
      return require('typescript').version;
    } catch (e) {
      return 'unknown';
    }
  }
  
  
  function getNpmVersion() {
    try {
      return execSync('npm -v').toString().replace(/\s/, '');
    } catch (e) {
      return 'unknown';
    }
  }
  
  
  function getDartVersion() {
    try {
      return execSync('dart --version 2>&1').toString().replace(/.+: (\S+) [\s\S]+/, '$1')
    } catch (e) {
      return 'unknown';
    }
  }
  
  
  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 = {
  
    installStart: (actionName) => {
      recordEvent('start', 'install', actionName);
    },
  
    installSuccess: (actionName, duration) => {
      recordEvent('success', 'install', actionName, duration);
    },
  
    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);
    }
  };
  