Bug 1120369 - Allow specifying the desired dataset in Histograms.json. r=vladan

This commit is contained in:
Georg Fritzsche 2015-01-29 15:17:24 +01:00
parent a35dbaeebf
commit f36ab0e55f
8 changed files with 384 additions and 196 deletions

View File

@ -4336,6 +4336,32 @@
"keyed": true,
"description": "a testing histogram; not meant to be touched"
},
"TELEMETRY_TEST_RELEASE_OPTOUT": {
"expires_in_version": "default",
"kind": "flag",
"releaseChannelCollection": "opt-out",
"description": "a testing histogram; not meant to be touched"
},
"TELEMETRY_TEST_RELEASE_OPTIN": {
"expires_in_version": "default",
"kind": "flag",
"releaseChannelCollection": "opt-in",
"description": "a testing histogram; not meant to be touched"
},
"TELEMETRY_TEST_KEYED_RELEASE_OPTIN": {
"expires_in_version": "default",
"kind": "flag",
"keyed": true,
"releaseChannelCollection": "opt-in",
"description": "a testing histogram; not meant to be touched"
},
"TELEMETRY_TEST_KEYED_RELEASE_OPTOUT": {
"expires_in_version": "default",
"kind": "flag",
"keyed": true,
"releaseChannelCollection": "opt-out",
"description": "a testing histogram; not meant to be touched"
},
"STARTUP_CRASH_DETECTED": {
"expires_in_version": "never",
"kind": "flag",

View File

@ -626,184 +626,7 @@ ClearIOReporting()
sTelemetryIOObserver = nullptr;
}
class KeyedHistogram {
public:
KeyedHistogram(const nsACString &name, const nsACString &expiration,
uint32_t histogramType, uint32_t min, uint32_t max,
uint32_t bucketCount);
nsresult GetHistogram(const nsCString& name, Histogram** histogram);
Histogram* GetHistogram(const nsCString& name);
uint32_t GetHistogramType() const { return mHistogramType; }
nsresult GetJSKeys(JSContext* cx, JS::CallArgs& args);
nsresult GetJSSnapshot(JSContext* cx, JS::Handle<JSObject*> obj);
void Clear();
private:
typedef nsBaseHashtableET<nsCStringHashKey, Histogram*> KeyedHistogramEntry;
typedef AutoHashtable<KeyedHistogramEntry> KeyedHistogramMapType;
KeyedHistogramMapType mHistogramMap;
struct ReflectKeysArgs {
JSContext* jsContext;
JS::AutoValueVector* vector;
};
static PLDHashOperator ReflectKeys(KeyedHistogramEntry* entry, void* arg);
static bool ReflectKeyedHistogram(KeyedHistogramEntry* entry,
JSContext* cx,
JS::Handle<JSObject*> obj);
static PLDHashOperator ClearHistogramEnumerator(KeyedHistogramEntry*, void*);
const nsCString mName;
const nsCString mExpiration;
const uint32_t mHistogramType;
const uint32_t mMin;
const uint32_t mMax;
const uint32_t mBucketCount;
};
KeyedHistogram::KeyedHistogram(const nsACString &name, const nsACString &expiration,
uint32_t histogramType, uint32_t min, uint32_t max,
uint32_t bucketCount)
: mHistogramMap()
, mName(name)
, mExpiration(expiration)
, mHistogramType(histogramType)
, mMin(min)
, mMax(max)
, mBucketCount(bucketCount)
{
}
nsresult
KeyedHistogram::GetHistogram(const nsCString& key, Histogram** histogram)
{
KeyedHistogramEntry* entry = mHistogramMap.GetEntry(key);
if (entry) {
*histogram = entry->mData;
return NS_OK;
}
nsCString histogramName = mName;
histogramName.Append(KEYED_HISTOGRAM_NAME_SEPARATOR);
histogramName.Append(key);
Histogram* h;
nsresult rv = HistogramGet(histogramName.get(), mExpiration.get(),
mHistogramType, mMin, mMax, mBucketCount,
true, &h);
if (NS_FAILED(rv)) {
return rv;
}
h->ClearFlags(Histogram::kUmaTargetedHistogramFlag);
h->SetFlags(Histogram::kExtendedStatisticsFlag);
*histogram = h;
entry = mHistogramMap.PutEntry(key);
if (MOZ_UNLIKELY(!entry)) {
return NS_ERROR_OUT_OF_MEMORY;
}
entry->mData = h;
return NS_OK;
}
Histogram*
KeyedHistogram::GetHistogram(const nsCString& key)
{
Histogram* h = nullptr;
if (NS_FAILED(GetHistogram(key, &h))) {
return nullptr;
}
return h;
}
/* static */
PLDHashOperator
KeyedHistogram::ClearHistogramEnumerator(KeyedHistogramEntry* entry, void*)
{
entry->mData->Clear();
return PL_DHASH_NEXT;
}
void
KeyedHistogram::Clear()
{
mHistogramMap.EnumerateEntries(&KeyedHistogram::ClearHistogramEnumerator, nullptr);
mHistogramMap.Clear();
}
/* static */
PLDHashOperator
KeyedHistogram::ReflectKeys(KeyedHistogramEntry* entry, void* arg)
{
ReflectKeysArgs* args = static_cast<ReflectKeysArgs*>(arg);
JS::RootedValue jsKey(args->jsContext);
const NS_ConvertUTF8toUTF16 key(entry->GetKey());
jsKey.setString(JS_NewUCStringCopyN(args->jsContext, key.Data(), key.Length()));
args->vector->append(jsKey);
return PL_DHASH_NEXT;
}
nsresult
KeyedHistogram::GetJSKeys(JSContext* cx, JS::CallArgs& args)
{
JS::AutoValueVector keys(cx);
if (!keys.reserve(mHistogramMap.Count())) {
return NS_ERROR_OUT_OF_MEMORY;
}
ReflectKeysArgs reflectArgs = { cx, &keys };
const uint32_t num = mHistogramMap.EnumerateEntries(&KeyedHistogram::ReflectKeys,
static_cast<void*>(&reflectArgs));
if (num != mHistogramMap.Count()) {
return NS_ERROR_FAILURE;
}
JS::RootedObject jsKeys(cx, JS_NewArrayObject(cx, keys));
if (!jsKeys) {
return NS_ERROR_FAILURE;
}
args.rval().setObject(*jsKeys);
return NS_OK;
}
/* static */
bool
KeyedHistogram::ReflectKeyedHistogram(KeyedHistogramEntry* entry, JSContext* cx, JS::Handle<JSObject*> obj)
{
JS::RootedObject histogramSnapshot(cx, JS_NewPlainObject(cx));
if (!histogramSnapshot) {
return false;
}
if (ReflectHistogramSnapshot(cx, histogramSnapshot, entry->mData) != REFLECT_OK) {
return false;
}
const NS_ConvertUTF8toUTF16 key(entry->GetKey());
if (!JS_DefineUCProperty(cx, obj, key.Data(), key.Length(),
histogramSnapshot, JSPROP_ENUMERATE)) {
return false;
}
return true;
}
nsresult
KeyedHistogram::GetJSSnapshot(JSContext* cx, JS::Handle<JSObject*> obj)
{
if (!mHistogramMap.ReflectIntoJS(&KeyedHistogram::ReflectKeyedHistogram, cx, obj)) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
class KeyedHistogram;
class TelemetryImpl MOZ_FINAL
: public nsITelemetry
@ -940,6 +763,44 @@ TelemetryImpl::CollectReports(nsIHandleReportCallback* aHandleReport,
"Memory used by the telemetry system.");
}
class KeyedHistogram {
public:
KeyedHistogram(const nsACString &name, const nsACString &expiration,
uint32_t histogramType, uint32_t min, uint32_t max,
uint32_t bucketCount);
nsresult GetHistogram(const nsCString& name, Histogram** histogram);
Histogram* GetHistogram(const nsCString& name);
uint32_t GetHistogramType() const { return mHistogramType; }
nsresult GetDataset(uint32_t* dataset) const;
nsresult GetJSKeys(JSContext* cx, JS::CallArgs& args);
nsresult GetJSSnapshot(JSContext* cx, JS::Handle<JSObject*> obj);
void Clear();
private:
typedef nsBaseHashtableET<nsCStringHashKey, Histogram*> KeyedHistogramEntry;
typedef AutoHashtable<KeyedHistogramEntry> KeyedHistogramMapType;
KeyedHistogramMapType mHistogramMap;
struct ReflectKeysArgs {
JSContext* jsContext;
JS::AutoValueVector* vector;
};
static PLDHashOperator ReflectKeys(KeyedHistogramEntry* entry, void* arg);
static bool ReflectKeyedHistogram(KeyedHistogramEntry* entry,
JSContext* cx,
JS::Handle<JSObject*> obj);
static PLDHashOperator ClearHistogramEnumerator(KeyedHistogramEntry*, void*);
const nsCString mName;
const nsCString mExpiration;
const uint32_t mHistogramType;
const uint32_t mMin;
const uint32_t mMax;
const uint32_t mBucketCount;
};
// A initializer to initialize histogram collection
StatisticsRecorder gStatisticsRecorder;
@ -951,6 +812,7 @@ struct TelemetryHistogram {
uint32_t histogramType;
uint32_t id_offset;
uint32_t expiration_offset;
uint32_t dataset;
bool extendedStatisticsOK;
bool keyed;
@ -992,6 +854,23 @@ IsValidHistogramName(const nsACString& name)
return !FindInReadable(nsCString(KEYED_HISTOGRAM_NAME_SEPARATOR), name);
}
bool
IsInDataset(const TelemetryHistogram& h, uint32_t dataset)
{
if (h.dataset == dataset) {
return true;
}
// The "optin on release channel" dataset is a superset of the
// "optout on release channel one".
if (dataset == nsITelemetry::DATASET_RELEASE_CHANNEL_OPTIN
&& h.dataset == nsITelemetry::DATASET_RELEASE_CHANNEL_OPTOUT) {
return true;
}
return false;
}
nsresult
CheckHistogramArguments(uint32_t histogramType, uint32_t min, uint32_t max,
uint32_t bucketCount, bool haveOptArgs)
@ -1272,6 +1151,26 @@ JSHistogram_Clear(JSContext *cx, unsigned argc, JS::Value *vp)
return true;
}
bool
JSHistogram_Dataset(JSContext *cx, unsigned argc, JS::Value *vp)
{
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
JSObject *obj = JS_THIS_OBJECT(cx, vp);
if (!obj) {
return false;
}
Histogram *h = static_cast<Histogram*>(JS_GetPrivate(obj));
Telemetry::ID id;
nsresult rv = TelemetryImpl::GetHistogramEnumId(h->histogram_name().c_str(), &id);
if (NS_SUCCEEDED(rv)) {
args.rval().setNumber(gHistograms[id].dataset);
return true;
}
return false;
}
nsresult
WrapAndReturnHistogram(Histogram *h, JSContext *cx, JS::MutableHandle<JS::Value> ret)
{
@ -1285,7 +1184,8 @@ WrapAndReturnHistogram(Histogram *h, JSContext *cx, JS::MutableHandle<JS::Value>
return NS_ERROR_FAILURE;
if (!(JS_DefineFunction(cx, obj, "add", JSHistogram_Add, 1, 0)
&& JS_DefineFunction(cx, obj, "snapshot", JSHistogram_Snapshot, 0, 0)
&& JS_DefineFunction(cx, obj, "clear", JSHistogram_Clear, 0, 0))) {
&& JS_DefineFunction(cx, obj, "clear", JSHistogram_Clear, 0, 0)
&& JS_DefineFunction(cx, obj, "dataset", JSHistogram_Dataset, 0, 0))) {
return NS_ERROR_FAILURE;
}
JS_SetPrivate(obj, h);
@ -1448,6 +1348,30 @@ JSKeyedHistogram_Clear(JSContext *cx, unsigned argc, JS::Value *vp)
return true;
}
bool
JSKeyedHistogram_Dataset(JSContext *cx, unsigned argc, JS::Value *vp)
{
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
JSObject *obj = JS_THIS_OBJECT(cx, vp);
if (!obj) {
return false;
}
KeyedHistogram* keyed = static_cast<KeyedHistogram*>(JS_GetPrivate(obj));
if (!keyed) {
return false;
}
uint32_t dataset = nsITelemetry::DATASET_RELEASE_CHANNEL_OPTIN;
nsresult rv = keyed->GetDataset(&dataset);;
if (NS_FAILED(rv)) {
return false;
}
args.rval().setNumber(dataset);
return true;
}
nsresult
WrapAndReturnKeyedHistogram(KeyedHistogram *h, JSContext *cx, JS::MutableHandle<JS::Value> ret)
{
@ -1462,7 +1386,8 @@ WrapAndReturnKeyedHistogram(KeyedHistogram *h, JSContext *cx, JS::MutableHandle<
if (!(JS_DefineFunction(cx, obj, "add", JSKeyedHistogram_Add, 2, 0)
&& JS_DefineFunction(cx, obj, "snapshot", JSKeyedHistogram_Snapshot, 1, 0)
&& JS_DefineFunction(cx, obj, "keys", JSKeyedHistogram_Keys, 0, 0)
&& JS_DefineFunction(cx, obj, "clear", JSKeyedHistogram_Clear, 0, 0))) {
&& JS_DefineFunction(cx, obj, "clear", JSKeyedHistogram_Clear, 0, 0)
&& JS_DefineFunction(cx, obj, "dataset", JSKeyedHistogram_Dataset, 0, 0))) {
return NS_ERROR_FAILURE;
}
@ -2887,13 +2812,15 @@ TelemetryImpl::GetLateWrites(JSContext *cx, JS::MutableHandle<JS::Value> ret)
}
nsresult
GetRegisteredHistogramIds(bool keyed, uint32_t *aCount, char*** aHistograms)
GetRegisteredHistogramIds(bool keyed, uint32_t dataset, uint32_t *aCount,
char*** aHistograms)
{
nsTArray<char*> collection;
for (size_t i = 0; i < ArrayLength(gHistograms); ++i) {
const TelemetryHistogram& h = gHistograms[i];
if (IsExpired(h.expiration()) || h.keyed != keyed) {
if (IsExpired(h.expiration()) || h.keyed != keyed ||
!IsInDataset(h, dataset)) {
continue;
}
@ -2912,15 +2839,17 @@ GetRegisteredHistogramIds(bool keyed, uint32_t *aCount, char*** aHistograms)
}
NS_IMETHODIMP
TelemetryImpl::RegisteredHistograms(uint32_t *aCount, char*** aHistograms)
TelemetryImpl::RegisteredHistograms(uint32_t aDataset, uint32_t *aCount,
char*** aHistograms)
{
return GetRegisteredHistogramIds(false, aCount, aHistograms);
return GetRegisteredHistogramIds(false, aDataset, aCount, aHistograms);
}
NS_IMETHODIMP
TelemetryImpl::RegisteredKeyedHistograms(uint32_t *aCount, char*** aHistograms)
TelemetryImpl::RegisteredKeyedHistograms(uint32_t aDataset, uint32_t *aCount,
char*** aHistograms)
{
return GetRegisteredHistogramIds(true, aCount, aHistograms);
return GetRegisteredHistogramIds(true, aDataset, aCount, aHistograms);
}
NS_IMETHODIMP
@ -3836,3 +3765,160 @@ XRE_TelemetryAccumulate(int aID, uint32_t aSample)
{
mozilla::Telemetry::Accumulate((mozilla::Telemetry::ID) aID, aSample);
}
KeyedHistogram::KeyedHistogram(const nsACString &name, const nsACString &expiration,
uint32_t histogramType, uint32_t min, uint32_t max,
uint32_t bucketCount)
: mHistogramMap()
, mName(name)
, mExpiration(expiration)
, mHistogramType(histogramType)
, mMin(min)
, mMax(max)
, mBucketCount(bucketCount)
{
}
nsresult
KeyedHistogram::GetHistogram(const nsCString& key, Histogram** histogram)
{
KeyedHistogramEntry* entry = mHistogramMap.GetEntry(key);
if (entry) {
*histogram = entry->mData;
return NS_OK;
}
nsCString histogramName = mName;
histogramName.Append(KEYED_HISTOGRAM_NAME_SEPARATOR);
histogramName.Append(key);
Histogram* h;
nsresult rv = HistogramGet(histogramName.get(), mExpiration.get(),
mHistogramType, mMin, mMax, mBucketCount,
true, &h);
if (NS_FAILED(rv)) {
return rv;
}
h->ClearFlags(Histogram::kUmaTargetedHistogramFlag);
h->SetFlags(Histogram::kExtendedStatisticsFlag);
*histogram = h;
entry = mHistogramMap.PutEntry(key);
if (MOZ_UNLIKELY(!entry)) {
return NS_ERROR_OUT_OF_MEMORY;
}
entry->mData = h;
return NS_OK;
}
Histogram*
KeyedHistogram::GetHistogram(const nsCString& key)
{
Histogram* h = nullptr;
if (NS_FAILED(GetHistogram(key, &h))) {
return nullptr;
}
return h;
}
nsresult
KeyedHistogram::GetDataset(uint32_t* dataset) const
{
MOZ_ASSERT(dataset);
Telemetry::ID id;
nsresult rv = TelemetryImpl::GetHistogramEnumId(mName.get(), &id);
if (NS_FAILED(rv)) {
return rv;
}
*dataset = gHistograms[id].dataset;
return NS_OK;
}
/* static */
PLDHashOperator
KeyedHistogram::ClearHistogramEnumerator(KeyedHistogramEntry* entry, void*)
{
entry->mData->Clear();
return PL_DHASH_NEXT;
}
void
KeyedHistogram::Clear()
{
mHistogramMap.EnumerateEntries(&KeyedHistogram::ClearHistogramEnumerator, nullptr);
mHistogramMap.Clear();
}
/* static */
PLDHashOperator
KeyedHistogram::ReflectKeys(KeyedHistogramEntry* entry, void* arg)
{
ReflectKeysArgs* args = static_cast<ReflectKeysArgs*>(arg);
JS::RootedValue jsKey(args->jsContext);
const NS_ConvertUTF8toUTF16 key(entry->GetKey());
jsKey.setString(JS_NewUCStringCopyN(args->jsContext, key.Data(), key.Length()));
args->vector->append(jsKey);
return PL_DHASH_NEXT;
}
nsresult
KeyedHistogram::GetJSKeys(JSContext* cx, JS::CallArgs& args)
{
JS::AutoValueVector keys(cx);
if (!keys.reserve(mHistogramMap.Count())) {
return NS_ERROR_OUT_OF_MEMORY;
}
ReflectKeysArgs reflectArgs = { cx, &keys };
const uint32_t num = mHistogramMap.EnumerateEntries(&KeyedHistogram::ReflectKeys,
static_cast<void*>(&reflectArgs));
if (num != mHistogramMap.Count()) {
return NS_ERROR_FAILURE;
}
JS::RootedObject jsKeys(cx, JS_NewArrayObject(cx, keys));
if (!jsKeys) {
return NS_ERROR_FAILURE;
}
args.rval().setObject(*jsKeys);
return NS_OK;
}
/* static */
bool
KeyedHistogram::ReflectKeyedHistogram(KeyedHistogramEntry* entry, JSContext* cx, JS::Handle<JSObject*> obj)
{
JS::RootedObject histogramSnapshot(cx, JS_NewPlainObject(cx));
if (!histogramSnapshot) {
return false;
}
if (ReflectHistogramSnapshot(cx, histogramSnapshot, entry->mData) != REFLECT_OK) {
return false;
}
const NS_ConvertUTF8toUTF16 key(entry->GetKey());
if (!JS_DefineUCProperty(cx, obj, key.Data(), key.Length(),
histogramSnapshot, JSPROP_ENUMERATE)) {
return false;
}
return true;
}
nsresult
KeyedHistogram::GetJSSnapshot(JSContext* cx, JS::Handle<JSObject*> obj)
{
if (!mHistogramMap.ReflectIntoJS(&KeyedHistogram::ReflectKeyedHistogram, cx, obj)) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}

View File

@ -460,7 +460,7 @@ let Impl = {
getHistograms: function getHistograms(hls) {
this._log.trace("getHistograms");
let registered = Telemetry.registeredHistograms([]);
let registered = Telemetry.registeredHistograms(Ci.nsITelemetry.DATASET_EXTENDED, []);
let ret = {};
for (let name of registered) {
@ -496,7 +496,7 @@ let Impl = {
getKeyedHistograms: function() {
this._log.trace("getKeyedHistograms");
let registered = Telemetry.registeredKeyedHistograms([]);
let registered = Telemetry.registeredKeyedHistograms(Ci.nsITelemetry.DATASET_EXTENDED, []);
let ret = {};
for (let id of registered) {
@ -771,7 +771,7 @@ let Impl = {
gatherStartupHistograms: function gatherStartupHistograms() {
this._log.trace("gatherStartupHistograms");
let info = Telemetry.registeredHistograms([]);
let info = Telemetry.registeredHistograms(Ci.nsITelemetry.DATASET_EXTENDED, []);
let snapshots = Telemetry.histogramSnapshots;
for (let name of info) {
// Only duplicate histograms with actual data.

View File

@ -60,10 +60,10 @@ def print_array_entry(histogram, name_index, exp_index):
cpp_guard = histogram.cpp_guard()
if cpp_guard:
print "#if defined(%s)" % cpp_guard
print " { %s, %s, %s, %s, %d, %d, %s, %s }," \
print " { %s, %s, %s, %s, %d, %d, %s, %s, %s }," \
% (histogram.low(), histogram.high(),
histogram.n_buckets(), histogram.nsITelemetry_kind(),
name_index, exp_index,
name_index, exp_index, histogram.dataset(),
"true" if histogram.extended_statistics_ok() else "false",
"true" if histogram.keyed() else "false")
if cpp_guard:

View File

@ -55,7 +55,8 @@ def exponential_buckets(dmin, dmax, n_buckets):
ret_array[bucket_index] = current
return ret_array
always_allowed_keys = ['kind', 'description', 'cpp_guard', 'expires_in_version', "alert_emails", 'keyed']
always_allowed_keys = ['kind', 'description', 'cpp_guard', 'expires_in_version',
'alert_emails', 'keyed', 'releaseChannelCollection']
class Histogram:
"""A class for representing a histogram definition."""
@ -88,6 +89,12 @@ symbol that should guard C/C++ definitions associated with the histogram."""
'exponential': 'EXPONENTIAL' }
table_dispatch(self.kind(), table,
lambda k: self._set_nsITelemetry_kind(k))
datasets = { 'opt-in': 'DATASET_RELEASE_CHANNEL_OPTIN',
'opt-out': 'DATASET_RELEASE_CHANNEL_OPTOUT' }
value = definition.get('releaseChannelCollection', 'opt-in')
if not value in datasets:
raise DefinitionException, "unknown release channel collection policy for " + name
self._dataset = "nsITelemetry::" + datasets[value]
def name(self):
"""Return the name of the histogram."""
@ -135,6 +142,10 @@ associated with the histogram. Returns None if no guarding is necessary."""
"""Returns True if this a keyed histogram, false otherwise."""
return self._keyed
def dataset(self):
"""Returns the dataset this histogram belongs into."""
return self._dataset
def extended_statistics_ok(self):
"""Return True if gathering extended statistics for this histogram
is enabled."""

View File

@ -29,6 +29,16 @@ interface nsITelemetry : nsISupports
const unsigned long HISTOGRAM_FLAG = 3;
const unsigned long HISTOGRAM_COUNT = 4;
/**
* Dataset types:
* DATASET_RELEASE_CHANNEL_OPTOUT - the basic dataset that is on-by-default on all channels
* DATASET_RELEASE_CHANNEL_OPTIN - the extended dataset that is opt-in on release,
* opt-out on pre-release channels.
*/
const unsigned long DATASET_RELEASE_CHANNEL_OPTOUT = 0;
const unsigned long DATASET_RELEASE_CHANNEL_OPTIN = 1;
/*
* An object containing a snapshot from all of the currently registered histograms.
* { name1: {data1}, name2:{data2}...}
@ -134,8 +144,11 @@ interface nsITelemetry : nsISupports
/**
* 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(out uint32_t count,
void registeredHistograms(in uint32_t dataset,
out uint32_t count,
[retval, array, size_is(count)] out string histograms);
/**
@ -151,6 +164,7 @@ interface nsITelemetry : nsISupports
* 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
* dataset() - identifies what dataset this is in: DATASET_RELEASE_CHANNEL_OPTOUT or ...OPTIN
*/
[implicit_jscontext, optional_argc]
jsval newHistogram(in ACString name, in ACString expiration,
@ -200,6 +214,7 @@ interface nsITelemetry : nsISupports
* snapshot([optional] string key) - If key is provided, returns a snapshot for the histogram with that key or null. If key is not provided, returns the snapshots of all the registered keys in the form {key1: snapshot1, key2: snapshot2, ...}.
* keys() - Returns an array with the string keys of the currently registered histograms
* clear() - Clears the registered histograms from this.
* dataset() - identifies what dataset this is in: DATASET_RELEASE_CHANNEL_OPTOUT or ...OPTIN
*/
[implicit_jscontext, optional_argc]
jsval newKeyedHistogram(in ACString name,
@ -212,8 +227,10 @@ interface nsITelemetry : nsISupports
/**
* Returns an array whose values are the names of histograms defined
* in Histograms.json.
*
* @param dataset - DATASET_RELEASE_CHANNEL_OPTOUT or ...OPTIN
*/
void registeredKeyedHistograms(out uint32_t count,
void registeredKeyedHistograms(in uint32_t dataset, out uint32_t count,
[retval, array, size_is(count)] out string histograms);
/**

View File

@ -259,7 +259,7 @@ function checkPayload(request, reason, successfulPings) {
do_check_true(TELEMETRY_TEST_FLAG in payload.histograms);
do_check_true(TELEMETRY_TEST_COUNT in payload.histograms);
let rh = Telemetry.registeredHistograms([]);
let rh = Telemetry.registeredHistograms(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, []);
for (let name of rh) {
if (/SQLITE/.test(name) && name in payload.histograms) {
do_check_true(("STARTUP_" + name) in payload.histograms);

View File

@ -15,7 +15,8 @@ function test_expired_histogram() {
var clone_id = "ExpiredClone";
var dummy = Telemetry.newHistogram(histogram_id, "28.0a1", Telemetry.HISTOGRAM_EXPONENTIAL, 1, 2, 3);
var dummy_clone = Telemetry.histogramFrom(clone_id, test_expired_id);
var rh = Telemetry.registeredHistograms([]);
var rh = Telemetry.registeredHistograms(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, []);
Assert.ok(!!rh);
dummy.add(1);
dummy_clone.add(1);
@ -558,6 +559,52 @@ function test_keyed_histogram() {
test_keyed_flag_histogram();
}
function test_datasets()
{
// Check that datasets work as expected.
const RELEASE_CHANNEL_OPTOUT = Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTOUT;
const RELEASE_CHANNEL_OPTIN = Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN;
// Histograms should default to the extended dataset
let h = Telemetry.getHistogramById("TELEMETRY_TEST_FLAG");
Assert.equal(h.dataset(), RELEASE_CHANNEL_OPTIN);
h = Telemetry.getKeyedHistogramById("TELEMETRY_TEST_KEYED_FLAG");
Assert.equal(h.dataset(), RELEASE_CHANNEL_OPTIN);
// Check test histograms with explicit dataset definitions
h = Telemetry.getHistogramById("TELEMETRY_TEST_RELEASE_OPTIN");
Assert.equal(h.dataset(), RELEASE_CHANNEL_OPTIN);
h = Telemetry.getHistogramById("TELEMETRY_TEST_RELEASE_OPTOUT");
Assert.equal(h.dataset(), RELEASE_CHANNEL_OPTOUT);
h = Telemetry.getKeyedHistogramById("TELEMETRY_TEST_KEYED_RELEASE_OPTIN");
Assert.equal(h.dataset(), RELEASE_CHANNEL_OPTIN);
h = Telemetry.getKeyedHistogramById("TELEMETRY_TEST_KEYED_RELEASE_OPTOUT");
Assert.equal(h.dataset(), RELEASE_CHANNEL_OPTOUT);
// Check that registeredHistogram works properly
let registered = Telemetry.registeredHistograms(RELEASE_CHANNEL_OPTIN, []);
registered = new Set(registered);
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);
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);
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);
Assert.ok(!registered.has("TELEMETRY_TEST_KEYED_FLAG"));
Assert.ok(registered.has("TELEMETRY_TEST_KEYED_RELEASE_OPTOUT"));
}
function generateUUID() {
let str = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator).generateUUID().toString();
// strip {}
@ -592,4 +639,5 @@ function run_test()
test_extended_stats();
test_expired_histogram();
test_keyed_histogram();
test_datasets();
}