зеркало из https://github.com/mozilla/gecko-dev.git
Backed out 2 changesets (bug 1425909) for mochitest C3 failures on test_memoryReporters.xul. on a CLOSED TREE
Backed out changeset 6bcaae60c82e (bug 1425909) Backed out changeset 0b5d96b317c3 (bug 1425909)
This commit is contained in:
Родитель
54a5db7d0a
Коммит
b709f2768b
|
@ -23,16 +23,14 @@ struct BaseScalarInfo {
|
||||||
uint32_t dataset;
|
uint32_t dataset;
|
||||||
mozilla::Telemetry::Common::RecordedProcessType record_in_processes;
|
mozilla::Telemetry::Common::RecordedProcessType record_in_processes;
|
||||||
bool keyed;
|
bool keyed;
|
||||||
bool builtin;
|
|
||||||
|
|
||||||
BaseScalarInfo(uint32_t aKind, uint32_t aDataset,
|
BaseScalarInfo(uint32_t aKind, uint32_t aDataset,
|
||||||
mozilla::Telemetry::Common::RecordedProcessType aRecordInProcess,
|
mozilla::Telemetry::Common::RecordedProcessType aRecordInProcess,
|
||||||
bool aKeyed, bool aBuiltin = true)
|
bool aKeyed)
|
||||||
: kind(aKind)
|
: kind(aKind)
|
||||||
, dataset(aDataset)
|
, dataset(aDataset)
|
||||||
, record_in_processes(aRecordInProcess)
|
, record_in_processes(aRecordInProcess)
|
||||||
, keyed(aKeyed)
|
, keyed(aKeyed)
|
||||||
, builtin(aBuiltin)
|
|
||||||
{}
|
{}
|
||||||
virtual ~BaseScalarInfo() {}
|
virtual ~BaseScalarInfo() {}
|
||||||
|
|
||||||
|
|
|
@ -1727,15 +1727,7 @@ TelemetryImpl::RegisterScalars(const nsACString& aCategoryName,
|
||||||
JS::Handle<JS::Value> aScalarData,
|
JS::Handle<JS::Value> aScalarData,
|
||||||
JSContext* cx)
|
JSContext* cx)
|
||||||
{
|
{
|
||||||
return TelemetryScalar::RegisterScalars(aCategoryName, aScalarData, false, cx);
|
return TelemetryScalar::RegisterScalars(aCategoryName, aScalarData, cx);
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
TelemetryImpl::RegisterBuiltinScalars(const nsACString& aCategoryName,
|
|
||||||
JS::Handle<JS::Value> aScalarData,
|
|
||||||
JSContext* cx)
|
|
||||||
{
|
|
||||||
return TelemetryScalar::RegisterScalars(aCategoryName, aScalarData, true, cx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
|
|
|
@ -67,7 +67,6 @@ XPCOMUtils.defineLazyModuleGetters(this, {
|
||||||
TelemetryModules: "resource://gre/modules/TelemetryModules.jsm",
|
TelemetryModules: "resource://gre/modules/TelemetryModules.jsm",
|
||||||
UpdatePing: "resource://gre/modules/UpdatePing.jsm",
|
UpdatePing: "resource://gre/modules/UpdatePing.jsm",
|
||||||
TelemetryHealthPing: "resource://gre/modules/TelemetryHealthPing.jsm",
|
TelemetryHealthPing: "resource://gre/modules/TelemetryHealthPing.jsm",
|
||||||
OS: "resource://gre/modules/osfile.jsm",
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -157,13 +156,6 @@ this.TelemetryController = Object.freeze({
|
||||||
return Impl.setupContentTelemetry(true);
|
return Impl.setupContentTelemetry(true);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* Used only for testing purposes.
|
|
||||||
*/
|
|
||||||
testPromiseJsProbeRegistration() {
|
|
||||||
return Promise.resolve(Impl._probeRegistrationPromise);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a notification.
|
* Send a notification.
|
||||||
*/
|
*/
|
||||||
|
@ -330,8 +322,6 @@ var Impl = {
|
||||||
_testMode: false,
|
_testMode: false,
|
||||||
// The task performing the delayed sending of the "new-profile" ping.
|
// The task performing the delayed sending of the "new-profile" ping.
|
||||||
_delayedNewPingTask: null,
|
_delayedNewPingTask: null,
|
||||||
// The promise used to wait for the JS probe registration (dynamic builtin).
|
|
||||||
_probeRegistrationPromise: null,
|
|
||||||
|
|
||||||
get _log() {
|
get _log() {
|
||||||
if (!this._logger) {
|
if (!this._logger) {
|
||||||
|
@ -689,11 +679,6 @@ var Impl = {
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable adding scalars in artifact builds and build faster modes.
|
|
||||||
// The function is async: we intentionally don't wait for it to complete
|
|
||||||
// as we don't want to delay startup.
|
|
||||||
this._probeRegistrationPromise = this.registerJsProbes();
|
|
||||||
|
|
||||||
// This will trigger displaying the datachoices infobar.
|
// This will trigger displaying the datachoices infobar.
|
||||||
TelemetryReportingPolicy.setup();
|
TelemetryReportingPolicy.setup();
|
||||||
|
|
||||||
|
@ -1053,64 +1038,4 @@ var Impl = {
|
||||||
.then(() => TelemetrySession.markNewProfilePingSent(),
|
.then(() => TelemetrySession.markNewProfilePingSent(),
|
||||||
e => this._log.error("sendNewProfilePing - failed to submit new-profile ping", e));
|
e => this._log.error("sendNewProfilePing - failed to submit new-profile ping", e));
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* Register 'dynamic builtin' probes from the JSON definition files.
|
|
||||||
* This is needed to support adding new probes in developer builds
|
|
||||||
* without rebuilding the whole codebase.
|
|
||||||
*
|
|
||||||
* This is not meant to be used outside of local developer builds.
|
|
||||||
*/
|
|
||||||
async registerJsProbes() {
|
|
||||||
// We don't support this outside of developer builds.
|
|
||||||
if (AppConstants.MOZILLA_OFFICIAL && !this._testMode) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._log.trace("registerJsProbes - registering builtin JS probes");
|
|
||||||
|
|
||||||
// Load the scalar probes JSON file.
|
|
||||||
const scalarProbeFilename = "ScalarArtifactDefinitions.json";
|
|
||||||
let scalarProbeFile = Services.dirsvc.get("GreBinD", Ci.nsIFile);
|
|
||||||
scalarProbeFile.append(scalarProbeFilename);
|
|
||||||
if (!scalarProbeFile.exists()) {
|
|
||||||
this._log.trace("registerJsProbes - no scalar builtin JS probes");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load the file off the disk.
|
|
||||||
let scalarJSProbes = {};
|
|
||||||
try {
|
|
||||||
let fileContent = await OS.File.read(scalarProbeFile.path, { encoding: "utf-8" });
|
|
||||||
scalarJSProbes = JSON.parse(fileContent, (property, value) => {
|
|
||||||
// Fixup the "kind" property: it's a string, and we need the constant
|
|
||||||
// coming from nsITelemetry.
|
|
||||||
if (property !== "kind" || typeof value != "string") {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
let newValue;
|
|
||||||
switch (value) {
|
|
||||||
case "nsITelemetry::SCALAR_TYPE_COUNT":
|
|
||||||
newValue = Telemetry.SCALAR_TYPE_COUNT;
|
|
||||||
break;
|
|
||||||
case "nsITelemetry::SCALAR_TYPE_BOOLEAN":
|
|
||||||
newValue = Telemetry.SCALAR_TYPE_BOOLEAN;
|
|
||||||
break;
|
|
||||||
case "nsITelemetry::SCALAR_TYPE_STRING":
|
|
||||||
newValue = Telemetry.SCALAR_TYPE_STRING;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return newValue;
|
|
||||||
});
|
|
||||||
} catch (ex) {
|
|
||||||
this._log.error(`registerJsProbes - there was an error loading {$scalarProbeFilename}`,
|
|
||||||
ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Register the builtin probes.
|
|
||||||
for (let category in scalarJSProbes) {
|
|
||||||
Telemetry.registerBuiltinScalars(category, scalarJSProbes[category]);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -137,14 +137,13 @@ struct DynamicScalarInfo : BaseScalarInfo {
|
||||||
|
|
||||||
DynamicScalarInfo(uint32_t aKind, bool aRecordOnRelease,
|
DynamicScalarInfo(uint32_t aKind, bool aRecordOnRelease,
|
||||||
bool aExpired, const nsACString& aName,
|
bool aExpired, const nsACString& aName,
|
||||||
bool aKeyed, bool aBuiltin)
|
bool aKeyed)
|
||||||
: BaseScalarInfo(aKind,
|
: BaseScalarInfo(aKind,
|
||||||
aRecordOnRelease ?
|
aRecordOnRelease ?
|
||||||
nsITelemetry::DATASET_RELEASE_CHANNEL_OPTOUT :
|
nsITelemetry::DATASET_RELEASE_CHANNEL_OPTOUT :
|
||||||
nsITelemetry::DATASET_RELEASE_CHANNEL_OPTIN,
|
nsITelemetry::DATASET_RELEASE_CHANNEL_OPTIN,
|
||||||
RecordedProcessType::All,
|
RecordedProcessType::All,
|
||||||
aKeyed,
|
aKeyed)
|
||||||
aBuiltin)
|
|
||||||
, mDynamicName(aName)
|
, mDynamicName(aName)
|
||||||
, mDynamicExpiration(aExpired)
|
, mDynamicExpiration(aExpired)
|
||||||
{}
|
{}
|
||||||
|
@ -855,10 +854,6 @@ ScalarMapType gScalarNameIDMap(kScalarCount);
|
||||||
ProcessesScalarsMapType gScalarStorageMap;
|
ProcessesScalarsMapType gScalarStorageMap;
|
||||||
// As above, for the keyed scalars.
|
// As above, for the keyed scalars.
|
||||||
ProcessesKeyedScalarsMapType gKeyedScalarStorageMap;
|
ProcessesKeyedScalarsMapType gKeyedScalarStorageMap;
|
||||||
// Provide separate storage for "dynamic builtin" plain and keyed scalars,
|
|
||||||
// needed to support "build faster" in local developer builds.
|
|
||||||
ProcessesScalarsMapType gDynamicBuiltinScalarStorageMap;
|
|
||||||
ProcessesKeyedScalarsMapType gDynamicBuiltinKeyedScalarStorageMap;
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
@ -1105,11 +1100,8 @@ internal_GetScalarByEnum(const StaticMutexAutoLock& lock,
|
||||||
|
|
||||||
const BaseScalarInfo &info = internal_GetScalarInfo(lock, aId);
|
const BaseScalarInfo &info = internal_GetScalarInfo(lock, aId);
|
||||||
|
|
||||||
// Dynamic scalars fixup: they are always stored in the "dynamic" process,
|
// Dynamic scalars fixup: they are always stored in the "dynamic" process.
|
||||||
// unless they are part of the "builtin" Firefox probes. Please note that
|
if (aId.dynamic) {
|
||||||
// "dynamic builtin" probes are meant to support "artifact" and "build faster"
|
|
||||||
// builds.
|
|
||||||
if (aId.dynamic && !info.builtin) {
|
|
||||||
aProcessStorage = ProcessID::Dynamic;
|
aProcessStorage = ProcessID::Dynamic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1119,16 +1111,11 @@ internal_GetScalarByEnum(const StaticMutexAutoLock& lock,
|
||||||
// set to the child storage if needed.
|
// set to the child storage if needed.
|
||||||
uint32_t storageId = static_cast<uint32_t>(aProcessStorage);
|
uint32_t storageId = static_cast<uint32_t>(aProcessStorage);
|
||||||
|
|
||||||
// Put dynamic-builtin scalars (used to support "build faster") in a
|
|
||||||
// separate storage.
|
|
||||||
ProcessesScalarsMapType& processStorage =
|
|
||||||
(aId.dynamic && info.builtin) ? gDynamicBuiltinScalarStorageMap : gScalarStorageMap;
|
|
||||||
|
|
||||||
// Get the process-specific storage or create one if it's not
|
// Get the process-specific storage or create one if it's not
|
||||||
// available.
|
// available.
|
||||||
if (!processStorage.Get(storageId, &scalarStorage)) {
|
if (!gScalarStorageMap.Get(storageId, &scalarStorage)) {
|
||||||
scalarStorage = new ScalarStorageMapType();
|
scalarStorage = new ScalarStorageMapType();
|
||||||
processStorage.Put(storageId, scalarStorage);
|
gScalarStorageMap.Put(storageId, scalarStorage);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the scalar is already allocated in the parent or in the child storage.
|
// Check if the scalar is already allocated in the parent or in the child storage.
|
||||||
|
@ -1270,11 +1257,8 @@ internal_GetKeyedScalarByEnum(const StaticMutexAutoLock& lock,
|
||||||
|
|
||||||
const BaseScalarInfo &info = internal_GetScalarInfo(lock, aId);
|
const BaseScalarInfo &info = internal_GetScalarInfo(lock, aId);
|
||||||
|
|
||||||
// Dynamic scalars fixup: they are always stored in the "dynamic" process,
|
// Dynamic scalars fixup: they are always stored in the "dynamic" process.
|
||||||
// unless they are part of the "builtin" Firefox probes. Please note that
|
if (aId.dynamic) {
|
||||||
// "dynamic builtin" probes are meant to support "artifact" and "build faster"
|
|
||||||
// builds.
|
|
||||||
if (aId.dynamic && !info.builtin) {
|
|
||||||
aProcessStorage = ProcessID::Dynamic;
|
aProcessStorage = ProcessID::Dynamic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1284,16 +1268,11 @@ internal_GetKeyedScalarByEnum(const StaticMutexAutoLock& lock,
|
||||||
// set to the child storage if needed.
|
// set to the child storage if needed.
|
||||||
uint32_t storageId = static_cast<uint32_t>(aProcessStorage);
|
uint32_t storageId = static_cast<uint32_t>(aProcessStorage);
|
||||||
|
|
||||||
// Put dynamic-builtin scalars (used to support "build faster") in a
|
|
||||||
// separate storage.
|
|
||||||
ProcessesKeyedScalarsMapType& processStorage =
|
|
||||||
(aId.dynamic && info.builtin) ? gDynamicBuiltinKeyedScalarStorageMap : gKeyedScalarStorageMap;
|
|
||||||
|
|
||||||
// Get the process-specific storage or create one if it's not
|
// Get the process-specific storage or create one if it's not
|
||||||
// available.
|
// available.
|
||||||
if (!processStorage.Get(storageId, &scalarStorage)) {
|
if (!gKeyedScalarStorageMap.Get(storageId, &scalarStorage)) {
|
||||||
scalarStorage = new KeyedScalarStorageMapType();
|
scalarStorage = new KeyedScalarStorageMapType();
|
||||||
processStorage.Put(storageId, scalarStorage);
|
gKeyedScalarStorageMap.Put(storageId, scalarStorage);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scalarStorage->Get(aId.id, &scalar)) {
|
if (scalarStorage->Get(aId.id, &scalar)) {
|
||||||
|
@ -1446,7 +1425,7 @@ internal_RegisterScalars(const StaticMutexAutoLock& lock,
|
||||||
CharPtrEntryType *existingKey = gScalarNameIDMap.GetEntry(scalarInfo.name());
|
CharPtrEntryType *existingKey = gScalarNameIDMap.GetEntry(scalarInfo.name());
|
||||||
if (existingKey) {
|
if (existingKey) {
|
||||||
// Change the scalar to expired if needed.
|
// Change the scalar to expired if needed.
|
||||||
if (scalarInfo.mDynamicExpiration && !scalarInfo.builtin) {
|
if (scalarInfo.mDynamicExpiration) {
|
||||||
DynamicScalarInfo& scalarData = (*gDynamicScalarInfo)[existingKey->mData.id];
|
DynamicScalarInfo& scalarData = (*gDynamicScalarInfo)[existingKey->mData.id];
|
||||||
scalarData.mDynamicExpiration = true;
|
scalarData.mDynamicExpiration = true;
|
||||||
}
|
}
|
||||||
|
@ -1509,8 +1488,6 @@ TelemetryScalar::DeInitializeGlobalState()
|
||||||
gScalarNameIDMap.Clear();
|
gScalarNameIDMap.Clear();
|
||||||
gScalarStorageMap.Clear();
|
gScalarStorageMap.Clear();
|
||||||
gKeyedScalarStorageMap.Clear();
|
gKeyedScalarStorageMap.Clear();
|
||||||
gDynamicBuiltinScalarStorageMap.Clear();
|
|
||||||
gDynamicBuiltinKeyedScalarStorageMap.Clear();
|
|
||||||
gDynamicScalarInfo = nullptr;
|
gDynamicScalarInfo = nullptr;
|
||||||
gInitDone = false;
|
gInitDone = false;
|
||||||
}
|
}
|
||||||
|
@ -2156,63 +2133,41 @@ TelemetryScalar::CreateSnapshots(unsigned int aDataset, bool aClearScalars, JSCo
|
||||||
nsDataHashtable<ProcessIDHashKey, ScalarArray> scalarsToReflect;
|
nsDataHashtable<ProcessIDHashKey, ScalarArray> scalarsToReflect;
|
||||||
{
|
{
|
||||||
StaticMutexAutoLock locker(gTelemetryScalarsMutex);
|
StaticMutexAutoLock locker(gTelemetryScalarsMutex);
|
||||||
|
// Iterate the scalars in gScalarStorageMap. The storage may contain empty or yet to be
|
||||||
|
// initialized scalars from all the supported processes.
|
||||||
|
for (auto iter = gScalarStorageMap.Iter(); !iter.Done(); iter.Next()) {
|
||||||
|
ScalarStorageMapType* scalarStorage = static_cast<ScalarStorageMapType*>(iter.Data());
|
||||||
|
ScalarArray& processScalars = scalarsToReflect.GetOrInsert(iter.Key());
|
||||||
|
|
||||||
// The snapshotting function is the same for both static and dynamic builtin scalars.
|
// Are we in the "Dynamic" process?
|
||||||
// We can use the same function and store the scalars in the same output storage.
|
bool isDynamicProcess = ProcessID::Dynamic == static_cast<ProcessID>(iter.Key());
|
||||||
auto snapshotter = [aDataset, &locker, &scalarsToReflect]
|
|
||||||
(ProcessesScalarsMapType& aProcessStorage, bool aIsBuiltinDynamic)
|
|
||||||
-> nsresult
|
|
||||||
{
|
|
||||||
// Iterate the scalars in aProcessStorage. The storage may contain empty or yet to be
|
|
||||||
// initialized scalars from all the supported processes.
|
|
||||||
for (auto iter = aProcessStorage.Iter(); !iter.Done(); iter.Next()) {
|
|
||||||
ScalarStorageMapType* scalarStorage = static_cast<ScalarStorageMapType*>(iter.Data());
|
|
||||||
ScalarArray& processScalars = scalarsToReflect.GetOrInsert(iter.Key());
|
|
||||||
|
|
||||||
// Are we in the "Dynamic" process?
|
// Iterate each available child storage.
|
||||||
bool isDynamicProcess = ProcessID::Dynamic == static_cast<ProcessID>(iter.Key());
|
for (auto childIter = scalarStorage->Iter(); !childIter.Done(); childIter.Next()) {
|
||||||
|
ScalarBase* scalar = static_cast<ScalarBase*>(childIter.Data());
|
||||||
|
|
||||||
// Iterate each available child storage.
|
// Get the informations for this scalar.
|
||||||
for (auto childIter = scalarStorage->Iter(); !childIter.Done(); childIter.Next()) {
|
const BaseScalarInfo& info =
|
||||||
ScalarBase* scalar = static_cast<ScalarBase*>(childIter.Data());
|
internal_GetScalarInfo(locker, ScalarKey{childIter.Key(),
|
||||||
|
isDynamicProcess});
|
||||||
|
|
||||||
// Get the informations for this scalar.
|
// Serialize the scalar if it's in the desired dataset.
|
||||||
const BaseScalarInfo& info =
|
if (IsInDataset(info.dataset, aDataset)) {
|
||||||
internal_GetScalarInfo(locker, ScalarKey{childIter.Key(),
|
// Get the scalar value.
|
||||||
aIsBuiltinDynamic ? true : isDynamicProcess});
|
nsCOMPtr<nsIVariant> scalarValue;
|
||||||
|
nsresult rv = scalar->GetValue(scalarValue);
|
||||||
// Serialize the scalar if it's in the desired dataset.
|
if (NS_FAILED(rv)) {
|
||||||
if (IsInDataset(info.dataset, aDataset)) {
|
return rv;
|
||||||
// Get the scalar value.
|
|
||||||
nsCOMPtr<nsIVariant> scalarValue;
|
|
||||||
nsresult rv = scalar->GetValue(scalarValue);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
// Append it to our list.
|
|
||||||
processScalars.AppendElement(mozilla::MakePair(info.name(), scalarValue));
|
|
||||||
}
|
}
|
||||||
|
// Append it to our list.
|
||||||
|
processScalars.AppendElement(mozilla::MakePair(info.name(), scalarValue));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NS_OK;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Take a snapshot of the scalars.
|
|
||||||
nsresult rv = snapshotter(gScalarStorageMap, false);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
// And a snapshot of the dynamic builtin ones.
|
|
||||||
rv = snapshotter(gDynamicBuiltinScalarStorageMap, true);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aClearScalars) {
|
if (aClearScalars) {
|
||||||
// The map already takes care of freeing the allocated memory.
|
// The map already takes care of freeing the allocated memory.
|
||||||
gScalarStorageMap.Clear();
|
gScalarStorageMap.Clear();
|
||||||
gDynamicBuiltinScalarStorageMap.Clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2286,61 +2241,41 @@ TelemetryScalar::CreateKeyedSnapshots(unsigned int aDataset, bool aClearScalars,
|
||||||
nsDataHashtable<ProcessIDHashKey, ScalarArray> scalarsToReflect;
|
nsDataHashtable<ProcessIDHashKey, ScalarArray> scalarsToReflect;
|
||||||
{
|
{
|
||||||
StaticMutexAutoLock locker(gTelemetryScalarsMutex);
|
StaticMutexAutoLock locker(gTelemetryScalarsMutex);
|
||||||
|
// Iterate the scalars in gKeyedScalarStorageMap. The storage may contain empty or yet
|
||||||
|
// to be initialized scalars from all the supported processes.
|
||||||
|
for (auto iter = gKeyedScalarStorageMap.Iter(); !iter.Done(); iter.Next()) {
|
||||||
|
KeyedScalarStorageMapType* scalarStorage =
|
||||||
|
static_cast<KeyedScalarStorageMapType*>(iter.Data());
|
||||||
|
ScalarArray& processScalars = scalarsToReflect.GetOrInsert(iter.Key());
|
||||||
|
|
||||||
auto snapshotter = [aDataset, &locker, &scalarsToReflect]
|
// Are we in the "Dynamic" process?
|
||||||
(ProcessesKeyedScalarsMapType& aProcessStorage,
|
bool isDynamicProcess = ProcessID::Dynamic == static_cast<ProcessID>(iter.Key());
|
||||||
bool aIsBuiltinDynamic) -> nsresult
|
|
||||||
{
|
|
||||||
// Iterate the scalars in aProcessStorage. The storage may contain empty or yet
|
|
||||||
// to be initialized scalars from all the supported processes.
|
|
||||||
for (auto iter = aProcessStorage.Iter(); !iter.Done(); iter.Next()) {
|
|
||||||
KeyedScalarStorageMapType* scalarStorage =
|
|
||||||
static_cast<KeyedScalarStorageMapType*>(iter.Data());
|
|
||||||
ScalarArray& processScalars = scalarsToReflect.GetOrInsert(iter.Key());
|
|
||||||
|
|
||||||
// Are we in the "Dynamic" process?
|
for (auto childIter = scalarStorage->Iter(); !childIter.Done(); childIter.Next()) {
|
||||||
bool isDynamicProcess = ProcessID::Dynamic == static_cast<ProcessID>(iter.Key());
|
KeyedScalar* scalar = static_cast<KeyedScalar*>(childIter.Data());
|
||||||
|
|
||||||
for (auto childIter = scalarStorage->Iter(); !childIter.Done(); childIter.Next()) {
|
// Get the informations for this scalar.
|
||||||
KeyedScalar* scalar = static_cast<KeyedScalar*>(childIter.Data());
|
const BaseScalarInfo& info =
|
||||||
|
internal_GetScalarInfo(locker, ScalarKey{childIter.Key(),
|
||||||
|
isDynamicProcess});
|
||||||
|
|
||||||
// Get the informations for this scalar.
|
// Serialize the scalar if it's in the desired dataset.
|
||||||
const BaseScalarInfo& info =
|
if (IsInDataset(info.dataset, aDataset)) {
|
||||||
internal_GetScalarInfo(locker, ScalarKey{childIter.Key(),
|
// Get the keys for this scalar.
|
||||||
aIsBuiltinDynamic ? true : isDynamicProcess});
|
nsTArray<KeyedScalar::KeyValuePair> scalarKeyedData;
|
||||||
|
nsresult rv = scalar->GetValue(scalarKeyedData);
|
||||||
// Serialize the scalar if it's in the desired dataset.
|
if (NS_FAILED(rv)) {
|
||||||
if (IsInDataset(info.dataset, aDataset)) {
|
return rv;
|
||||||
// Get the keys for this scalar.
|
|
||||||
nsTArray<KeyedScalar::KeyValuePair> scalarKeyedData;
|
|
||||||
nsresult rv = scalar->GetValue(scalarKeyedData);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
// Append it to our list.
|
|
||||||
processScalars.AppendElement(mozilla::MakePair(info.name(), scalarKeyedData));
|
|
||||||
}
|
}
|
||||||
|
// Append it to our list.
|
||||||
|
processScalars.AppendElement(mozilla::MakePair(info.name(), scalarKeyedData));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NS_OK;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Take a snapshot of the scalars.
|
|
||||||
nsresult rv = snapshotter(gKeyedScalarStorageMap, false);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
// And a snapshot of the dynamic builtin ones.
|
|
||||||
rv = snapshotter(gDynamicBuiltinKeyedScalarStorageMap, true);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aClearScalars) {
|
if (aClearScalars) {
|
||||||
// The map already takes care of freeing the allocated memory.
|
// The map already takes care of freeing the allocated memory.
|
||||||
gKeyedScalarStorageMap.Clear();
|
gKeyedScalarStorageMap.Clear();
|
||||||
gDynamicBuiltinKeyedScalarStorageMap.Clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2398,7 +2333,6 @@ TelemetryScalar::CreateKeyedSnapshots(unsigned int aDataset, bool aClearScalars,
|
||||||
nsresult
|
nsresult
|
||||||
TelemetryScalar::RegisterScalars(const nsACString& aCategoryName,
|
TelemetryScalar::RegisterScalars(const nsACString& aCategoryName,
|
||||||
JS::Handle<JS::Value> aScalarData,
|
JS::Handle<JS::Value> aScalarData,
|
||||||
bool aBuiltin,
|
|
||||||
JSContext* cx)
|
JSContext* cx)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(XRE_IsParentProcess(),
|
MOZ_ASSERT(XRE_IsParentProcess(),
|
||||||
|
@ -2497,7 +2431,7 @@ TelemetryScalar::RegisterScalars(const nsACString& aCategoryName,
|
||||||
// We defer the actual registration here in case any other event description is invalid.
|
// We defer the actual registration here in case any other event description is invalid.
|
||||||
// In that case we don't need to roll back any partial registration.
|
// In that case we don't need to roll back any partial registration.
|
||||||
newScalarInfos.AppendElement(DynamicScalarInfo{
|
newScalarInfos.AppendElement(DynamicScalarInfo{
|
||||||
kind, recordOnRelease, expired, fullName, keyed, aBuiltin
|
kind, recordOnRelease, expired, fullName, keyed
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2527,8 +2461,6 @@ TelemetryScalar::ClearScalars()
|
||||||
StaticMutexAutoLock locker(gTelemetryScalarsMutex);
|
StaticMutexAutoLock locker(gTelemetryScalarsMutex);
|
||||||
gScalarStorageMap.Clear();
|
gScalarStorageMap.Clear();
|
||||||
gKeyedScalarStorageMap.Clear();
|
gKeyedScalarStorageMap.Clear();
|
||||||
gDynamicBuiltinScalarStorageMap.Clear();
|
|
||||||
gDynamicBuiltinKeyedScalarStorageMap.Clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
|
@ -2543,26 +2475,23 @@ TelemetryScalar::GetScalarSizesOfIncludingThis(mozilla::MallocSizeOf aMallocSize
|
||||||
{
|
{
|
||||||
StaticMutexAutoLock locker(gTelemetryScalarsMutex);
|
StaticMutexAutoLock locker(gTelemetryScalarsMutex);
|
||||||
size_t n = 0;
|
size_t n = 0;
|
||||||
|
// Account for scalar data coming from parent and child processes.
|
||||||
auto getSizeOf = [aMallocSizeOf](auto &storageMap)
|
for (auto iter = gScalarStorageMap.Iter(); !iter.Done(); iter.Next()) {
|
||||||
{
|
ScalarStorageMapType* scalarStorage = static_cast<ScalarStorageMapType*>(iter.Data());
|
||||||
size_t partial = 0;
|
for (auto childIter = scalarStorage->Iter(); !childIter.Done(); childIter.Next()) {
|
||||||
for (auto iter = storageMap.Iter(); !iter.Done(); iter.Next()) {
|
ScalarBase* scalar = static_cast<ScalarBase*>(childIter.Data());
|
||||||
auto scalarStorage = iter.Data();
|
n += scalar->SizeOfIncludingThis(aMallocSizeOf);
|
||||||
for (auto childIter = scalarStorage->Iter(); !childIter.Done(); childIter.Next()) {
|
|
||||||
auto scalar = childIter.Data();
|
|
||||||
partial += scalar->SizeOfIncludingThis(aMallocSizeOf);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return partial;
|
}
|
||||||
};
|
// Also account for keyed scalar data coming from parent and child processes.
|
||||||
|
for (auto iter = gKeyedScalarStorageMap.Iter(); !iter.Done(); iter.Next()) {
|
||||||
// Account for all the storage used for the different scalar types.
|
KeyedScalarStorageMapType* scalarStorage =
|
||||||
n += getSizeOf(gScalarStorageMap);
|
static_cast<KeyedScalarStorageMapType*>(iter.Data());
|
||||||
n += getSizeOf(gKeyedScalarStorageMap);
|
for (auto childIter = scalarStorage->Iter(); !childIter.Done(); childIter.Next()) {
|
||||||
n += getSizeOf(gDynamicBuiltinScalarStorageMap);
|
KeyedScalar* scalar = static_cast<KeyedScalar*>(childIter.Data());
|
||||||
n += getSizeOf(gDynamicBuiltinKeyedScalarStorageMap);
|
n += scalar->SizeOfIncludingThis(aMallocSizeOf);
|
||||||
|
}
|
||||||
|
}
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2837,8 +2766,7 @@ TelemetryScalar::AddDynamicScalarDefinitions(
|
||||||
recordOnRelease,
|
recordOnRelease,
|
||||||
def.expired,
|
def.expired,
|
||||||
def.name,
|
def.name,
|
||||||
def.keyed,
|
def.keyed});
|
||||||
false /* builtin */});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
|
@ -56,7 +56,7 @@ void Set(mozilla::Telemetry::ScalarID aId, const nsAString& aKey, bool aValue);
|
||||||
void SetMaximum(mozilla::Telemetry::ScalarID aId, const nsAString& aKey, uint32_t aValue);
|
void SetMaximum(mozilla::Telemetry::ScalarID aId, const nsAString& aKey, uint32_t aValue);
|
||||||
|
|
||||||
nsresult RegisterScalars(const nsACString& aCategoryName, JS::Handle<JS::Value> aScalarData,
|
nsresult RegisterScalars(const nsACString& aCategoryName, JS::Handle<JS::Value> aScalarData,
|
||||||
bool aBuiltin, JSContext* cx);
|
JSContext* cx);
|
||||||
|
|
||||||
// Only to be used for testing.
|
// Only to be used for testing.
|
||||||
void ClearScalars();
|
void ClearScalars();
|
||||||
|
|
|
@ -5,7 +5,7 @@ Scalars
|
||||||
Historically we started to overload our histogram mechanism to also collect scalar data,
|
Historically we started to overload our histogram mechanism to also collect scalar data,
|
||||||
such as flag values, counts, labels and others.
|
such as flag values, counts, labels and others.
|
||||||
The scalar measurement types are the suggested way to collect that kind of scalar data.
|
The scalar measurement types are the suggested way to collect that kind of scalar data.
|
||||||
The serialized scalar data is submitted with the :doc:`main pings <../data/main-ping>`. Adding scalars is supported in artifact builds and build faster workflows.
|
The serialized scalar data is submitted with the :doc:`main pings <../data/main-ping>`.
|
||||||
|
|
||||||
.. important::
|
.. important::
|
||||||
|
|
||||||
|
@ -290,5 +290,3 @@ Version History
|
||||||
|
|
||||||
- Added support for recording new scalars from add-ons (`bug 1393801 <bug https://bugzilla.mozilla.org/show_bug.cgi?id=1393801>`_).
|
- Added support for recording new scalars from add-ons (`bug 1393801 <bug https://bugzilla.mozilla.org/show_bug.cgi?id=1393801>`_).
|
||||||
- Ignore re-registering existing scalars for a category instead of failing (`bug 1409323 <https://bugzilla.mozilla.org/show_bug.cgi?id=1409323>`_).
|
- Ignore re-registering existing scalars for a category instead of failing (`bug 1409323 <https://bugzilla.mozilla.org/show_bug.cgi?id=1409323>`_).
|
||||||
|
|
||||||
- Firefox 60: Enabled support for adding scalars in artifact builds and build-faster workflows (`bug 1425909 <https://bugzilla.mozilla.org/show_bug.cgi?id=1425909`_).
|
|
||||||
|
|
|
@ -6,10 +6,8 @@
|
||||||
# in a file provided as a command-line argument.
|
# in a file provided as a command-line argument.
|
||||||
|
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
from collections import OrderedDict
|
|
||||||
from shared_telemetry_utils import StringTable, static_assert, ParserError
|
from shared_telemetry_utils import StringTable, static_assert, ParserError
|
||||||
|
|
||||||
import json
|
|
||||||
import parse_scalars
|
import parse_scalars
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
@ -80,49 +78,17 @@ def write_scalar_tables(scalars, output):
|
||||||
"index overflow")
|
"index overflow")
|
||||||
|
|
||||||
|
|
||||||
def parse_scalar_definitions(filenames):
|
def main(output, *filenames):
|
||||||
|
# Load the scalars first.
|
||||||
if len(filenames) > 1:
|
if len(filenames) > 1:
|
||||||
raise Exception('We don\'t support loading from more than one file.')
|
raise Exception('We don\'t support loading from more than one file.')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
return parse_scalars.load_scalars(filenames[0])
|
scalars = parse_scalars.load_scalars(filenames[0])
|
||||||
except ParserError as ex:
|
except ParserError as ex:
|
||||||
print("\nError processing scalars:\n" + str(ex) + "\n")
|
print("\nError processing scalars:\n" + str(ex) + "\n")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
def generate_JSON_definitions(output, *filenames):
|
|
||||||
""" Write the scalar definitions to a JSON file.
|
|
||||||
|
|
||||||
:param output: the file to write the content to.
|
|
||||||
:param filenames: a list of filenames provided by the build system.
|
|
||||||
We only support a single file.
|
|
||||||
"""
|
|
||||||
scalars = parse_scalar_definitions(filenames)
|
|
||||||
|
|
||||||
scalar_definitions = OrderedDict()
|
|
||||||
for scalar in scalars:
|
|
||||||
category = scalar.category
|
|
||||||
|
|
||||||
if category not in scalar_definitions:
|
|
||||||
scalar_definitions[category] = OrderedDict()
|
|
||||||
|
|
||||||
scalar_definitions[category][scalar.name] = OrderedDict({
|
|
||||||
'kind': scalar.nsITelemetry_kind,
|
|
||||||
'keyed': scalar.keyed,
|
|
||||||
'record_on_release': True if scalar.dataset == 'opt-out' else False,
|
|
||||||
# We don't expire dynamic-builtin scalars: they're only meant for
|
|
||||||
# use in local developer builds anyway. They will expire when rebuilding.
|
|
||||||
'expired': False,
|
|
||||||
})
|
|
||||||
|
|
||||||
json.dump(scalar_definitions, output)
|
|
||||||
|
|
||||||
|
|
||||||
def main(output, *filenames):
|
|
||||||
# Load the scalars first.
|
|
||||||
scalars = parse_scalar_definitions(filenames)
|
|
||||||
|
|
||||||
# Write the scalar data file.
|
# Write the scalar data file.
|
||||||
print(banner, file=output)
|
print(banner, file=output)
|
||||||
print(file_header, file=output)
|
print(file_header, file=output)
|
||||||
|
|
|
@ -110,7 +110,6 @@ PYTHON_UNITTEST_MANIFESTS += [
|
||||||
]
|
]
|
||||||
|
|
||||||
GENERATED_FILES = [
|
GENERATED_FILES = [
|
||||||
'ScalarArtifactDefinitions.json',
|
|
||||||
'TelemetryEventData.h',
|
'TelemetryEventData.h',
|
||||||
'TelemetryEventEnums.h',
|
'TelemetryEventEnums.h',
|
||||||
'TelemetryHistogramData.inc',
|
'TelemetryHistogramData.inc',
|
||||||
|
@ -149,15 +148,6 @@ scalar_enums = GENERATED_FILES['TelemetryScalarEnums.h']
|
||||||
scalar_enums.script = 'gen_scalar_enum.py'
|
scalar_enums.script = 'gen_scalar_enum.py'
|
||||||
scalar_enums.inputs = scalar_files
|
scalar_enums.inputs = scalar_files
|
||||||
|
|
||||||
# Generate the JSON scalar definitions. They will only be
|
|
||||||
# used in artifact or "build faster" builds.
|
|
||||||
scalar_json_data = GENERATED_FILES['ScalarArtifactDefinitions.json']
|
|
||||||
scalar_json_data.script = 'gen_scalar_data.py:generate_JSON_definitions'
|
|
||||||
scalar_json_data.inputs = scalar_files
|
|
||||||
|
|
||||||
# Move the scalars JSON file to the directory where the Firefox binary is.
|
|
||||||
FINAL_TARGET_FILES += ['!ScalarArtifactDefinitions.json']
|
|
||||||
|
|
||||||
# Generate event files.
|
# Generate event files.
|
||||||
event_files = [
|
event_files = [
|
||||||
'Events.yaml',
|
'Events.yaml',
|
||||||
|
|
|
@ -541,17 +541,6 @@ interface nsITelemetry : nsISupports
|
||||||
[implicit_jscontext]
|
[implicit_jscontext]
|
||||||
void registerScalars(in ACString aCategoryName, in jsval aScalarData);
|
void registerScalars(in ACString aCategoryName, in jsval aScalarData);
|
||||||
|
|
||||||
/**
|
|
||||||
* Parent process only. Register dynamic builtin scalars. The parameters
|
|
||||||
* have the same meaning as the usual |registerScalars| function.
|
|
||||||
*
|
|
||||||
* This function is only meant to be used to support the "artifact build"/
|
|
||||||
* "built faster" developers by allowing to add new scalars without rebuilding
|
|
||||||
* the C++ components including the headers files.
|
|
||||||
*/
|
|
||||||
[implicit_jscontext]
|
|
||||||
void registerBuiltinScalars(in ACString aCategoryName, in jsval aScalarData);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resets all the stored events. This is intended to be only used in tests.
|
* Resets all the stored events. This is intended to be only used in tests.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -198,11 +198,6 @@ class ScalarType:
|
||||||
raise ParserError('{} - invalid expires: {}.\nSee: {}#required-fields'
|
raise ParserError('{} - invalid expires: {}.\nSee: {}#required-fields'
|
||||||
.format(self._name, expires, BASE_DOC_URL))
|
.format(self._name, expires, BASE_DOC_URL))
|
||||||
|
|
||||||
@property
|
|
||||||
def category(self):
|
|
||||||
"""Get the category name"""
|
|
||||||
return self._category_name
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
"""Get the scalar name"""
|
"""Get the scalar name"""
|
||||||
|
|
|
@ -1,137 +0,0 @@
|
||||||
/* Any copyright is dedicated to the Public Domain.
|
|
||||||
http://creativecommons.org/publicdomain/zero/1.0/
|
|
||||||
*/
|
|
||||||
|
|
||||||
const UINT_SCALAR = "telemetry.test.unsigned_int_kind";
|
|
||||||
const STRING_SCALAR = "telemetry.test.string_kind";
|
|
||||||
const BOOLEAN_SCALAR = "telemetry.test.boolean_kind";
|
|
||||||
const KEYED_UINT_SCALAR = "telemetry.test.keyed_unsigned_int";
|
|
||||||
|
|
||||||
ChromeUtils.import("resource://services-common/utils.js");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the path to the definitions file for the scalars.
|
|
||||||
*/
|
|
||||||
function getDefinitionsPath() {
|
|
||||||
// Write the scalar definition to the spec file in the binary directory.
|
|
||||||
let definitionFile = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
|
|
||||||
definitionFile = Services.dirsvc.get("GreBinD", Ci.nsIFile);
|
|
||||||
definitionFile.append("ScalarArtifactDefinitions.json");
|
|
||||||
return definitionFile.path;
|
|
||||||
}
|
|
||||||
|
|
||||||
add_task(async function test_setup() {
|
|
||||||
do_get_profile();
|
|
||||||
});
|
|
||||||
|
|
||||||
add_task({
|
|
||||||
// The test needs to write a file, and that fails in tests on Android.
|
|
||||||
// We don't really need the Android coverage, so skip on Android.
|
|
||||||
skip_if: () => AppConstants.platform == "android"
|
|
||||||
}, async function test_invalidJSON() {
|
|
||||||
const INVALID_JSON = "{ invalid,JSON { {1}";
|
|
||||||
const FILE_PATH = getDefinitionsPath();
|
|
||||||
|
|
||||||
// Write a corrupted JSON file.
|
|
||||||
await OS.File.writeAtomic(FILE_PATH, INVALID_JSON, { encoding: "utf-8", noOverwrite: false });
|
|
||||||
|
|
||||||
// Simulate Firefox startup. This should not throw!
|
|
||||||
await TelemetryController.testSetup();
|
|
||||||
await TelemetryController.testPromiseJsProbeRegistration();
|
|
||||||
|
|
||||||
// Cleanup.
|
|
||||||
await TelemetryController.testShutdown();
|
|
||||||
await OS.File.remove(FILE_PATH);
|
|
||||||
});
|
|
||||||
|
|
||||||
add_task({
|
|
||||||
// The test needs to write a file, and that fails in tests on Android.
|
|
||||||
// We don't really need the Android coverage, so skip on Android.
|
|
||||||
skip_if: () => AppConstants.platform == "android"
|
|
||||||
}, async function test_dynamicBuiltin() {
|
|
||||||
const DYNAMIC_SCALAR_SPEC = {
|
|
||||||
"telemetry.test": {
|
|
||||||
"builtin_dynamic": {
|
|
||||||
"kind": "nsITelemetry::SCALAR_TYPE_COUNT",
|
|
||||||
"expired": false,
|
|
||||||
"record_on_release": false,
|
|
||||||
"keyed": false
|
|
||||||
},
|
|
||||||
"builtin_dynamic_other": {
|
|
||||||
"kind": "nsITelemetry::SCALAR_TYPE_BOOLEAN",
|
|
||||||
"expired": false,
|
|
||||||
"record_on_release": false,
|
|
||||||
"keyed": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Telemetry.clearScalars();
|
|
||||||
|
|
||||||
// Let's write to the definition file to also cover the file
|
|
||||||
// loading part.
|
|
||||||
const FILE_PATH = getDefinitionsPath();
|
|
||||||
await CommonUtils.writeJSON(DYNAMIC_SCALAR_SPEC, FILE_PATH);
|
|
||||||
|
|
||||||
// Start TelemetryController to trigger loading the specs.
|
|
||||||
await TelemetryController.testReset();
|
|
||||||
await TelemetryController.testPromiseJsProbeRegistration();
|
|
||||||
|
|
||||||
// Store to that scalar.
|
|
||||||
const TEST_SCALAR1 = "telemetry.test.builtin_dynamic";
|
|
||||||
const TEST_SCALAR2 = "telemetry.test.builtin_dynamic_other";
|
|
||||||
Telemetry.scalarSet(TEST_SCALAR1, 3785);
|
|
||||||
Telemetry.scalarSet(TEST_SCALAR2, true);
|
|
||||||
|
|
||||||
// Check the values we tried to store.
|
|
||||||
const scalars =
|
|
||||||
Telemetry.snapshotScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false).parent;
|
|
||||||
|
|
||||||
// Check that they are serialized to the correct format.
|
|
||||||
Assert.equal(typeof(scalars[TEST_SCALAR1]), "number",
|
|
||||||
TEST_SCALAR1 + " must be serialized to the correct format.");
|
|
||||||
Assert.ok(Number.isInteger(scalars[TEST_SCALAR1]),
|
|
||||||
TEST_SCALAR1 + " must be a finite integer.");
|
|
||||||
Assert.equal(scalars[TEST_SCALAR1], 3785,
|
|
||||||
TEST_SCALAR1 + " must have the correct value.");
|
|
||||||
Assert.equal(typeof(scalars[TEST_SCALAR2]), "boolean",
|
|
||||||
TEST_SCALAR2 + " must be serialized to the correct format.");
|
|
||||||
Assert.equal(scalars[TEST_SCALAR2], true,
|
|
||||||
TEST_SCALAR2 + " must have the correct value.");
|
|
||||||
|
|
||||||
// Clean up.
|
|
||||||
await TelemetryController.testShutdown();
|
|
||||||
await OS.File.remove(FILE_PATH);
|
|
||||||
});
|
|
||||||
|
|
||||||
add_task(async function test_keyedDynamicBuiltin() {
|
|
||||||
Telemetry.clearScalars();
|
|
||||||
|
|
||||||
// Register the built-in scalars (let's not take the I/O hit).
|
|
||||||
Telemetry.registerBuiltinScalars("telemetry.test", {
|
|
||||||
"builtin_dynamic_keyed": {
|
|
||||||
"kind": Ci.nsITelemetry.SCALAR_TYPE_COUNT,
|
|
||||||
"expired": false,
|
|
||||||
"record_on_release": false,
|
|
||||||
"keyed": true
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Store to that scalar.
|
|
||||||
const TEST_SCALAR1 = "telemetry.test.builtin_dynamic_keyed";
|
|
||||||
Telemetry.keyedScalarSet(TEST_SCALAR1, "test-key", 3785);
|
|
||||||
|
|
||||||
// Check the values we tried to store.
|
|
||||||
const scalars =
|
|
||||||
Telemetry.snapshotKeyedScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false).parent;
|
|
||||||
|
|
||||||
// Check that they are serialized to the correct format.
|
|
||||||
Assert.equal(typeof(scalars[TEST_SCALAR1]), "object",
|
|
||||||
TEST_SCALAR1 + " must be a keyed scalar.");
|
|
||||||
Assert.equal(typeof(scalars[TEST_SCALAR1]["test-key"]), "number",
|
|
||||||
TEST_SCALAR1 + " must be serialized to the correct format.");
|
|
||||||
Assert.ok(Number.isInteger(scalars[TEST_SCALAR1]["test-key"]),
|
|
||||||
TEST_SCALAR1 + " must be a finite integer.");
|
|
||||||
Assert.equal(scalars[TEST_SCALAR1]["test-key"], 3785,
|
|
||||||
TEST_SCALAR1 + " must have the correct value.");
|
|
||||||
});
|
|
|
@ -64,7 +64,6 @@ skip-if = os == "android" # Disabled due to crashes (see bug 1331366)
|
||||||
skip-if = os == "android" # Disabled due to crashes (see bug 1367762)
|
skip-if = os == "android" # Disabled due to crashes (see bug 1367762)
|
||||||
tags = addons
|
tags = addons
|
||||||
[test_TelemetryScalars.js]
|
[test_TelemetryScalars.js]
|
||||||
[test_TelemetryScalars_buildFaster.js]
|
|
||||||
[test_TelemetryTimestamps.js]
|
[test_TelemetryTimestamps.js]
|
||||||
skip-if = toolkit == 'android'
|
skip-if = toolkit == 'android'
|
||||||
[test_TelemetryCaptureStack.js]
|
[test_TelemetryCaptureStack.js]
|
||||||
|
|
Загрузка…
Ссылка в новой задаче