Bug 1894703 - Set logging modules from a single preference r=padenot

This uses a new preference logging.config.modules. When the user sets a
MOZ_LOG string to this preference, it's parsed the same way and the
corresponding modules are enabled.

Differential Revision: https://phabricator.services.mozilla.com/D209249
This commit is contained in:
Julien Wajsberg 2024-05-23 08:14:16 +00:00
parent 4fa8b7bce2
commit 8d1becb7de
5 changed files with 80 additions and 0 deletions

View file

@ -10,6 +10,7 @@
#include "mozilla/Preferences.h"
#include "mozilla/Services.h"
#include "nsIObserverService.h"
#include "NSPRLogModulesParser.h"
#include "nsString.h"
#include "nsXULAppAPI.h"
#include "base/process_util.h"
@ -23,6 +24,7 @@ static const char kLoggingPrefLogFile[] = "logging.config.LOG_FILE";
static const char kLoggingPrefAddTimestamp[] = "logging.config.add_timestamp";
static const char kLoggingPrefSync[] = "logging.config.sync";
static const char kLoggingPrefStacks[] = "logging.config.profilerstacks";
static const char kLoggingPrefLogModules[] = "logging.config.modules";
namespace mozilla {
@ -85,6 +87,30 @@ static void LoadPrefValue(const char* aName) {
} else if (prefName.EqualsLiteral(kLoggingPrefStacks)) {
bool captureStacks = Preferences::GetBool(aName, false);
LogModule::SetCaptureStacks(captureStacks);
} else if (prefName.EqualsLiteral(kLoggingPrefLogModules)) {
// The content of the preference will be parsed as a MOZ_LOG string, then
// the corresponding log modules (if any) will be enabled, others will be
// disabled.
LogModule::DisableModules();
rv = Preferences::GetCString(aName, prefValue);
if (NS_FAILED(rv)) {
// If the preference is missing, there's nothing to set.
return;
}
NSPRLogModulesParser(
prefValue.BeginReading(),
[](const char* aName, LogLevel aLevel, int32_t aValue) mutable {
// Only the special string "profilerstacks" is taken into account,
// because we're especially interested in usage with the Firefox
// Profiler.
if (strcmp(aName, "profilerstacks") == 0) {
LogModule::SetCaptureStacks(true);
} else {
LogModule::Get(aName)->SetLevel(aLevel);
}
});
}
return;
}

View file

@ -774,6 +774,13 @@ class LogModuleManager {
}
}
void DisableModules() {
OffTheBooksMutexAutoLock guard(mModulesLock);
for (auto& m : mModules) {
(*(m.GetModifiableData()))->SetLevel(LogLevel::Disabled);
}
}
private:
OffTheBooksMutex mModulesLock;
nsClassHashtable<nsCharPtrHashKey, LogModule> mModules;
@ -841,6 +848,8 @@ void LogModule::SetCaptureStacks(bool aCaptureStacks) {
sLogModuleManager->SetCaptureStacks(aCaptureStacks);
}
void LogModule::DisableModules() { sLogModuleManager->DisableModules(); }
// This function is defined in gecko_logger/src/lib.rs
// We mirror the level in rust code so we don't get forwarded all of the
// rust logging and have to create an LogModule for each rust component.

View file

@ -125,6 +125,11 @@ class LogModule {
*/
static void SetCaptureStacks(bool aCaptureStacks);
/**
* Disable all log modules.
*/
static void DisableModules();
/**
* Indicates whether or not the given log level is enabled.
*/

View file

@ -0,0 +1,37 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
const kModulesPref = "logging.config.modules";
add_task(async () => {
Services.prefs.setStringPref(kModulesPref, "prof:5");
registerCleanupFunction(() => {
Services.prefs.clearUserPref(kModulesPref);
});
const entries = 10000;
const interval = 1;
const threads = ["GeckoMain"];
const features = ["nostacksampling"];
await Services.profiler.StartProfiler(entries, interval, features, threads);
const profileData = await Services.profiler.getProfileDataAsync();
await Services.profiler.StopProfiler();
const { markers, stringTable } = profileData.threads[0];
const stringIndexForLogMessages = stringTable.indexOf("LogMessages");
Assert.greaterOrEqual(
stringIndexForLogMessages,
0,
"A string index for the string LogMessages have been found."
);
// At least one log for the profiler json streaming operation should exist.
// See https://searchfox.org/mozilla-central/rev/445a6e86233c733c5557ef44e1d33444adaddefc/mozglue/baseprofiler/core/platform.cpp#2015
const logMessageMarkers = markers.data.filter(
tuple => tuple[markers.schema.name] === stringIndexForLogMessages
);
Assert.greaterOrEqual(
logMessageMarkers.length,
0,
"At least one log message have been found."
);
});

View file

@ -58,6 +58,9 @@ fail-if = ["os == 'android'"]
["test_localfile.js"]
["test_logFromPreference.js"]
skip-if = "(os == 'android' && release_or_beta)" # bug 1841818
["test_mac_bundle.js"]
["test_mac_xattrs.js"]