logger: enable the use of spdlog static loggers#118
Conversation
Signed-off-by: Niklas Eiling <niklas.eiling@eonerc.rwth-aachen.de>
ReviewSince you want the compiled in log level to be chosen at build-time I'd prefer the I can definitely get behind the possibility to reduce the runtime overhead of logging. Considering MacrosI'm also considering redefining the #define NODE_WARN(...) SPDLOG_WARN("node: " __VA_ARGS__)This is the way Linux Kernel Modules often add their prefix to log messages. Considering variadic constexpr inline functionsI personally really don't like the C preprocessor. C++ allows us to write e.g. ConclusionI'm really not sure what the best way to integrate the compile time switch for logging would be. |
|
I agree that it should be defined in cmake. I just wanted to start a discussion before I invest too much dev time into this. Prefixing log messages in not necessary though, as using the macros already implicitly give us the information about filename and even function from which we log. However, this only works when using the spdlog macros and not in the static spdlog loggers (e.g., The macros are defined as: #define SPDLOG_LOGGER_CALL(logger, level, ...) (logger)->log(spdlog::source_loc{__FILE__, __LINE__, SPDLOG_FUNCTION}, level, __VA_ARGS__)
#if SPDLOG_ACTIVE_LEVEL <= SPDLOG_LEVEL_DEBUG
#define SPDLOG_LOGGER_DEBUG(logger, ...) SPDLOG_LOGGER_CALL(logger, spdlog::level::debug, __VA_ARGS__)
#define SPDLOG_DEBUG(...) SPDLOG_LOGGER_DEBUG(spdlog::default_logger_raw(), __VA_ARGS__)
#else
#define SPDLOG_LOGGER_DEBUG(logger, ...) (void)0
#define SPDLOG_DEBUG(...) (void)0
#endifI don't really mind if you want to replace the preprocessor if with a if testing a costexpr, but we cannot get rid of the macro because with need to insert |
|
I am strongly against this. We would loose important context by limiting us to a single logging instance. E.g. the name of a node is also part of some loggers. So if we remove the logger name we dont know which node instance produced a certain message. Filename and line information is alao nothing I believe we should expose to the user. For debugging info, it could be nice. But we can still do this with macros and keeping individual logging instances. Furthermore, VILLASnode has some advanced ways of filtering logs based on the logger name. E.g. showing only logs of the memory management or disabling those. I dont see good enough arguments for making such a large change to the codebase. Do we have a use case for the real-time critial path where a few cycles matter? Branch prediction is to iur favour here and I think its a cost we can take. |
We don't need multiple logger instances for this though. We could add a prefix for info, warn and error and use filename and line infos for higher log level. This would be the best of both worlds, right?
I haven't done any measurements, but I believe writing to stdout or a file is more than a few cycles. We could also improve this by using spdlogs asynchronous loggers though. |
|
We are using multiple sinks for Syslog and logging to files: Expressions are applying different log levels based on the name of the logger. If we have a single logger instance, that would not be possible anymore. I find it pretty useful to selectively log/debug certain areas of the code (e.g. memory management or hooks only). My comment about branch prediction was not about the actual printing to stdout but only to the evaluation of the condition if a logging statement should be emitted or not (comparing the log level). I think we also have support for multiple debug (verbosity) levels, to differentiate between more inmportant and less important debugging info. How about if we only print file/line/function info when the debug level is active? I really tried hard to keep the log messages concise and not to overload the user with to may details. I fear that the log lines will become really long and users stop reading the logs carefully. |
|
OK so we could do something like this: #define VILLAS_LOG(module, level, ...) if (level >= spdlog::info) { \
villas::Log::get(module)->log(level, __VA_ARGS__) \
} else { \
SPDLOG_LOGGER_CALL(villas::Log::get(module), level, __VA_ARGS__) \
}and then in the modules #include "log.hpp"
#define FPGA_LOG(...) VILLAS_LOG("fpga", __VA_ARGS__)We could get even more evil with macro magic. But I guess we don't want to do that. |
|
I don't know if we really want to call Can we pass the logger instance here directly? |
|
Having to handle these logger instances is one thing I would like to avoid in any future change. I feel like this leads to people avoiding logging because it is cumbersome to pass a logger to every (new) place it is needed. Also there are a few places where loggers are named non-intuitively or classes using the wrong instance (e.g. of a super class). Personally, I don't use filtering (is @stv0g the only one who uses it?). I would rather log to a file and search/filter using Linux tools. So to me, having to handle logger instances is not worth the filtering capability. (And I assume here from the previous discussion that this is the only benefit separate loggers have). |
Signed-off-by: Niklas Eiling <niklas.eiling@eonerc.rwth-aachen.de>
I would like to start a discussion about enabling or even completely refactor VILLAS to use spdlogs macros for logging. See https://github.com/gabime/spdlog/wiki/1.-QuickStart#logging-macros for details.
Benefits would be:
Disadvantages:
Example of how this would look like:
Output: