/* * This module is a helper for recording telemetry data in Gecko’s telemetry * system. Currently, only data from certified apps will be recorded. * * There are three different types of metrics that can be used here: * Counter: This is a simple counter that increments by 1 each time it's * called. * * Linear: This type of metric creates a linear distributed set of buckets * which range between the min and max. You can specify the number * of buckets as well as the min and max. * * Exponential: This type of metric creates an exponential distributed set of * buckets ranging between min and max. You can specify the min, * max, and buckets. * * App Setup: * 1) Add the following to the app (e.g. index.html): * * * 2) Include AdvancedTelemetryHelper in the globals. * * Counter Metric Usage Example: * // This creates the histogram counter on this metric called * // 'mycount' * var count = new AdvancedTelemetryHelper(ATH.HISTOGRAM_COUNT, 'mycount'); * count.add(); //Increment the count. The count of the histogram is now 1. * // DO SOMETHING * count.add(); //Increment the count. The count of the histogram is now 2. * * Linear Metric Usage Example: * // This creates a linear histogram called 'mylinear' with minimum * // of 1 (0 not allowed as a minimum), max of 1000, with 10 buckets. * var linear = new AdvancedTelemetryHelper(ATH.HISTOGRAM_LINEAR, 'mylinear', * 1, 1000, 10); * // This adds the value 15 to the histogram 'mylinear' * linear.add(15); * // DO SOMETHING * // This adds to the existing histogram a value of 800. * linear.add(800); // The histogram now has two values, one in the 15 bucket * // and one in the bucket that holds the value 800 * * Exponential Metric Usage Example: * // This creates an exponential histogram called 'myexp' with minimum * // of 1 (0 not allowed as a minimum), max of 1000, with 10 buckets. * var exp = new AdvancedTelemetryHelper(ATH.HISTOGRAM_EXPONENTIAL, 'myexp', * 1, 1000, 10); * // This adds the value 15 to the histogram 'myexp' * exp.add(15); * // DO SOMETHING * // This adds to the existing histogram a value of 800. * exp.add(800); // The histogram now has two values, one in the 15 bucket * // and one in the bucket that holds the value 800 * * Caveats: * Note that after a histogram is created, it's not possible to change the type * of the histogram from one type to the other. It's necessary to create a new * Histogram. * * Each histogram should have a unique name. * */ /* globals SettingsListener */ (function(exports) { 'use strict'; const APP_TELEMETRY_LOG_PREFIX = 'telemetry'; const ATH = AdvancedTelemetryHelper; // Export Histogram types so they can be used by apps ATH.HISTOGRAM_COUNT = 4; ATH.HISTOGRAM_EXP = 0; ATH.HISTOGRAM_LINEAR = 1; // This is exposed for unit testing purposes ATH.TELEMETRY_LEVEL_KEY = 'metrics.selectedMetrics.level'; ATH.SETTINGS_INITIALIZED = false; // API for an exponential histogram entry. This function creates the // histogram in the system and prepares it subsequent .log(value) calls // against it. // : One of ATH.HISTOGRAM_COUNT, ATH.HISTOGRAM_EXP, // or ATH.HISTOGRAM_LINEAR. // : Unique name of the metric // : [Required for linear and exponential only]The minimum (non-zero) // numeric value for this histogram. // : [Required for linear and exponential only]The maximum numeric // value for this histogram. // : [Required for linear and exponential only]The total number of // buckets for this histogram. function AdvancedTelemetryHelper(type, name, min, max, buckets) { if (!ATH.SETTINGS_INITIALIZED) { ATH.SETTINGS_INITIALIZED = true; ATH.init(); } if (typeof type !== 'undefined' && typeof name !== 'undefined') { if (type === ATH.HISTOGRAM_COUNT) { this.createHistogram(name, ATH.HISTOGRAM_COUNT, 0, 0, 0); } else if (type === ATH.HISTOGRAM_EXP || type === ATH.HISTOGRAM_LINEAR) { this.createHistogram(name, type, min, max, buckets); } else { console.warn('Must pass a Histogram type and a unique Histogram name.'); } } else { console.warn('Must pass a Histogram type and a unique Histogram name.'); } } AdvancedTelemetryHelper.init = function init() { ATH.telemetryEnabledListener = function telemetryEnabledListener(enabled) { if (enabled === 'Enhanced') { ATH.TELEMETRY_LEVEL = true; } else { ATH.TELEMETRY_LEVEL = false; } }.bind(this); SettingsListener.observe(ATH.TELEMETRY_LEVEL_KEY, false, ATH.telemetryEnabledListener); }; AdvancedTelemetryHelper.prototype.createHistogram = function(name, type, min, max, buckets) { if (typeof ATH.TELEMETRY_LEVEL === 'undefined' || ATH.TELEMETRY_LEVEL) { if (typeof this.metricType !== 'undefined') { console.warn('Cannot redefine histogram. Must create a new object'); return; } this.metricType = type; if (typeof name !== 'undefined') { var varCount = 2; var re = /_/g; var message = APP_TELEMETRY_LOG_PREFIX; // Disallow underscores so telemetry system can parse it. this.metricName = name.replace(re, '-'); message += '|' + this.metricName; message += '|' + type + '|'; if (typeof min !== 'undefined') { varCount++; } if (typeof max !== 'undefined') { varCount++; } if (typeof buckets !== 'undefined') { varCount++; } if (varCount != 5) { console.warn('createHistogram must have 5 params.'); return; } if (min < 1) { min = 1; } message += min + '|' + max + '|' + buckets; console.info(message); } else { console.warn('A telemetry log entry requires a name.'); } } }; // API for logging against a pre-existing histogram. This records the value // for this particular histogram in the histogram system. // : The value to record against this histogram. // For a counter histogram, this can be empty or 1 can be passed. // For an exponential or linear histogram a valid value > 0 must be passed. AdvancedTelemetryHelper.prototype.add = function(value) { if (typeof ATH.TELEMETRY_LEVEL === 'undefined' || ATH.TELEMETRY_LEVEL) { if (this.metricType == ATH.HISTOGRAM_COUNT) { value = 1; } if (typeof value === 'undefined' || !value || value < 1) { console.warn('A valid value is required to log a histogram.'); return; } var message = APP_TELEMETRY_LOG_PREFIX + '|' + this.metricName + '|' + value; console.info(message); } }; exports.AdvancedTelemetryHelper = AdvancedTelemetryHelper; }(window));