1061 lines
31 KiB
JavaScript
1061 lines
31 KiB
JavaScript
/* Any copyright is dedicated to the Public Domain.
|
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
|
|
const INT_MAX = 0x7fffffff;
|
|
|
|
// Return an array of numbers from lower up to, excluding, upper
|
|
function numberRange(lower, upper) {
|
|
let a = [];
|
|
for (let i = lower; i < upper; ++i) {
|
|
a.push(i);
|
|
}
|
|
return a;
|
|
}
|
|
|
|
function check_histogram(glean_name, histogram_type, name, min, max) {
|
|
function add(val) {
|
|
let metric = Glean.testOnlyIpc[glean_name];
|
|
if (metric.accumulate) {
|
|
metric.accumulate(val);
|
|
} else {
|
|
metric.accumulateSingleSample(val);
|
|
}
|
|
}
|
|
var h = Telemetry.getHistogramById(name);
|
|
add(0);
|
|
var s = h.snapshot();
|
|
Assert.equal(0, s.sum);
|
|
|
|
var hgrams = Telemetry.getSnapshotForHistograms("main", false).parent;
|
|
let gh = hgrams[name];
|
|
Assert.equal(gh.histogram_type, histogram_type);
|
|
|
|
Assert.deepEqual(gh.range, [min, max]);
|
|
|
|
// Check that booleans work with nonboolean histograms
|
|
add(false);
|
|
add(true);
|
|
s = Object.values(h.snapshot().values);
|
|
Assert.deepEqual(s, [2, 1, 0]);
|
|
|
|
// Check that clearing works.
|
|
h.clear();
|
|
s = h.snapshot();
|
|
Assert.deepEqual(s.values, {});
|
|
Assert.equal(s.sum, 0);
|
|
|
|
add(0);
|
|
add(1);
|
|
var c = Object.values(h.snapshot().values);
|
|
Assert.deepEqual(c, [1, 1, 0]);
|
|
}
|
|
|
|
// This MUST be the very first test of this file.
|
|
add_task(
|
|
{
|
|
skip_if: () => gIsAndroid,
|
|
},
|
|
function test_instantiate() {
|
|
const ID = "TELEMETRY_TEST_COUNT";
|
|
let h = Telemetry.getHistogramById(ID);
|
|
|
|
// Instantiate the subsession histogram through |add| and make sure they match.
|
|
// This MUST be the first use of "TELEMETRY_TEST_COUNT" in this file, otherwise
|
|
// |add| will not instantiate the histogram.
|
|
Glean.testOnlyIpc.aCounterForHgram.add();
|
|
let snapshot = h.snapshot();
|
|
let subsession = Telemetry.getSnapshotForHistograms(
|
|
"main",
|
|
false /* clear */
|
|
).parent;
|
|
Assert.ok(ID in subsession);
|
|
Assert.equal(
|
|
snapshot.sum,
|
|
subsession[ID].sum,
|
|
"Histogram and subsession histogram sum must match."
|
|
);
|
|
// Clear the histogram, so we don't void the assumptions from the other tests.
|
|
h.clear();
|
|
}
|
|
);
|
|
|
|
add_task(async function test_parameterChecks() {
|
|
let kinds = [Telemetry.HISTOGRAM_EXPONENTIAL, Telemetry.HISTOGRAM_LINEAR];
|
|
let testNames = ["TELEMETRY_TEST_EXPONENTIAL", "TELEMETRY_TEST_LINEAR"];
|
|
let gleanNames = ["aTimingDist", "aMemoryDist"];
|
|
for (let i = 0; i < kinds.length; i++) {
|
|
let histogram_type = kinds[i];
|
|
let test_type = testNames[i];
|
|
let glean_name = gleanNames[i];
|
|
let [min, max, bucket_count] = [1, INT_MAX - 1, 10];
|
|
check_histogram(
|
|
glean_name,
|
|
histogram_type,
|
|
test_type,
|
|
min,
|
|
max,
|
|
bucket_count
|
|
);
|
|
}
|
|
});
|
|
|
|
add_task(async function test_parameterCountsKeyed() {
|
|
let histogramIds = [
|
|
"TELEMETRY_TEST_KEYED_BOOLEAN",
|
|
"TELEMETRY_TEST_KEYED_EXPONENTIAL",
|
|
"TELEMETRY_TEST_KEYED_LINEAR",
|
|
];
|
|
|
|
for (let id of histogramIds) {
|
|
let h = Telemetry.getKeyedHistogramById(id);
|
|
h.clear();
|
|
h.add("key");
|
|
Assert.deepEqual(
|
|
h.snapshot(),
|
|
{},
|
|
"Calling add('key') without a value should only log an error."
|
|
);
|
|
h.clear();
|
|
}
|
|
});
|
|
|
|
add_task(async function test_noSerialization() {
|
|
// Instantiate the storage for this histogram and make sure it doesn't
|
|
// get reflected into JS, as it has no interesting data in it.
|
|
Telemetry.getHistogramById("NEWTAB_PAGE_PINNED_SITES_COUNT");
|
|
let histograms = Telemetry.getSnapshotForHistograms(
|
|
"main",
|
|
false /* clear */
|
|
).parent;
|
|
Assert.equal(false, "NEWTAB_PAGE_PINNED_SITES_COUNT" in histograms);
|
|
});
|
|
|
|
add_task(async function test_boolean_histogram() {
|
|
var h = Telemetry.getHistogramById("TELEMETRY_TEST_BOOLEAN");
|
|
var r = h.snapshot().range;
|
|
// boolean histograms ignore numeric parameters
|
|
Assert.deepEqual(r, [1, 2]);
|
|
|
|
Glean.testOnlyIpc.aLabeledCounterForHgram.true.add();
|
|
Glean.testOnlyIpc.aLabeledCounterForHgram.false.add();
|
|
var s = h.snapshot();
|
|
Assert.equal(s.histogram_type, Telemetry.HISTOGRAM_BOOLEAN);
|
|
Assert.deepEqual(s.values, { 0: 1, 1: 1, 2: 0 });
|
|
Assert.equal(s.sum, 1);
|
|
});
|
|
|
|
add_task(async function test_count_histogram() {
|
|
let h = Telemetry.getHistogramById("TELEMETRY_TEST_COUNT");
|
|
h.clear();
|
|
let s = h.snapshot();
|
|
Assert.deepEqual(s.range, [1, 2]);
|
|
Assert.deepEqual(s.values, {});
|
|
Assert.equal(s.sum, 0);
|
|
Glean.testOnlyIpc.aCounterForHgram.add();
|
|
s = h.snapshot();
|
|
Assert.deepEqual(s.values, { 0: 1, 1: 0 });
|
|
Assert.equal(s.sum, 1);
|
|
Glean.testOnlyIpc.aCounterForHgram.add();
|
|
s = h.snapshot();
|
|
Assert.deepEqual(s.values, { 0: 2, 1: 0 });
|
|
Assert.equal(s.sum, 2);
|
|
});
|
|
|
|
add_task(async function test_categorical_histogram() {
|
|
let h = Telemetry.getHistogramById("TELEMETRY_TEST_CATEGORICAL_OPTOUT");
|
|
for (let v of [
|
|
"CommonLabel",
|
|
"CommonLabel",
|
|
"Label4",
|
|
"Label5",
|
|
"Label6",
|
|
0,
|
|
1,
|
|
]) {
|
|
Glean.testOnlyIpc.aLabeledCounterForCategorical[v].add();
|
|
}
|
|
for (let s of ["", "Label3", "1234"]) {
|
|
// Should not throw for unexpected values.
|
|
Glean.testOnlyIpc.aLabeledCounterForCategorical[s].add();
|
|
}
|
|
|
|
let snapshot = h.snapshot();
|
|
Assert.equal(snapshot.sum, 6);
|
|
Assert.deepEqual(snapshot.range, [1, 50]);
|
|
Assert.deepEqual(snapshot.values, { 0: 2, 1: 1, 2: 1, 3: 1, 4: 0 });
|
|
});
|
|
|
|
add_task(async function test_getCategoricalLabels() {
|
|
let h = Telemetry.getCategoricalLabels();
|
|
|
|
Assert.deepEqual(h.TELEMETRY_TEST_CATEGORICAL, [
|
|
"CommonLabel",
|
|
"Label2",
|
|
"Label3",
|
|
]);
|
|
Assert.deepEqual(h.TELEMETRY_TEST_CATEGORICAL_OPTOUT, [
|
|
"CommonLabel",
|
|
"Label4",
|
|
"Label5",
|
|
"Label6",
|
|
]);
|
|
Assert.deepEqual(h.TELEMETRY_TEST_CATEGORICAL_NVALUES, [
|
|
"CommonLabel",
|
|
"Label7",
|
|
"Label8",
|
|
]);
|
|
Assert.deepEqual(h.TELEMETRY_TEST_KEYED_CATEGORICAL, [
|
|
"CommonLabel",
|
|
"Label2",
|
|
"Label3",
|
|
]);
|
|
});
|
|
|
|
add_task(async function test_add_error_behaviour() {
|
|
const KEYED_HISTOGRAMS_TO_TEST = [
|
|
"TELEMETRY_TEST_KEYED_COUNT",
|
|
"TELEMETRY_TEST_KEYED_BOOLEAN",
|
|
];
|
|
|
|
// Check that |add| doesn't throw for keyed histograms.
|
|
for (let hist of KEYED_HISTOGRAMS_TO_TEST) {
|
|
const returnValue = Telemetry.getKeyedHistogramById(hist).add(
|
|
"some-key",
|
|
"unexpected-value"
|
|
);
|
|
Assert.strictEqual(
|
|
returnValue,
|
|
undefined,
|
|
"Adding to a keyed histogram must return 'undefined'."
|
|
);
|
|
}
|
|
});
|
|
|
|
add_task(async function test_API_return_values() {
|
|
// Check that the plain scalar functions don't allow to crash the browser.
|
|
// We expect 'undefined' to be returned so that .add(1).add() can't be called.
|
|
// See bug 1321349 for context.
|
|
let keyedHist = Telemetry.getKeyedHistogramById("TELEMETRY_TEST_KEYED_COUNT");
|
|
|
|
const RETURN_VALUES = [keyedHist.clear(), keyedHist.add("some-key", 1)];
|
|
|
|
for (let returnValue of RETURN_VALUES) {
|
|
Assert.strictEqual(
|
|
returnValue,
|
|
undefined,
|
|
"The function must return undefined"
|
|
);
|
|
}
|
|
});
|
|
|
|
add_task(async function test_getHistogramById() {
|
|
try {
|
|
Telemetry.getHistogramById("nonexistent");
|
|
do_throw("This can't happen");
|
|
} catch (e) {}
|
|
var h = Telemetry.getHistogramById("CYCLE_COLLECTOR");
|
|
var s = h.snapshot();
|
|
Assert.equal(s.histogram_type, Telemetry.HISTOGRAM_EXPONENTIAL);
|
|
Assert.deepEqual(s.range, [1, 10000]);
|
|
});
|
|
|
|
add_task(async function test_getSlowSQL() {
|
|
var slow = Telemetry.slowSQL;
|
|
Assert.ok("mainThread" in slow && "otherThreads" in slow);
|
|
});
|
|
|
|
// Check that telemetry doesn't record in private mode
|
|
add_task(async function test_privateMode() {
|
|
var h = Telemetry.getHistogramById("TELEMETRY_TEST_BOOLEAN");
|
|
var orig = h.snapshot();
|
|
Telemetry.canRecordExtended = false;
|
|
Glean.testOnlyIpc.aLabeledCounterForHgram.true.add();
|
|
Assert.deepEqual(orig, h.snapshot());
|
|
Telemetry.canRecordExtended = true;
|
|
Glean.testOnlyIpc.aLabeledCounterForHgram.true.add();
|
|
Assert.notDeepEqual(orig, h.snapshot());
|
|
});
|
|
|
|
add_task(async function test_expired_histogram() {
|
|
var test_expired_id = "TELEMETRY_TEST_EXPIRED";
|
|
Glean.testOnly.expiredHist.accumulateSingleSample(1);
|
|
|
|
for (let process of ["main", "content", "gpu", "extension"]) {
|
|
let histograms = Telemetry.getSnapshotForHistograms(
|
|
"main",
|
|
false /* clear */
|
|
);
|
|
if (!(process in histograms)) {
|
|
info("Nothing present for process " + process);
|
|
continue;
|
|
}
|
|
Assert.equal(histograms[process].__expired__, undefined);
|
|
}
|
|
let parentHgrams = Telemetry.getSnapshotForHistograms(
|
|
"main",
|
|
false /* clear */
|
|
).parent;
|
|
Assert.equal(parentHgrams[test_expired_id], undefined);
|
|
});
|
|
|
|
add_task(async function test_keyed_expired_histogram() {
|
|
var test_expired_id = "TELEMETRY_TEST_EXPIRED_KEYED";
|
|
var dummy = Telemetry.getKeyedHistogramById(test_expired_id);
|
|
dummy.add("someKey", 1);
|
|
|
|
const histograms = Telemetry.getSnapshotForKeyedHistograms(
|
|
"main",
|
|
false /* clear */
|
|
);
|
|
for (let process of ["parent", "content", "gpu", "extension"]) {
|
|
if (!(process in histograms)) {
|
|
info("Nothing present for process " + process);
|
|
continue;
|
|
}
|
|
Assert.ok(
|
|
!(test_expired_id in histograms[process]),
|
|
"The expired keyed histogram must not be reported"
|
|
);
|
|
}
|
|
});
|
|
|
|
add_task(async function test_keyed_histogram() {
|
|
// Check that invalid names get rejected.
|
|
|
|
let threw = false;
|
|
try {
|
|
Telemetry.getKeyedHistogramById(
|
|
"test::unknown histogram",
|
|
"never",
|
|
Telemetry.HISTOGRAM_BOOLEAN
|
|
);
|
|
} catch (e) {
|
|
// This should throw as it is an unknown ID
|
|
threw = true;
|
|
}
|
|
Assert.ok(threw, "getKeyedHistogramById should have thrown");
|
|
});
|
|
|
|
add_task(async function test_keyed_boolean_histogram() {
|
|
const KEYED_ID = "TELEMETRY_TEST_KEYED_BOOLEAN";
|
|
let KEYS = numberRange(0, 2).map(i => "key" + (i + 1));
|
|
KEYS.push("漢語");
|
|
let histogramBase = {
|
|
range: [1, 2],
|
|
bucket_count: 3,
|
|
histogram_type: 2,
|
|
sum: 1,
|
|
values: { 0: 0, 1: 1, 2: 0 },
|
|
};
|
|
let testHistograms = numberRange(0, 3).map(() =>
|
|
JSON.parse(JSON.stringify(histogramBase))
|
|
);
|
|
let testKeys = [];
|
|
let testSnapShot = {};
|
|
|
|
let h = Telemetry.getKeyedHistogramById(KEYED_ID);
|
|
for (let i = 0; i < 2; ++i) {
|
|
let key = KEYS[i];
|
|
h.add(key, true);
|
|
testSnapShot[key] = testHistograms[i];
|
|
testKeys.push(key);
|
|
|
|
Assert.deepEqual(h.keys().sort(), testKeys);
|
|
Assert.deepEqual(h.snapshot(), testSnapShot);
|
|
}
|
|
|
|
h = Telemetry.getKeyedHistogramById(KEYED_ID);
|
|
Assert.deepEqual(h.keys().sort(), testKeys);
|
|
Assert.deepEqual(h.snapshot(), testSnapShot);
|
|
|
|
let key = KEYS[2];
|
|
h.add(key, false);
|
|
testKeys.push(key);
|
|
testSnapShot[key] = testHistograms[2];
|
|
testSnapShot[key].sum = 0;
|
|
testSnapShot[key].values = { 0: 1, 1: 0 };
|
|
Assert.deepEqual(h.keys().sort(), testKeys);
|
|
Assert.deepEqual(h.snapshot(), testSnapShot);
|
|
|
|
let parentHgrams = Telemetry.getSnapshotForKeyedHistograms(
|
|
"main",
|
|
false /* clear */
|
|
).parent;
|
|
Assert.deepEqual(parentHgrams[KEYED_ID], testSnapShot);
|
|
|
|
h.clear();
|
|
Assert.deepEqual(h.keys(), []);
|
|
Assert.deepEqual(h.snapshot(), {});
|
|
});
|
|
|
|
add_task(async function test_keyed_count_histogram() {
|
|
const KEYED_ID = "TELEMETRY_TEST_KEYED_COUNT";
|
|
const KEYS = numberRange(0, 5).map(i => "key" + (i + 1));
|
|
let histogramBase = {
|
|
range: [1, 2],
|
|
bucket_count: 3,
|
|
histogram_type: 4,
|
|
sum: 0,
|
|
values: { 0: 1, 1: 0 },
|
|
};
|
|
let testHistograms = numberRange(0, 5).map(() =>
|
|
JSON.parse(JSON.stringify(histogramBase))
|
|
);
|
|
let testKeys = [];
|
|
let testSnapShot = {};
|
|
|
|
let h = Telemetry.getKeyedHistogramById(KEYED_ID);
|
|
h.clear();
|
|
for (let i = 0; i < 4; ++i) {
|
|
let key = KEYS[i];
|
|
let value = i * 2 + 1;
|
|
|
|
for (let k = 0; k < value; ++k) {
|
|
h.add(key);
|
|
}
|
|
testHistograms[i].values[0] = value;
|
|
testHistograms[i].sum = value;
|
|
testSnapShot[key] = testHistograms[i];
|
|
testKeys.push(key);
|
|
|
|
Assert.deepEqual(h.keys().sort(), testKeys);
|
|
Assert.deepEqual(h.snapshot()[key], testHistograms[i]);
|
|
Assert.deepEqual(h.snapshot(), testSnapShot);
|
|
}
|
|
|
|
h = Telemetry.getKeyedHistogramById(KEYED_ID);
|
|
Assert.deepEqual(h.keys().sort(), testKeys);
|
|
Assert.deepEqual(h.snapshot(), testSnapShot);
|
|
|
|
let key = KEYS[4];
|
|
h.add(key);
|
|
testKeys.push(key);
|
|
testHistograms[4].values[0] = 1;
|
|
testHistograms[4].sum = 1;
|
|
testSnapShot[key] = testHistograms[4];
|
|
|
|
Assert.deepEqual(h.keys().sort(), testKeys);
|
|
Assert.deepEqual(h.snapshot(), testSnapShot);
|
|
|
|
let parentHgrams = Telemetry.getSnapshotForKeyedHistograms(
|
|
"main",
|
|
false /* clear */
|
|
).parent;
|
|
Assert.deepEqual(parentHgrams[KEYED_ID], testSnapShot);
|
|
|
|
// Test clearing categorical histogram.
|
|
h.clear();
|
|
Assert.deepEqual(h.keys(), []);
|
|
Assert.deepEqual(h.snapshot(), {});
|
|
|
|
// Test leaving out the value argument. That should increment by 1.
|
|
h.add("key");
|
|
Assert.equal(h.snapshot().key.sum, 1);
|
|
});
|
|
|
|
add_task(async function test_keyed_categorical_histogram() {
|
|
const KEYED_ID = "TELEMETRY_TEST_KEYED_CATEGORICAL";
|
|
const KEYS = numberRange(0, 5).map(i => "key" + (i + 1));
|
|
|
|
let h = Telemetry.getKeyedHistogramById(KEYED_ID);
|
|
|
|
for (let k of KEYS) {
|
|
// Test adding both per label and index.
|
|
for (let v of ["CommonLabel", "Label2", "Label3", "Label3", 0, 0, 1]) {
|
|
h.add(k, v);
|
|
}
|
|
|
|
// The |add| method should not throw for unexpected values, but rather
|
|
// print an error message in the console.
|
|
for (let s of ["", "Label4", "1234"]) {
|
|
h.add(k, s);
|
|
}
|
|
}
|
|
|
|
// Check that the set of keys in the snapshot is what we expect.
|
|
let snapshot = h.snapshot();
|
|
let snapshotKeys = Object.keys(snapshot);
|
|
Assert.equal(KEYS.length, snapshotKeys.length);
|
|
Assert.ok(KEYS.every(k => snapshotKeys.includes(k)));
|
|
|
|
// Check the snapshot values.
|
|
for (let k of KEYS) {
|
|
Assert.ok(k in snapshot);
|
|
Assert.equal(snapshot[k].sum, 6);
|
|
Assert.deepEqual(snapshot[k].range, [1, 50]);
|
|
Assert.deepEqual(snapshot[k].values, { 0: 3, 1: 2, 2: 2, 3: 0 });
|
|
}
|
|
});
|
|
|
|
add_task(async function test_histogramSnapshots() {
|
|
let keyed = Telemetry.getKeyedHistogramById("TELEMETRY_TEST_KEYED_COUNT");
|
|
keyed.add("a", 1);
|
|
|
|
// Check that keyed histograms are not returned
|
|
let parentHgrams = Telemetry.getSnapshotForHistograms(
|
|
"main",
|
|
false /* clear */
|
|
).parent;
|
|
Assert.ok(!("TELEMETRY_TEST_KEYED_COUNT" in parentHgrams));
|
|
});
|
|
|
|
add_task(async function test_keyed_keys() {
|
|
let h = Telemetry.getKeyedHistogramById("TELEMETRY_TEST_KEYED_KEYS");
|
|
h.clear();
|
|
Telemetry.clearScalars();
|
|
|
|
// The |add| method should not throw for keys that are not allowed.
|
|
h.add("testkey", true);
|
|
h.add("thirdKey", false);
|
|
h.add("not-allowed", true);
|
|
|
|
// Check that we have the expected keys.
|
|
let snap = h.snapshot();
|
|
Assert.equal(Object.keys(snap).length, 2, "Only 2 keys must be recorded.");
|
|
Assert.ok("testkey" in snap, "'testkey' must be recorded.");
|
|
Assert.ok("thirdKey" in snap, "'thirdKey' must be recorded.");
|
|
Assert.deepEqual(
|
|
snap.testkey.values,
|
|
{ 0: 0, 1: 1, 2: 0 },
|
|
"'testkey' must contain the correct value."
|
|
);
|
|
Assert.deepEqual(
|
|
snap.thirdKey.values,
|
|
{ 0: 1, 1: 0 },
|
|
"'thirdKey' must contain the correct value."
|
|
);
|
|
|
|
// Keys that are not allowed must not be recorded.
|
|
Assert.ok(!("not-allowed" in snap), "'not-allowed' must not be recorded.");
|
|
|
|
// Check that these failures were correctly tracked.
|
|
const parentScalars = Telemetry.getSnapshotForKeyedScalars(
|
|
"main",
|
|
false
|
|
).parent;
|
|
const scalarName = "telemetry.accumulate_unknown_histogram_keys";
|
|
Assert.ok(
|
|
scalarName in parentScalars,
|
|
"Accumulation to unallowed keys must be reported."
|
|
);
|
|
Assert.ok(
|
|
"TELEMETRY_TEST_KEYED_KEYS" in parentScalars[scalarName],
|
|
"Accumulation to unallowed keys must be recorded with the correct key."
|
|
);
|
|
Assert.equal(
|
|
parentScalars[scalarName].TELEMETRY_TEST_KEYED_KEYS,
|
|
1,
|
|
"Accumulation to unallowed keys must report the correct value."
|
|
);
|
|
});
|
|
|
|
add_task(async function test_keyed_no_arguments() {
|
|
// Test for no accumulation when add is called with no arguments
|
|
let h = Telemetry.getKeyedHistogramById("TELEMETRY_TEST_KEYED_LINEAR");
|
|
h.clear();
|
|
|
|
h.add();
|
|
|
|
// No keys should be added due to no accumulation.
|
|
Assert.equal(h.keys().length, 0);
|
|
});
|
|
|
|
add_task(async function test_keyed_categorical_invalid_string() {
|
|
// Test for no accumulation when add is called on a
|
|
// keyed categorical histogram with an invalid string label.
|
|
let h = Telemetry.getKeyedHistogramById("TELEMETRY_TEST_KEYED_CATEGORICAL");
|
|
h.clear();
|
|
|
|
h.add("someKey", "#notALabel");
|
|
|
|
// No keys should be added due to no accumulation.
|
|
Assert.equal(h.keys().length, 0);
|
|
});
|
|
|
|
add_task(async function test_keyed_count_multiple_samples() {
|
|
let valid = [1, 1, 3, 0];
|
|
let invalid = ["1", "0", "", "random"];
|
|
let key = "somekeystring";
|
|
|
|
let h = Telemetry.getKeyedHistogramById("TELEMETRY_TEST_KEYED_COUNT");
|
|
h.clear();
|
|
|
|
// If the array contains even a single invalid value, no accumulation should take place
|
|
// Keep the valid values in front of invalid to check if it is simply accumulating as
|
|
// it's traversing the array and throwing upon first invalid value. That should not happen.
|
|
h.add(key, valid.concat(invalid));
|
|
let s1 = h.snapshot();
|
|
Assert.ok(!(key in s1));
|
|
|
|
h.add(key, valid);
|
|
let s2 = h.snapshot()[key];
|
|
Assert.deepEqual(s2.values, { 0: 4, 1: 0 });
|
|
Assert.equal(s2.sum, 5);
|
|
});
|
|
|
|
add_task(async function test_keyed_categorical_multiple_samples() {
|
|
let h = Telemetry.getKeyedHistogramById("TELEMETRY_TEST_KEYED_CATEGORICAL");
|
|
h.clear();
|
|
let valid = ["CommonLabel", "Label2", "Label3", "Label3", 0, 0, 1];
|
|
let invalid = ["", "Label4", "1234", "0", "1", 5000];
|
|
let key = "somekeystring";
|
|
|
|
// At least one invalid parameter, so no accumulation should happen here
|
|
// Valid values in front of invalid.
|
|
h.add(key, valid.concat(invalid));
|
|
let s1 = h.snapshot();
|
|
Assert.ok(!(key in s1));
|
|
|
|
h.add(key, valid);
|
|
let snapshot = h.snapshot()[key];
|
|
Assert.equal(snapshot.sum, 6);
|
|
Assert.deepEqual(Object.values(snapshot.values), [3, 2, 2, 0]);
|
|
});
|
|
|
|
add_task(async function test_keyed_boolean_multiple_samples() {
|
|
let valid = [true, false, 0, 1, 2];
|
|
let invalid = ["", "0", "1", ",2", "true", "false", "random"];
|
|
let key = "somekey";
|
|
|
|
let h = Telemetry.getKeyedHistogramById("TELEMETRY_TEST_KEYED_BOOLEAN");
|
|
h.clear();
|
|
|
|
// At least one invalid parameter, so no accumulation should happen here
|
|
// Valid values in front of invalid.
|
|
h.add(key, valid.concat(invalid));
|
|
let s1 = h.snapshot();
|
|
Assert.ok(!(key in s1));
|
|
|
|
h.add(key, valid);
|
|
let s = h.snapshot()[key];
|
|
Assert.deepEqual(s.values, { 0: 2, 1: 3, 2: 0 });
|
|
Assert.equal(s.sum, 3);
|
|
});
|
|
|
|
add_task(async function test_keyed_linear_multiple_samples() {
|
|
// According to telemetry.mozilla.org/histogram-simulator, bucket at
|
|
// index 1 of TELEMETRY_TEST_LINEAR has max value of 3.13K
|
|
let valid = [0, 1, 5, 10, 268450000, 268450001, Math.pow(2, 31) + 1];
|
|
let invalid = ["", "0", "1", "random"];
|
|
let key = "somestring";
|
|
|
|
let h = Telemetry.getKeyedHistogramById("TELEMETRY_TEST_KEYED_LINEAR");
|
|
h.clear();
|
|
|
|
// At least one invalid paramater, so no accumulations.
|
|
// Valid values in front of invalid.
|
|
h.add(key, valid.concat(invalid));
|
|
let s1 = h.snapshot();
|
|
Assert.ok(!(key in s1));
|
|
|
|
h.add(key, valid);
|
|
let s2 = h.snapshot()[key];
|
|
// Values >= INT32_MAX are accumulated as INT32_MAX - 1
|
|
Assert.equal(s2.sum, valid.reduce((acc, cur) => acc + cur) - 3);
|
|
Assert.deepEqual(s2.range, [1, 250000]);
|
|
Assert.deepEqual(s2.values, { 0: 1, 1: 3, 250000: 3 });
|
|
});
|
|
|
|
add_task(async function test_non_array_non_string_obj() {
|
|
let invalid_obj = {
|
|
prop1: "someValue",
|
|
prop2: "someOtherValue",
|
|
};
|
|
let key = "someString";
|
|
|
|
let h = Telemetry.getKeyedHistogramById("TELEMETRY_TEST_KEYED_LINEAR");
|
|
h.clear();
|
|
|
|
h.add(key, invalid_obj);
|
|
Assert.equal(h.keys().length, 0);
|
|
});
|
|
|
|
add_task(
|
|
{
|
|
skip_if: () => gIsAndroid,
|
|
},
|
|
async function test_clearHistogramsOnSnapshot() {
|
|
const COUNT = "TELEMETRY_TEST_COUNT";
|
|
let h = Telemetry.getHistogramById(COUNT);
|
|
h.clear();
|
|
let snapshot;
|
|
|
|
// The first snapshot should be empty, nothing recorded.
|
|
snapshot = Telemetry.getSnapshotForHistograms(
|
|
"main",
|
|
false /* clear */
|
|
).parent;
|
|
Assert.ok(!(COUNT in snapshot));
|
|
|
|
// After recording into a histogram, the data should be in the snapshot. Don't delete it.
|
|
Glean.testOnlyIpc.aCounterForHgram.add(1);
|
|
|
|
Assert.equal(h.snapshot().sum, 1);
|
|
snapshot = Telemetry.getSnapshotForHistograms(
|
|
"main",
|
|
false /* clear */
|
|
).parent;
|
|
Assert.ok(COUNT in snapshot);
|
|
Assert.equal(snapshot[COUNT].sum, 1);
|
|
|
|
// After recording into a histogram again, the data should be updated and in the snapshot.
|
|
// Clean up after.
|
|
Glean.testOnlyIpc.aCounterForHgram.add(41);
|
|
|
|
Assert.equal(h.snapshot().sum, 42);
|
|
snapshot = Telemetry.getSnapshotForHistograms(
|
|
"main",
|
|
true /* clear */
|
|
).parent;
|
|
Assert.ok(COUNT in snapshot);
|
|
Assert.equal(snapshot[COUNT].sum, 42);
|
|
|
|
// Finally, no data should be in the snapshot.
|
|
Assert.equal(h.snapshot().sum, 0);
|
|
snapshot = Telemetry.getSnapshotForHistograms(
|
|
"main",
|
|
false /* clear */
|
|
).parent;
|
|
Assert.ok(!(COUNT in snapshot));
|
|
}
|
|
);
|
|
|
|
add_task(async function test_multistore_individual_histogram() {
|
|
Telemetry.canRecordExtended = true;
|
|
|
|
let id;
|
|
let hist;
|
|
let snapshot;
|
|
|
|
id = "TELEMETRY_TEST_KEYED_MULTIPLE_STORES";
|
|
hist = Telemetry.getKeyedHistogramById(id);
|
|
snapshot = hist.snapshot();
|
|
Assert.deepEqual({}, snapshot, `Histogram ${id} should be empty.`);
|
|
hist.add("key-a", 1);
|
|
snapshot = hist.snapshot();
|
|
Assert.equal(
|
|
1,
|
|
snapshot["key-a"].sum,
|
|
`Histogram ${id} should have recorded one value.`
|
|
);
|
|
hist.clear();
|
|
snapshot = hist.snapshot();
|
|
Assert.deepEqual({}, snapshot, `Histogram ${id} should be cleared.`);
|
|
|
|
// When sync only, then the snapshot will be empty on the main store
|
|
id = "TELEMETRY_TEST_KEYED_SYNC_ONLY";
|
|
hist = Telemetry.getKeyedHistogramById(id);
|
|
snapshot = hist.snapshot();
|
|
Assert.equal(
|
|
undefined,
|
|
snapshot,
|
|
`Histogram ${id} should not be in the 'main' storage`
|
|
);
|
|
hist.add("key-a", 1);
|
|
snapshot = hist.snapshot();
|
|
Assert.equal(
|
|
undefined,
|
|
snapshot,
|
|
`Histogram ${id} should not be in the 'main' storage`
|
|
);
|
|
hist.clear();
|
|
snapshot = hist.snapshot();
|
|
Assert.equal(
|
|
undefined,
|
|
snapshot,
|
|
`Histogram ${id} should not be in the 'main' storage`
|
|
);
|
|
});
|
|
|
|
add_task(async function test_multistore_main_snapshot() {
|
|
Telemetry.canRecordExtended = true;
|
|
// Clear histograms
|
|
Telemetry.getSnapshotForHistograms("main", true);
|
|
Telemetry.getSnapshotForKeyedHistograms("main", true);
|
|
|
|
let id;
|
|
let hist;
|
|
let snapshot;
|
|
|
|
// Keyed histograms
|
|
|
|
// Fill with data
|
|
id = "TELEMETRY_TEST_KEYED_MULTIPLE_STORES";
|
|
hist = Telemetry.getKeyedHistogramById(id);
|
|
hist.add("key-a", 1);
|
|
|
|
id = "TELEMETRY_TEST_KEYED_SYNC_ONLY";
|
|
hist = Telemetry.getKeyedHistogramById(id);
|
|
hist.add("key-b", 1);
|
|
|
|
// Getting snapshot and NOT clearing (using default values for optional parameters)
|
|
snapshot = Telemetry.getSnapshotForKeyedHistograms().parent;
|
|
id = "TELEMETRY_TEST_KEYED_MULTIPLE_STORES";
|
|
Assert.ok(id in snapshot, `${id} should be in a main store snapshot`);
|
|
id = "TELEMETRY_TEST_KEYED_SYNC_ONLY";
|
|
Assert.ok(!(id in snapshot), `${id} should not be in a main store snapshot`);
|
|
|
|
// Data should still be in, getting snapshot and clearing
|
|
snapshot = Telemetry.getSnapshotForKeyedHistograms(
|
|
"main",
|
|
/* clear */ true
|
|
).parent;
|
|
id = "TELEMETRY_TEST_KEYED_MULTIPLE_STORES";
|
|
Assert.ok(id in snapshot, `${id} should be in a main store snapshot`);
|
|
id = "TELEMETRY_TEST_KEYED_SYNC_ONLY";
|
|
Assert.ok(!(id in snapshot), `${id} should not be in a main store snapshot`);
|
|
|
|
// Should be empty after clearing
|
|
snapshot = Telemetry.getSnapshotForKeyedHistograms(
|
|
"main",
|
|
/* clear */ false
|
|
).parent;
|
|
id = "TELEMETRY_TEST_KEYED_MULTIPLE_STORES";
|
|
Assert.ok(!(id in snapshot), `${id} should not be in a main store snapshot`);
|
|
id = "TELEMETRY_TEST_KEYED_SYNC_ONLY";
|
|
Assert.ok(!(id in snapshot), `${id} should not be in a main store snapshot`);
|
|
});
|
|
|
|
add_task(async function test_multistore_argument_handling() {
|
|
Telemetry.canRecordExtended = true;
|
|
// Clear histograms
|
|
Telemetry.getSnapshotForHistograms("main", true);
|
|
Telemetry.getSnapshotForHistograms("sync", true);
|
|
Telemetry.getSnapshotForKeyedHistograms("main", true);
|
|
Telemetry.getSnapshotForKeyedHistograms("sync", true);
|
|
|
|
let id;
|
|
let hist;
|
|
let snapshot;
|
|
|
|
// Keyed Histogram
|
|
|
|
id = "TELEMETRY_TEST_KEYED_MULTIPLE_STORES";
|
|
hist = Telemetry.getKeyedHistogramById(id);
|
|
hist.add("key-1", 37);
|
|
|
|
// No argument
|
|
snapshot = hist.snapshot();
|
|
Assert.equal(
|
|
37,
|
|
snapshot["key-1"].sum,
|
|
`${id} should be in a default store snapshot`
|
|
);
|
|
|
|
hist.clear();
|
|
snapshot = hist.snapshot();
|
|
Assert.ok(
|
|
!("key-1" in snapshot),
|
|
`${id} should be cleared in the default store`
|
|
);
|
|
|
|
snapshot = hist.snapshot({ store: "sync" });
|
|
Assert.equal(
|
|
37,
|
|
snapshot["key-1"].sum,
|
|
`${id} should not have been cleared in the sync store`
|
|
);
|
|
|
|
Assert.throws(
|
|
() => hist.snapshot(2, "or", "more", "arguments"),
|
|
/one argument/,
|
|
"snapshot should check argument count"
|
|
);
|
|
Assert.throws(
|
|
() => hist.snapshot(2),
|
|
/object argument/,
|
|
"snapshot should check argument type"
|
|
);
|
|
Assert.throws(
|
|
() => hist.snapshot({}),
|
|
/property/,
|
|
"snapshot should check for object property"
|
|
);
|
|
Assert.throws(
|
|
() => hist.snapshot({ store: 1 }),
|
|
/string/,
|
|
"snapshot should check object property's type"
|
|
);
|
|
|
|
Assert.throws(
|
|
() => hist.clear(2, "or", "more", "arguments"),
|
|
/one argument/,
|
|
"clear should check argument count"
|
|
);
|
|
Assert.throws(
|
|
() => hist.clear(2),
|
|
/object argument/,
|
|
"clear should check argument type"
|
|
);
|
|
Assert.throws(
|
|
() => hist.clear({}),
|
|
/property/,
|
|
"clear should check for object property"
|
|
);
|
|
Assert.throws(
|
|
() => hist.clear({ store: 1 }),
|
|
/string/,
|
|
"clear should check object property's type"
|
|
);
|
|
});
|
|
|
|
add_task(async function test_multistore_keyed_sync_snapshot() {
|
|
Telemetry.canRecordExtended = true;
|
|
// Clear histograms
|
|
Telemetry.getSnapshotForKeyedHistograms("main", true);
|
|
Telemetry.getSnapshotForKeyedHistograms("sync", true);
|
|
|
|
let id;
|
|
let hist;
|
|
let snapshot;
|
|
|
|
// Plain histograms
|
|
|
|
// Fill with data
|
|
id = "TELEMETRY_TEST_KEYED_LINEAR";
|
|
hist = Telemetry.getKeyedHistogramById(id);
|
|
hist.add("key-1", 1);
|
|
|
|
id = "TELEMETRY_TEST_KEYED_MULTIPLE_STORES";
|
|
hist = Telemetry.getKeyedHistogramById(id);
|
|
hist.add("key-1", 1);
|
|
|
|
id = "TELEMETRY_TEST_KEYED_SYNC_ONLY";
|
|
hist = Telemetry.getKeyedHistogramById(id);
|
|
hist.add("key-1", 1);
|
|
|
|
// Getting snapshot and clearing
|
|
snapshot = Telemetry.getSnapshotForKeyedHistograms(
|
|
"main",
|
|
/* clear */ true
|
|
).parent;
|
|
id = "TELEMETRY_TEST_KEYED_LINEAR";
|
|
Assert.ok(id in snapshot, `${id} should be in a main store snapshot`);
|
|
id = "TELEMETRY_TEST_KEYED_MULTIPLE_STORES";
|
|
Assert.ok(id in snapshot, `${id} should be in a main store snapshot`);
|
|
id = "TELEMETRY_TEST_KEYED_SYNC_ONLY";
|
|
Assert.ok(!(id in snapshot), `${id} should not be in a main store snapshot`);
|
|
|
|
snapshot = Telemetry.getSnapshotForKeyedHistograms(
|
|
"sync",
|
|
/* clear */ true
|
|
).parent;
|
|
id = "TELEMETRY_TEST_KEYED_LINEAR";
|
|
Assert.ok(!(id in snapshot), `${id} should not be in a sync store snapshot`);
|
|
id = "TELEMETRY_TEST_KEYED_MULTIPLE_STORES";
|
|
Assert.ok(id in snapshot, `${id} should be in a sync store snapshot`);
|
|
id = "TELEMETRY_TEST_KEYED_SYNC_ONLY";
|
|
Assert.ok(id in snapshot, `${id} should be in a sync store snapshot`);
|
|
});
|
|
|
|
add_task(async function test_multistore_keyed_individual_snapshot() {
|
|
Telemetry.canRecordExtended = true;
|
|
// Clear histograms
|
|
Telemetry.getSnapshotForKeyedHistograms("main", true);
|
|
Telemetry.getSnapshotForKeyedHistograms("sync", true);
|
|
|
|
let id;
|
|
let hist;
|
|
|
|
id = "TELEMETRY_TEST_KEYED_LINEAR";
|
|
hist = Telemetry.getKeyedHistogramById(id);
|
|
|
|
hist.add("key-1", 37);
|
|
Assert.deepEqual(37, hist.snapshot({ store: "main" })["key-1"].sum);
|
|
Assert.deepEqual(undefined, hist.snapshot({ store: "sync" }));
|
|
|
|
hist.clear({ store: "main" });
|
|
Assert.deepEqual({}, hist.snapshot({ store: "main" }));
|
|
Assert.deepEqual(undefined, hist.snapshot({ store: "sync" }));
|
|
|
|
hist.add("key-1", 4);
|
|
hist.clear({ store: "sync" });
|
|
Assert.deepEqual(4, hist.snapshot({ store: "main" })["key-1"].sum);
|
|
Assert.deepEqual(undefined, hist.snapshot({ store: "sync" }));
|
|
|
|
id = "TELEMETRY_TEST_KEYED_MULTIPLE_STORES";
|
|
hist = Telemetry.getKeyedHistogramById(id);
|
|
|
|
hist.add("key-1", 37);
|
|
Assert.deepEqual(37, hist.snapshot({ store: "main" })["key-1"].sum);
|
|
Assert.deepEqual(37, hist.snapshot({ store: "sync" })["key-1"].sum);
|
|
|
|
hist.clear({ store: "main" });
|
|
Assert.deepEqual({}, hist.snapshot({ store: "main" }));
|
|
Assert.deepEqual(37, hist.snapshot({ store: "sync" })["key-1"].sum);
|
|
|
|
hist.add("key-1", 3);
|
|
Assert.deepEqual(3, hist.snapshot({ store: "main" })["key-1"].sum);
|
|
Assert.deepEqual(40, hist.snapshot({ store: "sync" })["key-1"].sum);
|
|
|
|
hist.clear({ store: "sync" });
|
|
Assert.deepEqual(3, hist.snapshot({ store: "main" })["key-1"].sum);
|
|
Assert.deepEqual({}, hist.snapshot({ store: "sync" }));
|
|
|
|
id = "TELEMETRY_TEST_KEYED_SYNC_ONLY";
|
|
hist = Telemetry.getKeyedHistogramById(id);
|
|
|
|
hist.add("key-1", 37);
|
|
Assert.deepEqual(undefined, hist.snapshot({ store: "main" }));
|
|
Assert.deepEqual(37, hist.snapshot({ store: "sync" })["key-1"].sum);
|
|
|
|
hist.clear({ store: "main" });
|
|
Assert.deepEqual(undefined, hist.snapshot({ store: "main" }));
|
|
Assert.deepEqual(37, hist.snapshot({ store: "sync" })["key-1"].sum);
|
|
|
|
hist.add("key-1", 3);
|
|
Assert.deepEqual(undefined, hist.snapshot({ store: "main" }));
|
|
Assert.deepEqual(40, hist.snapshot({ store: "sync" })["key-1"].sum);
|
|
|
|
hist.clear({ store: "sync" });
|
|
Assert.deepEqual(undefined, hist.snapshot({ store: "main" }));
|
|
Assert.deepEqual({}, hist.snapshot({ store: "sync" }));
|
|
});
|
|
|
|
add_task(async function test_can_record_in_process_regression_bug_1530361() {
|
|
Telemetry.getSnapshotForHistograms("main", true);
|
|
|
|
// The socket and gpu processes should not have any histograms.
|
|
// Flag and count histograms have defaults, so if we're accidentally recording them
|
|
// in these processes they'd show up even immediately after being cleared.
|
|
let snapshot = Telemetry.getSnapshotForHistograms("main", true);
|
|
|
|
Assert.deepEqual(
|
|
snapshot.gpu,
|
|
{},
|
|
"No histograms should have been recorded for the gpu process"
|
|
);
|
|
Assert.deepEqual(
|
|
snapshot.socket,
|
|
{},
|
|
"No histograms should have been recorded for the socket process"
|
|
);
|
|
});
|
|
|
|
add_task(function test_knows_its_name() {
|
|
let h;
|
|
|
|
// Plain histograms
|
|
const histNames = [
|
|
"TELEMETRY_TEST_COUNT",
|
|
"TELEMETRY_TEST_CATEGORICAL",
|
|
"TELEMETRY_TEST_EXPIRED",
|
|
];
|
|
|
|
for (let name of histNames) {
|
|
h = Telemetry.getHistogramById(name);
|
|
Assert.equal(name, h.name());
|
|
}
|
|
|
|
// Keyed histograms
|
|
const keyedHistNames = [
|
|
"TELEMETRY_TEST_KEYED_EXPONENTIAL",
|
|
"TELEMETRY_TEST_KEYED_BOOLEAN",
|
|
"TELEMETRY_TEST_EXPIRED_KEYED",
|
|
];
|
|
|
|
for (let name of keyedHistNames) {
|
|
h = Telemetry.getKeyedHistogramById(name);
|
|
Assert.equal(name, h.name());
|
|
}
|
|
});
|