bug 1376600 - Remove registered(Keyed)Histograms r=Dexter

With the removal of the old addonHistograms, all histograms are now registered.
So removing registered(Keyed)Histograms should be straightforward?

Unfortunately not, as this was how we filtered data based on dataset
(opt-in/opt-out), so a little more fiddling was needed to get C++ to only
serialize dataset-appropriate data (instead of post-facto filtering it in JS).

MozReview-Commit-ID: HDplhmzmzJl

--HG--
extra : rebase_source : 9c38c97e39e3c4fb192288d751505e1f0f2a2c6d
This commit is contained in:
Chris H-C 2017-08-22 09:42:09 -04:00
parent 1e3bbf38d4
commit 28c67cf8bd
14 changed files with 244 additions and 270 deletions

View File

@ -13,9 +13,13 @@ const OUTER_VALUE = "outer-value-" + RAND;
function getEstimateChars() {
let snap;
if (gMultiProcessBrowser) {
snap = Services.telemetry.histogramSnapshots.content.FX_SESSION_RESTORE_DOM_STORAGE_SIZE_ESTIMATE_CHARS;
snap = Services.telemetry.snapshotHistograms(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN,
false /* subsession */,
false /* clear */).content.FX_SESSION_RESTORE_DOM_STORAGE_SIZE_ESTIMATE_CHARS;
} else {
snap = Services.telemetry.histogramSnapshots.parent.FX_SESSION_RESTORE_DOM_STORAGE_SIZE_ESTIMATE_CHARS;
snap = Services.telemetry.snapshotHistograms(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN,
false,
false).parent.FX_SESSION_RESTORE_DOM_STORAGE_SIZE_ESTIMATE_CHARS;
}
if (!snap) {
return 0;

View File

@ -111,9 +111,9 @@ function grabHistogramsFromContent(use_counter_middlefix, page_before = null) {
let gather = () => {
let snapshots;
if (Services.appinfo.browserTabsRemoteAutostart) {
snapshots = telemetry.histogramSnapshots.content;
snapshots = telemetry.snapshotHistograms(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false, false).content;
} else {
snapshots = telemetry.histogramSnapshots.parent;
snapshots = telemetry.snapshotHistograms(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false, false).parent;
}
let checkGet = (probe) => {
return snapshots[probe] ? snapshots[probe].sum : 0;

View File

@ -13,7 +13,9 @@ add_task(async function test_memory_distribution() {
Services.telemetry.canRecordExtended = true;
registerCleanupFunction(() => Services.telemetry.canRecordExtended = canRecordExtended);
Services.telemetry.snapshotSubsessionKeyedHistograms(true /*clear*/);
Services.telemetry.snapshotKeyedHistograms(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN,
true /* subsession */,
true /* clear */);
// Open a remote page in a new tab to trigger the WebNavigation:LoadURI.
let tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, "http://example.com");
@ -29,11 +31,13 @@ add_task(async function test_memory_distribution() {
// There is no good way to make sure that the parent received the histogram entries from the child processes.
// Let's stick to the ugly, spinning the event loop until we have a good approach (Bug 1357509).
await BrowserTestUtils.waitForCondition(() => {
let s = Services.telemetry.snapshotSubsessionKeyedHistograms().content["FX_TAB_REMOTE_NAVIGATION_DELAY_MS"];
let s = Services.telemetry.snapshotKeyedHistograms(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN,
true,
false).content["FX_TAB_REMOTE_NAVIGATION_DELAY_MS"];
return s && "WebNavigation:LoadURI" in s && "SessionStore:restoreTabContent" in s;
});
let s = Services.telemetry.snapshotSubsessionKeyedHistograms().content["FX_TAB_REMOTE_NAVIGATION_DELAY_MS"];
let s = Services.telemetry.snapshotKeyedHistograms(1, true, false).content["FX_TAB_REMOTE_NAVIGATION_DELAY_MS"];
let restoreTabSnapshot = s["SessionStore:restoreTabContent"];
ok(restoreTabSnapshot.sum > 0, "Zero delay for the restoreTabContent case is unlikely.");
ok(restoreTabSnapshot.sum < 10000, "More than 10 seconds delay for the restoreTabContent case is unlikely.");
@ -42,7 +46,9 @@ add_task(async function test_memory_distribution() {
ok(loadURISnapshot.sum > 0, "Zero delay for the LoadURI case is unlikely.");
ok(loadURISnapshot.sum < 10000, "More than 10 seconds delay for the LoadURI case is unlikely.");
Services.telemetry.snapshotSubsessionKeyedHistograms(true /*clear*/);
Services.telemetry.snapshotKeyedHistograms(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN,
true /* subsession */,
true /* clear */);
await BrowserTestUtils.removeTab(tab2);
await BrowserTestUtils.removeTab(tab1);

View File

@ -14,11 +14,15 @@ function arraySum(arr) {
}
function clearHistograms() {
Services.telemetry.snapshotSubsessionHistograms(true);
Services.telemetry.snapshotHistograms(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN,
true /* subsession */,
true /* clear */);
}
function getSnapshots(process) {
return Services.telemetry.snapshotSubsessionHistograms()[process];
return Services.telemetry.snapshotHistograms(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN,
true /* subsession */,
false /* clear */)[process];
}
// There is no good way to make sure that the parent received the histogram
@ -27,7 +31,9 @@ function getSnapshots(process) {
// approach (Bug 1357509).
function promiseTelemetryRecorded(id, process, expectedCount) {
let condition = () => {
let snapshot = Services.telemetry.snapshotSubsessionHistograms()[process][id];
let snapshot = Services.telemetry.snapshotHistograms(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN,
true /* subsession */,
false /* clear */)[process][id];
return snapshot && arraySum(snapshot.counts) >= expectedCount;
};
return ContentTaskUtils.waitForCondition(condition);

View File

@ -27,12 +27,16 @@ add_task(async function test_startup() {
let LAUNCH = "OSFILE_WORKER_LAUNCH_MS";
let READY = "OSFILE_WORKER_READY_MS";
let before = Services.telemetry.histogramSnapshots.parent;
let before = Services.telemetry.snapshotHistograms(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN,
false,
false).parent;
// Launch the OS.File worker
await File.getCurrentDirectory();
let after = Services.telemetry.histogramSnapshots.parent;
let after = Services.telemetry.snapshotHistograms(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN,
false,
false).parent;
do_print("Ensuring that we have recorded measures for histograms");
@ -47,13 +51,17 @@ add_task(async function test_startup() {
add_task(async function test_writeAtomic() {
let LABEL = "OSFILE_WRITEATOMIC_JANK_MS";
let before = Services.telemetry.histogramSnapshots.parent;
let before = Services.telemetry.snapshotHistograms(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN,
false,
false).parent;
// Perform a write.
let path = Path.join(Constants.Path.profileDir, "test_osfile_telemetry.tmp");
await File.writeAtomic(path, LABEL, { tmpPath: path + ".tmp" } );
let after = Services.telemetry.histogramSnapshots.parent;
let after = Services.telemetry.snapshotHistograms(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN,
false,
false).parent;
do_check_eq(getCount(after[LABEL]), getCount(before[LABEL]) + 1);
});

View File

@ -564,41 +564,33 @@ TelemetryImpl::SetHistogramRecordingEnabled(const nsACString &id, bool aEnabled)
}
NS_IMETHODIMP
TelemetryImpl::GetHistogramSnapshots(JSContext *cx, JS::MutableHandle<JS::Value> ret)
TelemetryImpl::SnapshotHistograms(unsigned int aDataset, bool aSubsession,
bool aClearHistograms, JSContext* aCx,
JS::MutableHandleValue aResult)
{
return TelemetryHistogram::CreateHistogramSnapshots(cx, ret, false, false);
}
NS_IMETHODIMP
TelemetryImpl::SnapshotSubsessionHistograms(bool clearSubsession,
JSContext *cx,
JS::MutableHandle<JS::Value> ret)
{
#if !defined(MOZ_WIDGET_ANDROID)
return TelemetryHistogram::CreateHistogramSnapshots(cx, ret, true,
clearSubsession);
#else
return NS_OK;
#if defined(MOZ_WIDGET_ANDROID)
if (aSubsession) {
return NS_OK;
}
#endif
return TelemetryHistogram::CreateHistogramSnapshots(aCx, aResult, aDataset,
aSubsession,
aClearHistograms);
}
NS_IMETHODIMP
TelemetryImpl::GetKeyedHistogramSnapshots(JSContext *cx, JS::MutableHandle<JS::Value> ret)
TelemetryImpl::SnapshotKeyedHistograms(unsigned int aDataset, bool aSubsession,
bool aClearHistograms, JSContext* aCx,
JS::MutableHandleValue aResult)
{
return TelemetryHistogram::GetKeyedHistogramSnapshots(cx, ret, false, false);
}
NS_IMETHODIMP
TelemetryImpl::SnapshotSubsessionKeyedHistograms(bool clearSubsession,
JSContext *cx,
JS::MutableHandle<JS::Value> ret)
{
#if !defined(MOZ_WIDGET_ANDROID)
return TelemetryHistogram::GetKeyedHistogramSnapshots(cx, ret, true,
clearSubsession);
#else
return NS_OK;
#if defined(MOZ_WIDGET_ANDROID)
if (aSubsession) {
return NS_OK;
}
#endif
return TelemetryHistogram::GetKeyedHistogramSnapshots(aCx, aResult, aDataset,
aSubsession,
aClearHistograms);
}
bool
@ -1119,23 +1111,6 @@ TelemetryImpl::GetLateWrites(JSContext *cx, JS::MutableHandle<JS::Value> ret)
return NS_OK;
}
NS_IMETHODIMP
TelemetryImpl::RegisteredHistograms(uint32_t aDataset, uint32_t *aCount,
char*** aHistograms)
{
return
TelemetryHistogram::RegisteredHistograms(aDataset, aCount, aHistograms);
}
NS_IMETHODIMP
TelemetryImpl::RegisteredKeyedHistograms(uint32_t aDataset, uint32_t *aCount,
char*** aHistograms)
{
return
TelemetryHistogram::RegisteredKeyedHistograms(aDataset, aCount,
aHistograms);
}
NS_IMETHODIMP
TelemetryImpl::GetHistogramById(const nsACString &name, JSContext *cx,
JS::MutableHandle<JS::Value> ret)

View File

@ -364,33 +364,6 @@ internal_IsRecordingEnabled(HistogramID id)
return !gHistogramRecordingDisabled[id];
}
nsresult
internal_GetRegisteredHistogramIds(bool keyed, uint32_t dataset,
uint32_t *aCount, char*** aHistograms)
{
nsTArray<char*> collection;
for (const auto & h : gHistogramInfos) {
if (IsExpiredVersion(h.expiration()) ||
h.keyed != keyed ||
!IsInDataset(h.dataset, dataset)) {
continue;
}
const char* id = h.name();
const size_t len = strlen(id);
collection.AppendElement(static_cast<char*>(nsMemory::Clone(id, len+1)));
}
const size_t bytes = collection.Length() * sizeof(char*);
char** histograms = static_cast<char**>(moz_xmalloc(bytes));
memcpy(histograms, collection.Elements(), bytes);
*aHistograms = histograms;
*aCount = collection.Length();
return NS_OK;
}
const char *
HistogramInfo::name() const
{
@ -2013,17 +1986,24 @@ TelemetryHistogram::GetHistogramName(HistogramID id)
}
nsresult
TelemetryHistogram::CreateHistogramSnapshots(JSContext *cx,
JS::MutableHandle<JS::Value> ret,
bool subsession,
bool clearSubsession)
TelemetryHistogram::CreateHistogramSnapshots(JSContext* aCx,
JS::MutableHandleValue aResult,
unsigned int aDataset,
bool aSubsession,
bool aClearSubsession)
{
#if defined(MOZ_WIDGET_ANDROID)
if (aSubsession) {
return NS_OK;
}
#endif
// Runs without protection from |gTelemetryHistogramMutex|
JS::Rooted<JSObject*> root_obj(cx, JS_NewPlainObject(cx));
JS::Rooted<JSObject*> root_obj(aCx, JS_NewPlainObject(aCx));
if (!root_obj) {
return NS_ERROR_FAILURE;
}
ret.setObject(*root_obj);
aResult.setObject(*root_obj);
// Include the GPU process in histogram snapshots only if we actually tried
// to launch a process for it.
@ -2032,18 +2012,15 @@ TelemetryHistogram::CreateHistogramSnapshots(JSContext *cx,
includeGPUProcess = gpm->AttemptedGPUProcess();
}
#if !defined(MOZ_WIDGET_ANDROID)
SessionType sessionType = SessionType(subsession);
#else
SessionType sessionType = SessionType::Session;
#endif
SessionType sessionType = SessionType(aSubsession);
for (uint32_t process = 0; process < static_cast<uint32_t>(ProcessID::Count); ++process) {
JS::Rooted<JSObject*> processObject(cx, JS_NewPlainObject(cx));
JS::Rooted<JSObject*> processObject(aCx, JS_NewPlainObject(aCx));
if (!processObject) {
return NS_ERROR_FAILURE;
}
if (!JS_DefineProperty(cx, root_obj, GetNameForProcessID(ProcessID(process)),
if (!JS_DefineProperty(aCx, root_obj,
GetNameForProcessID(ProcessID(process)),
processObject, JSPROP_ENUMERATE)) {
return NS_ERROR_FAILURE;
}
@ -2060,6 +2037,10 @@ TelemetryHistogram::CreateHistogramSnapshots(JSContext *cx,
continue;
}
if (!IsInDataset(info.dataset, aDataset)) {
continue;
}
bool shouldInstantiate =
info.histogramType == nsITelemetry::HISTOGRAM_FLAG;
Histogram* h = internal_GetHistogramById(id, ProcessID(process),
@ -2069,22 +2050,22 @@ TelemetryHistogram::CreateHistogramSnapshots(JSContext *cx,
continue;
}
JS::Rooted<JSObject*> hobj(cx, JS_NewPlainObject(cx));
JS::Rooted<JSObject*> hobj(aCx, JS_NewPlainObject(aCx));
if (!hobj) {
return NS_ERROR_FAILURE;
}
switch (internal_ReflectHistogramSnapshot(cx, hobj, h)) {
switch (internal_ReflectHistogramSnapshot(aCx, hobj, h)) {
case REFLECT_FAILURE:
return NS_ERROR_FAILURE;
case REFLECT_OK:
if (!JS_DefineProperty(cx, processObject, gHistogramInfos[id].name(),
if (!JS_DefineProperty(aCx, processObject, gHistogramInfos[id].name(),
hobj, JSPROP_ENUMERATE)) {
return NS_ERROR_FAILURE;
}
}
#if !defined(MOZ_WIDGET_ANDROID)
if ((sessionType == SessionType::Subsession) && clearSubsession) {
if ((sessionType == SessionType::Subsession) && aClearSubsession) {
h->Clear();
}
#endif
@ -2094,36 +2075,23 @@ TelemetryHistogram::CreateHistogramSnapshots(JSContext *cx,
}
nsresult
TelemetryHistogram::RegisteredHistograms(uint32_t aDataset, uint32_t *aCount,
char*** aHistograms)
{
StaticMutexAutoLock locker(gTelemetryHistogramMutex);
return internal_GetRegisteredHistogramIds(false,
aDataset, aCount, aHistograms);
}
nsresult
TelemetryHistogram::RegisteredKeyedHistograms(uint32_t aDataset,
uint32_t *aCount,
char*** aHistograms)
{
StaticMutexAutoLock locker(gTelemetryHistogramMutex);
return internal_GetRegisteredHistogramIds(true,
aDataset, aCount, aHistograms);
}
nsresult
TelemetryHistogram::GetKeyedHistogramSnapshots(JSContext *cx,
JS::MutableHandle<JS::Value> ret,
bool subsession,
bool clearSubsession)
TelemetryHistogram::GetKeyedHistogramSnapshots(JSContext* aCx,
JS::MutableHandleValue aResult,
unsigned int aDataset,
bool aSubsession,
bool aClearSubsession)
{
#if defined(MOZ_WIDGET_ANDROID)
if (aSubsession) {
return NS_OK;
}
#endif
// Runs without protection from |gTelemetryHistogramMutex|
JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
JS::Rooted<JSObject*> obj(aCx, JS_NewPlainObject(aCx));
if (!obj) {
return NS_ERROR_FAILURE;
}
ret.setObject(*obj);
aResult.setObject(*obj);
// Include the GPU process in histogram snapshots only if we actually tried
// to launch a process for it.
@ -2133,11 +2101,11 @@ TelemetryHistogram::GetKeyedHistogramSnapshots(JSContext *cx,
}
for (uint32_t process = 0; process < static_cast<uint32_t>(ProcessID::Count); ++process) {
JS::Rooted<JSObject*> processObject(cx, JS_NewPlainObject(cx));
JS::Rooted<JSObject*> processObject(aCx, JS_NewPlainObject(aCx));
if (!processObject) {
return NS_ERROR_FAILURE;
}
if (!JS_DefineProperty(cx, obj, GetNameForProcessID(ProcessID(process)),
if (!JS_DefineProperty(aCx, obj, GetNameForProcessID(ProcessID(process)),
processObject, JSPROP_ENUMERATE)) {
return NS_ERROR_FAILURE;
}
@ -2152,6 +2120,10 @@ TelemetryHistogram::GetKeyedHistogramSnapshots(JSContext *cx,
continue;
}
if (!IsInDataset(info.dataset, aDataset)) {
continue;
}
KeyedHistogram* keyed = internal_GetKeyedHistogramById(HistogramID(id),
ProcessID(process),
/* instantiate = */ false);
@ -2159,17 +2131,17 @@ TelemetryHistogram::GetKeyedHistogramSnapshots(JSContext *cx,
continue;
}
JS::RootedObject snapshot(cx, JS_NewPlainObject(cx));
JS::RootedObject snapshot(aCx, JS_NewPlainObject(aCx));
if (!snapshot) {
return NS_ERROR_FAILURE;
}
if (!NS_SUCCEEDED(keyed->GetJSSnapshot(cx, snapshot, subsession,
clearSubsession))) {
if (!NS_SUCCEEDED(keyed->GetJSSnapshot(aCx, snapshot, aSubsession,
aClearSubsession))) {
return NS_ERROR_FAILURE;
}
if (!JS_DefineProperty(cx, processObject, gHistogramInfos[id].name(),
if (!JS_DefineProperty(aCx, processObject, gHistogramInfos[id].name(),
snapshot, JSPROP_ENUMERATE)) {
return NS_ERROR_FAILURE;
}

View File

@ -60,20 +60,12 @@ const char*
GetHistogramName(mozilla::Telemetry::HistogramID id);
nsresult
CreateHistogramSnapshots(JSContext *cx, JS::MutableHandle<JS::Value> ret,
bool subsession, bool clearSubsession);
CreateHistogramSnapshots(JSContext* aCx, JS::MutableHandleValue aResult, unsigned int aDataset,
bool aSubsession, bool aClearSubsession);
nsresult
RegisteredHistograms(uint32_t aDataset, uint32_t *aCount,
char*** aHistograms);
nsresult
RegisteredKeyedHistograms(uint32_t aDataset, uint32_t *aCount,
char*** aHistograms);
nsresult
GetKeyedHistogramSnapshots(JSContext *cx, JS::MutableHandle<JS::Value> ret,
bool subsession, bool clearSubsession);
GetKeyedHistogramSnapshots(JSContext *aCx, JS::MutableHandleValue aResult, unsigned int aDataset,
bool aSubsession, bool aClearSubsession);
size_t
GetMapShallowSizesOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf);

View File

@ -863,22 +863,13 @@ var Impl = {
},
getHistograms: function getHistograms(subsession, clearSubsession) {
let registered =
Telemetry.registeredHistograms(this.getDatasetType(), []);
if (this._testing == false) {
// Omit telemetry test histograms outside of tests.
registered = registered.filter(n => !n.startsWith("TELEMETRY_TEST_"));
}
registered = registered.concat(registered.map(n => "STARTUP_" + n));
let hls = subsession ? Telemetry.snapshotSubsessionHistograms(clearSubsession)
: Telemetry.histogramSnapshots;
let hls = Telemetry.snapshotHistograms(this.getDatasetType(), subsession, clearSubsession);
let ret = {};
for (let [process, histograms] of Object.entries(hls)) {
ret[process] = {};
for (let [name, value] of Object.entries(histograms)) {
if (registered.includes(name)) {
if (this._testing || !name.startsWith("TELEMETRY_TEST_")) {
ret[process][name] = this.packHistogram(value);
}
}
@ -888,21 +879,13 @@ var Impl = {
},
getKeyedHistograms(subsession, clearSubsession) {
let registered =
Telemetry.registeredKeyedHistograms(this.getDatasetType(), []);
if (this._testing == false) {
// Omit telemetry test histograms outside of tests.
registered = registered.filter(id => !id.startsWith("TELEMETRY_TEST_"));
}
let khs = subsession ? Telemetry.snapshotSubsessionKeyedHistograms(clearSubsession)
: Telemetry.keyedHistogramSnapshots;
let khs = Telemetry.snapshotKeyedHistograms(this.getDatasetType(), subsession, clearSubsession);
let ret = {};
for (let [process, histograms] of Object.entries(khs)) {
ret[process] = {};
for (let [name, value] of Object.entries(histograms)) {
if (registered.includes(name)) {
if (this._testing || !name.startsWith("TELEMETRY_TEST_")) {
let keys = Object.keys(value);
if (keys.length == 0) {
// Skip empty keyed histogram

View File

@ -52,27 +52,25 @@ interface nsITelemetry : nsISupports
/**
* An object containing a snapshot from all of the currently registered histograms from all processes.
* { process1: {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, HISTOGRAM_BOOLEAN
* or HISTOGRAM_COUNT
* Serializes the histograms from the given dataset to a JSON-style object.
* The returned structure looks like:
* { process1: {name1: {histogramData1}, name2:{histogramData2}...}}
*
* Where histogramDataN has the following properties:
* min - minimum bucket size
* max - maximum bucket size
* histogram_type - HISTOGRAM_EXPONENTIAL, HISTOGRAM_LINEAR, HISTOGRAM_BOOLEAN,
* HISTOGRAM_FLAG, HISTOGRAM_COUNT, or HISTOGRAM_CATEGORICAL
* counts - array representing contents of the buckets in the histogram
* ranges - an array with calculated bucket sizes
* ranges - array with calculated bucket sizes
* sum - sum of the bucket contents
*
* @param aDataset DATASET_RELEASE_CHANNEL_OPTOUT or DATASET_RELEASE_CHANNEL_OPTIN.
* @param aSubsession Whether to return the internally-duplicated subsession histograms
* @param aClear Whether to clear out the subsession histograms after snapshotting (only works if aSubsession is true)
*/
[implicit_jscontext]
readonly attribute jsval histogramSnapshots;
/**
* Get a snapshot of the internally duplicated subsession histograms.
* @param clear Whether to clear out the subsession histograms after snapshotting.
* @return An object as histogramSnapshots, except this contains the internally duplicated histograms for subsession telemetry.
*/
[implicit_jscontext]
jsval snapshotSubsessionHistograms([optional] in boolean clear);
jsval snapshotHistograms(in uint32_t aDataset, in boolean aSubsession, in boolean aClear);
/**
* The amount of time, in milliseconds, that the last session took
@ -214,16 +212,6 @@ interface nsITelemetry : nsISupports
[implicit_jscontext]
readonly attribute jsval lateWrites;
/**
* Returns an array whose values are the names of histograms defined
* in Histograms.json.
*
* @param dataset - DATASET_RELEASE_CHANNEL_OPTOUT or DATASET_RELEASE_CHANNEL_OPTIN
*/
void registeredHistograms(in uint32_t dataset,
out uint32_t count,
[retval, array, size_is(count)] out string histograms);
/**
* Create and return a histogram registered in TelemetryHistograms.h.
*
@ -238,30 +226,17 @@ interface nsITelemetry : nsISupports
[implicit_jscontext]
jsval getHistogramById(in ACString id);
/*
* An object containing a snapshot from all of the currently registered keyed histograms.
* { process1: {name1: {histogramData1}, name2:{histogramData2}...}}
* where the histogramData is as described in histogramSnapshots.
*/
[implicit_jscontext]
readonly attribute jsval keyedHistogramSnapshots;
/**
* Get a snapshot of the internally duplicated subsession keyed histograms.
* @param clear Whether to clear out the subsession histograms after snapshotting.
* @return An object as histogramSnapshots, except this contains the internally duplicated keyed histograms for subsession telemetry.
*/
[implicit_jscontext]
jsval snapshotSubsessionKeyedHistograms([optional] in boolean clear);
/**
* Returns an array whose values are the names of histograms defined
* in Histograms.json.
* Serializes the keyed histograms from the given dataset to a JSON-style object.
* The returned structure looks like:
* { process1: {name1: {histogramData1}, name2:{histogramData2}...}}
*
* @param dataset - DATASET_RELEASE_CHANNEL_OPTOUT or ...OPTIN
* @param aDataset DATASET_RELEASE_CHANNEL_OPTOUT or DATASET_RELEASE_CHANNEL_OPTIN.
* @param aSubsession Whether to return the internally-duplicated subsession keyed histograms
* @param aClear Whether to clear out the subsession keyed histograms after snapshotting (only works if aSubsession is true)
*/
void registeredKeyedHistograms(in uint32_t dataset, out uint32_t count,
[retval, array, size_is(count)] out string histograms);
[implicit_jscontext]
jsval snapshotKeyedHistograms(in uint32_t aDataset, in boolean aSubsession, in boolean aClear);
/**
* Create and return a histogram registered in TelemetryHistograms.h.

View File

@ -46,8 +46,8 @@ GetSnapshots(JSContext* cx, nsCOMPtr<nsITelemetry> mTelemetry,
const char* name, JS::MutableHandleValue valueOut, bool is_keyed)
{
JS::RootedValue snapshots(cx);
nsresult rv = is_keyed ? mTelemetry->GetKeyedHistogramSnapshots(cx, &snapshots)
: mTelemetry->GetHistogramSnapshots(cx, &snapshots);
nsresult rv = is_keyed ? mTelemetry->SnapshotKeyedHistograms(nsITelemetry::DATASET_RELEASE_CHANNEL_OPTIN, false, false, cx, &snapshots)
: mTelemetry->SnapshotHistograms(nsITelemetry::DATASET_RELEASE_CHANNEL_OPTIN, false, false, cx, &snapshots);
JS::RootedValue snapshot(cx);
GetProperty(cx, "parent", snapshots, &snapshot);

View File

@ -72,7 +72,9 @@ function check_histogram(histogram_type, name, min, max, bucket_count) {
for (let i of s.counts) {
do_check_eq(i, 1);
}
var hgrams = Telemetry.histogramSnapshots.parent;
var hgrams = Telemetry.snapshotHistograms(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN,
false,
false).parent;
let gh = hgrams[name]
do_check_eq(gh.histogram_type, histogram_type);
@ -114,7 +116,9 @@ function test_instantiate() {
// |add| will not instantiate the histogram.
h.add(1);
let snapshot = h.snapshot();
let subsession = Telemetry.snapshotSubsessionHistograms().parent;
let subsession = Telemetry.snapshotHistograms(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN,
true /* subsession */,
false /* clear */).parent;
Assert.ok(ID in subsession);
Assert.equal(snapshot.sum, subsession[ID].sum,
"Histogram and subsession histogram sum must match.");
@ -172,7 +176,10 @@ 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");
do_check_false("NEWTAB_PAGE_PINNED_SITES_COUNT" in Telemetry.histogramSnapshots.parent);
let histograms = Telemetry.snapshotHistograms(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN,
false /* subsession */,
false /* clear */).parent;
do_check_false("NEWTAB_PAGE_PINNED_SITES_COUNT" in histograms);
});
add_task(async function test_boolean_histogram() {
@ -434,20 +441,23 @@ add_task(async function test_histogramRecording() {
add_task(async function test_expired_histogram() {
var test_expired_id = "TELEMETRY_TEST_EXPIRED";
var dummy = Telemetry.getHistogramById(test_expired_id);
var rh = Telemetry.registeredHistograms(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, []);
Assert.ok(!!rh);
dummy.add(1);
for (let process of ["main", "content", "gpu", "extension"]) {
if (!(process in Telemetry.histogramSnapshots)) {
let histograms = Telemetry.snapshotHistograms(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN,
false /* subsession */,
false /* clear */);
if (!(process in histograms)) {
do_print("Nothing present for process " + process);
continue;
}
do_check_eq(Telemetry.histogramSnapshots[process].__expired__, undefined);
do_check_eq(histograms[process].__expired__, undefined);
}
do_check_eq(Telemetry.histogramSnapshots.parent[test_expired_id], undefined);
do_check_eq(rh[test_expired_id], undefined);
let parentHgrams = Telemetry.snapshotHistograms(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN,
false /* subsession */,
false /* clear */).parent;
do_check_eq(parentHgrams[test_expired_id], undefined);
});
add_task(async function test_keyed_histogram() {
@ -503,8 +513,10 @@ add_task(async function test_keyed_boolean_histogram() {
Assert.deepEqual(h.keys().sort(), testKeys);
Assert.deepEqual(h.snapshot(), testSnapShot);
let allSnapshots = Telemetry.keyedHistogramSnapshots.parent;
Assert.deepEqual(allSnapshots[KEYED_ID], testSnapShot);
let parentHgrams = Telemetry.snapshotKeyedHistograms(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN,
false /* subsession */,
false /* clear */).parent;
Assert.deepEqual(parentHgrams[KEYED_ID], testSnapShot);
h.clear();
Assert.deepEqual(h.keys(), []);
@ -559,8 +571,10 @@ add_task(async function test_keyed_count_histogram() {
Assert.deepEqual(h.keys().sort(), testKeys);
Assert.deepEqual(h.snapshot(), testSnapShot);
let allSnapshots = Telemetry.keyedHistogramSnapshots.parent;
Assert.deepEqual(allSnapshots[KEYED_ID], testSnapShot);
let parentHgrams = Telemetry.snapshotKeyedHistograms(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN,
false /* subsession */,
false /* clear */).parent;
Assert.deepEqual(parentHgrams[KEYED_ID], testSnapShot);
// Test clearing categorical histogram.
h.clear();
@ -632,8 +646,10 @@ add_task(async function test_keyed_flag_histogram() {
Assert.deepEqual(h.keys().sort(), [KEY]);
Assert.deepEqual(h.snapshot(), testSnapshot);
let allSnapshots = Telemetry.keyedHistogramSnapshots.parent;
Assert.deepEqual(allSnapshots[KEYED_ID], testSnapshot);
let parentHgrams = Telemetry.snapshotKeyedHistograms(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN,
false /* subsession */,
false /* clear */).parent;
Assert.deepEqual(parentHgrams[KEYED_ID], testSnapshot);
h.clear();
Assert.deepEqual(h.keys(), []);
@ -782,7 +798,10 @@ add_task(async function test_histogramSnapshots() {
keyed.add("a", 1);
// Check that keyed histograms are not returned
Assert.ok(!("TELEMETRY_TEST_KEYED_COUNT" in Telemetry.histogramSnapshots.parent));
let parentHgrams = Telemetry.snapshotHistograms(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN,
false /* subsession */,
false /* clear */).parent;
Assert.ok(!("TELEMETRY_TEST_KEYED_COUNT" in parentHgrams));
});
add_task(async function test_datasets() {
@ -792,24 +811,32 @@ add_task(async function test_datasets() {
const RELEASE_CHANNEL_OPTIN = Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN;
// Check that registeredHistogram works properly
let registered = Telemetry.registeredHistograms(RELEASE_CHANNEL_OPTIN, []);
registered = new Set(registered);
let registered = Telemetry.snapshotHistograms(RELEASE_CHANNEL_OPTIN,
false /* subsession */,
false /* clear */);
registered = new Set(Object.keys(registered.parent));
Assert.ok(registered.has("TELEMETRY_TEST_FLAG"));
Assert.ok(registered.has("TELEMETRY_TEST_RELEASE_OPTIN"));
Assert.ok(registered.has("TELEMETRY_TEST_RELEASE_OPTOUT"));
registered = Telemetry.registeredHistograms(RELEASE_CHANNEL_OPTOUT, []);
registered = new Set(registered);
registered = Telemetry.snapshotHistograms(RELEASE_CHANNEL_OPTOUT,
false /* subsession */,
false /* clear */);
registered = new Set(Object.keys(registered.parent));
Assert.ok(!registered.has("TELEMETRY_TEST_FLAG"));
Assert.ok(!registered.has("TELEMETRY_TEST_RELEASE_OPTIN"));
Assert.ok(registered.has("TELEMETRY_TEST_RELEASE_OPTOUT"));
// Check that registeredKeyedHistograms works properly
registered = Telemetry.registeredKeyedHistograms(RELEASE_CHANNEL_OPTIN, []);
registered = new Set(registered);
registered = Telemetry.snapshotKeyedHistograms(RELEASE_CHANNEL_OPTIN,
false /* subsession */,
false /* clear */);
registered = new Set(Object.keys(registered.parent));
Assert.ok(registered.has("TELEMETRY_TEST_KEYED_FLAG"));
Assert.ok(registered.has("TELEMETRY_TEST_KEYED_RELEASE_OPTOUT"));
registered = Telemetry.registeredKeyedHistograms(RELEASE_CHANNEL_OPTOUT, []);
registered = new Set(registered);
registered = Telemetry.snapshotKeyedHistograms(RELEASE_CHANNEL_OPTOUT,
false /* subsession */,
false /* clear */);
registered = new Set(Object.keys(registered.parent));
Assert.ok(!registered.has("TELEMETRY_TEST_KEYED_FLAG"));
Assert.ok(registered.has("TELEMETRY_TEST_KEYED_RELEASE_OPTOUT"));
});
@ -825,15 +852,23 @@ function test_subsession() {
// Both original and duplicate should start out the same.
h.clear();
let snapshot = Telemetry.histogramSnapshots.parent;
let subsession = Telemetry.snapshotSubsessionHistograms().parent;
let snapshot = Telemetry.snapshotHistograms(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN,
false /* subsession */,
false /* clear */).parent;
let subsession = Telemetry.snapshotHistograms(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN,
true /* subsession */,
false /* clear */).parent;
Assert.ok(!(COUNT in snapshot));
Assert.ok(!(COUNT in subsession));
// They should instantiate and pick-up the count.
h.add(1);
snapshot = Telemetry.histogramSnapshots.parent;
subsession = Telemetry.snapshotSubsessionHistograms().parent;
snapshot = Telemetry.snapshotHistograms(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN,
false /* subsession */,
false /* clear */).parent;
subsession = Telemetry.snapshotHistograms(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN,
true /* subsession */,
false /* clear */).parent;
Assert.ok(COUNT in snapshot);
Assert.ok(COUNT in subsession);
Assert.equal(snapshot[COUNT].sum, 1);
@ -841,15 +876,23 @@ function test_subsession() {
// They should still reset properly.
h.clear();
snapshot = Telemetry.histogramSnapshots.parent;
subsession = Telemetry.snapshotSubsessionHistograms().parent;
snapshot = Telemetry.snapshotHistograms(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN,
false /* subsession */,
false /* clear */).parent;
subsession = Telemetry.snapshotHistograms(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN,
true /* subsession */,
false /* clear */).parent;
Assert.ok(!(COUNT in snapshot));
Assert.ok(!(COUNT in subsession));
// Both should instantiate and pick-up the count.
h.add(1);
snapshot = Telemetry.histogramSnapshots.parent;
subsession = Telemetry.snapshotSubsessionHistograms().parent;
snapshot = Telemetry.snapshotHistograms(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN,
false /* subsession */,
false /* clear */).parent;
subsession = Telemetry.snapshotHistograms(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN,
true /* subsession */,
false /* clear */).parent;
Assert.ok(COUNT in snapshot);
Assert.ok(COUNT in subsession);
Assert.equal(snapshot[COUNT].sum, 1);
@ -857,16 +900,24 @@ function test_subsession() {
// Check that we are able to only reset the duplicate histogram.
h.clear(true);
snapshot = Telemetry.histogramSnapshots.parent;
subsession = Telemetry.snapshotSubsessionHistograms().parent;
snapshot = Telemetry.snapshotHistograms(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN,
false /* subsession */,
false /* clear */).parent;
subsession = Telemetry.snapshotHistograms(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN,
true /* subsession */,
false /* clear */).parent;
Assert.ok(COUNT in snapshot);
Assert.ok(!(COUNT in subsession));
Assert.equal(snapshot[COUNT].sum, 1);
// Both should register the next count.
h.add(1);
snapshot = Telemetry.histogramSnapshots.parent;
subsession = Telemetry.snapshotSubsessionHistograms().parent;
snapshot = Telemetry.snapshotHistograms(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN,
false /* subsession */,
false /* clear */).parent;
subsession = Telemetry.snapshotHistograms(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN,
true /* subsession */,
false /* clear */).parent;
Assert.equal(snapshot[COUNT].sum, 2);
Assert.equal(subsession[COUNT].sum, 1);
@ -876,8 +927,12 @@ function test_subsession() {
flag.clear();
h.add(1);
flag.add(1);
snapshot = Telemetry.histogramSnapshots.parent;
subsession = Telemetry.snapshotSubsessionHistograms(true).parent;
snapshot = Telemetry.snapshotHistograms(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN,
false /* subsession */,
false /* clear */).parent;
subsession = Telemetry.snapshotHistograms(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN,
true /* subsession */,
true /* clear */).parent;
Assert.ok(COUNT in snapshot);
Assert.ok(COUNT in subsession);
Assert.ok(FLAG in snapshot);
@ -889,8 +944,12 @@ function test_subsession() {
// The next subsesssion snapshot should show the histograms
// got reset.
snapshot = Telemetry.histogramSnapshots.parent;
subsession = Telemetry.snapshotSubsessionHistograms().parent;
snapshot = Telemetry.snapshotHistograms(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN,
false /* subsession */,
false /* clear */).parent;
subsession = Telemetry.snapshotHistograms(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN,
true /* subsession */,
false /* clear */).parent;
Assert.ok(COUNT in snapshot);
Assert.ok(!(COUNT in subsession));
Assert.ok(FLAG in snapshot);

View File

@ -756,8 +756,6 @@ add_task(async function test_checkSubsessionHistograms() {
const KEYED_ID = "TELEMETRY_TEST_KEYED_COUNT";
const count = Telemetry.getHistogramById(COUNT_ID);
const keyed = Telemetry.getKeyedHistogramById(KEYED_ID);
const registeredIds =
new Set(Telemetry.registeredHistograms(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, []));
const stableHistograms = new Set([
"TELEMETRY_TEST_FLAG",
@ -781,10 +779,6 @@ add_task(async function test_checkSubsessionHistograms() {
// check for deep equality on known stable histograms.
let checkHistograms = (classic, subsession, message) => {
for (let id of Object.keys(subsession)) {
if (!registeredIds.has(id)) {
continue;
}
Assert.ok(id in classic, message + ` (${id})`);
if (stableHistograms.has(id)) {
Assert.deepEqual(classic[id],
@ -799,10 +793,6 @@ add_task(async function test_checkSubsessionHistograms() {
// Same as above, except for keyed histograms.
let checkKeyedHistograms = (classic, subsession, message) => {
for (let id of Object.keys(subsession)) {
if (!registeredIds.has(id)) {
continue;
}
Assert.ok(id in classic, message);
if (stableKeyedHistograms.has(id)) {
Assert.deepEqual(classic[id],

View File

@ -33,7 +33,9 @@ add_task(async function init() {
add_task(async function test_reload() {
do_print("Forging data");
let data = {};
let telemetrySnapshots = Services.telemetry.histogramSnapshots.parent;
let telemetrySnapshots = Services.telemetry.snapshotHistograms(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN,
false /* subsession */,
false /* clear */).parent;
let i = 0;
for (let k of Object.keys(HISTOGRAMS)) {
let id = HISTOGRAMS[k];
@ -64,7 +66,9 @@ add_task(async function test_reload() {
// Now wait until Telemetry is updated
await wait;
telemetrySnapshots = Services.telemetry.histogramSnapshots.parent;
telemetrySnapshots = Services.telemetry.snapshotHistograms(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN,
false /* subsession */,
false /* clear */).parent;
for (let k of Object.keys(HISTOGRAMS)) {
let id = HISTOGRAMS[k];
do_print("Testing histogram " + id);