Home | History | Annotate | Download | only in webapp
      1 // Copyright (c) 2011 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
      7  * The webapp reads the plugin's connection statistics frequently (once per
      8  * second). It logs statistics to the server less frequently, to keep
      9  * bandwidth and storage costs down. This class bridges that gap, by
     10  * accumulating high-frequency numeric data, and providing statistics
     11  * summarising that data.
     12  */
     13 
     14 'use strict';
     15 
     16 /** @suppress {duplicate} */
     17 var remoting = remoting || {};
     18 
     19 /**
     20  * @constructor
     21  */
     22 remoting.StatsAccumulator = function() {
     23   /**
     24    * A map from names to lists of values.
     25    * @private
     26    * @type Object.<string, Array.<number>>
     27    */
     28   this.valueLists_ = {};
     29 
     30   /**
     31    * The first time, after this object was most recently initialized or emptied,
     32    * at which a value was added to this object.
     33    * @private
     34    * @type {?number}
     35    */
     36   this.timeOfFirstValue_ = null;
     37 };
     38 
     39 /**
     40  * Adds values to this object.
     41  *
     42  * @param {Object.<string, number>} newValues
     43  */
     44 remoting.StatsAccumulator.prototype.add = function(newValues) {
     45   for (var key in newValues) {
     46     this.getValueList(key).push(newValues[key]);
     47   }
     48   if (!this.timeOfFirstValue_) {
     49     this.timeOfFirstValue_ = new Date().getTime();
     50   }
     51 };
     52 
     53 /**
     54  * Empties this object.
     55  */
     56 remoting.StatsAccumulator.prototype.empty = function() {
     57   this.valueLists_ = {};
     58   this.timeOfFirstValue_ = null;
     59 };
     60 
     61 /**
     62  * Gets the number of milliseconds since the first value was added to this
     63  * object, after this object was most recently initialized or emptied.
     64  *
     65  * @return {number} milliseconds since the first value
     66  */
     67 remoting.StatsAccumulator.prototype.getTimeSinceFirstValue = function() {
     68   if (!this.timeOfFirstValue_) {
     69     return 0;
     70   }
     71   return new Date().getTime() - this.timeOfFirstValue_;
     72 };
     73 
     74 /**
     75  * Calculates the mean of the values for a given key.
     76  *
     77  * @param {string} key
     78  * @return {number} the mean of the values for that key
     79  */
     80 remoting.StatsAccumulator.prototype.calcMean = function(key) {
     81   /**
     82    * @param {Array.<number>} values
     83    * @return {number}
     84    */
     85   var calcMean = function(values) {
     86     if (values.length == 0) {
     87       return 0.0;
     88     }
     89     var sum = 0;
     90     for (var i = 0; i < values.length; i++) {
     91       sum += values[i];
     92     }
     93     return sum / values.length;
     94   };
     95   return this.map(key, calcMean);
     96 };
     97 
     98 /**
     99  * Applies a given map to the list of values for a given key.
    100  *
    101  * @param {string} key
    102  * @param {function(Array.<number>): number} map
    103  * @return {number} the result of applying that map to the list of values for
    104  *     that key
    105  */
    106 remoting.StatsAccumulator.prototype.map = function(key, map) {
    107   return map(this.getValueList(key));
    108 };
    109 
    110 /**
    111  * Gets the list of values for a given key.
    112  * If this object contains no values for that key, then this routine creates
    113  * an empty list, stores it in this object, and returns it.
    114  *
    115  * @private
    116  * @param {string} key
    117  * @return {Array.<number>} the list of values for that key
    118  */
    119 remoting.StatsAccumulator.prototype.getValueList = function(key) {
    120   var valueList = this.valueLists_[key];
    121   if (!valueList) {
    122     valueList = [];
    123     this.valueLists_[key] = valueList;
    124   }
    125   return valueList;
    126 };
    127