зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to autoland
--HG-- extra : rebase_source : 314f463721337b68ff25177cdb5d9eb7dcde7371
This commit is contained in:
Коммит
1e57d7d5e5
2
CLOBBER
2
CLOBBER
|
@ -22,4 +22,4 @@
|
|||
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
|
||||
# don't change CLOBBER for WebIDL changes any more.
|
||||
|
||||
Bug 1351074 - required because bug 1352982 means removing a .jsm requires a clobber
|
||||
Bug 1356151 - Clobber needed after bug 1353295 was backed out
|
||||
|
|
|
@ -260,10 +260,27 @@ Target.prototype = {
|
|||
this._logHistogram(data.metric);
|
||||
},
|
||||
|
||||
_getAddonHistogram(item) {
|
||||
let appName = this._getAddonHistogramName(item, APPNAME_IDX);
|
||||
let histName = this._getAddonHistogramName(item, HISTNAME_IDX);
|
||||
|
||||
return Services.telemetry.getAddonHistogram(appName, CUSTOM_HISTOGRAM_PREFIX
|
||||
+ histName);
|
||||
},
|
||||
|
||||
_getAddonHistogramName(item, index) {
|
||||
let array = item.split('_');
|
||||
return array[index].toUpperCase();
|
||||
},
|
||||
|
||||
_clearTelemetryData() {
|
||||
developerHUD._histograms.forEach(function(item) {
|
||||
Services.telemetry.getKeyedHistogramById(item).clear();
|
||||
});
|
||||
|
||||
developerHUD._customHistograms.forEach(item => {
|
||||
this._getAddonHistogram(item).clear();
|
||||
});
|
||||
},
|
||||
|
||||
_sendTelemetryData() {
|
||||
|
@ -274,6 +291,7 @@ Target.prototype = {
|
|||
let frame = this.frame;
|
||||
let payload = {
|
||||
keyedHistograms: {},
|
||||
addonHistograms: {}
|
||||
};
|
||||
// Package the hud histograms.
|
||||
developerHUD._histograms.forEach(function(item) {
|
||||
|
@ -281,6 +299,20 @@ Target.prototype = {
|
|||
Services.telemetry.getKeyedHistogramById(item).snapshot();
|
||||
});
|
||||
|
||||
// Package the registered hud custom histograms
|
||||
developerHUD._customHistograms.forEach(item => {
|
||||
let appName = this._getAddonHistogramName(item, APPNAME_IDX);
|
||||
let histName = CUSTOM_HISTOGRAM_PREFIX +
|
||||
this._getAddonHistogramName(item, HISTNAME_IDX);
|
||||
let addonHist = Services.telemetry.getAddonHistogram(appName, histName).snapshot();
|
||||
if (!(appName in payload.addonHistograms)) {
|
||||
payload.addonHistograms[appName] = {};
|
||||
}
|
||||
// Do not include histograms with sum of 0.
|
||||
if (addonHist.sum > 0) {
|
||||
payload.addonHistograms[appName][histName] = addonHist;
|
||||
}
|
||||
});
|
||||
shell.sendEvent(frame, 'advanced-telemetry-update', Cu.cloneInto(payload, frame));
|
||||
},
|
||||
|
||||
|
|
|
@ -125,8 +125,6 @@ var gFailedOpaqueLayerMessages = [];
|
|||
var gFailedAssignedLayer = false;
|
||||
var gFailedAssignedLayerMessages = [];
|
||||
|
||||
var gStartAfter = undefined;
|
||||
|
||||
// The enabled-state of the test-plugins, stored so they can be reset later
|
||||
var gTestPluginEnabledStates = null;
|
||||
|
||||
|
@ -391,12 +389,6 @@ function InitAndStartRefTests()
|
|||
gFocusFilterMode = prefs.getCharPref("reftest.focusFilterMode");
|
||||
} catch(e) {}
|
||||
|
||||
try {
|
||||
gStartAfter = prefs.getCharPref("reftest.startAfter");
|
||||
} catch(e) {
|
||||
gStartAfter = undefined;
|
||||
}
|
||||
|
||||
#ifdef MOZ_STYLO
|
||||
try {
|
||||
gCompareStyloToGecko = prefs.getBoolPref("reftest.compareStyloToGecko");
|
||||
|
@ -552,24 +544,7 @@ function StartTests()
|
|||
}
|
||||
|
||||
if (gShuffle) {
|
||||
if (gStartAfter !== undefined) {
|
||||
logger.error("Can't resume from a crashed test when " +
|
||||
"--shuffle is enabled, continue by shuffling " +
|
||||
"all the tests");
|
||||
DoneTests();
|
||||
return;
|
||||
}
|
||||
Shuffle(gURLs);
|
||||
} else if (gStartAfter !== undefined) {
|
||||
// Skip through previously crashed test
|
||||
// We have to do this after chunking so we don't break the numbers
|
||||
var crash_idx = gURLs.map(function(url) {
|
||||
return url['url1']['spec'];
|
||||
}).indexOf(gStartAfter);
|
||||
if (crash_idx == -1) {
|
||||
throw "Can't find the previously crashed test";
|
||||
}
|
||||
gURLs = gURLs.slice(crash_idx + 1);
|
||||
}
|
||||
|
||||
gTotalTests = gURLs.length;
|
||||
|
|
|
@ -227,15 +227,12 @@ class RemoteReftest(RefTest):
|
|||
def stopWebServer(self, options):
|
||||
self.server.stop()
|
||||
|
||||
def createReftestProfile(self, options, manifest, startAfter=None):
|
||||
def createReftestProfile(self, options, manifest):
|
||||
profile = RefTest.createReftestProfile(self,
|
||||
options,
|
||||
manifest,
|
||||
server=options.remoteWebServer,
|
||||
port=options.httpPort)
|
||||
if startAfter is not None:
|
||||
print ("WARNING: Continuing after a crash is not supported for remote "
|
||||
"reftest yet.")
|
||||
profileDir = profile.profile
|
||||
|
||||
prefs = {}
|
||||
|
|
|
@ -247,7 +247,7 @@ class RefTest(object):
|
|||
return os.path.normpath(os.path.join(self.oldcwd, os.path.expanduser(path)))
|
||||
|
||||
def createReftestProfile(self, options, manifests, server='localhost', port=0,
|
||||
profile_to_clone=None, startAfter=None):
|
||||
profile_to_clone=None):
|
||||
"""Sets up a profile for reftest.
|
||||
|
||||
:param options: Object containing command line options
|
||||
|
@ -286,9 +286,6 @@ class RefTest(object):
|
|||
prefs['reftest.logLevel'] = options.log_tbpl_level or 'info'
|
||||
prefs['reftest.manifests'] = json.dumps(manifests)
|
||||
|
||||
if startAfter is not None:
|
||||
prefs['reftest.startAfter'] = startAfter
|
||||
|
||||
if options.e10s:
|
||||
prefs['browser.tabs.remote.autostart'] = True
|
||||
prefs['extensions.e10sBlocksEnabling'] = False
|
||||
|
@ -352,7 +349,6 @@ class RefTest(object):
|
|||
else:
|
||||
profile = mozprofile.Profile(**kwargs)
|
||||
|
||||
if os.path.join(here, 'chrome') not in options.extraProfileFiles:
|
||||
options.extraProfileFiles.append(os.path.join(here, 'chrome'))
|
||||
|
||||
self.copyExtraFilesToProfile(options, profile)
|
||||
|
@ -660,7 +656,7 @@ class RefTest(object):
|
|||
runner.cleanup()
|
||||
if not status and crashed:
|
||||
status = 1
|
||||
return status, self.lastTestSeen
|
||||
return status
|
||||
|
||||
def runSerialTests(self, manifests, options, cmdargs=None):
|
||||
debuggerInfo = None
|
||||
|
@ -669,10 +665,6 @@ class RefTest(object):
|
|||
options.debuggerInteractive)
|
||||
|
||||
profileDir = None
|
||||
startAfter = None # When the previous run crashed, we skip the tests we ran before
|
||||
prevStartAfter = None
|
||||
status = 1 # Just to start the loop
|
||||
while status != 0:
|
||||
try:
|
||||
if cmdargs is None:
|
||||
cmdargs = []
|
||||
|
@ -680,16 +672,14 @@ class RefTest(object):
|
|||
if self.use_marionette:
|
||||
cmdargs.append('-marionette')
|
||||
|
||||
profile = self.createReftestProfile(options,
|
||||
manifests,
|
||||
startAfter=startAfter)
|
||||
profile = self.createReftestProfile(options, manifests)
|
||||
profileDir = profile.profile # name makes more sense
|
||||
|
||||
# browser environment
|
||||
browserEnv = self.buildBrowserEnv(options, profileDir)
|
||||
|
||||
self.log.info("Running with e10s: {}".format(options.e10s))
|
||||
status, startAfter = self.runApp(profile,
|
||||
status = self.runApp(profile,
|
||||
binary=options.app,
|
||||
cmdargs=cmdargs,
|
||||
# give the JS harness 30 seconds to deal with
|
||||
|
@ -704,19 +694,6 @@ class RefTest(object):
|
|||
leak_thresholds=options.leakThresholds,
|
||||
stack_fixer=get_stack_fixer_function(options.utilityPath,
|
||||
options.symbolsPath))
|
||||
self.cleanup(profileDir)
|
||||
if startAfter is not None and options.shuffle:
|
||||
self.log.error("Can not resume from a crash with --shuffle "
|
||||
"enabled. Please consider disabling --shuffle")
|
||||
break
|
||||
if startAfter == prevStartAfter:
|
||||
# If the test stuck on the same test, or there the crashed
|
||||
# test appeared more then once, stop
|
||||
self.log.error("Force stop because we keep running into "
|
||||
"test \"{}\"".format(startAfter))
|
||||
break
|
||||
prevStartAfter = startAfter
|
||||
# TODO: we need to emit an SUITE-END log if it crashed
|
||||
finally:
|
||||
self.cleanup(profileDir)
|
||||
return status
|
||||
|
|
|
@ -1315,6 +1315,31 @@ TelemetryImpl::AddSQLInfo(JSContext *cx, JS::Handle<JSObject*> rootObj, bool mai
|
|||
statsObj, JSPROP_ENUMERATE);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
TelemetryImpl::RegisterAddonHistogram(const nsACString &id,
|
||||
const nsACString &name,
|
||||
uint32_t histogramType,
|
||||
uint32_t min, uint32_t max,
|
||||
uint32_t bucketCount,
|
||||
uint8_t optArgCount)
|
||||
{
|
||||
return TelemetryHistogram::RegisterAddonHistogram
|
||||
(id, name, histogramType, min, max, bucketCount, optArgCount);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
TelemetryImpl::GetAddonHistogram(const nsACString &id, const nsACString &name,
|
||||
JSContext *cx, JS::MutableHandle<JS::Value> ret)
|
||||
{
|
||||
return TelemetryHistogram::GetAddonHistogram(id, name, cx, ret);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
TelemetryImpl::UnregisterAddonHistograms(const nsACString &id)
|
||||
{
|
||||
return TelemetryHistogram::UnregisterAddonHistograms(id);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
TelemetryImpl::SetHistogramRecordingEnabled(const nsACString &id, bool aEnabled)
|
||||
{
|
||||
|
@ -1340,6 +1365,12 @@ TelemetryImpl::SnapshotSubsessionHistograms(bool clearSubsession,
|
|||
#endif
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
TelemetryImpl::GetAddonHistogramSnapshots(JSContext *cx, JS::MutableHandle<JS::Value> ret)
|
||||
{
|
||||
return TelemetryHistogram::GetAddonHistogramSnapshots(cx, ret);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
TelemetryImpl::GetKeyedHistogramSnapshots(JSContext *cx, JS::MutableHandle<JS::Value> ret)
|
||||
{
|
||||
|
@ -2927,6 +2958,7 @@ TelemetryImpl::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
|
|||
{
|
||||
size_t n = aMallocSizeOf(this);
|
||||
|
||||
// Ignore the hashtables in mAddonMap; they are not significant.
|
||||
n += TelemetryHistogram::GetMapShallowSizesOfExcludingThis(aMallocSizeOf);
|
||||
n += TelemetryScalar::GetMapShallowSizesOfExcludingThis(aMallocSizeOf);
|
||||
n += mWebrtcTelemetry.SizeOfExcludingThis(aMallocSizeOf);
|
||||
|
|
|
@ -57,8 +57,8 @@ namespace TelemetryIPCAccumulator = mozilla::TelemetryIPCAccumulator;
|
|||
//
|
||||
// * Functions named TelemetryHistogram::*. This is the external interface.
|
||||
// Entries and exits to these functions are serialised using
|
||||
// |gTelemetryHistogramMutex|, except for GetKeyedHistogramSnapshots and
|
||||
// CreateHistogramSnapshots.
|
||||
// |gTelemetryHistogramMutex|, except for GetAddonHistogramSnapshots,
|
||||
// GetKeyedHistogramSnapshots and CreateHistogramSnapshots.
|
||||
//
|
||||
// Avoiding races and deadlocks:
|
||||
//
|
||||
|
@ -138,6 +138,14 @@ struct HistogramInfo {
|
|||
nsresult label_id(const char* label, uint32_t* labelId) const;
|
||||
};
|
||||
|
||||
struct AddonHistogramInfo {
|
||||
uint32_t min;
|
||||
uint32_t max;
|
||||
uint32_t bucketCount;
|
||||
uint32_t histogramType;
|
||||
Histogram *h;
|
||||
};
|
||||
|
||||
enum reflectStatus {
|
||||
REFLECT_OK,
|
||||
REFLECT_CORRUPT,
|
||||
|
@ -146,6 +154,17 @@ enum reflectStatus {
|
|||
|
||||
typedef StatisticsRecorder::Histograms::iterator HistogramIterator;
|
||||
|
||||
typedef nsBaseHashtableET<nsCStringHashKey, AddonHistogramInfo>
|
||||
AddonHistogramEntryType;
|
||||
|
||||
typedef AutoHashtable<AddonHistogramEntryType>
|
||||
AddonHistogramMapType;
|
||||
|
||||
typedef nsBaseHashtableET<nsCStringHashKey, AddonHistogramMapType *>
|
||||
AddonEntryType;
|
||||
|
||||
typedef AutoHashtable<AddonEntryType> AddonMapType;
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
|
@ -171,6 +190,8 @@ bool gCorruptHistograms[mozilla::Telemetry::HistogramCount];
|
|||
// This is for gHistograms, gHistogramStringTable
|
||||
#include "TelemetryHistogramData.inc"
|
||||
|
||||
AddonMapType gAddonMap;
|
||||
|
||||
// The singleton StatisticsRecorder object for this process.
|
||||
base::StatisticsRecorder* gStatisticsRecorder = nullptr;
|
||||
|
||||
|
@ -1121,6 +1142,108 @@ internal_GetKeyedHistogramById(const nsACString &name)
|
|||
} // namespace
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PRIVATE: functions related to addon histograms
|
||||
|
||||
namespace {
|
||||
|
||||
// Compute the name to pass into Histogram for the addon histogram
|
||||
// 'name' from the addon 'id'. We can't use 'name' directly because it
|
||||
// might conflict with other histograms in other addons or even with our
|
||||
// own.
|
||||
void
|
||||
internal_AddonHistogramName(const nsACString &id, const nsACString &name,
|
||||
nsACString &ret)
|
||||
{
|
||||
ret.Append(id);
|
||||
ret.Append(':');
|
||||
ret.Append(name);
|
||||
}
|
||||
|
||||
bool
|
||||
internal_CreateHistogramForAddon(const nsACString &name,
|
||||
AddonHistogramInfo &info)
|
||||
{
|
||||
Histogram *h;
|
||||
nsresult rv = internal_HistogramGet(PromiseFlatCString(name).get(), "never",
|
||||
info.histogramType, info.min, info.max,
|
||||
info.bucketCount, true, &h);
|
||||
if (NS_FAILED(rv)) {
|
||||
return false;
|
||||
}
|
||||
// Don't let this histogram be reported via the normal means
|
||||
// (e.g. Telemetry.registeredHistograms); we'll make it available in
|
||||
// other ways.
|
||||
h->ClearFlags(Histogram::kUmaTargetedHistogramFlag);
|
||||
info.h = h;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
internal_AddonHistogramReflector(AddonHistogramEntryType *entry,
|
||||
JSContext *cx, JS::Handle<JSObject*> obj)
|
||||
{
|
||||
AddonHistogramInfo &info = entry->mData;
|
||||
|
||||
// Never even accessed the histogram.
|
||||
if (!info.h) {
|
||||
// Have to force creation of HISTOGRAM_FLAG histograms.
|
||||
if (info.histogramType != nsITelemetry::HISTOGRAM_FLAG)
|
||||
return true;
|
||||
|
||||
if (!internal_CreateHistogramForAddon(entry->GetKey(), info)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (internal_IsEmpty(info.h)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> snapshot(cx, JS_NewPlainObject(cx));
|
||||
if (!snapshot) {
|
||||
// Just consider this to be skippable.
|
||||
return true;
|
||||
}
|
||||
switch (internal_ReflectHistogramSnapshot(cx, snapshot, info.h)) {
|
||||
case REFLECT_FAILURE:
|
||||
case REFLECT_CORRUPT:
|
||||
return false;
|
||||
case REFLECT_OK:
|
||||
const nsACString &histogramName = entry->GetKey();
|
||||
if (!JS_DefineProperty(cx, obj, PromiseFlatCString(histogramName).get(),
|
||||
snapshot, JSPROP_ENUMERATE)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
internal_AddonReflector(AddonEntryType *entry, JSContext *cx,
|
||||
JS::Handle<JSObject*> obj)
|
||||
{
|
||||
const nsACString &addonId = entry->GetKey();
|
||||
JS::Rooted<JSObject*> subobj(cx, JS_NewPlainObject(cx));
|
||||
if (!subobj) {
|
||||
return false;
|
||||
}
|
||||
|
||||
AddonHistogramMapType *map = entry->mData;
|
||||
if (!(map->ReflectIntoJS(internal_AddonHistogramReflector, cx, subobj)
|
||||
&& JS_DefineProperty(cx, obj, PromiseFlatCString(addonId).get(),
|
||||
subobj, JSPROP_ENUMERATE))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
@ -1891,6 +2014,7 @@ void TelemetryHistogram::DeInitializeGlobalState()
|
|||
gCanRecordExtended = false;
|
||||
gHistogramMap.Clear();
|
||||
gKeyedHistograms.Clear();
|
||||
gAddonMap.Clear();
|
||||
gInitDone = false;
|
||||
}
|
||||
|
||||
|
@ -2295,12 +2419,143 @@ TelemetryHistogram::GetKeyedHistogramSnapshots(JSContext *cx,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
TelemetryHistogram::RegisterAddonHistogram(const nsACString &id,
|
||||
const nsACString &name,
|
||||
uint32_t histogramType,
|
||||
uint32_t min, uint32_t max,
|
||||
uint32_t bucketCount,
|
||||
uint8_t optArgCount)
|
||||
{
|
||||
StaticMutexAutoLock locker(gTelemetryHistogramMutex);
|
||||
if (histogramType == nsITelemetry::HISTOGRAM_EXPONENTIAL ||
|
||||
histogramType == nsITelemetry::HISTOGRAM_LINEAR) {
|
||||
if (optArgCount != 3) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
// Sanity checks for histogram parameters.
|
||||
if (min >= max)
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
|
||||
if (bucketCount <= 2)
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
|
||||
if (min < 1)
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
} else {
|
||||
min = 1;
|
||||
max = 2;
|
||||
bucketCount = 3;
|
||||
}
|
||||
|
||||
AddonEntryType *addonEntry = gAddonMap.GetEntry(id);
|
||||
if (!addonEntry) {
|
||||
addonEntry = gAddonMap.PutEntry(id);
|
||||
if (MOZ_UNLIKELY(!addonEntry)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
addonEntry->mData = new AddonHistogramMapType();
|
||||
}
|
||||
|
||||
AddonHistogramMapType *histogramMap = addonEntry->mData;
|
||||
AddonHistogramEntryType *histogramEntry = histogramMap->GetEntry(name);
|
||||
// Can't re-register the same histogram.
|
||||
if (histogramEntry) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
histogramEntry = histogramMap->PutEntry(name);
|
||||
if (MOZ_UNLIKELY(!histogramEntry)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
AddonHistogramInfo &info = histogramEntry->mData;
|
||||
info.min = min;
|
||||
info.max = max;
|
||||
info.bucketCount = bucketCount;
|
||||
info.histogramType = histogramType;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
TelemetryHistogram::GetAddonHistogram(const nsACString &id,
|
||||
const nsACString &name,
|
||||
JSContext *cx,
|
||||
JS::MutableHandle<JS::Value> ret)
|
||||
{
|
||||
AddonHistogramInfo* info = nullptr;
|
||||
{
|
||||
StaticMutexAutoLock locker(gTelemetryHistogramMutex);
|
||||
AddonEntryType *addonEntry = gAddonMap.GetEntry(id);
|
||||
// The given id has not been registered.
|
||||
if (!addonEntry) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
AddonHistogramMapType *histogramMap = addonEntry->mData;
|
||||
AddonHistogramEntryType *histogramEntry = histogramMap->GetEntry(name);
|
||||
// The given histogram name has not been registered.
|
||||
if (!histogramEntry) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
info = &histogramEntry->mData;
|
||||
if (!info->h) {
|
||||
nsAutoCString actualName;
|
||||
internal_AddonHistogramName(id, name, actualName);
|
||||
if (!internal_CreateHistogramForAddon(actualName, *info)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Runs without protection from |gTelemetryHistogramMutex|
|
||||
return internal_WrapAndReturnHistogram(info->h, cx, ret);
|
||||
}
|
||||
|
||||
nsresult
|
||||
TelemetryHistogram::UnregisterAddonHistograms(const nsACString &id)
|
||||
{
|
||||
StaticMutexAutoLock locker(gTelemetryHistogramMutex);
|
||||
AddonEntryType *addonEntry = gAddonMap.GetEntry(id);
|
||||
if (addonEntry) {
|
||||
// Histogram's destructor is private, so this is the best we can do.
|
||||
// The histograms the addon created *will* stick around, but they
|
||||
// will be deleted if and when the addon registers histograms with
|
||||
// the same names.
|
||||
delete addonEntry->mData;
|
||||
gAddonMap.RemoveEntry(addonEntry);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
TelemetryHistogram::GetAddonHistogramSnapshots(JSContext *cx,
|
||||
JS::MutableHandle<JS::Value> ret)
|
||||
{
|
||||
// Runs without protection from |gTelemetryHistogramMutex|
|
||||
JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
|
||||
if (!obj) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (!gAddonMap.ReflectIntoJS(internal_AddonReflector, cx, obj)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
ret.setObject(*obj);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
size_t
|
||||
TelemetryHistogram::GetMapShallowSizesOfExcludingThis(mozilla::MallocSizeOf
|
||||
aMallocSizeOf)
|
||||
{
|
||||
StaticMutexAutoLock locker(gTelemetryHistogramMutex);
|
||||
return gHistogramMap.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
return gAddonMap.ShallowSizeOfExcludingThis(aMallocSizeOf) +
|
||||
gHistogramMap.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
size_t
|
||||
|
|
|
@ -76,6 +76,21 @@ RegisteredKeyedHistograms(uint32_t aDataset, uint32_t *aCount,
|
|||
nsresult
|
||||
GetKeyedHistogramSnapshots(JSContext *cx, JS::MutableHandle<JS::Value> ret);
|
||||
|
||||
nsresult
|
||||
RegisterAddonHistogram(const nsACString &id, const nsACString &name,
|
||||
uint32_t histogramType, uint32_t min, uint32_t max,
|
||||
uint32_t bucketCount, uint8_t optArgCount);
|
||||
|
||||
nsresult
|
||||
GetAddonHistogram(const nsACString &id, const nsACString &name,
|
||||
JSContext *cx, JS::MutableHandle<JS::Value> ret);
|
||||
|
||||
nsresult
|
||||
UnregisterAddonHistograms(const nsACString &id);
|
||||
|
||||
nsresult
|
||||
GetAddonHistogramSnapshots(JSContext *cx, JS::MutableHandle<JS::Value> ret);
|
||||
|
||||
size_t
|
||||
GetMapShallowSizesOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf);
|
||||
|
||||
|
|
|
@ -910,6 +910,23 @@ var Impl = {
|
|||
return ret;
|
||||
},
|
||||
|
||||
getAddonHistograms: function getAddonHistograms() {
|
||||
let ahs = Telemetry.addonHistogramSnapshots;
|
||||
let ret = {};
|
||||
|
||||
for (let addonName in ahs) {
|
||||
let addonHistograms = ahs[addonName];
|
||||
let packedHistograms = {};
|
||||
for (let name in addonHistograms) {
|
||||
packedHistograms[name] = this.packHistogram(addonHistograms[name]);
|
||||
}
|
||||
if (Object.keys(packedHistograms).length != 0)
|
||||
ret[addonName] = packedHistograms;
|
||||
}
|
||||
|
||||
return ret;
|
||||
},
|
||||
|
||||
getKeyedHistograms(subsession, clearSubsession) {
|
||||
let registered =
|
||||
Telemetry.registeredKeyedHistograms(this.getDatasetType(), []);
|
||||
|
@ -1316,6 +1333,12 @@ var Impl = {
|
|||
payloadObj.fileIOReports = protect(() => Telemetry.fileIOReports);
|
||||
payloadObj.lateWrites = protect(() => Telemetry.lateWrites);
|
||||
|
||||
// Add the addon histograms if they are present
|
||||
let addonHistograms = protect(() => this.getAddonHistograms());
|
||||
if (addonHistograms && Object.keys(addonHistograms).length > 0) {
|
||||
payloadObj.addonHistograms = addonHistograms;
|
||||
}
|
||||
|
||||
payloadObj.addonDetails = protect(() => AddonManagerPrivate.getTelemetryDetails());
|
||||
|
||||
let clearUIsession = !(reason == REASON_GATHER_PAYLOAD || reason == REASON_GATHER_SUBSESSION_PAYLOAD);
|
||||
|
|
|
@ -69,6 +69,7 @@ Structure:
|
|||
fileIOReports: {...},
|
||||
lateWrites: {...},
|
||||
addonDetails: {...},
|
||||
addonHistograms: {...},
|
||||
UIMeasurements: [...], // Android only
|
||||
slowSQL: {...},
|
||||
slowSQLstartup: {...},
|
||||
|
@ -147,7 +148,7 @@ The recorded events are defined in the `Events.yaml <https://dxr.mozilla.org/moz
|
|||
|
||||
childPayloads
|
||||
-------------
|
||||
The Telemetry payloads sent by child processes, recorded on child process shutdown (event ``content-child-shutdown`` observed). They are reduced session payloads, only available with e10s. Among some other things, they don't contain histograms, keyed histograms, addon details, or UI Telemetry.
|
||||
The Telemetry payloads sent by child processes, recorded on child process shutdown (event ``content-child-shutdown`` observed). They are reduced session payloads, only available with e10s. Among some other things, they don't contain histograms, keyed histograms, addon details, addon histograms, or UI Telemetry.
|
||||
|
||||
Note: Child payloads are not collected and cleared with subsession splits, they are currently only meaningful when analysed from ``saved-session`` or ``main`` pings with ``reason`` set to ``shutdown``.
|
||||
|
||||
|
@ -632,6 +633,10 @@ Structure:
|
|||
...
|
||||
}
|
||||
|
||||
addonHistograms
|
||||
---------------
|
||||
This section contains the histogram registered by the addons (`see here <https://dxr.mozilla.org/mozilla-central/rev/584870f1cbc5d060a57e147ce249f736956e2b62/toolkit/components/telemetry/nsITelemetry.idl#303>`_). This section is not present if no addon histogram is available.
|
||||
|
||||
UITelemetry
|
||||
-----------
|
||||
See the ``UITelemetry data format`` documentation.
|
||||
|
|
|
@ -315,6 +315,46 @@ interface nsITelemetry : nsISupports
|
|||
*/
|
||||
readonly attribute boolean isOfficialTelemetry;
|
||||
|
||||
/** Addon telemetry hooks */
|
||||
|
||||
/**
|
||||
* Register a histogram for an addon. Throws an error if the
|
||||
* histogram name has been registered previously.
|
||||
*
|
||||
* @param addon_id - Unique ID of the addon
|
||||
* @param name - Unique histogram name
|
||||
* @param histogram_type - HISTOGRAM_EXPONENTIAL, HISTOGRAM_LINEAR,
|
||||
* HISTOGRAM_BOOLEAN or HISTOGRAM_COUNT
|
||||
* @param min - Minimal bucket size
|
||||
* @param max - Maximum bucket size
|
||||
* @param bucket_count - number of buckets in the histogram
|
||||
*/
|
||||
[optional_argc]
|
||||
void registerAddonHistogram(in ACString addon_id, in ACString name,
|
||||
in unsigned long histogram_type,
|
||||
[optional] in uint32_t min,
|
||||
[optional] in uint32_t max,
|
||||
[optional] in uint32_t bucket_count);
|
||||
|
||||
/**
|
||||
* Return a histogram previously registered via
|
||||
* registerAddonHistogram. Throws an error if the id/name combo has
|
||||
* not been registered via registerAddonHistogram.
|
||||
*
|
||||
* @param addon_id - Unique ID of the addon
|
||||
* @param name - Registered histogram name
|
||||
*
|
||||
*/
|
||||
[implicit_jscontext]
|
||||
jsval getAddonHistogram(in ACString addon_id, in ACString name);
|
||||
|
||||
/**
|
||||
* Delete all histograms associated with the given addon id.
|
||||
*
|
||||
* @param addon_id - Unique ID of the addon
|
||||
*/
|
||||
void unregisterAddonHistograms(in ACString addon_id);
|
||||
|
||||
/**
|
||||
* Enable/disable recording for this histogram at runtime.
|
||||
* Recording is enabled by default, unless listed at kRecordingInitiallyDisabledIDs[].
|
||||
|
@ -325,6 +365,18 @@ interface nsITelemetry : nsISupports
|
|||
*/
|
||||
void setHistogramRecordingEnabled(in ACString id, in boolean enabled);
|
||||
|
||||
/**
|
||||
* An object containing a snapshot from all of the currently
|
||||
* registered addon histograms.
|
||||
* { addon-id1 : data1, ... }
|
||||
*
|
||||
* where data is an object whose properties are the names of the
|
||||
* addon's histograms and whose corresponding values are as in
|
||||
* histogramSnapshots.
|
||||
*/
|
||||
[implicit_jscontext]
|
||||
readonly attribute jsval addonHistogramSnapshots;
|
||||
|
||||
/**
|
||||
* Read data from the previous run. After the callback is called, the last
|
||||
* shutdown time is available in lastShutdownDuration and any late
|
||||
|
|
|
@ -430,6 +430,94 @@ add_task(function* test_histogramRecording() {
|
|||
"Histogram value should have incremented by 1 due to recording.");
|
||||
});
|
||||
|
||||
add_task(function* test_addons() {
|
||||
var addon_id = "testing-addon";
|
||||
var fake_addon_id = "fake-addon";
|
||||
var name1 = "testing-histogram1";
|
||||
var register = Telemetry.registerAddonHistogram;
|
||||
expect_success(() =>
|
||||
register(addon_id, name1, Telemetry.HISTOGRAM_LINEAR, 1, 5, 6));
|
||||
// Can't register the same histogram multiple times.
|
||||
expect_fail(() =>
|
||||
register(addon_id, name1, Telemetry.HISTOGRAM_LINEAR, 1, 5, 6));
|
||||
// Make sure we can't get at it with another name.
|
||||
expect_fail(() => Telemetry.getAddonHistogram(fake_addon_id, name1));
|
||||
|
||||
// Check for reflection capabilities.
|
||||
var h1 = Telemetry.getAddonHistogram(addon_id, name1);
|
||||
// Verify that although we've created storage for it, we don't reflect it into JS.
|
||||
var snapshots = Telemetry.addonHistogramSnapshots;
|
||||
do_check_false(name1 in snapshots[addon_id]);
|
||||
h1.add(1);
|
||||
h1.add(3);
|
||||
var s1 = h1.snapshot();
|
||||
do_check_eq(s1.histogram_type, Telemetry.HISTOGRAM_LINEAR);
|
||||
do_check_eq(s1.min, 1);
|
||||
do_check_eq(s1.max, 5);
|
||||
do_check_eq(s1.counts[1], 1);
|
||||
do_check_eq(s1.counts[3], 1);
|
||||
|
||||
var name2 = "testing-histogram2";
|
||||
expect_success(() =>
|
||||
register(addon_id, name2, Telemetry.HISTOGRAM_LINEAR, 2, 4, 4));
|
||||
|
||||
var h2 = Telemetry.getAddonHistogram(addon_id, name2);
|
||||
h2.add(2);
|
||||
h2.add(3);
|
||||
var s2 = h2.snapshot();
|
||||
do_check_eq(s2.histogram_type, Telemetry.HISTOGRAM_LINEAR);
|
||||
do_check_eq(s2.min, 2);
|
||||
do_check_eq(s2.max, 4);
|
||||
do_check_eq(s2.counts[1], 1);
|
||||
do_check_eq(s2.counts[2], 1);
|
||||
|
||||
// Check that we can register histograms for a different addon with
|
||||
// identical names.
|
||||
var extra_addon = "testing-extra-addon";
|
||||
expect_success(() =>
|
||||
register(extra_addon, name1, Telemetry.HISTOGRAM_BOOLEAN));
|
||||
|
||||
// Check that we can register flag histograms.
|
||||
var flag_addon = "testing-flag-addon";
|
||||
var flag_histogram = "flag-histogram";
|
||||
expect_success(() =>
|
||||
register(flag_addon, flag_histogram, Telemetry.HISTOGRAM_FLAG));
|
||||
expect_success(() =>
|
||||
register(flag_addon, name2, Telemetry.HISTOGRAM_LINEAR, 2, 4, 4));
|
||||
|
||||
// Check that we reflect registered addons and histograms.
|
||||
snapshots = Telemetry.addonHistogramSnapshots;
|
||||
do_check_true(addon_id in snapshots)
|
||||
do_check_true(extra_addon in snapshots);
|
||||
do_check_true(flag_addon in snapshots);
|
||||
|
||||
// Check that we have data for our created histograms.
|
||||
do_check_true(name1 in snapshots[addon_id]);
|
||||
do_check_true(name2 in snapshots[addon_id]);
|
||||
var s1_alt = snapshots[addon_id][name1];
|
||||
var s2_alt = snapshots[addon_id][name2];
|
||||
do_check_eq(s1_alt.min, s1.min);
|
||||
do_check_eq(s1_alt.max, s1.max);
|
||||
do_check_eq(s1_alt.histogram_type, s1.histogram_type);
|
||||
do_check_eq(s2_alt.min, s2.min);
|
||||
do_check_eq(s2_alt.max, s2.max);
|
||||
do_check_eq(s2_alt.histogram_type, s2.histogram_type);
|
||||
|
||||
// Even though we've registered it, it shouldn't show up until data is added to it.
|
||||
do_check_false(name1 in snapshots[extra_addon]);
|
||||
|
||||
// Flag histograms should show up automagically.
|
||||
do_check_true(flag_histogram in snapshots[flag_addon]);
|
||||
do_check_false(name2 in snapshots[flag_addon]);
|
||||
|
||||
// Check that we can remove addon histograms.
|
||||
Telemetry.unregisterAddonHistograms(addon_id);
|
||||
snapshots = Telemetry.addonHistogramSnapshots;
|
||||
do_check_false(addon_id in snapshots);
|
||||
// Make sure other addons are unaffected.
|
||||
do_check_true(extra_addon in snapshots);
|
||||
});
|
||||
|
||||
add_task(function* test_expired_histogram() {
|
||||
var test_expired_id = "TELEMETRY_TEST_EXPIRED";
|
||||
var dummy = Telemetry.getHistogramById(test_expired_id);
|
||||
|
|
|
@ -42,6 +42,8 @@ const APP_NAME = "XPCShell";
|
|||
|
||||
const IGNORE_HISTOGRAM_TO_CLONE = "MEMORY_HEAP_ALLOCATED";
|
||||
const IGNORE_CLONED_HISTOGRAM = "test::ignore_me_also";
|
||||
const ADDON_NAME = "Telemetry test addon";
|
||||
const ADDON_HISTOGRAM = "addon-histogram";
|
||||
// Add some unicode characters here to ensure that sending them works correctly.
|
||||
const SHUTDOWN_TIME = 10000;
|
||||
const FAILED_PROFILE_LOCK_ATTEMPTS = 2;
|
||||
|
@ -99,6 +101,11 @@ function fakeIdleNotification(topic) {
|
|||
function setupTestData() {
|
||||
|
||||
Services.startup.interrupted = true;
|
||||
Telemetry.registerAddonHistogram(ADDON_NAME, ADDON_HISTOGRAM,
|
||||
Telemetry.HISTOGRAM_LINEAR,
|
||||
1, 5, 6);
|
||||
let h1 = Telemetry.getAddonHistogram(ADDON_NAME, ADDON_HISTOGRAM);
|
||||
h1.add(1);
|
||||
let h2 = Telemetry.getHistogramById("TELEMETRY_TEST_COUNT");
|
||||
h2.add();
|
||||
|
||||
|
@ -413,6 +420,11 @@ function checkPayload(payload, reason, successfulPings, savedPings) {
|
|||
Assert.ok("MEMORY_JS_GC_HEAP" in payload.histograms); // UNITS_BYTES
|
||||
Assert.ok("MEMORY_JS_COMPARTMENTS_SYSTEM" in payload.histograms); // UNITS_COUNT
|
||||
|
||||
// We should have included addon histograms.
|
||||
Assert.ok("addonHistograms" in payload);
|
||||
Assert.ok(ADDON_NAME in payload.addonHistograms);
|
||||
Assert.ok(ADDON_HISTOGRAM in payload.addonHistograms[ADDON_NAME]);
|
||||
|
||||
Assert.ok(("mainThread" in payload.slowSQL) &&
|
||||
("otherThreads" in payload.slowSQL));
|
||||
|
||||
|
@ -1884,7 +1896,7 @@ add_task(function* test_schedulerNothingDue() {
|
|||
add_task(function* test_pingExtendedStats() {
|
||||
const EXTENDED_PAYLOAD_FIELDS = [
|
||||
"chromeHangs", "threadHangStats", "log", "slowSQL", "fileIOReports", "lateWrites",
|
||||
"addonDetails", "webrtc"
|
||||
"addonHistograms", "addonDetails", "webrtc"
|
||||
];
|
||||
|
||||
if (AppConstants.platform == "android") {
|
||||
|
|
Загрузка…
Ссылка в новой задаче