Logging
General
To write out messages of any kind from DAPHNE internals we use the spdlog library.
E.g., not from a user's print()
statement but when std::cout << "my value: " << value << std::endl;
is needed. With
spdlog, the previous std::cout
example would read like this: spdlog::info("my value: {}", value);
. The only
difference being that we now need to choose a log level (which is arbitrarily chosen to be info in this case).
Usage
- Before using the logging functionality, the loggers need to be created and registered. Due to the nature of how
singletons work in C++, this has to be done once per binary (e.g.,
daphne
,run_tests
,libAllKernels.so
,libCUDAKernels.so
, etc). For the mentioned binaries this has already been taken care of (either somewhere near the main program entry point or via context creation in case of the libs). All setup is handled by the classDaphneLogger
(with some extras inConfigParser
). -
Log messages can be submitted in two forms:
spdlog::warn("my warning");
spdlog::get("default")->warn("my warning");
The two statements have the same effect. But while the former is a short form for using the default logger, the latter explicitly chooses the logger via the static
get()
method. Thisget()
method is to be used with caution as it involves acquiring a lock, which is to be avoided in performance critical sections of the code. In the initial implementation there is a logger for runtime kernels provided by the context object to work around this limitation. See the matrix multiplication kernel insrc/runtime/local/kernels/MatMult.cpp
for example usage. -
We can have several loggers, which can be configured differently. For example, to control how messages are logged in the CUDA compiler pass
MarkCUDAOpsPass
, a logger named "compiler::cuda" is used. Additionally, avoiding the use ofspdlog::get()
is demonstrated there. For each used logger, an entry infallback_loggers
(seeDaphneLogger.cpp
) must exist to prevent crashing when using an unconfigured logger. - To configure log levels, formatting and output options, the
DaphneUserConfig
andConfigParser
have been extended. See an example of this in theUserConfig.json
in the root directory of the DAPHNE code base. - At the moment, the output options of our logging infrastructure are a bit limited (initial version). A logger currently
always emits messages to the console's
stdout
and optionally to a file if a file name is given in the configuration. - The format of log messages can be customized. See the examples in
UserConfig.json
and the spdlog documentation. - If a logger is called while running unit tests (
run_tests
executable), make sure to#include <run_tests.h>
and callauto dctx = setupContextAndLogger();
somewhere before calling the kernel to be tested. - Logging can be set to only work from a certain log level and above. This mechanism also serves as a global toggle.
To set the log level limit, set
{ "log-level-limit": "OFF" },
. In this example, taken fromUserConfig.json
, all logging is switched off, regardless of configuration.
Log Levels
These are the available log levels (taken from <spdlog/common.h>
). Since it's an enum, their numeric values
start from 0
for TRACE
to 6
for OFF
.
namespace level {
enum level_enum : int
{
trace = SPDLOG_LEVEL_TRACE,
debug = SPDLOG_LEVEL_DEBUG,
info = SPDLOG_LEVEL_INFO,
warn = SPDLOG_LEVEL_WARN,
err = SPDLOG_LEVEL_ERROR,
critical = SPDLOG_LEVEL_CRITICAL,
off = SPDLOG_LEVEL_OFF,
n_levels
};
ToDo
- Guideline when which log level is recommended
- Toggle console output
- Other log sinks