// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. /** * @fileoverview * The webapp reads the plugin's connection statistics frequently (once per * second). It logs statistics to the server less frequently, to keep * bandwidth and storage costs down. This class bridges that gap, by * accumulating high-frequency numeric data, and providing statistics * summarising that data. */ 'use strict'; /** @suppress {duplicate} */ var remoting = remoting || {}; /** * @constructor */ remoting.StatsAccumulator = function() { /** * A map from names to lists of values. * @private * @type Object.> */ this.valueLists_ = {}; /** * The first time, after this object was most recently initialized or emptied, * at which a value was added to this object. * @private * @type {?number} */ this.timeOfFirstValue_ = null; }; /** * Adds values to this object. * * @param {Object.} newValues */ remoting.StatsAccumulator.prototype.add = function(newValues) { for (var key in newValues) { this.getValueList(key).push(newValues[key]); } if (!this.timeOfFirstValue_) { this.timeOfFirstValue_ = new Date().getTime(); } }; /** * Empties this object. */ remoting.StatsAccumulator.prototype.empty = function() { this.valueLists_ = {}; this.timeOfFirstValue_ = null; }; /** * Gets the number of milliseconds since the first value was added to this * object, after this object was most recently initialized or emptied. * * @return {number} milliseconds since the first value */ remoting.StatsAccumulator.prototype.getTimeSinceFirstValue = function() { if (!this.timeOfFirstValue_) { return 0; } return new Date().getTime() - this.timeOfFirstValue_; }; /** * Calculates the mean of the values for a given key. * * @param {string} key * @return {number} the mean of the values for that key */ remoting.StatsAccumulator.prototype.calcMean = function(key) { /** * @param {Array.} values * @return {number} */ var calcMean = function(values) { if (values.length == 0) { return 0.0; } var sum = 0; for (var i = 0; i < values.length; i++) { sum += values[i]; } return sum / values.length; }; return this.map(key, calcMean); }; /** * Applies a given map to the list of values for a given key. * * @param {string} key * @param {function(Array.): number} map * @return {number} the result of applying that map to the list of values for * that key */ remoting.StatsAccumulator.prototype.map = function(key, map) { return map(this.getValueList(key)); }; /** * Gets the list of values for a given key. * If this object contains no values for that key, then this routine creates * an empty list, stores it in this object, and returns it. * * @private * @param {string} key * @return {Array.} the list of values for that key */ remoting.StatsAccumulator.prototype.getValueList = function(key) { var valueList = this.valueLists_[key]; if (!valueList) { valueList = []; this.valueLists_[key] = valueList; } return valueList; };