mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 05:11:16 +00:00
Backed out 9 changesets (bug 1796585, bug 1796152, bug 1797284, bug 1796554
, bug 1800076, bug 1802349, bug 1797497) for causing mochitest failures in xpcom/base/nsTraceRefcnt.cpp. CLOSED TREE
Backed out changeset 6002e93434a2 (bug 1802349) Backed out changeset 000cd664c157 (bug 1800076) Backed out changeset e3534e639e2c (bug1796554
) Backed out changeset 1d22428d764c (bug 1797497) Backed out changeset b0dbe35d48be (bug 1797284) Backed out changeset b415d4b85ab6 (bug 1796585) Backed out changeset dc1c2ffbc38e (bug1796554
) Backed out changeset c44bae1f03f5 (bug 1796152) Backed out changeset 3eab5e71b1c7 (bug 1796152)
This commit is contained in:
parent
e8693c6f13
commit
18b90e2c5a
@ -110,7 +110,6 @@ export type RecordingState =
|
||||
export type PageContext =
|
||||
| "devtools"
|
||||
| "devtools-remote"
|
||||
| "aboutlogging"
|
||||
| "aboutprofiling"
|
||||
| "aboutprofiling-remote";
|
||||
|
||||
|
@ -452,7 +452,6 @@ function getPrefPostfix(pageContext) {
|
||||
switch (pageContext) {
|
||||
case "devtools":
|
||||
case "aboutprofiling":
|
||||
case "aboutlogging":
|
||||
// Don't use any postfix on the prefs.
|
||||
return "";
|
||||
case "devtools-remote":
|
||||
|
@ -2,90 +2,48 @@
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src chrome:; object-src 'none'">
|
||||
<meta name="color-scheme" content="light dark">
|
||||
<title data-l10n-id="about-logging-title"></title>
|
||||
<link rel="stylesheet" href="chrome://global/skin/aboutLogging.css">
|
||||
<link rel="stylesheet" href="chrome://global/skin/in-content/info-pages.css">
|
||||
<script src="chrome://global/content/aboutLogging.js"></script>
|
||||
<link rel="localization" href="toolkit/about/aboutLogging.ftl">
|
||||
</head>
|
||||
<body id="body">
|
||||
<div class="main-content">
|
||||
<div id="logging">
|
||||
<h1 id="title" data-l10n-id="about-logging-page-title"></h1>
|
||||
<div class=page-section>
|
||||
<div hidden id=error class=info-box>
|
||||
<div class=info-box-label data-l10n-id="about-logging-error"></div>
|
||||
<div id=error-description></div>
|
||||
<div data-l10n-id="about-logging-configuration-url-ignored"></div>
|
||||
</div>
|
||||
<div hidden id=some-elements-unavailable class=info-box>
|
||||
<div class=info-box-label data-l10n-id="about-logging-info"></div>
|
||||
<div data-l10n-id="about-logging-some-elements-disabled"></div>
|
||||
</div>
|
||||
</div>
|
||||
<button id="toggle-logging-button" data-l10n-id="about-logging-start-logging"></button>
|
||||
<div id=log-module-selection class=page-section>
|
||||
<h2 data-l10n-id="about-logging-log-modules-selection"></h2>
|
||||
<div>
|
||||
<label for="current-log-modules" data-l10n-id="about-logging-currently-enabled-log-modules"></label>
|
||||
<div id="current-log-modules"></div>
|
||||
<span id="no-log-modules" data-l10n-id="about-logging-no-log-modules"></span>
|
||||
</div>
|
||||
<div>
|
||||
<label for="log-modules" data-l10n-id="about-logging-new-log-modules"></label>
|
||||
<input type="text" name="log-modules" id="log-modules" value="">
|
||||
<button id="set-log-modules-button" data-l10n-id="about-logging-set-log-modules"></button>
|
||||
</div>
|
||||
<div id=preset-selector-section>
|
||||
<label for="logging-preset-selector" data-l10n-id="about-logging-logging-preset-selector-text"></label>
|
||||
<select name="logging-preset-selector" id=logging-preset-dropdown></select>
|
||||
<div id="logging-preset-description"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id=logging-output class=page-section>
|
||||
<div>
|
||||
<span hidden id="buttons-disabled" data-l10n-id="about-logging-buttons-disabled"></span>
|
||||
</div>
|
||||
<h2 data-l10n-id="about-logging-logging-output-selection"></h2>
|
||||
<div id=logging-output-profiler class="radio-entry">
|
||||
<input type="radio" id="radio-logging-profiler" name="logging-output" value="profiler" checked>
|
||||
<label for="profiler" data-l10n-id="about-logging-logging-to-profiler"></label>
|
||||
</div>
|
||||
<div id=logging-output-file class="radio-entry">
|
||||
<input type="radio" id="radio-logging-file" name="logging-output" value="file">
|
||||
<label for="file" data-l10n-id="about-logging-logging-to-file"></label>
|
||||
<div>
|
||||
<span hidden id="buttons-disabled" data-l10n-id="about-logging-buttons-disabled"></span>
|
||||
</div>
|
||||
<div>
|
||||
<div id="log-file-configuration">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src chrome:; object-src 'none'">
|
||||
<meta name="color-scheme" content="light dark">
|
||||
<title data-l10n-id="about-logging-title"></title>
|
||||
<link rel="stylesheet" href="chrome://global/skin/aboutNetworking.css">
|
||||
<script src="chrome://global/content/aboutLogging.js"></script>
|
||||
<link rel="localization" href="toolkit/about/aboutLogging.ftl">
|
||||
</head>
|
||||
<body id="body">
|
||||
<div class="main-content">
|
||||
<div id="logging">
|
||||
<div>
|
||||
<label for="current-log-file" data-l10n-id="about-logging-current-log-file"></label>
|
||||
<div id="current-log-file"></div>
|
||||
<span id="no-log-file" data-l10n-id="about-logging-no-log-file"></span>
|
||||
<button id="start-logging-button" data-l10n-id="about-logging-start-logging"></button>
|
||||
<button id="stop-logging-button" data-l10n-id="about-logging-stop-logging"></button>
|
||||
</div>
|
||||
<br>
|
||||
<br>
|
||||
<div>
|
||||
<label for="log-file" data-l10n-id="about-logging-new-log-file"></label>
|
||||
<label data-l10n-id="about-logging-current-log-file"></label>
|
||||
<div id="current-log-file"></div><br>
|
||||
<input type="text" name="log-file" id="log-file">
|
||||
<button id="open-log-file-button" data-l10n-id="about-logging-open-log-file-dir"></button>
|
||||
<button id="set-log-file-button" data-l10n-id="about-logging-set-log-file"></button>
|
||||
</div>
|
||||
<div>
|
||||
<label data-l10n-id="about-logging-current-log-modules"></label>
|
||||
<div id="current-log-modules"></div><br>
|
||||
<input type="text" name="log-modules" id="log-modules" value="timestamp,sync,nsHttp:5,cache2:5,nsSocketTransport:5,nsHostResolver:5">
|
||||
<button id="set-log-modules-button" data-l10n-id="about-logging-set-log-modules"></button>
|
||||
</div>
|
||||
<br>
|
||||
<br>
|
||||
|
||||
<p id="log-tutorial" data-l10n-id="about-logging-log-tutorial">
|
||||
<a data-l10n-name="logging" href="https://firefox-source-docs.mozilla.org/networking/http/logging.html"></a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<p id="log-tutorial" data-l10n-id="about-logging-log-tutorial">
|
||||
<a data-l10n-name="logging" href="https://firefox-source-docs.mozilla.org/networking/http/logging.html"></a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -3,9 +3,6 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
const { XPCOMUtils } = ChromeUtils.importESModule(
|
||||
"resource://gre/modules/XPCOMUtils.sys.mjs"
|
||||
);
|
||||
const gDashboard = Cc["@mozilla.org/network/dashboard;1"].getService(
|
||||
Ci.nsIDashboard
|
||||
);
|
||||
@ -13,295 +10,11 @@ const gDirServ = Cc["@mozilla.org/file/directory_service;1"].getService(
|
||||
Ci.nsIDirectoryServiceProvider
|
||||
);
|
||||
|
||||
const { ProfilerMenuButton } = ChromeUtils.import(
|
||||
"resource://devtools/client/performance-new/popup/menu-button.jsm.js"
|
||||
);
|
||||
const { CustomizableUI } = ChromeUtils.import(
|
||||
"resource:///modules/CustomizableUI.jsm"
|
||||
);
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "ProfilerPopupBackground", function() {
|
||||
return ChromeUtils.import(
|
||||
"resource://devtools/client/performance-new/popup/background.jsm.js"
|
||||
);
|
||||
});
|
||||
|
||||
const $ = document.querySelector.bind(document);
|
||||
const $$ = document.querySelectorAll.bind(document);
|
||||
|
||||
function fileEnvVarPresent() {
|
||||
return Services.env.get("MOZ_LOG_FILE") || Services.env.get("NSPR_LOG_FILE");
|
||||
}
|
||||
|
||||
function moduleEnvVarPresent() {
|
||||
return Services.env.get("MOZ_LOG") || Services.env.get("NSPR_LOG");
|
||||
}
|
||||
|
||||
/**
|
||||
* All the information associated with a logging presets:
|
||||
* - `modules` is the list of log modules and option, the same that would have
|
||||
* been set as a MOZ_LOG environment variable
|
||||
* - l10nIds.label and l10nIds.description are the Ids of the strings that
|
||||
* appear in the dropdown selector, and a one-liner describing the purpose of
|
||||
* a particular logging preset
|
||||
* - profilerPreset is the name of a Firefox Profiler preset [1]. In general,
|
||||
* the profiler preset will have the correct set of threads for a particular
|
||||
* logging preset, so that all logging statements are recorded in the profile
|
||||
* as markers.
|
||||
*
|
||||
* [1]: The keys of https://searchfox.org/mozilla-central/rev/88f285c5163f73abd209d4f73cfa476660351982/devtools/client/performance-new/popup/background.jsm.js#119
|
||||
*/
|
||||
const gLoggingPresets = {
|
||||
networking: {
|
||||
modules:
|
||||
"timestamp,sync,nsHttp:5,cache2:5,nsSocketTransport:5,nsHostResolver:5",
|
||||
l10nIds: {
|
||||
label: "about-logging-preset-networking-label",
|
||||
description: "about-logging-preset-networking-description",
|
||||
},
|
||||
profilerPreset: "networking",
|
||||
},
|
||||
"media-playback": {
|
||||
modules:
|
||||
"cubeb:5,PlatformDecoderModule:5,AudioSink:5,AudioSinkWrapper:5,MediaDecoderStateMachine:4,MediaDecoder:4",
|
||||
l10nIds: {
|
||||
label: "about-logging-preset-media-playback-label",
|
||||
description: "about-logging-preset-media-playback-description",
|
||||
},
|
||||
profilerPreset: "media",
|
||||
},
|
||||
custom: {
|
||||
modules: "",
|
||||
l10nIds: {
|
||||
label: "about-logging-preset-custom-label",
|
||||
description: "about-logging-preset-custom-description",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const gLoggingSettings = {
|
||||
// Possible values: "profiler" and "file".
|
||||
loggingOutputType: "profiler",
|
||||
running: false,
|
||||
// If non-null, the profiler preset to use. If null, the preset selected in
|
||||
// the dropdown is going to be used. It is also possible to use a "custom"
|
||||
// preset and an explicit list of modules.
|
||||
loggingPreset: null,
|
||||
// If non-null, the profiler preset to use. If a logging preset is being used,
|
||||
// and this is null, the profiler preset associated to the logging preset is
|
||||
// going to be used. Otherwise, a generic profiler preset is going to be used
|
||||
// ("firefox-platform").
|
||||
profilerPreset: null,
|
||||
// If non-null, the threads that will be recorded by the Firefox Profiler. If
|
||||
// null, the threads from the profiler presets are going to be used.
|
||||
profilerThreads: null,
|
||||
};
|
||||
|
||||
// When the profiler has been started, this holds the promise the
|
||||
// Services.profiler.StartProfiler returns, to ensure the profiler has
|
||||
// effectively started.
|
||||
let gProfilerPromise = null;
|
||||
|
||||
function presets() {
|
||||
return gLoggingPresets;
|
||||
}
|
||||
|
||||
function settings() {
|
||||
return gLoggingSettings;
|
||||
}
|
||||
|
||||
function profilerPromise() {
|
||||
return gProfilerPromise;
|
||||
}
|
||||
|
||||
function populatePresets() {
|
||||
let dropdown = $("#logging-preset-dropdown");
|
||||
for (let presetName in gLoggingPresets) {
|
||||
let preset = gLoggingPresets[presetName];
|
||||
let option = document.createElement("option");
|
||||
document.l10n.setAttributes(option, preset.l10nIds.label);
|
||||
option.value = presetName;
|
||||
dropdown.appendChild(option);
|
||||
if (option.value === gLoggingSettings.loggingPreset) {
|
||||
option.setAttribute("selected", true);
|
||||
}
|
||||
}
|
||||
|
||||
function setPresetAndDescription(preset) {
|
||||
document.l10n.setAttributes(
|
||||
$("#logging-preset-description"),
|
||||
gLoggingPresets[preset].l10nIds.description
|
||||
);
|
||||
gLoggingSettings.loggingPreset = preset;
|
||||
}
|
||||
|
||||
dropdown.onchange = function() {
|
||||
// When switching to custom, leave the existing module list, to allow
|
||||
// editing.
|
||||
if (dropdown.value != "custom") {
|
||||
$("#log-modules").value = gLoggingPresets[dropdown.value].modules;
|
||||
}
|
||||
setPresetAndDescription(dropdown.value);
|
||||
setLogModules();
|
||||
Services.prefs.setCharPref("logging.config.preset", dropdown.value);
|
||||
};
|
||||
|
||||
$("#log-modules").value = gLoggingPresets[dropdown.value].modules;
|
||||
setPresetAndDescription(dropdown.value);
|
||||
// When changing the list switch to custom.
|
||||
$("#log-modules").oninput = e => {
|
||||
dropdown.value = "custom";
|
||||
};
|
||||
}
|
||||
|
||||
function updateLoggingOutputType(profilerOutputType) {
|
||||
gLoggingSettings.loggingOutputType = profilerOutputType;
|
||||
|
||||
if (gLoggingSettings.loggingOutputType === "profiler") {
|
||||
// hide options related to file output for clarity
|
||||
$("#log-file-configuration").hidden = true;
|
||||
} else if (gLoggingSettings.loggingOutputType === "file") {
|
||||
$("#log-file-configuration").hidden = false;
|
||||
$("#no-log-file").hidden = !!$("#current-log-file").innerText.length;
|
||||
}
|
||||
|
||||
Services.prefs.setCharPref(
|
||||
"logging.config.output_type",
|
||||
gLoggingSettings.loggingOutputType
|
||||
);
|
||||
}
|
||||
|
||||
function displayErrorMessage(error) {
|
||||
var err = $("#error");
|
||||
err.hidden = false;
|
||||
|
||||
var errorDescription = $("#error-description");
|
||||
document.l10n.setAttributes(errorDescription, error.l10nId, {
|
||||
k: error.key,
|
||||
v: error.value,
|
||||
});
|
||||
}
|
||||
|
||||
class ParseError extends Error {
|
||||
constructor(l10nId, key, value) {
|
||||
super(name);
|
||||
this.l10nId = l10nId;
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
}
|
||||
name = "ParseError";
|
||||
l10nId;
|
||||
key;
|
||||
value;
|
||||
}
|
||||
|
||||
function parseURL() {
|
||||
let options = new URL(document.location.href).searchParams;
|
||||
|
||||
if (!options) {
|
||||
return;
|
||||
}
|
||||
|
||||
let modulesOverriden = null,
|
||||
outputTypeOverriden = null,
|
||||
loggingPresetOverriden = null,
|
||||
threadsOverriden = null,
|
||||
profilerPresetOverriden = null;
|
||||
try {
|
||||
for (let [k, v] of options) {
|
||||
switch (k) {
|
||||
case "modules":
|
||||
case "module":
|
||||
modulesOverriden = v;
|
||||
break;
|
||||
case "output":
|
||||
case "output-type":
|
||||
if (v !== "profiler" && v !== "file") {
|
||||
throw new ParseError("about-logging-invalid-output", k, v);
|
||||
}
|
||||
outputTypeOverriden = v;
|
||||
break;
|
||||
case "preset":
|
||||
case "logging-preset":
|
||||
if (!Object.keys(gLoggingPresets).includes(v)) {
|
||||
throw new ParseError("about-logging-unknown-logging-preset", k, v);
|
||||
}
|
||||
loggingPresetOverriden = v;
|
||||
break;
|
||||
case "threads":
|
||||
case "thread":
|
||||
threadsOverriden = v;
|
||||
break;
|
||||
case "profiler-preset":
|
||||
if (!Object.keys(ProfilerPopupBackground.presets).includes(v)) {
|
||||
throw new Error(["about-logging-unknown-profiler-preset", k, v]);
|
||||
}
|
||||
profilerPresetOverriden = v;
|
||||
break;
|
||||
default:
|
||||
throw new ParseError("about-logging-unknown-option", k, v);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
displayErrorMessage(e);
|
||||
return;
|
||||
}
|
||||
|
||||
// Detect combinations that don't make sense
|
||||
if (
|
||||
(profilerPresetOverriden || threadsOverriden) &&
|
||||
outputTypeOverriden == "file"
|
||||
) {
|
||||
displayErrorMessage(
|
||||
new ParseError("about-logging-file-and-profiler-override")
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Configuration is deemed at least somewhat valid, override each setting in
|
||||
// turn
|
||||
let someElementsDisabled = false;
|
||||
|
||||
if (modulesOverriden || loggingPresetOverriden) {
|
||||
// Don't allow changing those if set by the URL
|
||||
let logModules = $("#log-modules");
|
||||
var dropdown = $("#logging-preset-dropdown");
|
||||
if (loggingPresetOverriden) {
|
||||
dropdown.value = loggingPresetOverriden;
|
||||
dropdown.onchange();
|
||||
}
|
||||
if (modulesOverriden) {
|
||||
logModules.value = modulesOverriden;
|
||||
dropdown.value = "custom";
|
||||
dropdown.onchange();
|
||||
dropdown.disabled = true;
|
||||
someElementsDisabled = true;
|
||||
}
|
||||
logModules.disabled = true;
|
||||
$("#set-log-modules-button").disabled = true;
|
||||
$("#logging-preset-dropdown").disabled = true;
|
||||
someElementsDisabled = true;
|
||||
setLogModules();
|
||||
updateLogModules();
|
||||
}
|
||||
if (outputTypeOverriden) {
|
||||
$$("input[type=radio]").forEach(e => {
|
||||
e.setAttribute("disabled", true);
|
||||
someElementsDisabled = true;
|
||||
e.checked = e.value == outputTypeOverriden;
|
||||
});
|
||||
}
|
||||
if (loggingPresetOverriden) {
|
||||
gLoggingSettings.loggingPreset = loggingPresetOverriden;
|
||||
}
|
||||
if (profilerPresetOverriden) {
|
||||
gLoggingSettings.profilerPreset = profilerPresetOverriden;
|
||||
}
|
||||
if (threadsOverriden) {
|
||||
gLoggingSettings.profilerThreads = threadsOverriden;
|
||||
}
|
||||
|
||||
$("#some-elements-unavailable").hidden = !someElementsDisabled;
|
||||
function col(element) {
|
||||
let col = document.createElement("td");
|
||||
let content = document.createTextNode(element);
|
||||
col.appendChild(content);
|
||||
return col;
|
||||
}
|
||||
|
||||
let gInited = false;
|
||||
@ -312,53 +25,22 @@ function init() {
|
||||
gInited = true;
|
||||
gDashboard.enableLogging = true;
|
||||
|
||||
populatePresets();
|
||||
parseURL();
|
||||
|
||||
let setLogButton = $("#set-log-file-button");
|
||||
let setLogButton = document.getElementById("set-log-file-button");
|
||||
setLogButton.addEventListener("click", setLogFile);
|
||||
|
||||
let setModulesButton = $("#set-log-modules-button");
|
||||
let setModulesButton = document.getElementById("set-log-modules-button");
|
||||
setModulesButton.addEventListener("click", setLogModules);
|
||||
|
||||
let toggleLoggingButton = $("#toggle-logging-button");
|
||||
toggleLoggingButton.addEventListener("click", startStopLogging);
|
||||
let startLoggingButton = document.getElementById("start-logging-button");
|
||||
startLoggingButton.addEventListener("click", startLogging);
|
||||
|
||||
$$("input[type=radio]").forEach(radio => {
|
||||
radio.onchange = e => {
|
||||
updateLoggingOutputType(e.target.value);
|
||||
};
|
||||
});
|
||||
|
||||
try {
|
||||
let loggingOutputType = Services.prefs.getCharPref(
|
||||
"logging.config.output_type"
|
||||
);
|
||||
if (loggingOutputType.length) {
|
||||
updateLoggingOutputType(loggingOutputType);
|
||||
}
|
||||
} catch {
|
||||
updateLoggingOutputType("profiler");
|
||||
}
|
||||
|
||||
try {
|
||||
let loggingPreset = Services.prefs.getCharPref("logging.config.preset");
|
||||
gLoggingSettings.loggingPreset = loggingPreset;
|
||||
} catch {}
|
||||
|
||||
try {
|
||||
let running = Services.prefs.getBoolPref("logging.config.running");
|
||||
gLoggingSettings.running = running;
|
||||
$("#toggle-logging-button").setAttribute(
|
||||
"data-l10n-id",
|
||||
`about-logging-${gLoggingSettings.running ? "stop" : "start"}-logging`
|
||||
);
|
||||
} catch {}
|
||||
let stopLoggingButton = document.getElementById("stop-logging-button");
|
||||
stopLoggingButton.addEventListener("click", stopLogging);
|
||||
|
||||
try {
|
||||
let file = gDirServ.getFile("TmpD", {});
|
||||
file.append("log.txt");
|
||||
$("#log-file").value = file.path;
|
||||
document.getElementById("log-file").value = file.path;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
@ -371,23 +53,20 @@ function init() {
|
||||
|
||||
// If we can't set the file and the modules at runtime,
|
||||
// the start and stop buttons wouldn't really do anything.
|
||||
if (
|
||||
(setLogButton.disabled || setModulesButton.disabled) &&
|
||||
moduleEnvVarPresent()
|
||||
) {
|
||||
$("#buttons-disabled").hidden = false;
|
||||
toggleLoggingButton.disabled = true;
|
||||
if (setLogButton.disabled && setModulesButton.disabled) {
|
||||
startLoggingButton.disabled = true;
|
||||
stopLoggingButton.disabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
function updateLogFile(file) {
|
||||
function updateLogFile() {
|
||||
let logPath = "";
|
||||
|
||||
// Try to get the environment variable for the log file
|
||||
logPath =
|
||||
Services.env.get("MOZ_LOG_FILE") || Services.env.get("NSPR_LOG_FILE");
|
||||
let currentLogFile = $("#current-log-file");
|
||||
let setLogFileButton = $("#set-log-file-button");
|
||||
let currentLogFile = document.getElementById("current-log-file");
|
||||
let setLogFileButton = document.getElementById("set-log-file-button");
|
||||
|
||||
// If the log file was set from an env var, we disable the ability to set it
|
||||
// at runtime.
|
||||
@ -397,21 +76,19 @@ function updateLogFile(file) {
|
||||
} else if (gDashboard.getLogPath() != ".moz_log") {
|
||||
// There may be a value set by a pref.
|
||||
currentLogFile.innerText = gDashboard.getLogPath();
|
||||
} else if (file !== undefined) {
|
||||
currentLogFile.innerText = file;
|
||||
} else {
|
||||
try {
|
||||
let file = gDirServ.getFile("TmpD", {});
|
||||
file.append("log.txt");
|
||||
$("#log-file").value = file.path;
|
||||
document.getElementById("log-file").value = file.path;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
// Fall back to the temp dir
|
||||
currentLogFile.innerText = $("#log-file").value;
|
||||
currentLogFile.innerText = document.getElementById("log-file").value;
|
||||
}
|
||||
|
||||
let openLogFileButton = $("#open-log-file-button");
|
||||
let openLogFileButton = document.getElementById("open-log-file-button");
|
||||
openLogFileButton.disabled = true;
|
||||
|
||||
if (currentLogFile.innerText.length) {
|
||||
@ -425,8 +102,6 @@ function updateLogFile(file) {
|
||||
};
|
||||
}
|
||||
}
|
||||
$("#no-log-file").hidden = !!currentLogFile.innerText.length;
|
||||
$("#current-log-file").hidden = !currentLogFile.innerText.length;
|
||||
}
|
||||
|
||||
function updateLogModules() {
|
||||
@ -435,8 +110,8 @@ function updateLogModules() {
|
||||
Services.env.get("MOZ_LOG") ||
|
||||
Services.env.get("MOZ_LOG_MODULES") ||
|
||||
Services.env.get("NSPR_LOG_MODULES");
|
||||
let currentLogModules = $("#current-log-modules");
|
||||
let setLogModulesButton = $("#set-log-modules-button");
|
||||
let currentLogModules = document.getElementById("current-log-modules");
|
||||
let setLogModulesButton = document.getElementById("set-log-modules-button");
|
||||
if (logModules.length) {
|
||||
currentLogModules.innerText = logModules;
|
||||
// If the log modules are set by an environment variable at startup, do not
|
||||
@ -477,27 +152,19 @@ function updateLogModules() {
|
||||
}
|
||||
}
|
||||
|
||||
if (activeLogModules.length !== 0) {
|
||||
currentLogModules.innerText = activeLogModules.join(",");
|
||||
currentLogModules.hidden = false;
|
||||
$("#no-log-modules").hidden = true;
|
||||
} else {
|
||||
currentLogModules.innerText = "";
|
||||
currentLogModules.hidden = true;
|
||||
$("#no-log-modules").hidden = false;
|
||||
}
|
||||
currentLogModules.innerText = activeLogModules.join(",");
|
||||
}
|
||||
}
|
||||
|
||||
function setLogFile() {
|
||||
let setLogButton = $("#set-log-file-button");
|
||||
let setLogButton = document.getElementById("set-log-file-button");
|
||||
if (setLogButton.disabled) {
|
||||
// There's no point trying since it wouldn't work anyway.
|
||||
return;
|
||||
}
|
||||
let logFile = $("#log-file").value.trim();
|
||||
let logFile = document.getElementById("log-file").value.trim();
|
||||
Services.prefs.setCharPref("logging.config.LOG_FILE", logFile);
|
||||
updateLogFile(logFile);
|
||||
updateLogFile();
|
||||
}
|
||||
|
||||
function clearLogModules() {
|
||||
@ -514,149 +181,50 @@ function clearLogModules() {
|
||||
}
|
||||
|
||||
function setLogModules() {
|
||||
if (moduleEnvVarPresent()) {
|
||||
let setLogModulesButton = document.getElementById("set-log-modules-button");
|
||||
if (setLogModulesButton.disabled) {
|
||||
// The modules were set via env var, so we shouldn't try to change them.
|
||||
return;
|
||||
}
|
||||
|
||||
let modules = $("#log-modules").value.trim();
|
||||
let modules = document.getElementById("log-modules").value.trim();
|
||||
|
||||
// Clear previously set log modules.
|
||||
clearLogModules();
|
||||
|
||||
if (modules.length !== 0) {
|
||||
let logModules = modules.split(",");
|
||||
for (let module of logModules) {
|
||||
if (module == "timestamp") {
|
||||
Services.prefs.setBoolPref("logging.config.add_timestamp", true);
|
||||
} else if (module == "rotate") {
|
||||
// XXX: rotate is not yet supported.
|
||||
} else if (module == "append") {
|
||||
// XXX: append is not yet supported.
|
||||
} else if (module == "sync") {
|
||||
Services.prefs.setBoolPref("logging.config.sync", true);
|
||||
} else if (module == "profilerstacks") {
|
||||
Services.prefs.setBoolPref("logging.config.profilerstacks", true);
|
||||
} else {
|
||||
let lastColon = module.lastIndexOf(":");
|
||||
let key = module.slice(0, lastColon);
|
||||
let value = parseInt(module.slice(lastColon + 1), 10);
|
||||
Services.prefs.setIntPref(`logging.${key}`, value);
|
||||
}
|
||||
let logModules = modules.split(",");
|
||||
for (let module of logModules) {
|
||||
if (module == "timestamp") {
|
||||
Services.prefs.setBoolPref("logging.config.add_timestamp", true);
|
||||
} else if (module == "rotate") {
|
||||
// XXX: rotate is not yet supported.
|
||||
} else if (module == "append") {
|
||||
// XXX: append is not yet supported.
|
||||
} else if (module == "sync") {
|
||||
Services.prefs.setBoolPref("logging.config.sync", true);
|
||||
} else if (module == "profilerstacks") {
|
||||
Services.prefs.setBoolPref("logging.config.profilerstacks", true);
|
||||
} else {
|
||||
let lastColon = module.lastIndexOf(":");
|
||||
let key = module.slice(0, lastColon);
|
||||
let value = parseInt(module.slice(lastColon + 1), 10);
|
||||
Services.prefs.setIntPref(`logging.${key}`, value);
|
||||
}
|
||||
}
|
||||
|
||||
updateLogModules();
|
||||
}
|
||||
|
||||
function isLogging() {
|
||||
try {
|
||||
return Services.prefs.getBoolPref("logging.config.running");
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function startStopLogging() {
|
||||
if (isLogging()) {
|
||||
document.l10n.setAttributes(
|
||||
$("#toggle-logging-button"),
|
||||
"about-logging-start-logging"
|
||||
);
|
||||
stopLogging();
|
||||
} else {
|
||||
document.l10n.setAttributes(
|
||||
$("#toggle-logging-button"),
|
||||
"about-logging-stop-logging"
|
||||
);
|
||||
startLogging();
|
||||
}
|
||||
}
|
||||
|
||||
function startLogging() {
|
||||
setLogFile();
|
||||
setLogModules();
|
||||
if (gLoggingSettings.loggingOutputType === "profiler") {
|
||||
const pageContext = "aboutlogging";
|
||||
const supportedFeatures = Services.profiler.GetFeatures();
|
||||
if (gLoggingSettings.loggingPreset != "custom") {
|
||||
// Change the preset before starting the profiler, so that the
|
||||
// underlying profiler code picks up the right configuration.
|
||||
const profilerPreset =
|
||||
gLoggingPresets[gLoggingSettings.loggingPreset].profilerPreset;
|
||||
ProfilerPopupBackground.changePreset(
|
||||
"aboutlogging",
|
||||
profilerPreset,
|
||||
supportedFeatures
|
||||
);
|
||||
} else {
|
||||
// a baseline set of threads, and possibly others, overriden by the URL
|
||||
ProfilerPopupBackground.changePreset(
|
||||
"aboutlogging",
|
||||
"firefox-platform",
|
||||
supportedFeatures
|
||||
);
|
||||
}
|
||||
let {
|
||||
entries,
|
||||
interval,
|
||||
features,
|
||||
threads,
|
||||
duration,
|
||||
} = ProfilerPopupBackground.getRecordingSettings(
|
||||
pageContext,
|
||||
Services.profiler.GetFeatures()
|
||||
);
|
||||
|
||||
if (gLoggingSettings.profilerThreads) {
|
||||
threads.push(...gLoggingSettings.profilerThreads.split(","));
|
||||
// Small hack: if cubeb is being logged, it's almost always necessary (and
|
||||
// never harmful) to enable audio callback tracing, otherwise, no log
|
||||
// statements will be recorded from real-time threads.
|
||||
if (gLoggingSettings.profilerThreads.includes("cubeb")) {
|
||||
features.push("audiocallbacktracing");
|
||||
}
|
||||
}
|
||||
const win = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
const windowid = win?.gBrowser?.selectedBrowser?.browsingContext?.browserId;
|
||||
|
||||
// Force displaying the profiler button in the navbar if not preset, so
|
||||
// that there is a visual indication profiling is in progress.
|
||||
if (!ProfilerMenuButton.isInNavbar()) {
|
||||
// Ensure the widget is enabled.
|
||||
Services.prefs.setBoolPref(
|
||||
"devtools.performance.popup.feature-flag",
|
||||
true
|
||||
);
|
||||
// Enable the profiler menu button.
|
||||
ProfilerMenuButton.addToNavbar();
|
||||
// Dispatch the change event manually, so that the shortcuts will also be
|
||||
// added.
|
||||
CustomizableUI.dispatchToolboxEvent("customizationchange");
|
||||
}
|
||||
|
||||
gProfilerPromise = Services.profiler.StartProfiler(
|
||||
entries,
|
||||
interval,
|
||||
features,
|
||||
threads,
|
||||
windowid,
|
||||
duration
|
||||
);
|
||||
} else {
|
||||
setLogFile();
|
||||
}
|
||||
Services.prefs.setBoolPref("logging.config.running", true);
|
||||
}
|
||||
|
||||
async function stopLogging() {
|
||||
if (gLoggingSettings.loggingOutputType === "profiler") {
|
||||
await ProfilerPopupBackground.captureProfile("aboutlogging");
|
||||
} else {
|
||||
Services.prefs.clearUserPref("logging.config.LOG_FILE");
|
||||
updateLogFile();
|
||||
}
|
||||
Services.prefs.setBoolPref("logging.config.running", false);
|
||||
function stopLogging() {
|
||||
clearLogModules();
|
||||
// clear the log file as well
|
||||
Services.prefs.clearUserPref("logging.config.LOG_FILE");
|
||||
updateLogFile();
|
||||
}
|
||||
|
||||
// We use the pageshow event instead of onload. This is needed because sometimes
|
||||
|
@ -152,6 +152,3 @@ skip-if =
|
||||
debug # Bug 1388959
|
||||
[browser_about_networking.js]
|
||||
skip-if = socketprocess_networking
|
||||
[browser_about_logging.js]
|
||||
skip-if =
|
||||
tsan # Bug 1804081
|
||||
|
@ -1,395 +0,0 @@
|
||||
const PAGE = "about:logging";
|
||||
|
||||
function clearLoggingPrefs() {
|
||||
for (let pref of Services.prefs.getBranch("logging.").getChildList("")) {
|
||||
info(`Clearing: ${pref}`);
|
||||
Services.prefs.clearUserPref(pref);
|
||||
}
|
||||
}
|
||||
|
||||
// Before running, save any MOZ_LOG environment variable that might be preset,
|
||||
// and restore them at the end of this test.
|
||||
add_setup(async function saveRestoreLogModules() {
|
||||
let savedLogModules = Services.env.get("MOZ_LOG");
|
||||
Services.env.set("MOZ_LOG", "");
|
||||
registerCleanupFunction(() => {
|
||||
info(" -- Restoring log modules: " + savedLogModules);
|
||||
clearLoggingPrefs();
|
||||
for (let pref of savedLogModules.split(",")) {
|
||||
let [logModule, level] = pref.split(":");
|
||||
Services.prefs.setIntPref("logging." + logModule, parseInt(level));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Test that some UI elements are disabled in some cirumstances.
|
||||
add_task(async function testElementsDisabled() {
|
||||
// This test needs a MOZ_LOG env var set.
|
||||
Services.env.set("MOZ_LOG", "example:4");
|
||||
await BrowserTestUtils.withNewTab(PAGE, async browser => {
|
||||
await SpecialPowers.spawn(browser, [], async () => {
|
||||
let $ = content.document.querySelector.bind(content.document);
|
||||
Assert.ok(
|
||||
$("#set-log-modules-button").disabled,
|
||||
"Because a MOZ_LOG env var is set by the harness, it should be impossible to set new log modules."
|
||||
);
|
||||
});
|
||||
});
|
||||
Services.env.set("MOZ_LOG", "");
|
||||
|
||||
await BrowserTestUtils.withNewTab(
|
||||
PAGE + "?modules=example:5&output=profiler",
|
||||
async browser => {
|
||||
await SpecialPowers.spawn(browser, [], async () => {
|
||||
let $ = content.document.querySelector.bind(content.document);
|
||||
Assert.ok(
|
||||
!$("#some-elements-unavailable").hidden,
|
||||
"If a log modules are configured via URL params, a warning should be visible."
|
||||
);
|
||||
Assert.ok(
|
||||
$("#set-log-modules-button").disabled,
|
||||
"If a log modules are configured via URL params, some in-page elements should be disabled (button)."
|
||||
);
|
||||
Assert.ok(
|
||||
$("#log-modules").disabled,
|
||||
"If a log modules are configured via URL params, some in-page elements should be disabled (input)."
|
||||
);
|
||||
Assert.ok(
|
||||
$("#logging-preset-dropdown").disabled,
|
||||
"If a log modules are configured via URL params, some in-page elements should be disabled (dropdown)."
|
||||
);
|
||||
Assert.ok(
|
||||
$("#radio-logging-profiler").disabled &&
|
||||
$("#radio-logging-file").disabled,
|
||||
"If the ouptut type is configured via URL param, the radio buttons should be disabled."
|
||||
);
|
||||
});
|
||||
}
|
||||
);
|
||||
await BrowserTestUtils.withNewTab(
|
||||
PAGE + "?preset=media-playback",
|
||||
async browser => {
|
||||
await SpecialPowers.spawn(browser, [], async () => {
|
||||
let $ = content.document.querySelector.bind(content.document);
|
||||
Assert.ok(
|
||||
!$("#some-elements-unavailable").hidden,
|
||||
"If a preset is selected via URL, a warning should be displayed."
|
||||
);
|
||||
Assert.ok(
|
||||
$("#set-log-modules-button").disabled,
|
||||
"If a preset is selected via URL, some in-page elements should be disabled (button)."
|
||||
);
|
||||
Assert.ok(
|
||||
$("#log-modules").disabled,
|
||||
"If a preset is selected via URL, some in-page elements should be disabled (input)."
|
||||
);
|
||||
Assert.ok(
|
||||
$("#logging-preset-dropdown").disabled,
|
||||
"If a preset is selected via URL, some in-page elements should be disabled (dropdown)."
|
||||
);
|
||||
});
|
||||
}
|
||||
);
|
||||
clearLoggingPrefs();
|
||||
});
|
||||
|
||||
// Test URL parameters
|
||||
const modulesInURL = "example:4,otherexample:5";
|
||||
const presetInURL = "media-playback";
|
||||
const threadsInURL = "example,otherexample";
|
||||
const profilerPresetInURL = "media";
|
||||
add_task(async function testURLParameters() {
|
||||
await BrowserTestUtils.withNewTab(
|
||||
PAGE + "?modules=" + modulesInURL,
|
||||
async browser => {
|
||||
await SpecialPowers.spawn(browser, [modulesInURL], async modulesInURL => {
|
||||
let $ = content.document.querySelector.bind(content.document);
|
||||
Assert.ok(
|
||||
!$("#some-elements-unavailable").hidden,
|
||||
"If modules are selected via URL, a warning should be displayed."
|
||||
);
|
||||
var inPageSorted = $("#current-log-modules")
|
||||
.innerText.split(",")
|
||||
.sort()
|
||||
.join(",");
|
||||
var inURLSorted = modulesInURL
|
||||
.split(",")
|
||||
.sort()
|
||||
.join(",");
|
||||
Assert.equal(
|
||||
inPageSorted,
|
||||
inURLSorted,
|
||||
"When selecting modules via URL params, the same modules are reflected in the page."
|
||||
);
|
||||
});
|
||||
}
|
||||
);
|
||||
await BrowserTestUtils.withNewTab(
|
||||
{
|
||||
gBrowser,
|
||||
url: PAGE + "?preset=" + presetInURL,
|
||||
},
|
||||
async browser => {
|
||||
await SpecialPowers.spawn(browser, [presetInURL], async presetInURL => {
|
||||
let $ = content.document.querySelector.bind(content.document);
|
||||
Assert.ok(
|
||||
!$("#some-elements-unavailable").hidden,
|
||||
"If a preset is selected via URL, a warning should be displayed."
|
||||
);
|
||||
var inPageSorted = $("#current-log-modules")
|
||||
.innerText.split(",")
|
||||
.sort()
|
||||
.join(",");
|
||||
var presetSorted = content
|
||||
.presets()
|
||||
[presetInURL].modules.split(",")
|
||||
.sort()
|
||||
.join(",");
|
||||
Assert.equal(
|
||||
inPageSorted,
|
||||
presetSorted,
|
||||
"When selecting a preset via URL params, the correct log modules are reflected in the page."
|
||||
);
|
||||
});
|
||||
}
|
||||
);
|
||||
await BrowserTestUtils.withNewTab(
|
||||
{
|
||||
gBrowser,
|
||||
url: PAGE + "?profiler-preset=" + profilerPresetInURL,
|
||||
},
|
||||
async browser => {
|
||||
await SpecialPowers.spawn(browser, [profilerPresetInURL], async inURL => {
|
||||
let $ = content.document.querySelector.bind(content.document);
|
||||
// Threads override doesn't have a UI element, the warning shouldn't
|
||||
// be displayed.
|
||||
Assert.ok(
|
||||
$("#some-elements-unavailable").hidden,
|
||||
"When overriding the profiler preset, no warning is displayed on the page."
|
||||
);
|
||||
var inSettings = content.settings().profilerPreset;
|
||||
Assert.equal(
|
||||
inSettings,
|
||||
inURL,
|
||||
"When overriding the profiler preset via URL param, the correct preset is set in the logging manager settings."
|
||||
);
|
||||
});
|
||||
}
|
||||
);
|
||||
await BrowserTestUtils.withNewTab(
|
||||
{
|
||||
gBrowser,
|
||||
url: PAGE + "?invalid-param",
|
||||
},
|
||||
async browser => {
|
||||
await SpecialPowers.spawn(browser, [profilerPresetInURL], async inURL => {
|
||||
let $ = content.document.querySelector.bind(content.document);
|
||||
Assert.ok(
|
||||
!$("#error").hidden,
|
||||
"When an invalid URL param is passed in, the page displays a warning."
|
||||
);
|
||||
});
|
||||
}
|
||||
);
|
||||
clearLoggingPrefs();
|
||||
});
|
||||
|
||||
// Test various things related to presets: that it's populated correctly, that
|
||||
// setting presets work in terms of UI, but also that it sets the logging.*
|
||||
// prefs correctly.
|
||||
add_task(async function testAboutLoggingPresets() {
|
||||
await BrowserTestUtils.withNewTab(PAGE, async browser => {
|
||||
await SpecialPowers.spawn(browser, [], async () => {
|
||||
let $ = content.document.querySelector.bind(content.document);
|
||||
let presetsDropdown = $("#logging-preset-dropdown");
|
||||
Assert.equal(
|
||||
Object.keys(content.presets()).length,
|
||||
presetsDropdown.childNodes.length,
|
||||
"Presets populated."
|
||||
);
|
||||
|
||||
Assert.equal(presetsDropdown.value, "networking");
|
||||
$("#set-log-modules-button").click();
|
||||
Assert.ok(
|
||||
$("#no-log-modules").hidden && !$("#current-log-modules").hidden,
|
||||
"When log modules are set, they are visible."
|
||||
);
|
||||
var lengthModuleListNetworking = $("#log-modules").value.length;
|
||||
var lengthCurrentModuleListNetworking = $("#current-log-modules")
|
||||
.innerText.length;
|
||||
Assert.notEqual(
|
||||
lengthModuleListNetworking,
|
||||
0,
|
||||
"When setting a profiler preset, the module string is non-empty (input)."
|
||||
);
|
||||
Assert.notEqual(
|
||||
lengthCurrentModuleListNetworking,
|
||||
0,
|
||||
"When setting a profiler preset, the module string is non-empty (selected modules)."
|
||||
);
|
||||
|
||||
// Change preset
|
||||
presetsDropdown.value = "media-playback";
|
||||
presetsDropdown.dispatchEvent(new content.Event("change"));
|
||||
|
||||
// Check the following after "onchange".
|
||||
// eslint-disable-next-line mozilla/no-arbitrary-setTimeout
|
||||
await new Promise(resolve => content.setTimeout(resolve, 0));
|
||||
|
||||
Assert.equal(
|
||||
presetsDropdown.value,
|
||||
"media-playback",
|
||||
"Selecting another preset is reflected in the page"
|
||||
);
|
||||
$("#set-log-modules-button").click();
|
||||
Assert.ok(
|
||||
$("#no-log-modules").hidden && !$("#current-log-modules").hidden,
|
||||
"When other log modules are set, they are still visible"
|
||||
);
|
||||
Assert.notEqual(
|
||||
$("#log-modules").value.length,
|
||||
0,
|
||||
"When setting a profiler preset, the module string is non-empty (input)."
|
||||
);
|
||||
Assert.notEqual(
|
||||
$("#current-log-modules").innerText.length,
|
||||
0,
|
||||
"When setting a profiler preset, the module string is non-empty (selected modules)."
|
||||
);
|
||||
Assert.notEqual(
|
||||
$("#log-modules").value.length,
|
||||
lengthModuleListNetworking,
|
||||
"When setting another profiler preset, the module string changes (input)."
|
||||
);
|
||||
let currentLogModulesString = $("#current-log-modules").innerText;
|
||||
Assert.notEqual(
|
||||
currentLogModulesString.length,
|
||||
lengthCurrentModuleListNetworking,
|
||||
|
||||
"When setting another profiler preset, the module string changes (selected modules)."
|
||||
);
|
||||
|
||||
// After setting some log modules via the preset dropdown, verify
|
||||
// that they have been reflected to logging.* preferences.
|
||||
var activeLogModules = [];
|
||||
let children = Services.prefs.getBranch("logging.").getChildList("");
|
||||
for (let pref of children) {
|
||||
if (pref.startsWith("config.")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
let value = Services.prefs.getIntPref(`logging.${pref}`);
|
||||
activeLogModules.push(`${pref}:${value}`);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
let mod;
|
||||
while ((mod = activeLogModules.pop())) {
|
||||
Assert.ok(
|
||||
currentLogModulesString.includes(mod),
|
||||
`${mod} was effectively set`
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
clearLoggingPrefs();
|
||||
});
|
||||
|
||||
// Here we test that starting and stopping log collection to the Firefox
|
||||
// Profiler opens a new tab. We don't actually check the content of the profile.
|
||||
add_task(async function testProfilerOpens() {
|
||||
await BrowserTestUtils.withNewTab(PAGE, async browser => {
|
||||
let profilerOpenedPromise = BrowserTestUtils.waitForNewTab(
|
||||
gBrowser,
|
||||
"https://example.com/",
|
||||
false
|
||||
);
|
||||
SpecialPowers.spawn(browser, [], async savedLogModules => {
|
||||
let $ = content.document.querySelector.bind(content.document);
|
||||
// Override the URL the profiler uses to avoid hitting external
|
||||
// resources (and crash).
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [
|
||||
["devtools.performance.recording.ui-base-url", "https://example.com"],
|
||||
["devtools.performance.recording.ui-base-url-path", "/"],
|
||||
],
|
||||
});
|
||||
$("#radio-logging-file").click();
|
||||
$("#radio-logging-profiler").click();
|
||||
$("#logging-preset-dropdown").value = "networking";
|
||||
$("#logging-preset-dropdown").dispatchEvent(new content.Event("change"));
|
||||
$("#set-log-modules-button").click();
|
||||
$("#toggle-logging-button").click();
|
||||
// Wait for the profiler to start. This can be very slow.
|
||||
await content.profilerPromise();
|
||||
// Wait for some time for good measure while the profiler collects some
|
||||
// data. We don't really care about the data itself.
|
||||
// eslint-disable-next-line mozilla/no-arbitrary-setTimeout
|
||||
await new Promise(resolve => content.setTimeout(resolve, 1000));
|
||||
$("#toggle-logging-button").click();
|
||||
});
|
||||
let tab = await profilerOpenedPromise;
|
||||
Assert.ok(true, "Profiler tab opened after profiling");
|
||||
await BrowserTestUtils.removeTab(tab);
|
||||
});
|
||||
clearLoggingPrefs();
|
||||
});
|
||||
|
||||
// Same test, outputing to a file, with network logging, while opening and
|
||||
// closing a tab. We only check that the file exists and has a non-zero size.
|
||||
add_task(async function testLogFileFound() {
|
||||
await BrowserTestUtils.withNewTab(PAGE, async browser => {
|
||||
await SpecialPowers.spawn(browser, [], async () => {
|
||||
// Clear any previous log file.
|
||||
let $ = content.document.querySelector.bind(content.document);
|
||||
$("#radio-logging-file").click();
|
||||
$("#log-file").value = "";
|
||||
$("#log-file").dispatchEvent(new content.Event("change"));
|
||||
$("#set-log-file-button").click();
|
||||
|
||||
Assert.ok(
|
||||
!$("#no-log-file").hidden,
|
||||
"When a log file hasn't been set, it's indicated as such."
|
||||
);
|
||||
});
|
||||
});
|
||||
await BrowserTestUtils.withNewTab(PAGE, async browser => {
|
||||
let logPath = await SpecialPowers.spawn(browser, [], async () => {
|
||||
let $ = content.document.querySelector.bind(content.document);
|
||||
$("#radio-logging-file").click();
|
||||
// Set the log file (use the default path)
|
||||
$("#set-log-file-button").click();
|
||||
var logPath = $("#current-log-file").innerText;
|
||||
// Set log modules for networking
|
||||
$("#logging-preset-dropdown").value = "networking";
|
||||
$("#logging-preset-dropdown").dispatchEvent(new content.Event("change"));
|
||||
$("#set-log-modules-button").click();
|
||||
return logPath;
|
||||
});
|
||||
|
||||
// No need to start or stop logging when logging to a file. Just open
|
||||
// a tab, any URL will do. Wait for this tab to be loaded so we're sure
|
||||
// something (anything) has happened in necko.
|
||||
let tab = await BrowserTestUtils.openNewForegroundTab(
|
||||
gBrowser,
|
||||
"https://example.com",
|
||||
true /* waitForLoad */
|
||||
);
|
||||
await BrowserTestUtils.removeTab(tab);
|
||||
let logDirectory = PathUtils.parent(logPath);
|
||||
let logBasename = PathUtils.filename(logPath);
|
||||
let entries = await IOUtils.getChildren(logDirectory);
|
||||
let foundNonEmptyLogFile = false;
|
||||
for (let entry of entries) {
|
||||
if (entry.includes(logBasename)) {
|
||||
info("Log file found: " + entry);
|
||||
let fileinfo = await IOUtils.stat(entry);
|
||||
foundNonEmptyLogFile |= fileinfo.size > 0;
|
||||
}
|
||||
}
|
||||
Assert.ok(foundNonEmptyLogFile, "Found at least one non-empty log file.");
|
||||
});
|
||||
clearLoggingPrefs();
|
||||
});
|
@ -2,26 +2,10 @@
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
## The following feature name must be treated as a brand.
|
||||
##
|
||||
## They cannot be:
|
||||
## - Transliterated.
|
||||
## - Translated.
|
||||
##
|
||||
## Declension should be avoided where possible, leaving the original
|
||||
## brand unaltered in prominent UI positions.
|
||||
##
|
||||
## For further details, consult:
|
||||
## https://mozilla-l10n.github.io/styleguides/mozilla_general/#brands-copyright-and-trademark
|
||||
|
||||
-profiler-brand-name = Firefox Profiler
|
||||
|
||||
# This is the title of the page
|
||||
about-logging-title = About Logging
|
||||
about-logging-page-title = Logging manager
|
||||
about-logging-current-log-file = Current log file:
|
||||
about-logging-new-log-file = New log file:
|
||||
about-logging-currently-enabled-log-modules = Currently enabled log modules:
|
||||
about-logging-current-log-file = Current Log File:
|
||||
about-logging-current-log-modules = Current Log Modules:
|
||||
about-logging-log-tutorial =
|
||||
See <a data-l10n-name="logging">HTTP Logging</a>
|
||||
for instructions on how to use this tool.
|
||||
@ -31,39 +15,3 @@ about-logging-set-log-file = Set Log File
|
||||
about-logging-set-log-modules = Set Log Modules
|
||||
about-logging-start-logging = Start Logging
|
||||
about-logging-stop-logging = Stop Logging
|
||||
about-logging-buttons-disabled = Logging configured via environment variables, dynamic configuration unavailable.
|
||||
about-logging-some-elements-disabled = Logging configured via URL, some configuration options are unavailable
|
||||
about-logging-info = Info:
|
||||
about-logging-log-modules-selection = Log module selection
|
||||
about-logging-new-log-modules = New log modules:
|
||||
about-logging-logging-output-selection = Logging output
|
||||
about-logging-logging-to-file = Logging to a file
|
||||
about-logging-logging-to-profiler = Logging to the { -profiler-brand-name }
|
||||
about-logging-no-log-modules = None
|
||||
about-logging-no-log-file = None
|
||||
about-logging-logging-preset-selector-text = Logging preset:
|
||||
|
||||
## Logging presets
|
||||
|
||||
about-logging-preset-networking-label = Networking
|
||||
about-logging-preset-networking-description = Log modules to diagnose networking issues
|
||||
about-logging-preset-media-playback-label = Media playback
|
||||
about-logging-preset-media-playback-description = Log modules to diagnose media playback issues (not video-conferencing issues)
|
||||
about-logging-preset-custom-label = Custom
|
||||
about-logging-preset-custom-description = Log modules manually selected
|
||||
|
||||
# Error handling
|
||||
about-logging-error = Error:
|
||||
|
||||
## Variables:
|
||||
## $k (String) - Variable name
|
||||
## $v (String) - Variable value
|
||||
|
||||
about-logging-invalid-output = Invalid value “{ $v }“ for key “{ $k }“
|
||||
about-logging-unknown-logging-preset = Unknown logging preset “{ $v }“
|
||||
about-logging-unknown-profiler-preset = Unknown profiler preset “{ $v }“
|
||||
about-logging-unknown-option = Unknown about:logging option “{ $k }“
|
||||
about-logging-configuration-url-ignored = Configuration URL ignored
|
||||
about-logging-file-and-profiler-override = Can’t force file output and override profiler options at the same time
|
||||
|
||||
about-logging-configured-via-url = Option configured via URL
|
||||
|
@ -1,83 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
@import url("chrome://global/skin/in-content/common.css");
|
||||
|
||||
html {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/** Content area **/
|
||||
|
||||
.main-content {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
#logging {
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
div.page-section {
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
div.page-section > div {
|
||||
padding-inline-start: 0.5em;
|
||||
padding-bottom: 2em;
|
||||
}
|
||||
|
||||
div.page-section > div.radio-entry {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
#current-log-modules,
|
||||
#no-log-modules {
|
||||
font-family: monospace;
|
||||
padding-inline-start: 8px;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
#current-log-file,
|
||||
#no-log-file {
|
||||
font-family: monospace;
|
||||
padding-inline-start: 8px;
|
||||
}
|
||||
|
||||
#logging-preset-description {
|
||||
padding-inline-start: 8px;
|
||||
}
|
||||
|
||||
input[type=text] {
|
||||
width: 100%;
|
||||
font-family: monospace;
|
||||
padding-inline-start: 0;
|
||||
}
|
||||
|
||||
input[type=radio] {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.info-box {
|
||||
width: 100%;
|
||||
padding: 0.3em 1em;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.info-box-label {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
#error {
|
||||
background-color: rgba(240, 40, 40, 0.5);
|
||||
border: 1px solid rgba(240, 40, 40, 0.6);
|
||||
}
|
||||
|
||||
#some-elements-unavailable {
|
||||
background-color: var(--in-content-box-info-background);
|
||||
border-color: var(--in-content-box-border-color);
|
||||
}
|
@ -16,7 +16,6 @@
|
||||
skin/classic/global/aboutMemory.css (../../shared/aboutMemory.css)
|
||||
skin/classic/global/aboutNetError.css (../../shared/aboutNetError.css)
|
||||
skin/classic/global/aboutNetworking.css (../../shared/aboutNetworking.css)
|
||||
skin/classic/global/aboutLogging.css (../../shared/aboutLogging.css)
|
||||
skin/classic/global/aboutReader.css (../../shared/aboutReader.css)
|
||||
skin/classic/global/aboutReaderPocket.css (../../shared/aboutReaderPocket.css)
|
||||
skin/classic/global/aboutRights.css (../../shared/aboutRights.css)
|
||||
|
@ -1,352 +1,7 @@
|
||||
Gecko Logging
|
||||
=============
|
||||
|
||||
A minimal C++ logging framework is provided for use in core Gecko code. It is
|
||||
enabled for all builds and is thread-safe.
|
||||
|
||||
This page covers enabling logging for particular logging module, configuring
|
||||
the logging output, and how to use the logging facilities in native code.
|
||||
|
||||
Enabling and configuring logging
|
||||
++++++++++++++++++++++++++++++++
|
||||
|
||||
Caveat: sandboxing when logging to a file
|
||||
-----------------------------------------
|
||||
|
||||
A sandboxed content process cannot write to ``stderr`` or any file. The easiest
|
||||
way to log these processes is to disable the content sandbox by setting the
|
||||
preference ``security.sandbox.content.level`` to ``0``, or setting the environment
|
||||
variable ``MOZ_DISABLE_CONTENT_SANDBOX`` to ``1``.
|
||||
|
||||
On Windows, you can still see child process messages by using DOS (not the
|
||||
``MOZ_LOG_FILE`` variable defined below) to redirect output to a file. For
|
||||
example: ``MOZ_LOG="CameraChild:5" mach run >& my_log_file.txt`` will include
|
||||
debug messages from the camera's child actor that lives in a (sandboxed) content
|
||||
process.
|
||||
|
||||
Logging to the Firefox Profiler
|
||||
-------------------------------
|
||||
|
||||
When a log statement is logged on a thread and the `Firefox Profiler
|
||||
<https://profiler.firefox.com>`_ is profiling that thread, the log statements is
|
||||
recorded as a profiler marker.
|
||||
|
||||
This allows getting logs alongside profiler markers and lots of performance
|
||||
and contextual informations, in a way that doesn't require disabling the
|
||||
sandbox, and works accross all processes.
|
||||
|
||||
The profile can be downloaded and shared e.g. via Bugzilla or email, or
|
||||
uploaded, and the logging statements will be visible either in the marker chart
|
||||
or the marker table.
|
||||
|
||||
While it is possible to manually configure logging module and start the profiler
|
||||
with the right set of threads to profile, ``about:logging`` makes this task a lot
|
||||
simpler and error-proof.
|
||||
|
||||
|
||||
The ``MOZ_LOG`` syntax
|
||||
----------------------
|
||||
|
||||
Logging is configured using a special but simple syntax: which module should be
|
||||
enabled, at which level, and what logging options should be enabled or disabled.
|
||||
|
||||
The syntax is a list of terms, separated by commas. There are two types of
|
||||
terms:
|
||||
|
||||
- A log module and its level, separated by a colon (``:``), such as
|
||||
``example_module:5`` to enable the module ``example_module`` at logging level
|
||||
``5`` (verbose). This `searchfox query
|
||||
<https://searchfox.org/mozilla-central/search?q=LazyLogModule+.*%5C%28%22&path=&case=true®exp=true>`_
|
||||
returns the complete list of modules available.
|
||||
- A special string in the following table, to configure the logging behaviour.
|
||||
Some configuration switch take an integer parameter, in which case it's
|
||||
separated from the string by a colon (``:``). Most switches only apply in a
|
||||
specific output context, noted in the **Context** column.
|
||||
|
||||
+----------------------+---------+-------------------------------------------------------------------------------------------+
|
||||
| Special module name | Context | Action |
|
||||
+======================+=========+===========================================================================================+
|
||||
| append | File | Append new logs to existing log file. |
|
||||
+----------------------+---------+-------------------------------------------------------------------------------------------+
|
||||
| sync | File | Print each log synchronously, this is useful to check behavior in real time or get logs |
|
||||
| | | immediately before crash. |
|
||||
+----------------------+---------+-------------------------------------------------------------------------------------------+
|
||||
| raw | File | Print exactly what has been specified in the format string, without the |
|
||||
| | | process/thread/timestamp, etc. prefix. |
|
||||
+----------------------+---------+-------------------------------------------------------------------------------------------+
|
||||
| timestamp | File | Insert timestamp at start of each log line. |
|
||||
+----------------------+---------+-------------------------------------------------------------------------------------------+
|
||||
| rotate:**N** | File | | This limits the produced log files' size. Only most recent **N megabytes** of log data |
|
||||
| | | | is saved. We rotate four log files with .0, .1, .2, .3 extensions. Note: this option |
|
||||
| | | | disables 'append' and forces 'timestamp'. |
|
||||
+----------------------+---------+-------------------------------------------------------------------------------------------+
|
||||
| maxsize:**N** | File | Limit the log to **N** MB. Only work in append mode. |
|
||||
+----------------------+---------+-------------------------------------------------------------------------------------------+
|
||||
| prependheader | File | Prepend a simple header while distinguishing logging. Useful in append mode. |
|
||||
+----------------------+---------+-------------------------------------------------------------------------------------------+
|
||||
| profilerstacks | Profiler| | When profiling with the Firefox Profiler and log modules are enabled, capture the call |
|
||||
| | | | stack for each log statement. |
|
||||
+----------------------+---------+-------------------------------------------------------------------------------------------+
|
||||
|
||||
This syntax is used for most methods of enabling logging, with the exception of
|
||||
settings preferences directly, see :ref:`this section <Enabling logging using preferences>` for directions.
|
||||
|
||||
|
||||
Enabling Logging
|
||||
----------------
|
||||
|
||||
Enabling logging can be done in a variety of ways:
|
||||
|
||||
- via environment variables
|
||||
- via command line switches
|
||||
- using ``about:config`` preferences
|
||||
- using ``about:logging``
|
||||
|
||||
The first two allow logging from the start of the application and are also
|
||||
useful in case of a crash (when ``sync`` output is requested, this can also be
|
||||
done with ``about:config`` as well to a certain extent). The last two
|
||||
allow enabling and disabling logging at runtime and don't require using the
|
||||
command-line.
|
||||
|
||||
By default all logging output is disabled.
|
||||
|
||||
Enabling logging using ``about:logging``
|
||||
''''''''''''''''''''''''''''''''''''''''
|
||||
|
||||
``about:logging`` allows enabling logging by entering a ``MOZ_LOG`` string in the
|
||||
text input, and validating.
|
||||
|
||||
Options allow logging to a file or using the Firefox Profiler, that can be
|
||||
started and stopped right from the page.
|
||||
|
||||
Logging presets for common scenarios are available in a drop-down. They can be
|
||||
associated with a profiler preset.
|
||||
|
||||
It is possible, via URL parameters, to select a particular logging
|
||||
configuration, or to override certain parameters in a preset. This is useful to
|
||||
ask a user to gather logs efficiently without having to fiddle with prefs and/or
|
||||
environment variable.
|
||||
|
||||
URL parameters are described in the following table:
|
||||
|
||||
+---------------------+---------------------------------------------------------------------------------------------+
|
||||
| Parameter | Description |
|
||||
+=====================+=============================================================================================+
|
||||
| ``preset`` | a `logging preset <https://searchfox.org/mozilla-central/search?q=gLoggingPresets>`_ |
|
||||
+---------------------+---------------------------------------------------------------------------------------------+
|
||||
| ``logging-preset`` | alias for ``preset`` |
|
||||
+---------------------+---------------------------------------------------------------------------------------------+
|
||||
| ``modules`` | a string in ``MOZ_LOG`` syntax |
|
||||
+---------------------+---------------------------------------------------------------------------------------------+
|
||||
| ``module`` | alias for ``modules`` |
|
||||
+---------------------+---------------------------------------------------------------------------------------------+
|
||||
| ``threads`` | a list of threads to profile, overrides what a profiler preset would have picked |
|
||||
+---------------------+---------------------------------------------------------------------------------------------+
|
||||
| ``thread`` | alias for ``threads`` |
|
||||
+---------------------+---------------------------------------------------------------------------------------------+
|
||||
| ``output`` | either ``profiler`` or ``file`` |
|
||||
+---------------------+---------------------------------------------------------------------------------------------+
|
||||
| ``output-type`` | alias for ``output`` |
|
||||
+---------------------+---------------------------------------------------------------------------------------------+
|
||||
| ``profiler-preset`` | a `profiler preset <https://searchfox.org/mozilla-central/search?q=%40type+{Presets}>`_ |
|
||||
+---------------------+---------------------------------------------------------------------------------------------+
|
||||
|
||||
If a preset is selected, then ``threads`` or ``modules`` can be used to override the
|
||||
profiled threads or logging modules enabled, but keeping other aspects of the
|
||||
preset. If no preset is selected, then a generic profiling preset is used,
|
||||
``firefox-platform``. For example:
|
||||
|
||||
::
|
||||
|
||||
about:logging?output=profiler&preset=media-playback&modules=cubeb:4,AudioSinkWrapper:4:AudioSink:4
|
||||
|
||||
will profile the threads in the ``Media`` profiler preset, but will only log
|
||||
specific log modules (instead of the `long list
|
||||
<https://searchfox.org/mozilla-central/search?q="media-playback"&path=toolkit%2Fcontent%2FaboutLogging.js>`_
|
||||
in the ``media-playback`` preset). In addition, it disallows logging to a file.
|
||||
|
||||
Enabling logging using environment variables
|
||||
''''''''''''''''''''''''''''''''''''''''''''
|
||||
|
||||
On UNIX, setting and environment variable can be done in a variety of ways
|
||||
|
||||
::
|
||||
|
||||
set MOZ_LOG="example_logger:3"
|
||||
export MOZ_LOG="example_logger:3"
|
||||
MOZ_LOG="example_logger:3" ./mach run
|
||||
|
||||
In the Windows Command Prompt (``cmd.exe``), don't use quotes:
|
||||
|
||||
::
|
||||
|
||||
set MOZ_LOG=example_logger:3
|
||||
|
||||
If you want this on GeckoView example, use the following adb command to launch process:
|
||||
|
||||
::
|
||||
|
||||
adb shell am start -n org.mozilla.geckoview_example/.GeckoViewActivity --es env0 "MOZ_LOG=example_logger:3"
|
||||
|
||||
There are special module names to change logging behavior. You can specify one or more special module names without logging level.
|
||||
|
||||
For example, if you want to specify ``sync``, ``timestamp`` and ``rotate``:
|
||||
|
||||
::
|
||||
|
||||
set MOZ_LOG="example_logger:3,timestamp,sync,rotate:10"
|
||||
|
||||
Enabling logging usually outputs the logging statements to the terminal. To
|
||||
have the logs written to a file instead (one file per process), the environment
|
||||
variable ``MOZ_LOG_FILE`` can be used. Logs will be written at this path
|
||||
(either relative or absolute), suffixed by a process type and its PID.
|
||||
``MOZ_LOG`` files are text files and have the extension ``.moz_log``.
|
||||
|
||||
For example, setting:
|
||||
|
||||
::
|
||||
|
||||
set MOZ_LOG_FILE="firefox-logs"
|
||||
|
||||
can create a number of files like so:
|
||||
|
||||
::
|
||||
|
||||
firefox-log-main.96353.moz_log
|
||||
firefox-log-child.96354.moz_log
|
||||
|
||||
respectively for a parent process of PID 96353 and a child process of PID
|
||||
96354.
|
||||
|
||||
Enabling logging using command-line flags
|
||||
'''''''''''''''''''''''''''''''''''''''''
|
||||
|
||||
The ``MOZ_LOG`` syntax can be used with the command line switch on the same
|
||||
name, and specifying a file with ``MOZ_LOG_FILE`` works in the same way:
|
||||
|
||||
::
|
||||
|
||||
./mach run -MOZ_LOG=timestamp,rotate:200,example_module:5 -MOZ_LOG_FILE=%TEMP%\firefox-logs
|
||||
|
||||
will enable verbose (``5``) logging for the module ``example_module``, with
|
||||
timestamp prepended to each line, rotate the logs with 4 files of each 50MB
|
||||
(for a total of 200MB), and write the output to the temporary directory on
|
||||
Windows, with name starting with ``firefox-logs``.
|
||||
|
||||
.. _Enabling logging using preferences:
|
||||
|
||||
Enabling logging using preferences
|
||||
''''''''''''''''''''''''''''''''''
|
||||
|
||||
To adjust the logging after Firefox has started, you can set prefs under the
|
||||
`logging.` prefix. For example, setting `logging.foo` to `3` will set the log
|
||||
module `foo` to start logging at level 3. A number of special prefs can be set,
|
||||
described in the table below:
|
||||
|
||||
+-------------------------------------+------------+-------------------------------+--------------------------------------------------------+
|
||||
| Preference name | Preference | Preference value | Description |
|
||||
+=====================================+============+===============================+========================================================+
|
||||
| ``logging.config.clear_on_startup`` | bool | -- | Whether to clear all prefs under ``logging.`` |
|
||||
+-------------------------------------+------------+-------------------------------+--------------------------------------------------------+
|
||||
| ``logging.config.LOG_FILE`` | string | A path (relative or absolute) | The path to which the log files will be written. |
|
||||
+-------------------------------------+------------+-------------------------------+--------------------------------------------------------+
|
||||
| ``logging.config.add_timestamp`` | bool | -- | Whether to prefix all lines by a timestamp. |
|
||||
+-------------------------------------+------------+-------------------------------+--------------------------------------------------------+
|
||||
| ``logging.config.sync`` | bool | -- | Whether to flush the stream after each log statements. |
|
||||
+-------------------------------------+------------+-------------------------------+--------------------------------------------------------+
|
||||
| ``logging.config.profilerstacks`` | bool | -- | | When logging to the Firefox Profiler, whether to |
|
||||
| | | | | include the call stack in each logging statement. |
|
||||
+-------------------------------------+------------+-------------------------------+--------------------------------------------------------+
|
||||
|
||||
Enabling logging in Rust code
|
||||
-----------------------------
|
||||
|
||||
We're gradually adding more Rust code to Gecko, and Rust crates typically use a
|
||||
different approach to logging. Many Rust libraries use the `log
|
||||
<https://docs.rs/log>`_ crate to log messages, which works together with
|
||||
`env_logger <https://docs.rs/env_logger>`_ at the application level to control
|
||||
what's actually printed via `RUST_LOG`.
|
||||
|
||||
You can set an overall logging level, though it could be quite verbose:
|
||||
|
||||
::
|
||||
|
||||
set RUST_LOG="debug"
|
||||
|
||||
You can also target individual modules by path:
|
||||
|
||||
::
|
||||
|
||||
set RUST_LOG="style::style_resolver=debug"
|
||||
|
||||
.. note::
|
||||
For Linux/MacOS users, you need to use `export` rather than `set`.
|
||||
|
||||
.. note::
|
||||
Sometimes it can be useful to only log child processes and ignore the parent
|
||||
process. In Firefox 57 and later, you can use `RUST_LOG_CHILD` instead of
|
||||
`RUST_LOG` to specify log settings that will only apply to child processes.
|
||||
|
||||
The `log` crate lists the available `log levels <https://docs.rs/log/0.3.8/log/enum.LogLevel.html>`_:
|
||||
|
||||
+-----------+---------------------------------------------------------------------------------------------------------+
|
||||
| Log Level | Purpose |
|
||||
+===========+=========================================================================================================+
|
||||
| error | Designates very serious errors. |
|
||||
+-----------+---------------------------------------------------------------------------------------------------------+
|
||||
| warn | Designates hazardous situations. |
|
||||
+-----------+---------------------------------------------------------------------------------------------------------+
|
||||
| info | Designates useful information. |
|
||||
+-----------+---------------------------------------------------------------------------------------------------------+
|
||||
| debug | Designates lower priority information. |
|
||||
+-----------+---------------------------------------------------------------------------------------------------------+
|
||||
| trace | Designates very low priority, often extremely verbose, information. |
|
||||
+-----------+---------------------------------------------------------------------------------------------------------+
|
||||
|
||||
It is common for debug and trace to be disabled at compile time in release builds, so you may need a debug build if you want logs from those levels.
|
||||
|
||||
Check the `env_logger <https://docs.rs/env_logger>`_ docs for more details on logging options.
|
||||
|
||||
Additionally, a mapping from `RUST_LOG` is available. When using the `MOZ_LOG`
|
||||
syntax, it is possible to enable logging in rust crate using a similar syntax:
|
||||
|
||||
::
|
||||
|
||||
MOZ_LOG=rust_crate_name::*:4
|
||||
|
||||
will enable `debug` logging for all log statements in the crate
|
||||
``rust_crate_name``.
|
||||
|
||||
`*` can be replaced by a series of modules if more specificity is needed:
|
||||
|
||||
::
|
||||
|
||||
MOZ_LOG=rust_crate_name::module::submodule:4
|
||||
|
||||
will enable `debug` logging for all log statements in the sub-module
|
||||
``submodule`` of the module ``module`` of the crate ``rust_crate_name``.
|
||||
|
||||
|
||||
A table mapping Rust log levels to `MOZ_LOG` log level is available below:
|
||||
|
||||
+----------------+---------------+-----------------+
|
||||
| Rust log level | MOZ_LOG level | Numerical value |
|
||||
+================+===============+=================+
|
||||
| off | Disabled | 0 |
|
||||
+----------------+---------------+-----------------+
|
||||
| error | Error | 1 |
|
||||
+----------------+---------------+-----------------+
|
||||
| warn | Warning | 2 |
|
||||
+----------------+---------------+-----------------+
|
||||
| info | Info | 3 |
|
||||
+----------------+---------------+-----------------+
|
||||
| debug | Debug | 4 |
|
||||
+----------------+---------------+-----------------+
|
||||
| trace | Verbose | 5 |
|
||||
+----------------+---------------+-----------------+
|
||||
|
||||
Working with ``MOZ_LOG`` in the code
|
||||
++++++++++++++++++++++++++++++++++++
|
||||
A minimal C++ logging framework is provided for use in core Gecko code. It is enabled for all builds and is thread-safe.
|
||||
|
||||
Declaring a Log Module
|
||||
----------------------
|
||||
@ -433,3 +88,114 @@ Example Usage
|
||||
MOZ_LOG(sLogger, LogLevel::Error, ("i should be 10!"));
|
||||
}
|
||||
}
|
||||
|
||||
Enabling Logging
|
||||
----------------
|
||||
|
||||
The log level for a module is controlled by setting an environment variable before launching the application. It can also be adjusted by setting prefs. By default all logging output is disabled.
|
||||
|
||||
::
|
||||
|
||||
set MOZ_LOG="example_logger:3"
|
||||
|
||||
In the Windows Command Prompt (`cmd.exe`), don't use quotes:
|
||||
|
||||
::
|
||||
|
||||
set MOZ_LOG=example_logger:3
|
||||
|
||||
If you want this on GeckoView example, use the following adb command to launch process:
|
||||
|
||||
::
|
||||
|
||||
adb shell am start -n org.mozilla.geckoview_example/.GeckoViewActivity --es env0 "MOZ_LOG=example_logger:3"
|
||||
|
||||
There are special module names to change logging behavior. You can specify one or more special module names without logging level.
|
||||
|
||||
+-------------------------+-------------------------------------------------------------------------------------------+
|
||||
| Special module name | Action |
|
||||
+=========================+===========================================================================================+
|
||||
| append | Append new logs to existing log file. |
|
||||
+-------------------------+-------------------------------------------------------------------------------------------+
|
||||
| sync | Print each log synchronously, this is useful to check behavior in real time or get logs |
|
||||
| | immediately before crash. |
|
||||
+-------------------------+-------------------------------------------------------------------------------------------+
|
||||
| raw | Print exactly what has been specified in the format string, without the |
|
||||
| | process/thread/timestamp, etc. prefix. |
|
||||
+-------------------------+-------------------------------------------------------------------------------------------+
|
||||
| timestamp | Insert timestamp at start of each log line. |
|
||||
+-------------------------+-------------------------------------------------------------------------------------------+
|
||||
| rotate: **N** | | This limits the produced log files' size. Only most recent **N megabytes** of log data |
|
||||
| | | is saved. We rotate four log files with .0, .1, .2, .3 extensions. Note: this option |
|
||||
| | | disables 'append' and forces 'timestamp'. |
|
||||
+-------------------------+-------------------------------------------------------------------------------------------+
|
||||
|
||||
For example, if you want to specify `sync`, `timestamp` and `rotate`:
|
||||
|
||||
::
|
||||
|
||||
set MOZ_LOG="example_logger:3,timestamp,sync,rotate:10"
|
||||
|
||||
To adjust the logging after Firefox has started, you can set prefs under the `logging.` prefix. For example, setting `logging.foo` to `3` will set the log module `foo` to start logging at level 3. The special boolean prefs `logging.config.sync` and `logging.config.add_timestamp` can be used to control the `sync` and `timestamp` properties described above.
|
||||
|
||||
.. warning::
|
||||
A sandboxed content process cannot write to stderr or any file. The easiest way to log these processes is to disable the content sandbox by setting the preference `security.sandbox.content.level` to `0`. On Windows, you can still see child process messages by using DOS (not the `MOZ_LOG_FILE` variable defined below) to redirect output to a file. For example: `MOZ_LOG="CameraChild:5" mach run >& my_log_file.txt` will include debug messages from the camera's child actor that lives in a (sandboxed) content process.
|
||||
|
||||
Redirecting logging output to a file
|
||||
------------------------------------
|
||||
|
||||
Logging output can be redirected to a file by passing its path via an environment variable.
|
||||
|
||||
.. note::
|
||||
By default logging output goes to `stderr`.
|
||||
|
||||
::
|
||||
|
||||
set MOZ_LOG_FILE="log.txt"
|
||||
|
||||
The `rotate` and `append` options described above only apply when logging to a file.
|
||||
|
||||
The special pref `logging.config.LOG_FILE` can be set at runtime to change the log file being output to.
|
||||
|
||||
Logging Rust
|
||||
------------
|
||||
|
||||
We're gradually adding more Rust code to Gecko, and Rust crates typically use a different approach to logging. Many Rust libraries use the `log <https://docs.rs/log>`_ crate to log messages, which works together with `env_logger <https://docs.rs/env_logger>`_ at the application level to control what's actually printed via `RUST_LOG`.
|
||||
|
||||
You can set an overall logging level, though it could be quite verbose:
|
||||
|
||||
::
|
||||
|
||||
set RUST_LOG="debug"
|
||||
|
||||
You can also target individual modules by path:
|
||||
|
||||
::
|
||||
|
||||
set RUST_LOG="style::style_resolver=debug"
|
||||
|
||||
.. note::
|
||||
For Linux/MacOS users, you need to use `export` rather than `set`.
|
||||
|
||||
.. note::
|
||||
Sometimes it can be useful to only log child processes and ignore the parent process. In Firefox 57 and later, you can use `RUST_LOG_CHILD` instead of `RUST_LOG` to specify log settings that will only apply to child processes.
|
||||
|
||||
The `log` crate lists the available `log levels <https://docs.rs/log/0.3.8/log/enum.LogLevel.html>`_:
|
||||
|
||||
+-----------+---------------------------------------------------------------------------------------------------------+
|
||||
| Log Level | Purpose |
|
||||
+===========+=========================================================================================================+
|
||||
| error | Designates very serious errors. |
|
||||
+-----------+---------------------------------------------------------------------------------------------------------+
|
||||
| warn | Designates hazardous situations. |
|
||||
+-----------+---------------------------------------------------------------------------------------------------------+
|
||||
| info | Designates useful information. |
|
||||
+-----------+---------------------------------------------------------------------------------------------------------+
|
||||
| debug | Designates lower priority information. |
|
||||
+-----------+---------------------------------------------------------------------------------------------------------+
|
||||
| trace | Designates very low priority, often extremely verbose, information. |
|
||||
+-----------+---------------------------------------------------------------------------------------------------------+
|
||||
|
||||
It is common for debug and trace to be disabled at compile time in release builds, so you may need a debug build if you want logs from those levels.
|
||||
|
||||
Check the `env_logger <https://docs.rs/env_logger>`_ docs for more details on logging options.
|
||||
|
Loading…
Reference in New Issue
Block a user