--- a/ipc/chromium/src/base/histogram.cc
+++ b/ipc/chromium/src/base/histogram.cc
@@ -1043,16 +1043,71 @@ FlagHistogram::AddSampleSet(const Sample
return;
}
size_t one_index = BucketIndex(1);
if (sample.counts(one_index) == 1) {
Accumulate(1, 1, one_index);
}
}
+
+//------------------------------------------------------------------------------
+// CountHistogram:
+//------------------------------------------------------------------------------
+
+Histogram *
+CountHistogram::FactoryGet(const std::string &name, Flags flags)
+{
+ Histogram *h(nullptr);
+
+ if (!StatisticsRecorder::FindHistogram(name, &h)) {
+ CountHistogram *fh = new CountHistogram(name);
+ fh->InitializeBucketRange();
+ fh->SetFlags(flags);
+ h = StatisticsRecorder::RegisterOrDeleteDuplicate(fh);
+ }
+
+ return h;
+}
+
+CountHistogram::CountHistogram(const std::string &name)
+ : LinearHistogram(name, 1, 2, 3) {
+}
+
+Histogram::ClassType
+CountHistogram::histogram_type() const
+{
+ return COUNT_HISTOGRAM;
+}
+
+void
+CountHistogram::Accumulate(Sample value, Count count, size_t index)
+{
+ size_t zero_index = BucketIndex(0);
+ LinearHistogram::Accumulate(1, 1, zero_index);
+}
+
+void
+CountHistogram::AddSampleSet(const SampleSet& sample) {
+ DCHECK_EQ(bucket_count(), sample.size());
+ // We can't be sure the SampleSet provided came from another CountHistogram,
+ // so we at least check that the unused buckets are empty.
+
+ const size_t indices[] = { BucketIndex(0), BucketIndex(1), BucketIndex(2) };
+
+ if (sample.counts(indices[1]) != 0 || sample.counts(indices[2]) != 0) {
+ return;
+ }
+
+ if (sample.counts(indices[0]) != 0) {
+ Accumulate(1, sample.counts(indices[0]), indices[0]);
+ }
+}
+
+
//------------------------------------------------------------------------------
// CustomHistogram:
//------------------------------------------------------------------------------
Histogram* CustomHistogram::FactoryGet(const std::string& name,
const std::vector<Sample>& custom_ranges,
Flags flags) {
Histogram* histogram(NULL);
--- a/ipc/chromium/src/base/histogram.h
+++ b/ipc/chromium/src/base/histogram.h
@@ -273,16 +273,17 @@ class Histogram {
// These enums are used to facilitate deserialization of renderer histograms
// into the browser.
enum ClassType {
HISTOGRAM,
LINEAR_HISTOGRAM,
BOOLEAN_HISTOGRAM,
FLAG_HISTOGRAM,
+ COUNT_HISTOGRAM,
CUSTOM_HISTOGRAM,
NOT_VALID_IN_RENDERER
};
enum BucketLayout {
EXPONENTIAL,
LINEAR,
CUSTOM
@@ -685,16 +686,34 @@ public:
private:
explicit FlagHistogram(const std::string &name);
bool mSwitched;
DISALLOW_COPY_AND_ASSIGN(FlagHistogram);
};
+// CountHistogram only allows a single monotic counter value.
+class CountHistogram : public LinearHistogram
+{
+public:
+ static Histogram *FactoryGet(const std::string &name, Flags flags);
+
+ virtual ClassType histogram_type() const;
+
+ virtual void Accumulate(Sample value, Count count, size_t index);
+
+ virtual void AddSampleSet(const SampleSet& sample);
+
+private:
+ explicit CountHistogram(const std::string &name);
+
+ DISALLOW_COPY_AND_ASSIGN(CountHistogram);
+};
+
//------------------------------------------------------------------------------
// CustomHistogram is a histogram for a set of custom integers.
class CustomHistogram : public Histogram {
public:
static Histogram* FactoryGet(const std::string& name,
const std::vector<Sample>& custom_ranges,
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -4203,16 +4203,21 @@
"n_values": 30,
"description": "Number of telemetry pings evicted at startup"
},
"TELEMETRY_TEST_FLAG": {
"expires_in_version": "never",
"kind": "flag",
"description": "a testing histogram; not meant to be touched"
},
+ "TELEMETRY_TEST_COUNT": {
+ "expires_in_version": "never",
+ "kind": "count",
+ "description": "a testing histogram; not meant to be touched"
+ },
"STARTUP_CRASH_DETECTED": {
"expires_in_version": "never",
"kind": "flag",
"description": "Whether there was a crash during the last startup"
},
"SAFE_MODE_USAGE": {
"expires_in_version": "never",
"kind": "enumerated",
--- a/toolkit/components/telemetry/Telemetry.cpp
+++ b/toolkit/components/telemetry/Telemetry.cpp
@@ -722,17 +722,18 @@ IsExpired(const Histogram *histogram){
return histogram->histogram_name() == EXPIRED_ID;
}
nsresult
HistogramGet(const char *name, const char *expiration, uint32_t min, uint32_t max,
uint32_t bucketCount, uint32_t histogramType, Histogram **result)
{
if (histogramType != nsITelemetry::HISTOGRAM_BOOLEAN
- && histogramType != nsITelemetry::HISTOGRAM_FLAG) {
+ && histogramType != nsITelemetry::HISTOGRAM_FLAG
+ && histogramType != nsITelemetry::HISTOGRAM_COUNT) {
// Sanity checks for histogram parameters.
if (min >= max)
return NS_ERROR_ILLEGAL_VALUE;
if (bucketCount <= 2)
return NS_ERROR_ILLEGAL_VALUE;
if (min < 1)
@@ -755,16 +756,19 @@ HistogramGet(const char *name, const cha
*result = LinearHistogram::FactoryGet(name, min, max, bucketCount, Histogram::kUmaTargetedHistogramFlag);
break;
case nsITelemetry::HISTOGRAM_BOOLEAN:
*result = BooleanHistogram::FactoryGet(name, Histogram::kUmaTargetedHistogramFlag);
break;
case nsITelemetry::HISTOGRAM_FLAG:
*result = FlagHistogram::FactoryGet(name, Histogram::kUmaTargetedHistogramFlag);
break;
+ case nsITelemetry::HISTOGRAM_COUNT:
+ *result = CountHistogram::FactoryGet(name, Histogram::kUmaTargetedHistogramFlag);
+ break;
default:
return NS_ERROR_INVALID_ARG;
}
return NS_OK;
}
// O(1) histogram lookup by numeric id
nsresult
@@ -898,43 +902,47 @@ IsEmpty(const Histogram *h)
h->SnapshotSample(&ss);
return ss.counts(0) == 0 && ss.sum() == 0;
}
bool
JSHistogram_Add(JSContext *cx, unsigned argc, JS::Value *vp)
{
- JS::CallArgs args = CallArgsFromVp(argc, vp);
- if (!args.length()) {
- JS_ReportError(cx, "Expected one argument");
+ JSObject *obj = JS_THIS_OBJECT(cx, vp);
+ if (!obj) {
return false;
}
- if (!(args[0].isNumber() || args[0].isBoolean())) {
- JS_ReportError(cx, "Not a number");
- return false;
- }
-
- int32_t value;
- if (!JS::ToInt32(cx, args[0], &value)) {
- return false;
+ Histogram *h = static_cast<Histogram*>(JS_GetPrivate(obj));
+ Histogram::ClassType type = h->histogram_type();
+
+ int32_t value = 1;
+ if (type != base::CountHistogram::COUNT_HISTOGRAM) {
+ JS::CallArgs args = CallArgsFromVp(argc, vp);
+ if (!args.length()) {
+ JS_ReportError(cx, "Expected one argument");
+ return false;
+ }
+
+ if (!(args[0].isNumber() || args[0].isBoolean())) {
+ JS_ReportError(cx, "Not a number");
+ return false;
+ }
+
+ if (!JS::ToInt32(cx, args[0], &value)) {
+ return false;
+ }
}
if (TelemetryImpl::CanRecord()) {
- JSObject *obj = JS_THIS_OBJECT(cx, vp);
- if (!obj) {
- return false;
- }
-
- Histogram *h = static_cast<Histogram*>(JS_GetPrivate(obj));
h->Add(value);
}
+
return true;
-
}
bool
JSHistogram_Snapshot(JSContext *cx, unsigned argc, JS::Value *vp)
{
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
JSObject *obj = JS_THIS_OBJECT(cx, vp);
if (!obj) {
@@ -1577,20 +1585,22 @@ TelemetryImpl::UnregisterAddonHistograms
NS_IMETHODIMP
TelemetryImpl::GetHistogramSnapshots(JSContext *cx, JS::MutableHandle<JS::Value> ret)
{
JS::Rooted<JSObject*> root_obj(cx, JS_NewObject(cx, nullptr, JS::NullPtr(), JS::NullPtr()));
if (!root_obj)
return NS_ERROR_FAILURE;
ret.setObject(*root_obj);
- // Ensure that all the HISTOGRAM_FLAG histograms have been created, so
- // that their values are snapshotted.
+ // Ensure that all the HISTOGRAM_FLAG & HISTOGRAM_COUNT histograms have
+ // been created, so that their values are snapshotted.
for (size_t i = 0; i < Telemetry::HistogramCount; ++i) {
- if (gHistograms[i].histogramType == nsITelemetry::HISTOGRAM_FLAG) {
+ const uint32_t type = gHistograms[i].histogramType;
+ if (type == nsITelemetry::HISTOGRAM_FLAG ||
+ type == nsITelemetry::HISTOGRAM_COUNT) {
Histogram *h;
DebugOnly<nsresult> rv = GetHistogramByEnumId(Telemetry::ID(i), &h);
MOZ_ASSERT(NS_SUCCEEDED(rv));
}
};
StatisticsRecorder::Histograms hs;
StatisticsRecorder::GetHistograms(&hs);
--- a/toolkit/components/telemetry/gen-histogram-bucket-ranges.py
+++ b/toolkit/components/telemetry/gen-histogram-bucket-ranges.py
@@ -23,17 +23,18 @@ def main(argv):
for histogram in histogram_tools.from_file(filename):
name = histogram.name()
parameters = OrderedDict()
table = {
'boolean': '2',
'flag': '3',
'enumerated': '1',
'linear': '1',
- 'exponential': '0'
+ 'exponential': '0',
+ 'count': '4',
}
# Use __setitem__ because Python lambdas are so limited.
histogram_tools.table_dispatch(histogram.kind(), table,
lambda k: parameters.__setitem__('kind', k))
if histogram.low() == 0:
parameters['min'] = 1
else:
parameters['min'] = histogram.low()
--- a/toolkit/components/telemetry/gen-histogram-data.py
+++ b/toolkit/components/telemetry/gen-histogram-data.py
@@ -92,16 +92,19 @@ def static_assert(expression, message):
print "static_assert(%s, \"%s\");" % (expression, message)
def static_asserts_for_boolean(histogram):
pass
def static_asserts_for_flag(histogram):
pass
+def static_asserts_for_count(histogram):
+ pass
+
def static_asserts_for_enumerated(histogram):
n_values = histogram.high()
static_assert("%s > 2" % n_values,
"Not enough values for %s" % histogram.name())
def shared_static_asserts(histogram):
name = histogram.name()
low = histogram.low()
@@ -123,16 +126,17 @@ def write_histogram_static_asserts(histo
print """
// Perform the checks at the beginning of HistogramGet at
// compile time, so that incorrect histogram definitions
// give compile-time errors, not runtime errors."""
table = {
'boolean' : static_asserts_for_boolean,
'flag' : static_asserts_for_flag,
+ 'count': static_asserts_for_count,
'enumerated' : static_asserts_for_enumerated,
'linear' : static_asserts_for_linear,
'exponential' : static_asserts_for_exponential,
}
for histogram in histograms:
histogram_tools.table_dispatch(histogram.kind(), table,
lambda f: f(histogram))
--- a/toolkit/components/telemetry/histogram_tools.py
+++ b/toolkit/components/telemetry/histogram_tools.py
@@ -60,48 +60,49 @@ always_allowed_keys = ['kind', 'descript
class Histogram:
"""A class for representing a histogram definition."""
def __init__(self, name, definition):
"""Initialize a histogram named name with the given definition.
definition is a dict-like object that must contain at least the keys:
- 'kind': The kind of histogram. Must be one of 'boolean', 'flag',
- 'enumerated', 'linear', or 'exponential'.
+ 'count', 'enumerated', 'linear', or 'exponential'.
- 'description': A textual description of the histogram.
The key 'cpp_guard' is optional; if present, it denotes a preprocessor
symbol that should guard C/C++ definitions associated with the histogram."""
self.verify_attributes(name, definition)
self._name = name
self._description = definition['description']
self._kind = definition['kind']
self._cpp_guard = definition.get('cpp_guard')
self._extended_statistics_ok = definition.get('extended_statistics_ok', False)
self._expiration = definition.get('expires_in_version')
self.compute_bucket_parameters(definition)
table = { 'boolean': 'BOOLEAN',
'flag': 'FLAG',
+ 'count': 'COUNT',
'enumerated': 'LINEAR',
'linear': 'LINEAR',
'exponential': 'EXPONENTIAL' }
table_dispatch(self.kind(), table,
lambda k: self._set_nsITelemetry_kind(k))
def name(self):
"""Return the name of the histogram."""
return self._name
def description(self):
"""Return the description of the histogram."""
return self._description
def kind(self):
"""Return the kind of the histogram.
-Will be one of 'boolean', 'flag', 'enumerated', 'linear', or 'exponential'."""
+Will be one of 'boolean', 'flag', 'count', 'enumerated', 'linear', or 'exponential'."""
return self._kind
def expiration(self):
"""Return the expiration version of the histogram."""
return self._expiration
def nsITelemetry_kind(self):
"""Return the nsITelemetry constant corresponding to the kind of
@@ -132,40 +133,43 @@ associated with the histogram. Returns
"""Return True if gathering extended statistics for this histogram
is enabled."""
return self._extended_statistics_ok
def ranges(self):
"""Return an array of lower bounds for each bucket in the histogram."""
table = { 'boolean': linear_buckets,
'flag': linear_buckets,
+ 'count': linear_buckets,
'enumerated': linear_buckets,
'linear': linear_buckets,
'exponential': exponential_buckets }
return table_dispatch(self.kind(), table,
lambda p: p(self.low(), self.high(), self.n_buckets()))
def compute_bucket_parameters(self, definition):
table = {
'boolean': Histogram.boolean_flag_bucket_parameters,
'flag': Histogram.boolean_flag_bucket_parameters,
+ 'count': Histogram.boolean_flag_bucket_parameters,
'enumerated': Histogram.enumerated_bucket_parameters,
'linear': Histogram.linear_bucket_parameters,
'exponential': Histogram.exponential_bucket_parameters
}
table_dispatch(self.kind(), table,
lambda p: self.set_bucket_parameters(*p(definition)))
def verify_attributes(self, name, definition):
global always_allowed_keys
general_keys = always_allowed_keys + ['low', 'high', 'n_buckets']
table = {
'boolean': always_allowed_keys,
'flag': always_allowed_keys,
+ 'count': always_allowed_keys,
'enumerated': always_allowed_keys + ['n_values'],
'linear': general_keys,
'exponential': general_keys + ['extended_statistics_ok']
}
table_dispatch(definition['kind'], table,
lambda allowed_keys: Histogram.check_keys(name, definition, allowed_keys))
Histogram.check_expiration(name, definition)
--- a/toolkit/components/telemetry/nsITelemetry.idl
+++ b/toolkit/components/telemetry/nsITelemetry.idl
@@ -7,38 +7,41 @@
#include "nsIFile.idl"
[scriptable,function, uuid(3d3b9075-5549-4244-9c08-b64fefa1dd60)]
interface nsIFetchTelemetryDataCallback : nsISupports
{
void complete();
};
-[scriptable, uuid(4e4bfc35-dac6-4b28-ade4-7e45760051d5)]
+[scriptable, uuid(df355bbf-437d-4332-80e6-a8a54db959f3)]
interface nsITelemetry : nsISupports
{
/**
* Histogram types:
* HISTOGRAM_EXPONENTIAL - buckets increase exponentially
* HISTOGRAM_LINEAR - buckets increase linearly
* HISTOGRAM_BOOLEAN - For storing 0/1 values
* HISTOGRAM_FLAG - For storing a single value; its count is always == 1.
+ * HISTOGRAM_COUNT - For storing counter values without bucketing.
*/
const unsigned long HISTOGRAM_EXPONENTIAL = 0;
const unsigned long HISTOGRAM_LINEAR = 1;
const unsigned long HISTOGRAM_BOOLEAN = 2;
const unsigned long HISTOGRAM_FLAG = 3;
+ const unsigned long HISTOGRAM_COUNT = 4;
/*
* An object containing a snapshot from all of the currently registered histograms.
* { name1: {data1}, name2:{data2}...}
* where data is consists of the following properties:
* min - Minimal bucket size
* max - Maximum bucket size
- * histogram_type - HISTOGRAM_EXPONENTIAL, HISTOGRAM_LINEAR, or HISTOGRAM_BOOLEAN
+ * histogram_type - HISTOGRAM_EXPONENTIAL, HISTOGRAM_LINEAR, HISTOGRAM_BOOLEAN
+ * or HISTOGRAM_COUNT
* counts - array representing contents of the buckets in the histogram
* ranges - an array with calculated bucket sizes
* sum - sum of the bucket contents
* static - true for histograms defined in TelemetryHistograms.h, false for ones defined with newHistogram
*/
[implicit_jscontext]
readonly attribute jsval histogramSnapshots;
@@ -138,17 +141,17 @@ interface nsITelemetry : nsISupports
/**
* Create and return a histogram. Parameters:
*
* @param name Unique histogram name
* @param expiration Expiration version
* @param min - Minimal bucket size
* @param max - Maximum bucket size
* @param bucket_count - number of buckets in the histogram.
- * @param type - HISTOGRAM_EXPONENTIAL, HISTOGRAM_LINEAR or HISTOGRAM_BOOLEAN
+ * @param type - HISTOGRAM_EXPONENTIAL, HISTOGRAM_LINEAR, HISTOGRAM_BOOLEAN or HISTOGRAM_COUNT
* The returned object has the following functions:
* add(int) - Adds an int value to the appropriate bucket
* snapshot() - Returns a snapshot of the histogram with the same data fields as in histogramSnapshots()
* clear() - Zeros out the histogram's buckets and sum
*/
[implicit_jscontext]
jsval newHistogram(in ACString name, in ACString expiration, in uint32_t min, in uint32_t max, in uint32_t bucket_count, in unsigned long histogram_type);
@@ -187,18 +190,18 @@ interface nsITelemetry : nsISupports
* Register a histogram for an addon. Throws an error if the
* histogram name has been registered previously.
*
* @param addon_id - Unique ID of the addon
* @param name - Unique histogram name
* @param min - Minimal bucket size
* @param max - Maximum bucket size
* @param bucket_count - number of buckets in the histogram
- * @param histogram_type - HISTOGRAM_EXPONENTIAL, HISTOGRAM_LINEAR, or
- * HISTOGRAM_BOOLEAN
+ * @param histogram_type - HISTOGRAM_EXPONENTIAL, HISTOGRAM_LINEAR,
+ * HISTOGRAM_BOOLEAN or HISTOGRAM_COUNT
*/
void registerAddonHistogram(in ACString addon_id, in ACString name,
in uint32_t min, in uint32_t max,
in uint32_t bucket_count,
in unsigned long histogram_type);
/**
* Return a histogram previously registered via
--- a/toolkit/components/telemetry/tests/unit/head.js
+++ b/toolkit/components/telemetry/tests/unit/head.js
@@ -1,15 +1,16 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// copied from toolkit/mozapps/extensions/test/xpcshell/head_addons.js
const XULAPPINFO_CONTRACTID = "@mozilla.org/xre/app-info;1";
const XULAPPINFO_CID = Components.ID("{c763b610-9d49-455a-bbd2-ede71682a1ac}");
+let gAppInfo;
function createAppInfo(id, name, version, platformVersion) {
gAppInfo = {
// nsIXULAppInfo
vendor: "Mozilla",
name: name,
ID: id,
version: version,
--- a/toolkit/components/telemetry/tests/unit/test_TelemetryPing.js
+++ b/toolkit/components/telemetry/tests/unit/test_TelemetryPing.js
@@ -85,18 +85,20 @@ function registerPingHandler(handler) {
}
function setupTestData() {
Telemetry.newHistogram(IGNORE_HISTOGRAM, "never", 1, 2, 3, Telemetry.HISTOGRAM_BOOLEAN);
Telemetry.histogramFrom(IGNORE_CLONED_HISTOGRAM, IGNORE_HISTOGRAM_TO_CLONE);
Services.startup.interrupted = true;
Telemetry.registerAddonHistogram(ADDON_NAME, ADDON_HISTOGRAM, 1, 5, 6,
Telemetry.HISTOGRAM_LINEAR);
- h1 = Telemetry.getAddonHistogram(ADDON_NAME, ADDON_HISTOGRAM);
+ let h1 = Telemetry.getAddonHistogram(ADDON_NAME, ADDON_HISTOGRAM);
h1.add(1);
+ let h2 = Telemetry.getHistogramById("TELEMETRY_TEST_COUNT");
+ h2.add();
}
function getSavedHistogramsFile(basename) {
let tmpDir = Services.dirsvc.get("ProfD", Ci.nsIFile);
let histogramsFile = tmpDir.clone();
histogramsFile.append(basename);
if (histogramsFile.exists()) {
histogramsFile.remove(true);
@@ -221,19 +223,24 @@ function checkPayload(request, reason, s
if (isWindows) {
do_check_true(payload.simpleMeasurements.startupSessionRestoreReadBytes > 0);
do_check_true(payload.simpleMeasurements.startupSessionRestoreWriteBytes > 0);
}
const TELEMETRY_PING = "TELEMETRY_PING";
const TELEMETRY_SUCCESS = "TELEMETRY_SUCCESS";
const TELEMETRY_TEST_FLAG = "TELEMETRY_TEST_FLAG";
+ const TELEMETRY_TEST_COUNT = "TELEMETRY_TEST_COUNT";
const READ_SAVED_PING_SUCCESS = "READ_SAVED_PING_SUCCESS";
+
do_check_true(TELEMETRY_PING in payload.histograms);
do_check_true(READ_SAVED_PING_SUCCESS in payload.histograms);
+ do_check_true(TELEMETRY_TEST_FLAG in payload.histograms);
+ do_check_true(TELEMETRY_TEST_COUNT in payload.histograms);
+
let rh = Telemetry.registeredHistograms([]);
for (let name of rh) {
if (/SQLITE/.test(name) && name in payload.histograms) {
do_check_true(("STARTUP_" + name) in payload.histograms);
}
}
do_check_false(IGNORE_HISTOGRAM in payload.histograms);
do_check_false(IGNORE_CLONED_HISTOGRAM in payload.histograms);
@@ -246,16 +253,29 @@ function checkPayload(request, reason, s
values: {0:1, 1:0},
sum: 0,
sum_squares_lo: 0,
sum_squares_hi: 0
};
let flag = payload.histograms[TELEMETRY_TEST_FLAG];
do_check_eq(uneval(flag), uneval(expected_flag));
+ // We should have a test count.
+ const expected_count = {
+ range: [1, 2],
+ bucket_count: 3,
+ histogram_type: 4,
+ values: {0:1, 1:0},
+ sum: 1,
+ sum_squares_lo: 1,
+ sum_squares_hi: 0,
+ };
+ let count = payload.histograms[TELEMETRY_TEST_COUNT];
+ do_check_eq(uneval(count), uneval(expected_count));
+
// There should be one successful report from the previous telemetry ping.
const expected_tc = {
range: [1, 2],
bucket_count: 3,
histogram_type: 2,
values: {0:1, 1:successfulPings, 2:0},
sum: successfulPings,
sum_squares_lo: successfulPings,
--- a/toolkit/components/telemetry/tests/unit/test_nsITelemetry.js
+++ b/toolkit/components/telemetry/tests/unit/test_nsITelemetry.js
@@ -167,16 +167,33 @@ function test_flag_histogram()
h.add(3);
var c3 = h.snapshot().counts;
var s3 = h.snapshot().sum;
do_check_eq(uneval(c3), uneval([0, 1, 0]));
do_check_eq(s3, 1);
do_check_eq(h.snapshot().histogram_type, Telemetry.FLAG_HISTOGRAM);
}
+function test_count_histogram()
+{
+ let h = Telemetry.newHistogram("test::count histogram", "never", 1, 2, 3, Telemetry.HISTOGRAM_COUNT);
+ let s = h.snapshot();
+ do_check_eq(uneval(s.ranges), uneval([0, 1, 2]));
+ do_check_eq(uneval(s.counts), uneval([0, 0, 0]));
+ do_check_eq(s.sum, 0);
+ h.add();
+ s = h.snapshot();
+ do_check_eq(uneval(s.counts), uneval([1, 0, 0]));
+ do_check_eq(s.sum, 1);
+ h.add();
+ s = h.snapshot();
+ do_check_eq(uneval(s.counts), uneval([2, 0, 0]));
+ do_check_eq(s.sum, 2);
+}
+
function test_getHistogramById() {
try {
Telemetry.getHistogramById("nonexistent");
do_throw("This can't happen");
} catch (e) {
}
var h = Telemetry.getHistogramById("CYCLE_COLLECTOR");
@@ -212,31 +229,37 @@ function compareHistograms(h1, h2) {
}
function test_histogramFrom() {
// Test one histogram of each type.
let names = [
"CYCLE_COLLECTOR", // EXPONENTIAL
"GC_REASON_2", // LINEAR
"GC_RESET", // BOOLEAN
- "TELEMETRY_TEST_FLAG" // FLAG
+ "TELEMETRY_TEST_FLAG", // FLAG
+ "TELEMETRY_TEST_COUNT", // COUNT
];
for each (let name in names) {
let [min, max, bucket_count] = [1, INT_MAX - 1, 10]
let original = Telemetry.getHistogramById(name);
let clone = Telemetry.histogramFrom("clone" + name, name);
compareHistograms(original, clone);
}
- // Additionally, set the flag on TELEMETRY_TEST_FLAG, and check it gets set on the clone.
+ // Additionally, set TELEMETRY_TEST_FLAG and TELEMETRY_TEST_COUNT
+ // and check they get set on the clone.
let testFlag = Telemetry.getHistogramById("TELEMETRY_TEST_FLAG");
testFlag.add(1);
+ let testCount = Telemetry.getHistogramById("TELEMETRY_TEST_COUNT");
+ testCount.add();
let clone = Telemetry.histogramFrom("FlagClone", "TELEMETRY_TEST_FLAG");
compareHistograms(testFlag, clone);
+ clone = Telemetry.histogramFrom("CountClone", "TELEMETRY_TEST_COUNT");
+ compareHistograms(testCount, clone);
}
function test_getSlowSQL() {
var slow = Telemetry.slowSQL;
do_check_true(("mainThread" in slow) && ("otherThreads" in slow));
}
function test_addons() {
@@ -373,16 +396,17 @@ function run_test()
}
// Instantiate the storage for this histogram and make sure it doesn't
// get reflected into JS, as it has no interesting data in it.
let h = Telemetry.getHistogramById("NEWTAB_PAGE_PINNED_SITES_COUNT");
do_check_false("NEWTAB_PAGE_PINNED_SITES_COUNT" in Telemetry.histogramSnapshots);
test_boolean_histogram();
+ test_count_histogram();
test_getHistogramById();
test_histogramFrom();
test_getSlowSQL();
test_privateMode();
test_addons();
test_extended_stats();
test_expired_histogram();
}