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:
Narcis Beleuzu 2018-02-01 19:45:22 +02:00
Родитель 54a5db7d0a
Коммит b709f2768b
12 изменённых файлов: 82 добавлений и 439 удалений

Просмотреть файл

@ -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]