mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-13 21:35:39 +00:00
Bug 723561. Create telemetry stopwatch helper to easily store and retrieve timestamp data. r=gavin
This commit is contained in:
parent
3597d04455
commit
3f3930d9db
@ -70,6 +70,10 @@ EXTRA_COMPONENTS = \
|
||||
TelemetryPing.js \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_JS_MODULES = \
|
||||
TelemetryStopwatch.jsm \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = \
|
||||
Telemetry.cpp \
|
||||
$(NULL)
|
||||
|
100
toolkit/components/telemetry/TelemetryStopwatch.jsm
Normal file
100
toolkit/components/telemetry/TelemetryStopwatch.jsm
Normal file
@ -0,0 +1,100 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
|
||||
let EXPORTED_SYMBOLS = ["TelemetryStopwatch"];
|
||||
|
||||
let Telemetry = Cc["@mozilla.org/base/telemetry;1"]
|
||||
.getService(Ci.nsITelemetry);
|
||||
|
||||
// simpleTimers are directly associated with a histogram
|
||||
// name. objectTimers are associated with an object _and_
|
||||
// a histogram name.
|
||||
let simpleTimers = {};
|
||||
let objectTimers = new WeakMap();
|
||||
|
||||
let TelemetryStopwatch = {
|
||||
/**
|
||||
* Starts a timer associated with a telemetry histogram. The timer can be
|
||||
* directly associated with a histogram, or with a pair of a histogram and
|
||||
* an object.
|
||||
*
|
||||
* @param aHistogram a string which must be a valid histogram name
|
||||
* from TelemetryHistograms.h
|
||||
*
|
||||
* @param aObj Optional parameter. If specified, the timer is associated
|
||||
* with this object, meaning that multiple timers for a same
|
||||
* histogram may be run concurrently, as long as they are
|
||||
* associated with different objects.
|
||||
*
|
||||
* @return true if the timer was successfully started, false otherwise. If a
|
||||
* timer already exists, it can't be started again, and the existing
|
||||
* one will be cleared in order to avoid measurements errors.
|
||||
*/
|
||||
start: function(aHistogram, aObj) {
|
||||
if (!validTypes(aHistogram, aObj))
|
||||
return false;
|
||||
|
||||
let timers;
|
||||
if (aObj) {
|
||||
timers = objectTimers.get(aObj, {});
|
||||
objectTimers.set(aObj, timers);
|
||||
} else {
|
||||
timers = simpleTimers;
|
||||
}
|
||||
|
||||
if (timers.hasOwnProperty(aHistogram)) {
|
||||
delete timers[aHistogram];
|
||||
Cu.reportError("TelemetryStopwatch: key was already initialized");
|
||||
return false;
|
||||
}
|
||||
|
||||
timers[aHistogram] = Date.now();
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Stops the timer associated with the given histogram (and object),
|
||||
* calculates the time delta between start and finish, and adds the value
|
||||
* to the histogram.
|
||||
*
|
||||
* @param aHistogram a string which must be a valid histogram name
|
||||
* from TelemetryHistograms.h. If an invalid name
|
||||
* is given, the function will throw.
|
||||
*
|
||||
* @param aObj Optional parameter which associates the histogram timer with
|
||||
* the given object.
|
||||
*
|
||||
* @return true if the timer was succesfully stopped and the data was
|
||||
* added to the histogram, false otherwise.
|
||||
*/
|
||||
finish: function(aHistogram, aObj) {
|
||||
if (!validTypes(aHistogram, aObj))
|
||||
return false;
|
||||
|
||||
let timers = aObj
|
||||
? objectTimers.get(aObj, {})
|
||||
: simpleTimers;
|
||||
|
||||
let start = timers[aHistogram];
|
||||
delete timers[aHistogram];
|
||||
|
||||
if (start) {
|
||||
let delta = Date.now() - start;
|
||||
let histogram = Telemetry.getHistogramById(aHistogram);
|
||||
histogram.add(delta);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function validTypes(aKey, aObj) {
|
||||
return (typeof aKey == "string") &&
|
||||
(aObj === undefined || typeof aObj == "object");
|
||||
}
|
@ -0,0 +1,109 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
|
||||
const Telemetry = Cc["@mozilla.org/base/telemetry;1"]
|
||||
.getService(Ci.nsITelemetry);
|
||||
|
||||
let tmpScope = {};
|
||||
Cu.import("resource:///modules/TelemetryStopwatch.jsm", tmpScope);
|
||||
let TelemetryStopwatch = tmpScope.TelemetryStopwatch;
|
||||
|
||||
// We can't create a histogram here since the ones created with
|
||||
// newHistogram are not seen by getHistogramById that the module uses.
|
||||
const HIST_NAME = "TELEMETRY_PING";
|
||||
const HIST_NAME2 = "RANGE_CHECKSUM_ERRORS";
|
||||
|
||||
let refObj = {}, refObj2 = {};
|
||||
|
||||
let originalCount1, originalCount2;
|
||||
|
||||
function run_test() {
|
||||
let histogram = Telemetry.getHistogramById(HIST_NAME);
|
||||
let snapshot = histogram.snapshot();
|
||||
originalCount1 = snapshot.counts.reduce(function (a,b) a += b);
|
||||
|
||||
histogram = Telemetry.getHistogramById(HIST_NAME2);
|
||||
snapshot = histogram.snapshot();
|
||||
originalCount2 = snapshot.counts.reduce(function (a,b) a += b);
|
||||
|
||||
do_check_false(TelemetryStopwatch.start(3));
|
||||
do_check_false(TelemetryStopwatch.start({}));
|
||||
do_check_false(TelemetryStopwatch.start("", 3));
|
||||
do_check_false(TelemetryStopwatch.start("", ""));
|
||||
do_check_false(TelemetryStopwatch.start({}, {}));
|
||||
|
||||
do_check_true(TelemetryStopwatch.start("mark1"));
|
||||
do_check_true(TelemetryStopwatch.start("mark2"));
|
||||
|
||||
do_check_true(TelemetryStopwatch.start("mark1", refObj));
|
||||
do_check_true(TelemetryStopwatch.start("mark2", refObj));
|
||||
|
||||
// Same timer can't be re-started before being stopped
|
||||
do_check_false(TelemetryStopwatch.start("mark1"));
|
||||
do_check_false(TelemetryStopwatch.start("mark1", refObj));
|
||||
|
||||
// Can't stop a timer that was accidentaly started twice
|
||||
do_check_false(TelemetryStopwatch.finish("mark1"));
|
||||
do_check_false(TelemetryStopwatch.finish("mark1", refObj));
|
||||
|
||||
do_check_true(TelemetryStopwatch.start("NON-EXISTENT_HISTOGRAM"));
|
||||
try {
|
||||
TelemetryStopwatch.finish("NON-EXISTENT_HISTOGRAM");
|
||||
do_throw("Non-existent histogram name should throw an error.");
|
||||
} catch (e) {}
|
||||
|
||||
do_check_true(TelemetryStopwatch.start("NON-EXISTENT_HISTOGRAM", refObj));
|
||||
try {
|
||||
TelemetryStopwatch.finish("NON-EXISTENT_HISTOGRAM", refObj);
|
||||
do_throw("Non-existent histogram name should throw an error.");
|
||||
} catch (e) {}
|
||||
|
||||
do_check_true(TelemetryStopwatch.start(HIST_NAME));
|
||||
do_check_true(TelemetryStopwatch.start(HIST_NAME2));
|
||||
do_check_true(TelemetryStopwatch.start(HIST_NAME, refObj));
|
||||
do_check_true(TelemetryStopwatch.start(HIST_NAME2, refObj));
|
||||
do_check_true(TelemetryStopwatch.start(HIST_NAME, refObj2));
|
||||
do_check_true(TelemetryStopwatch.start(HIST_NAME2, refObj2));
|
||||
|
||||
do_check_true(TelemetryStopwatch.finish(HIST_NAME));
|
||||
do_check_true(TelemetryStopwatch.finish(HIST_NAME2));
|
||||
do_check_true(TelemetryStopwatch.finish(HIST_NAME, refObj));
|
||||
do_check_true(TelemetryStopwatch.finish(HIST_NAME2, refObj));
|
||||
do_check_true(TelemetryStopwatch.finish(HIST_NAME, refObj2));
|
||||
do_check_true(TelemetryStopwatch.finish(HIST_NAME2, refObj2));
|
||||
|
||||
// Verify that TS.finish deleted the timers
|
||||
do_check_false(TelemetryStopwatch.finish(HIST_NAME));
|
||||
do_check_false(TelemetryStopwatch.finish(HIST_NAME, refObj));
|
||||
|
||||
// Verify that they can be used again
|
||||
do_check_true(TelemetryStopwatch.start(HIST_NAME));
|
||||
do_check_true(TelemetryStopwatch.start(HIST_NAME, refObj));
|
||||
do_check_true(TelemetryStopwatch.finish(HIST_NAME));
|
||||
do_check_true(TelemetryStopwatch.finish(HIST_NAME, refObj));
|
||||
|
||||
|
||||
do_check_false(TelemetryStopwatch.finish("unknown-mark")); // Unknown marker
|
||||
do_check_false(TelemetryStopwatch.finish("unknown-mark", {})); // Unknown object
|
||||
do_check_false(TelemetryStopwatch.finish(HIST_NAME, {})); // Known mark on unknown object
|
||||
|
||||
finishTest();
|
||||
}
|
||||
|
||||
function finishTest() {
|
||||
let histogram = Telemetry.getHistogramById(HIST_NAME);
|
||||
let snapshot = histogram.snapshot();
|
||||
let newCount = snapshot.counts.reduce(function (a,b) a += b);
|
||||
|
||||
do_check_eq(newCount - originalCount1, 5, "The correct number of histograms were added for histogram 1.");
|
||||
|
||||
histogram = Telemetry.getHistogramById(HIST_NAME2);
|
||||
snapshot = histogram.snapshot();
|
||||
newCount = snapshot.counts.reduce(function (a,b) a += b);
|
||||
|
||||
do_check_eq(newCount - originalCount2, 3, "The correct number of histograms were added for histogram 2.");
|
||||
}
|
@ -7,3 +7,4 @@ tail =
|
||||
# Bug 676989: test fails consistently on Android
|
||||
# fail-if = os == "android"
|
||||
[test_TelemetryPing_idle.js]
|
||||
[test_TelemetryStopwatch.js]
|
||||
|
Loading…
Reference in New Issue
Block a user