1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5/**
6 * @fileoverview Utility methods for accessing chrome.metricsPrivate API.
7 *
8 * To be included as a first script in main.html
9 */
10
11var metrics = {};
12
13/**
14 * A map from interval name to interval start timestamp.
15 */
16metrics.intervals = {};
17
18/**
19 * Start the named time interval.
20 * Should be followed by a call to recordInterval with the same name.
21 *
22 * @param {string} name Unique interval name.
23 */
24metrics.startInterval = function(name) {
25  metrics.intervals[name] = Date.now();
26};
27
28metrics.startInterval('Load.Total');
29metrics.startInterval('Load.Script');
30
31/**
32 * Convert a short metric name to the full format.
33 *
34 * @param {string} name Short metric name.
35 * @return {string} Full metric name.
36 * @private
37 */
38metrics.convertName_ = function(name) {
39  return 'FileBrowser.' + name;
40};
41
42/**
43 * Wrapper method for calling chrome.fileManagerPrivate safely.
44 * @param {string} name Method name.
45 * @param {Array.<Object>} args Arguments.
46 * @private
47 */
48metrics.call_ = function(name, args) {
49  try {
50    chrome.metricsPrivate[name].apply(chrome.metricsPrivate, args);
51  } catch (e) {
52    console.error(e.stack);
53  }
54};
55
56/**
57 * Create a decorator function that calls a chrome.metricsPrivate function
58 * with the same name and correct parameters.
59 *
60 * @param {string} name Method name.
61 */
62metrics.decorate = function(name) {
63  metrics[name] = function() {
64    var args = Array.apply(null, arguments);
65    args[0] = metrics.convertName_(args[0]);
66    metrics.call_(name, args);
67    if (metrics.log) {
68      console.log('chrome.metricsPrivate.' + name, args);
69    }
70  };
71};
72
73metrics.decorate('recordMediumCount');
74metrics.decorate('recordSmallCount');
75metrics.decorate('recordTime');
76metrics.decorate('recordUserAction');
77
78/**
79 * Complete the time interval recording.
80 *
81 * Should be preceded by a call to startInterval with the same name. *
82 *
83 * @param {string} name Unique interval name.
84 */
85metrics.recordInterval = function(name) {
86  if (name in metrics.intervals) {
87    metrics.recordTime(name, Date.now() - metrics.intervals[name]);
88  } else {
89    console.error('Unknown interval: ' + name);
90  }
91};
92
93/**
94 * Record an enum value.
95 *
96 * @param {string} name Metric name.
97 * @param {Object} value Enum value.
98 * @param {Array.<Object>|number} validValues Array of valid values
99 *                                            or a boundary number value.
100 */
101metrics.recordEnum = function(name, value, validValues) {
102  var boundaryValue;
103  var index;
104  if (validValues.constructor.name == 'Array') {
105    index = validValues.indexOf(value);
106    boundaryValue = validValues.length;
107  } else {
108    index = value;
109    boundaryValue = validValues;
110  }
111  // Collect invalid values in the overflow bucket at the end.
112  if (index < 0 || index > boundaryValue)
113    index = boundaryValue;
114
115  // Setting min to 1 looks strange but this is exactly the recommended way
116  // of using histograms for enum-like types. Bucket #0 works as a regular
117  // bucket AND the underflow bucket.
118  // (Source: UMA_HISTOGRAM_ENUMERATION definition in base/metrics/histogram.h)
119  var metricDescr = {
120    'metricName': metrics.convertName_(name),
121    'type': 'histogram-linear',
122    'min': 1,
123    'max': boundaryValue,
124    'buckets': boundaryValue + 1
125  };
126  metrics.call_('recordValue', [metricDescr, index]);
127  if (metrics.log) {
128    console.log('chrome.metricsPrivate.recordValue',
129        [metricDescr.metricName, index, value]);
130  }
131};
132