Logging¶
Setup¶
Each framework (WebCore, WebKit, WebKitLegacy, WTF) enable their own logging infrastructure independently (though the infrastructure itself is shared). If you want to log a message, #include
the relevant framework's Logging.h
header. Then, you can use the macros below.
Beware that you can't #include
multiple framework's Logging.h
headers at the same time - they each define a macro LOG_CHANNEL_PREFIX
which will conflict with each other. Only #include
the Logging.h
header from your specific framework.
If you want to do more advanced operations, like searching through the list of log channels, #include
your framework's LogInitialization.h
header. These do not conflict across frameworks, so you can do something like
#include "LogInitialization.h"
#include <WebCore/LogInitialization.h>
#include <WTF/LogInitialization.h>
Indeed, WebKit does this to initialize all frameworks' log channels during Web Process startup.
Logging messages¶
There are a few relevant macros for logging messages:
LOG()
: Log a printf-style message in debug builds. Requires you to name a logging channel to output to.LOG_WITH_STREAM()
Log an iostream-style message in debug builds. Requires you to name a logging channel to output to.RELEASE_LOG()
: Just likeLOG()
but logs in both debug and release builds. Requires you to name a logging channel to output to.WTFLogAlways()
: Mainly for local debugging, unconditionally output a message. Does not require a logging channel to output to.
Here's an example invocation of LOG()
:
LOG(MediaQueries, "HTMLMediaElement %p selectNextSourceChild evaluating media queries", this);
That first argument is a log channel. These have 2 purposes:
- Individual channels can be enabled/disabled independently (So you can get all the WebGL logging without getting any Loading logging)
- When multiple channels are enabled, and you're viewing the logs, you can search/filter by the channel
Here's an example invocation of LOG_WITH_STREAM()
:
LOG_WITH_STREAM(Scrolling, stream << "ScrollingTree::commitTreeState - removing unvisited node " << nodeID);
The macro sets up a local variable named stream
which the second argument can direct messages to. The second argument is a collection of statements - not expressions like LOG()
and RELEASE_LOG()
. So, you can do things like this:
LOG_WITH_STREAM(TheLogChannel,
for (const auto& something : stuffToLog)
stream << " " << something;
);
The reason why (most of) these use macros is so the entire thing can be compiled out when logging is disabled. Consider this:
LOG(TheLogChannel, "The result is %d", someSuperComplicatedCalculation());
If these were not macros, you'd have to pay for someSuperComplicatedCalculation()
whether logging is enabled or not.
Enabling and disabling log channels¶
Channels are enabled/disabled at startup by passing a carefully crafted string to initializeLogChannelsIfNecessary()
. On the macOS and iOS ports, this string comes from the defaults database. On other UNIX systems and Windows, it comes from environment variables.
You can read the grammar of this string in initializeLogChannelsIfNecessary()
. Here is an example:
WebGL -Loading
You can also specify the string all
to enable all logging.
On macOS/iOS and Windows, each framework has its own individually supplied string that it uses to enable its own logging channels. On Linux, all frameworks share the same string.
Linux¶
Set the WEBKIT_DEBUG
environment variable.
WEBKIT_DEBUG=Scrolling Tools/Scripts/run-minibrowser --gtk --debug
macOS¶
On macOS, you can, for example, enable the Language
log channel with these terminal commands:
for identifier in com.apple.WebKit.WebContent.Development com.apple.WebKit.WebContent org.webkit.MiniBrowser com.apple.WebKit.WebKitTestRunner org.webkit.DumpRenderTree -g /Users/$USER/Library/Containers/com.apple.Safari/Data/Library/Preferences/com.apple.Safari.plist; do
for key in WTFLogging WebCoreLogging WebKitLogging WebKit2Logging; do
defaults write ${identifier} "${key}" "Language"
done
done
You may also need to specify these strings to com.apple.WebKit.WebContent.Development
, the global domain, or the Safari container, depending on what you're running.
You may also pass this key and value as an argument:
Tools/Scripts/run-minibrowser --debug -WebCoreLogging Scrolling
Windows¶
Set the WTFLogging
, WebCoreLogging
or WebKit2Logging
environment variables.
It outputs logs both to stderr and OutputDebugString
on Windows. Console applications (jsc.exe, WebKitTestRunner.exe, etc) can use stderr, but GUI applications (MiniBrowser.exe). Attach a debugger to see the message of OutputDebugString
. Use Child Process Debugging Power Tool to automatically attach child processes.
Adding a new log channel¶
Simply add a line to your framework's Logging.h
header. Depending on how the accompanying Logging.cpp
file is set up, you may need to add a parallel line there. That should be all you need. It is acceptable to have log channels in different frameworks with the same name - this is what LOG_CHANNEL_PREFIX
is for.
JavaScriptCore and dataLog¶
WebKit has another logging infrastructure dataLog
. JavaScriptCore is mainly using it. To enable the JSC logging, set a environment variable or give a command switch to jsc
. For example, JSC_logGC=2
or run-jsc --logGC=2
. Give --debug
switch to run-jsc
script if you build a debug build.
Invoking run-jsc --options
lists all options and possible values. On Windows, invoke perl Tools/Scripts/run-jsc --options
or WebKitBuild/Release/bin64/jsc.exe --options
.