From 7a72f18a55652b7166fb4adec37431c892e37fc9 Mon Sep 17 00:00:00 2001 From: Philippe Proulx Date: Tue, 14 Nov 2023 14:25:39 -0500 Subject: [PATCH] cpp-common: add `logging.hpp` (`bt2c::Logger` and BT_CPPLOG*() macros) This new file contains the `bt2c::Logger` class of which an instance contains: * An actor: a self component class, a self component, a self message iterator, or a named module. * A current logging level. * A logging tag. The class offers the logNoThrow(), logMemNoThrow(), logErrnoNoThrow(), logErrorAndThrow(), logErrorAndRethrow(), logErrorErrnoAndThrow(), and logErrorErrnoAndRethrow() method templates to log using a given level, optionally append a cause to the error of the current thread using the correct actor, and optionally throw or rethrow. The methods above expect a format string and zero or more arguments to be formatted with fmt::format(). There are also versions with `Str` in the name which accept a single string. All the logging methods are `const` so that you may log with a `const bt2c::Logger`: they don't change any user-visible state. Then, the various BT_CPPLOG*() macros call one of the log*() methods on a logger instance with the current file name, function name, and line number, forwarding the other arguments to the method. Those macros are unfortunately needed for the file/function/line information, similar to SPDLOG_LOGGER_INFO() vs. the info() method. The macros of which the name ends with `_SPEC` accept a specific logger; the other ones use the fixed `_mLogger` logger, which will be the case most of the time (logging from a user component or message iterator). Example: BT_CPPLOGE_APPEND_CAUSE_AND_THROW(Error, "Failed to add {0} items to `{1}` (expecting {0}, not {2})", expCount, containerName, count); Internally, the logging methods fill `_mBuf` with fmt::format_to() and pass the resulting string to some bt_log_write*() function. Argument evaluation and formatting only happens if logging and/or error cause appending will also happen. Create a logger from another one with a different tag like this: MyThing::MyThing(const bt2c::Logger& parentLogger, ...) : _mLogger {parentLogger, "MY-THING"}, ... Make some code conditional to having some logging active for a given level with the wouldLog*() methods (uses BT_LOG_ON_CUR_LVL() internally): if (_mLogger.wouldLogD()) { // code which only exists to log BT_CPPLOGD(...); } Note that this first version is not thread-safe (the underlying logging framework is, but `_mBuf` isn't protected for a given logger). Signed-off-by: Philippe Proulx Change-Id: Iacb4c26e42c868f27e3a85b9fe163acac870624f Reviewed-on: https://review.lttng.org/c/babeltrace/+/11388 Reviewed-by: Simon Marchi Tested-by: jenkins CI-Build: Simon Marchi --- src/Makefile.am | 1 + src/cpp-common/bt2c/logging.hpp | 971 ++++++++++++++++++++++++++++++++ 2 files changed, 972 insertions(+) create mode 100644 src/cpp-common/bt2c/logging.hpp diff --git a/src/Makefile.am b/src/Makefile.am index 04c960d6..debe1020 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -47,6 +47,7 @@ noinst_HEADERS = \ cpp-common/bt2c/glib-up.hpp \ cpp-common/bt2c/lib-str.hpp \ cpp-common/bt2c/libc-up.hpp \ + cpp-common/bt2c/logging.hpp \ cpp-common/bt2c/read-fixed-len-int.hpp \ cpp-common/bt2c/safe-ops.hpp \ cpp-common/bt2c/std-int.hpp \ diff --git a/src/cpp-common/bt2c/logging.hpp b/src/cpp-common/bt2c/logging.hpp new file mode 100644 index 00000000..893ee131 --- /dev/null +++ b/src/cpp-common/bt2c/logging.hpp @@ -0,0 +1,971 @@ +/* + * SPDX-FileCopyrightText: 2023 Philippe Proulx + * SPDX-License-Identifier: MIT + */ + +#ifndef BABELTRACE_CPP_COMMON_BT2C_LOGGING_HPP +#define BABELTRACE_CPP_COMMON_BT2C_LOGGING_HPP + +#include +#include +#include +#include +#include + +#include + +#include "common/assert.h" +#include "cpp-common/bt2/private-query-executor.hpp" +#include "cpp-common/bt2/self-component-class.hpp" +#include "cpp-common/bt2/self-component-port.hpp" +#include "cpp-common/bt2/self-message-iterator.hpp" +#include "cpp-common/bt2s/optional.hpp" +#include "cpp-common/vendor/fmt/core.h" +#include "logging/log-api.h" + +namespace bt2c { + +/* + * A logger contains an actor (self component class, self component, + * self message iterator, or simple module name), a current logging + * level, and a logging tag. + * + * It offers the logNoThrow(), logMemNoThrow(), logErrnoNoThrow(), + * logErrorAndThrow(), logErrorAndRethrow(), logErrorErrnoAndThrow(), + * and logErrorErrnoAndRethrow() method templates to log using a given + * level, optionally append a cause to the error of the current thread + * using the correct actor, and optionally throw or rethrow. + * + * The methods above expect a format string and zero or more arguments + * to be formatted with fmt::format(). + */ +class Logger final +{ +public: + /* Available log levels */ + enum class Level + { + TRACE = BT_LOG_TRACE, + DEBUG = BT_LOG_DEBUG, + INFO = BT_LOG_INFO, + WARNING = BT_LOG_WARNING, + ERROR = BT_LOG_ERROR, + FATAL = BT_LOG_FATAL, + NONE = BT_LOG_NONE, + }; + + /* + * Builds a logger from the self component class `selfCompCls` using + * the tag `tag` and the logging level of `privQueryExec`. + */ + explicit Logger(const bt2::SelfComponentClass selfCompCls, + const bt2::PrivateQueryExecutor privQueryExec, std::string tag) noexcept : + _mSelfCompCls {selfCompCls}, + _mLevel {static_cast(privQueryExec.loggingLevel())}, _mTag {std::move(tag)} + { + } + + /* + * Builds a logger from the self component `selfComp` using the tag + * `tag`. + */ + explicit Logger(const bt2::SelfComponent selfComp, std::string tag) noexcept : + _mSelfComp {selfComp}, _mLevel {static_cast(selfComp.loggingLevel())}, _mTag { + std::move( + tag)} + { + } + + /* + * Builds a logger from the self source component `selfComp` using + * the tag `tag`. + */ + explicit Logger(const bt2::SelfSourceComponent selfComp, std::string tag) noexcept : + Logger { + bt2::SelfComponent {bt_self_component_source_as_self_component(selfComp.libObjPtr())}, + std::move(tag)} + { + } + + /* + * Builds a logger from the self filter component `selfComp` using + * the tag `tag`. + */ + explicit Logger(const bt2::SelfFilterComponent selfComp, std::string tag) noexcept : + Logger { + bt2::SelfComponent {bt_self_component_filter_as_self_component(selfComp.libObjPtr())}, + std::move(tag)} + { + } + + /* + * Builds a logger from the self sink component `selfComp` using the + * tag `tag`. + */ + explicit Logger(const bt2::SelfSinkComponent selfComp, std::string tag) noexcept : + Logger {bt2::SelfComponent {bt_self_component_sink_as_self_component(selfComp.libObjPtr())}, + std::move(tag)} + { + } + + /* + * Builds a logger from the self message iterator `selfMsgIter` + * using the tag `tag`. + */ + explicit Logger(const bt2::SelfMessageIterator selfMsgIter, std::string tag) noexcept : + Logger {selfMsgIter.component(), std::move(tag)} + { + _mSelfMsgIter = selfMsgIter; + } + + /* + * Builds a logger from the module named `moduleName` using the tag + * `tag` and logging level `logLevel`. + */ + explicit Logger(std::string moduleName, std::string tag, const Level logLevel) noexcept : + _mModuleName {std::move(moduleName)}, _mLevel {logLevel}, _mTag {std::move(tag)} + { + } + + /* + * Builds a logger from another logger `other` using the new tag + * `newTag`. + */ + explicit Logger(const Logger& other, std::string newTag) : + _mSelfComp {other._mSelfComp}, _mSelfMsgIter {other._mSelfMsgIter}, + _mModuleName {other._mModuleName}, _mLevel {other._mLevel}, _mTag {std::move(newTag)} + { + } + + /* + * Current logging level. + */ + Level level() const noexcept + { + return _mLevel; + } + + /* + * Current logging level converted to a `bt_log_level` value. + * + * For legacy code. + */ + bt_log_level cLevel() const noexcept + { + return static_cast(_mLevel); + } + + /* + * Whether or not this logger would log at the level `level`. + */ + bool wouldLog(const Level level) const noexcept + { + return BT_LOG_ON_CUR_LVL(static_cast(level), static_cast(_mLevel)); + } + + /* + * Whether or not this logger would log at the trace level. + */ + bool wouldLogT() const noexcept + { + return this->wouldLog(Level::TRACE); + } + + /* + * Whether or not this logger would log at the debug level. + */ + bool wouldLogD() const noexcept + { + return this->wouldLog(Level::DEBUG); + } + + /* + * Whether or not this logger would log at the info level. + */ + bool wouldLogI() const noexcept + { + return this->wouldLog(Level::INFO); + } + + /* + * Whether or not this logger would log at the warning level. + */ + bool wouldLogW() const noexcept + { + return this->wouldLog(Level::WARNING); + } + + /* + * Whether or not this logger would log at the error level. + */ + bool wouldLogE() const noexcept + { + return this->wouldLog(Level::ERROR); + } + + /* + * Whether or not this logger would log at the fatal level. + */ + bool wouldLogF() const noexcept + { + return this->wouldLog(Level::FATAL); + } + + /* + * Logging tag. + */ + const std::string& tag() const noexcept + { + return _mTag; + } + + /* + * Self component class actor, or `bt2s::nullopt` if none. + */ + const bt2s::optional& selfCompCls() const noexcept + { + return _mSelfCompCls; + } + + /* + * Self component actor, or `bt2s::nullopt` if none. + */ + const bt2s::optional& selfComp() const noexcept + { + return _mSelfComp; + } + + /* + * Self message iterator actor, or `bt2s::nullopt` if none. + */ + const bt2s::optional& selfMsgIter() const noexcept + { + return _mSelfMsgIter; + } + + /* + * Name of module actor, or `bt2s::nullopt` if none. + */ + const bt2s::optional& moduleName() const noexcept + { + return _mModuleName; + } + +private: + struct _StdLogWriter final + { + static void write(const char * const fileName, const char * const funcName, + const unsigned lineNo, const Level level, const char * const tag, + const void *, unsigned int, const char *, const char * const msg) noexcept + { + bt_log_write(fileName, funcName, lineNo, static_cast(level), tag, msg); + } + }; + +public: + /* + * Logs using the level `LevelV`. + * + * This method forwards `fmt` and `args` to fmt::format() to create + * the log message. + * + * If `AppendCauseV` is true, this method also appends a cause to + * the error of the current thread using the same message. + */ + template + void logNoThrow(const char * const fileName, const char * const funcName, + const unsigned int lineNo, const char * const fmt, ArgTs&&...args) const + { + this->_logNoThrow<_StdLogWriter, LevelV, AppendCauseV>( + fileName, funcName, lineNo, nullptr, 0, nullptr, fmt, std::forward(args)...); + } + + /* + * Logs `msg` using the level `LevelV`. + * + * If `AppendCauseV` is true, this method also appends a cause to + * the error of the current thread using the same message. + */ + template + void logStrNoThrow(const char * const fileName, const char * const funcName, + const unsigned int lineNo, const char * const msg) const + { + this->_logStrNoThrow<_StdLogWriter, LevelV, AppendCauseV>(fileName, funcName, lineNo, + nullptr, 0, nullptr, msg); + } + + /* + * Like logAndNoThrow() with the `Level::ERROR` level, but also + * throws a default-constructed instance of `ExcT`. + */ + template + [[noreturn]] void logErrorAndThrow(const char * const fileName, const char * const funcName, + const unsigned int lineNo, const char * const fmt, + ArgTs&&...args) const + { + this->logNoThrow(fileName, funcName, lineNo, fmt, + std::forward(args)...); + throw ExcT {}; + } + + /* + * Like logStrAndNoThrow() with the `Level::ERROR` level, but also + * throws a default-constructed instance of `ExcT`. + */ + template + [[noreturn]] void logErrorStrAndThrow(const char * const fileName, const char * const funcName, + const unsigned int lineNo, const char * const msg) const + { + this->logStrNoThrow(fileName, funcName, lineNo, msg); + throw ExcT {}; + } + + /* + * Like logAndNoThrow() with the `Level::ERROR` level, but also + * rethrows. + */ + template + [[noreturn]] void logErrorAndRethrow(const char * const fileName, const char * const funcName, + const unsigned int lineNo, const char * const fmt, + ArgTs&&...args) const + { + this->logNoThrow(fileName, funcName, lineNo, fmt, + std::forward(args)...); + throw; + } + + /* + * Like logStrAndNoThrow() with the `Level::ERROR` level, but also + * rethrows. + */ + template + [[noreturn]] void logErrorStrAndRethrow(const char * const fileName, + const char * const funcName, const unsigned int lineNo, + const char * const msg) const + { + this->logStrNoThrow(fileName, funcName, lineNo, msg); + throw; + } + +private: + struct _ErrnoLogWriter final + { + static void write(const char * const fileName, const char * const funcName, + const unsigned lineNo, const Level level, const char * const tag, + const void *, unsigned int, const char * const initMsg, + const char * const msg) noexcept + { + bt_log_write_errno(funcName, fileName, lineNo, static_cast(level), tag, + initMsg, msg); + } + }; + +public: + /* + * Logs the message of `errno` using the level `LevelV`. + * + * The log message starts with `initMsg`, is followed with the + * message for `errno`, and then with what fmt::format() creates + * given `fmt` and `args`. + * + * If `AppendCauseV` is true, this method also appends a cause to + * the error of the current thread using the same message. + */ + template + void logErrnoNoThrow(const char * const fileName, const char * const funcName, + const unsigned int lineNo, const char * const initMsg, + const char * const fmt, ArgTs&&...args) const + { + this->_logNoThrow<_ErrnoLogWriter, LevelV, AppendCauseV>( + fileName, funcName, lineNo, nullptr, 0, initMsg, fmt, std::forward(args)...); + } + + /* + * Logs the message of `errno` using the level `LevelV`. + * + * The log message starts with `initMsg`, is followed with the + * message for `errno`, and then with `msg`. + * + * If `AppendCauseV` is true, this method also appends a cause to + * the error of the current thread using the same message. + */ + template + void logErrnoStrNoThrow(const char * const fileName, const char * const funcName, + const unsigned int lineNo, const char * const initMsg, + const char * const msg) const + { + this->_logStrNoThrow<_ErrnoLogWriter, LevelV, AppendCauseV>(fileName, funcName, lineNo, + nullptr, 0, initMsg, msg); + } + + /* + * Like logErrnoNoThrow() with the `Level::ERROR` level, but also + * throws a default-constructed instance of `ExcT`. + */ + template + [[noreturn]] void logErrorErrnoAndThrow(const char * const fileName, + const char * const funcName, const unsigned int lineNo, + const char * const initMsg, const char * const fmt, + ArgTs&&...args) const + { + this->logErrnoNoThrow(fileName, funcName, lineNo, initMsg, fmt, + std::forward(args)...); + throw ExcT {}; + } + + /* + * Like logErrnoStrNoThrow() with the `Level::ERROR` level, but also + * throws a default-constructed instance of `ExcT`. + */ + template + [[noreturn]] void + logErrorErrnoStrAndThrow(const char * const fileName, const char * const funcName, + const unsigned int lineNo, const char * const initMsg, + const char * const msg) const + { + this->logErrnoStrNoThrow(fileName, funcName, lineNo, initMsg, + msg); + throw ExcT {}; + } + + /* + * Like logErrnoNoThrow() with the `Level::ERROR` level, but also + * rethrows. + */ + template + [[noreturn]] void logErrorErrnoAndRethrow(const char * const fileName, + const char * const funcName, + const unsigned int lineNo, const char * const initMsg, + const char * const fmt, ArgTs&&...args) const + { + this->logErrnoNoThrow(fileName, funcName, lineNo, initMsg, fmt, + std::forward(args)...); + throw; + } + + /* + * Like logErrnoStrNoThrow() with the `Level::ERROR` level, but also + * rethrows. + */ + template + [[noreturn]] void + logErrorErrnoStrAndRethrow(const char * const fileName, const char * const funcName, + const unsigned int lineNo, const char * const initMsg, + const char * const msg) const + { + this->logErrnoStrNoThrow(fileName, funcName, lineNo, initMsg, + msg); + throw; + } + +private: + struct _MemLogWriter final + { + static void write(const char * const fileName, const char * const funcName, + const unsigned lineNo, const Level level, const char * const tag, + const void * const memData, const unsigned int memLen, const char *, + const char * const msg) noexcept + { + bt_log_write_mem(funcName, fileName, lineNo, static_cast(level), tag, + memData, memLen, msg); + } + }; + +public: + /* + * Logs memory data using the level `LevelV`. + * + * This method forwards `fmt` and `args` to fmt::format() to create + * the log message. + */ + template + void logMemNoThrow(const char * const fileName, const char * const funcName, + const unsigned int lineNo, const void * const memData, + const unsigned int memLen, const char * const fmt, ArgTs&&...args) const + { + this->_logNoThrow<_MemLogWriter, LevelV, false>(fileName, funcName, lineNo, memData, memLen, + nullptr, fmt, std::forward(args)...); + } + + /* + * Logs memory data using the level `LevelV`, starting with the + * message `msg`. + */ + template + void logMemStrNoThrow(const char * const fileName, const char * const funcName, + const unsigned int lineNo, const void * const memData, + const unsigned int memLen, const char * const msg) const + { + this->_logStrNoThrow<_MemLogWriter, LevelV, false>(fileName, funcName, lineNo, memData, + memLen, nullptr, msg); + } + +private: + /* + * Formats a log message with fmt::format() given `fmt` and `args`, + * and the forwards everything to _logStrNoThrow(). + */ + template + void _logNoThrow(const char * const fileName, const char * const funcName, + const unsigned int lineNo, const void * const memData, + const std::size_t memLen, const char * const initMsg, const char * const fmt, + ArgTs&&...args) const + { + /* Only format arguments if logging or appending an error cause */ + if (G_UNLIKELY(this->wouldLog(LevelV) || AppendCauseV)) { + /* + * Format arguments to our buffer (fmt::format_to() doesn't + * append a null character). + */ + _mBuf.clear(); + fmt::format_to(std::back_inserter(_mBuf), fmt, std::forward(args)...); + _mBuf.push_back('\0'); + } + + this->_logStrNoThrow(fileName, funcName, lineNo, memData, + memLen, initMsg, _mBuf.data()); + } + + /* + * Logs `msg` using the level `LevelV`. + * + * Calls LogWriterT::write() to write the actual log. + * + * If `AppendCauseV` is true, this method also appends a cause to + * the error of the current thread using the same message. + */ + template + void _logStrNoThrow(const char * const fileName, const char * const funcName, + const unsigned int lineNo, const void * const memData, + const std::size_t memLen, const char * const initMsg, + const char * const msg) const + { + /* Log if needed */ + if (this->wouldLog(LevelV)) { + LogWriterT::write(fileName, funcName, lineNo, LevelV, _mTag.data(), memData, memLen, + initMsg, msg); + } + + /* Append an error cause if needed */ + if (AppendCauseV) { + if (_mSelfMsgIter) { + bt_current_thread_error_append_cause_from_message_iterator( + _mSelfMsgIter->libObjPtr(), fileName, lineNo, "%s", _mBuf.data()); + } else if (_mSelfComp) { + bt_current_thread_error_append_cause_from_component( + _mSelfComp->libObjPtr(), fileName, lineNo, "%s", _mBuf.data()); + } else if (_mSelfCompCls) { + bt_current_thread_error_append_cause_from_component_class( + _mSelfCompCls->libObjPtr(), fileName, lineNo, "%s", _mBuf.data()); + } else { + BT_ASSERT_DBG(_mModuleName); + bt_current_thread_error_append_cause_from_unknown(_mModuleName->data(), fileName, + lineNo, "%s", _mBuf.data()); + } + } + } + + /* At least one of the following four members has a value */ + bt2s::optional _mSelfCompCls; + bt2s::optional _mSelfComp; + bt2s::optional _mSelfMsgIter; + bt2s::optional _mModuleName; + + /* Current logging level */ + Level _mLevel; + + /* Logging tag */ + std::string _mTag; + + /* Formatting buffer */ + mutable std::vector _mBuf; +}; + +} /* namespace bt2c */ + +/* Internal: default logger name */ +#define _BT_CPPLOG_DEF_LOGGER _mLogger + +/* + * Calls logNoThrow() on `_logger` to log using the level `_lvl` without + * appending nor throwing. + */ +#define BT_CPPLOG_EX(_lvl, _logger, _fmt, ...) \ + do { \ + if (G_UNLIKELY((_logger).wouldLog(_lvl))) { \ + (_logger).logNoThrow<(_lvl), false>(__FILE__, __func__, __LINE__, (_fmt), \ + ##__VA_ARGS__); \ + } \ + } while (0) + +/* + * BT_CPPLOG_EX() with specific logging levels. + */ +#define BT_CPPLOGT_SPEC(_logger, _fmt, ...) \ + BT_CPPLOG_EX(bt2c::Logger::Level::TRACE, (_logger), (_fmt), ##__VA_ARGS__) +#define BT_CPPLOGD_SPEC(_logger, _fmt, ...) \ + BT_CPPLOG_EX(bt2c::Logger::Level::DEBUG, (_logger), (_fmt), ##__VA_ARGS__) +#define BT_CPPLOGI_SPEC(_logger, _fmt, ...) \ + BT_CPPLOG_EX(bt2c::Logger::Level::INFO, (_logger), (_fmt), ##__VA_ARGS__) +#define BT_CPPLOGW_SPEC(_logger, _fmt, ...) \ + BT_CPPLOG_EX(bt2c::Logger::Level::WARNING, (_logger), (_fmt), ##__VA_ARGS__) +#define BT_CPPLOGE_SPEC(_logger, _fmt, ...) \ + BT_CPPLOG_EX(bt2c::Logger::Level::ERROR, (_logger), (_fmt), ##__VA_ARGS__) +#define BT_CPPLOGF_SPEC(_logger, _fmt, ...) \ + BT_CPPLOG_EX(bt2c::Logger::Level::FATAL, (_logger), (_fmt), ##__VA_ARGS__) + +/* + * BT_CPPLOG_EX() with specific logging levels and using the default + * logger. + */ +#define BT_CPPLOGT(_fmt, ...) BT_CPPLOGT_SPEC(_BT_CPPLOG_DEF_LOGGER, (_fmt), ##__VA_ARGS__) +#define BT_CPPLOGD(_fmt, ...) BT_CPPLOGD_SPEC(_BT_CPPLOG_DEF_LOGGER, (_fmt), ##__VA_ARGS__) +#define BT_CPPLOGI(_fmt, ...) BT_CPPLOGI_SPEC(_BT_CPPLOG_DEF_LOGGER, (_fmt), ##__VA_ARGS__) +#define BT_CPPLOGW(_fmt, ...) BT_CPPLOGW_SPEC(_BT_CPPLOG_DEF_LOGGER, (_fmt), ##__VA_ARGS__) +#define BT_CPPLOGE(_fmt, ...) BT_CPPLOGE_SPEC(_BT_CPPLOG_DEF_LOGGER, (_fmt), ##__VA_ARGS__) +#define BT_CPPLOGF(_fmt, ...) BT_CPPLOGF_SPEC(_BT_CPPLOG_DEF_LOGGER, (_fmt), ##__VA_ARGS__) + +/* + * Calls logStrNoThrow() on `_logger` to log using the level `_lvl` + * without appending nor throwing. + */ +#define BT_CPPLOG_STR_EX(_lvl, _logger, _msg) \ + (_logger).logStrNoThrow<(_lvl), false>(__FILE__, __func__, __LINE__, (_msg)) + +/* + * BT_CPPLOG_STR_EX() with specific logging levels. + */ +#define BT_CPPLOGT_STR_SPEC(_logger, _msg) \ + BT_CPPLOG_STR_EX(bt2c::Logger::Level::TRACE, (_logger), (_msg)) +#define BT_CPPLOGD_STR_SPEC(_logger, _msg) \ + BT_CPPLOG_STR_EX(bt2c::Logger::Level::DEBUG, (_logger), (_msg)) +#define BT_CPPLOGI_STR_SPEC(_logger, _msg) \ + BT_CPPLOG_STR_EX(bt2c::Logger::Level::INFO, (_logger), (_msg)) +#define BT_CPPLOGW_STR_SPEC(_logger, _msg) \ + BT_CPPLOG_STR_EX(bt2c::Logger::Level::WARNING, (_logger), (_msg)) +#define BT_CPPLOGE_STR_SPEC(_logger, _msg) \ + BT_CPPLOG_STR_EX(bt2c::Logger::Level::ERROR, (_logger), (_msg)) +#define BT_CPPLOGF_STR_SPEC(_logger, _msg) \ + BT_CPPLOG_STR_EX(bt2c::Logger::Level::FATAL, (_logger), (_msg)) + +/* + * BT_CPPLOG_STR_EX() with specific logging levels and using the default + * logger. + */ +#define BT_CPPLOGT_STR(_msg) BT_CPPLOGT_STR_SPEC(_BT_CPPLOG_DEF_LOGGER, (_msg)) +#define BT_CPPLOGD_STR(_msg) BT_CPPLOGD_STR_SPEC(_BT_CPPLOG_DEF_LOGGER, (_msg)) +#define BT_CPPLOGI_STR(_msg) BT_CPPLOGI_STR_SPEC(_BT_CPPLOG_DEF_LOGGER, (_msg)) +#define BT_CPPLOGW_STR(_msg) BT_CPPLOGW_STR_SPEC(_BT_CPPLOG_DEF_LOGGER, (_msg)) +#define BT_CPPLOGE_STR(_msg) BT_CPPLOGE_STR_SPEC(_BT_CPPLOG_DEF_LOGGER, (_msg)) +#define BT_CPPLOGF_STR(_msg) BT_CPPLOGF_STR_SPEC(_BT_CPPLOG_DEF_LOGGER, (_msg)) + +/* + * Calls logMemNoThrow() on `_logger` to log using the level `_lvl` + * without appending nor throwing. + */ +#define BT_CPPLOG_MEM_EX(_lvl, _logger, _mem_data, _mem_len, _fmt, ...) \ + do { \ + if (G_UNLIKELY((_logger).wouldLog(_lvl))) { \ + (_logger).logMemNoThrow<(_lvl)>(__FILE__, __func__, __LINE__, (_mem_data), (_mem_len), \ + (_fmt), ##__VA_ARGS__); \ + } \ + } while (0) + +/* + * BT_CPPLOG_MEM_EX() with specific logging levels. + */ +#define BT_CPPLOGT_MEM_SPEC(_logger, _mem_data, _mem_len, _fmt, ...) \ + BT_CPPLOG_MEM_EX(bt2c::Logger::Level::TRACE, (_logger), (_mem_data), (_mem_len), (_fmt), \ + ##__VA_ARGS__) +#define BT_CPPLOGD_MEM_SPEC(_logger, _mem_data, _mem_len, _fmt, ...) \ + BT_CPPLOG_MEM_EX(bt2c::Logger::Level::DEBUG, (_logger), (_mem_data), (_mem_len), (_fmt), \ + ##__VA_ARGS__) +#define BT_CPPLOGI_MEM_SPEC(_logger, _mem_data, _mem_len, _fmt, ...) \ + BT_CPPLOG_MEM_EX(bt2c::Logger::Level::INFO, (_logger), (_mem_data), (_mem_len), (_fmt), \ + ##__VA_ARGS__) +#define BT_CPPLOGW_MEM_SPEC(_logger, _mem_data, _mem_len, _fmt, ...) \ + BT_CPPLOG_MEM_EX(bt2c::Logger::Level::WARNING, (_logger), (_mem_data), (_mem_len), (_fmt), \ + ##__VA_ARGS__) +#define BT_CPPLOGE_MEM_SPEC(_logger, _mem_data, _mem_len, _fmt, ...) \ + BT_CPPLOG_MEM_EX(bt2c::Logger::Level::ERROR, (_logger), (_mem_data), (_mem_len), (_fmt), \ + ##__VA_ARGS__) +#define BT_CPPLOGF_MEM_SPEC(_logger, _mem_data, _mem_len, _fmt, ...) \ + BT_CPPLOG_MEM_EX(bt2c::Logger::Level::FATAL, (_logger), (_mem_data), (_mem_len), (_fmt), \ + ##__VA_ARGS__) + +/* + * BT_CPPLOG_MEM_EX() with specific logging levels and using the default + * logger. + */ +#define BT_CPPLOGT_MEM(_mem_data, _mem_len, _fmt, ...) \ + BT_CPPLOGT_MEM_SPEC(_BT_CPPLOG_DEF_LOGGER, (_mem_data), (_mem_len), (_fmt), ##__VA_ARGS__) +#define BT_CPPLOGD_MEM(_mem_data, _mem_len, _fmt, ...) \ + BT_CPPLOGD_MEM_SPEC(_BT_CPPLOG_DEF_LOGGER, (_mem_data), (_mem_len), (_fmt), ##__VA_ARGS__) +#define BT_CPPLOGI_MEM(_mem_data, _mem_len, _fmt, ...) \ + BT_CPPLOGI_MEM_SPEC(_BT_CPPLOG_DEF_LOGGER, (_mem_data), (_mem_len), (_fmt), ##__VA_ARGS__) +#define BT_CPPLOGW_MEM(_mem_data, _mem_len, _fmt, ...) \ + BT_CPPLOGW_MEM_SPEC(_BT_CPPLOG_DEF_LOGGER, (_mem_data), (_mem_len), (_fmt), ##__VA_ARGS__) +#define BT_CPPLOGE_MEM(_mem_data, _mem_len, _fmt, ...) \ + BT_CPPLOGE_MEM_SPEC(_BT_CPPLOG_DEF_LOGGER, (_mem_data), (_mem_len), (_fmt), ##__VA_ARGS__) +#define BT_CPPLOGF_MEM(_mem_data, _mem_len, _fmt, ...) \ + BT_CPPLOGF_MEM_SPEC(_BT_CPPLOG_DEF_LOGGER, (_mem_data), (_mem_len), (_fmt), ##__VA_ARGS__) + +/* + * Calls logMemStrNoThrow() on `_logger` to log using the level `_lvl` + * without appending nor throwing. + */ +#define BT_CPPLOG_MEM_STR_EX(_lvl, _logger, _mem_data, _mem_len, _msg) \ + (_logger).logMemStrNoThrow<(_lvl)>(__FILE__, __func__, __LINE__, (_mem_data), (_mem_len), \ + (_msg)) + +/* + * BT_CPPLOG_MEM_STR_EX() with specific logging levels. + */ +#define BT_CPPLOGT_MEM_STR_SPEC(_logger, _mem_data, _mem_len, _msg) \ + BT_CPPLOG_MEM_STR_EX(bt2c::Logger::Level::TRACE, (_logger), (_mem_data), (_mem_len), (_msg)) +#define BT_CPPLOGD_MEM_STR_SPEC(_logger, _mem_data, _mem_len, _msg) \ + BT_CPPLOG_MEM_STR_EX(bt2c::Logger::Level::DEBUG, (_logger), (_mem_data), (_mem_len), (_msg)) +#define BT_CPPLOGI_MEM_STR_SPEC(_logger, _mem_data, _mem_len, _msg) \ + BT_CPPLOG_MEM_STR_EX(bt2c::Logger::Level::INFO, (_logger), (_mem_data), (_mem_len), (_msg)) +#define BT_CPPLOGW_MEM_STR_SPEC(_logger, _mem_data, _mem_len, _msg) \ + BT_CPPLOG_MEM_STR_EX(bt2c::Logger::Level::WARNING, (_logger), (_mem_data), (_mem_len), (_msg)) +#define BT_CPPLOGE_MEM_STR_SPEC(_logger, _mem_data, _mem_len, _msg) \ + BT_CPPLOG_MEM_STR_EX(bt2c::Logger::Level::ERROR, (_logger), (_mem_data), (_mem_len), (_msg)) +#define BT_CPPLOGF_MEM_STR_SPEC(_logger, _mem_data, _mem_len, _msg) \ + BT_CPPLOG_MEM_STR_EX(bt2c::Logger::Level::FATAL, (_logger), (_mem_data), (_mem_len), (_msg)) + +/* + * BT_CPPLOG_MEM_STR_EX() with specific logging levels and using the + * default logger. + */ +#define BT_CPPLOGT_MEM_STR(_mem_data, _mem_len, _msg) \ + BT_CPPLOGT_MEM_STR_SPEC(_BT_CPPLOG_DEF_LOGGER, (_mem_data), (_mem_len), (_msg)) +#define BT_CPPLOGD_MEM_STR(_mem_data, _mem_len, _msg) \ + BT_CPPLOGD_MEM_STR_SPEC(_BT_CPPLOG_DEF_LOGGER, (_mem_data), (_mem_len), (_msg)) +#define BT_CPPLOGI_MEM_STR(_mem_data, _mem_len, _msg) \ + BT_CPPLOGI_MEM_STR_SPEC(_BT_CPPLOG_DEF_LOGGER, (_mem_data), (_mem_len), (_msg)) +#define BT_CPPLOGW_MEM_STR(_mem_data, _mem_len, _msg) \ + BT_CPPLOGW_MEM_STR_SPEC(_BT_CPPLOG_DEF_LOGGER, (_mem_data), (_mem_len), (_msg)) +#define BT_CPPLOGE_MEM_STR(_mem_data, _mem_len, _msg) \ + BT_CPPLOGE_MEM_STR_SPEC(_BT_CPPLOG_DEF_LOGGER, (_mem_data), (_mem_len), (_msg)) +#define BT_CPPLOGF_MEM_STR(_mem_data, _mem_len, _msg) \ + BT_CPPLOGF_MEM_STR_SPEC(_BT_CPPLOG_DEF_LOGGER, (_mem_data), (_mem_len), (_msg)) + +/* + * Calls logErrnoNoThrow() on `_logger` to log using the level `_lvl` + * and initial message `_init_msg` without appending nor throwing. + */ +#define BT_CPPLOG_ERRNO_EX(_lvl, _logger, _init_msg, _fmt, ...) \ + do { \ + if (G_UNLIKELY((_logger).wouldLog(_lvl))) { \ + (_logger).logErrnoNoThrow<(_lvl), false>(__FILE__, __func__, __LINE__, (_init_msg), \ + (_fmt), ##__VA_ARGS__); \ + } \ + } while (0) + +/* + * BT_CPPLOG_ERRNO_EX() with specific logging levels. + */ +#define BT_CPPLOGT_ERRNO_SPEC(_logger, _init_msg, _fmt, ...) \ + BT_CPPLOG_ERRNO_EX(bt2c::Logger::Level::TRACE, (_logger), (_init_msg), (_fmt), ##__VA_ARGS__) +#define BT_CPPLOGD_ERRNO_SPEC(_logger, _init_msg, _fmt, ...) \ + BT_CPPLOG_ERRNO_EX(bt2c::Logger::Level::DEBUG, (_logger), (_init_msg), (_fmt), ##__VA_ARGS__) +#define BT_CPPLOGI_ERRNO_SPEC(_logger, _init_msg, _fmt, ...) \ + BT_CPPLOG_ERRNO_EX(bt2c::Logger::Level::INFO, (_logger), (_init_msg), (_fmt), ##__VA_ARGS__) +#define BT_CPPLOGW_ERRNO_SPEC(_logger, _init_msg, _fmt, ...) \ + BT_CPPLOG_ERRNO_EX(bt2c::Logger::Level::WARNING, (_logger), (_init_msg), (_fmt), ##__VA_ARGS__) +#define BT_CPPLOGE_ERRNO_SPEC(_logger, _init_msg, _fmt, ...) \ + BT_CPPLOG_ERRNO_EX(bt2c::Logger::Level::ERROR, (_logger), (_init_msg), (_fmt), ##__VA_ARGS__) +#define BT_CPPLOGF_ERRNO_SPEC(_logger, _init_msg, _fmt, ...) \ + BT_CPPLOG_ERRNO_EX(bt2c::Logger::Level::FATAL, (_logger), (_init_msg), (_fmt), ##__VA_ARGS__) + +/* + * BT_CPPLOG_ERRNO_EX() with specific logging levels and using the + * default logger. + */ +#define BT_CPPLOGT_ERRNO(_init_msg, _fmt, ...) \ + BT_CPPLOGT_ERRNO_SPEC(_BT_CPPLOG_DEF_LOGGER, (_init_msg), (_fmt), ##__VA_ARGS__) +#define BT_CPPLOGD_ERRNO(_init_msg, _fmt, ...) \ + BT_CPPLOGD_ERRNO_SPEC(_BT_CPPLOG_DEF_LOGGER, (_init_msg), (_fmt), ##__VA_ARGS__) +#define BT_CPPLOGI_ERRNO(_init_msg, _fmt, ...) \ + BT_CPPLOGI_ERRNO_SPEC(_BT_CPPLOG_DEF_LOGGER, (_init_msg), (_fmt), ##__VA_ARGS__) +#define BT_CPPLOGW_ERRNO(_init_msg, _fmt, ...) \ + BT_CPPLOGW_ERRNO_SPEC(_BT_CPPLOG_DEF_LOGGER, (_init_msg), (_fmt), ##__VA_ARGS__) +#define BT_CPPLOGE_ERRNO(_init_msg, _fmt, ...) \ + BT_CPPLOGE_ERRNO_SPEC(_BT_CPPLOG_DEF_LOGGER, (_init_msg), (_fmt), ##__VA_ARGS__) +#define BT_CPPLOGF_ERRNO(_init_msg, _fmt, ...) \ + BT_CPPLOGF_ERRNO_SPEC(_BT_CPPLOG_DEF_LOGGER, (_init_msg), (_fmt), ##__VA_ARGS__) + +/* + * Calls logErrnoStrNoThrow() on `_logger` to log using the level `_lvl` + * and initial message `_init_msg` without appending nor throwing. + */ +#define BT_CPPLOG_ERRNO_STR_EX(_lvl, _logger, _init_msg, _msg) \ + (_logger).logErrnoStrNoThrow<(_lvl), false>(__FILE__, __func__, __LINE__, (_init_msg), (_msg)) + +/* + * BT_CPPLOG_ERRNO_STR_EX() with specific logging levels. + */ +#define BT_CPPLOGT_ERRNO_STR_SPEC(_logger, _init_msg, _msg) \ + BT_CPPLOG_ERRNO_STR_EX(bt2c::Logger::Level::TRACE, (_logger), (_init_msg), (_msg)) +#define BT_CPPLOGD_ERRNO_STR_SPEC(_logger, _init_msg, _msg) \ + BT_CPPLOG_ERRNO_STR_EX(bt2c::Logger::Level::DEBUG, (_logger), (_init_msg), (_msg)) +#define BT_CPPLOGI_ERRNO_STR_SPEC(_logger, _init_msg, _msg) \ + BT_CPPLOG_ERRNO_STR_EX(bt2c::Logger::Level::INFO, (_logger), (_init_msg), (_msg)) +#define BT_CPPLOGW_ERRNO_STR_SPEC(_logger, _init_msg, _msg) \ + BT_CPPLOG_ERRNO_STR_EX(bt2c::Logger::Level::WARNING, (_logger), (_init_msg), (_msg)) +#define BT_CPPLOGE_ERRNO_STR_SPEC(_logger, _init_msg, _msg) \ + BT_CPPLOG_ERRNO_STR_EX(bt2c::Logger::Level::ERROR, (_logger), (_init_msg), (_msg)) +#define BT_CPPLOGF_ERRNO_STR_SPEC(_logger, _init_msg, _msg) \ + BT_CPPLOG_ERRNO_STR_EX(bt2c::Logger::Level::FATAL, (_logger), (_init_msg), (_msg)) + +/* + * BT_CPPLOG_ERRNO_STR_EX() with specific logging levels and using the + * default logger. + */ +#define BT_CPPLOGT_ERRNO_STR(_init_msg, _msg) \ + BT_CPPLOGT_ERRNO_STR_SPEC(_BT_CPPLOG_DEF_LOGGER, (_init_msg), (_msg)) +#define BT_CPPLOGD_ERRNO_STR(_init_msg, _msg) \ + BT_CPPLOGD_ERRNO_STR_SPEC(_BT_CPPLOG_DEF_LOGGER, (_init_msg), (_msg)) +#define BT_CPPLOGI_ERRNO_STR(_init_msg, _msg) \ + BT_CPPLOGI_ERRNO_STR_SPEC(_BT_CPPLOG_DEF_LOGGER, (_init_msg), (_msg)) +#define BT_CPPLOGW_ERRNO_STR(_init_msg, _msg) \ + BT_CPPLOGW_ERRNO_STR_SPEC(_BT_CPPLOG_DEF_LOGGER, (_init_msg), (_msg)) +#define BT_CPPLOGE_ERRNO_STR(_init_msg, _msg) \ + BT_CPPLOGE_ERRNO_STR_SPEC(_BT_CPPLOG_DEF_LOGGER, (_init_msg), (_msg)) +#define BT_CPPLOGF_ERRNO_STR(_init_msg, _msg) \ + BT_CPPLOGF_ERRNO_STR_SPEC(_BT_CPPLOG_DEF_LOGGER, (_init_msg), (_msg)) + +/* + * Calls logErrorAndThrow() on `_logger` to log an error, append a cause + * to the error of the current thread, and throw an instance of + * `_exc_cls`. + */ +#define BT_CPPLOGE_APPEND_CAUSE_AND_THROW_SPEC(_logger, _exc_cls, _fmt, ...) \ + (_logger).logErrorAndThrow(__FILE__, __func__, __LINE__, (_fmt), ##__VA_ARGS__) + +/* + * Calls logErrorAndThrow() on `_logger` to log an error, append a cause + * to the error of the current thread, and throw an instance of + * `_exc_cls`. + */ +#define BT_CPPLOGE_APPEND_CAUSE_AND_THROW_SPEC(_logger, _exc_cls, _fmt, ...) \ + (_logger).logErrorAndThrow(__FILE__, __func__, __LINE__, (_fmt), ##__VA_ARGS__) + +/* + * BT_CPPLOGE_APPEND_CAUSE_AND_THROW_SPEC() using the default logger. + */ +#define BT_CPPLOGE_APPEND_CAUSE_AND_THROW(_exc_cls, _fmt, ...) \ + BT_CPPLOGE_APPEND_CAUSE_AND_THROW_SPEC(_BT_CPPLOG_DEF_LOGGER, _exc_cls, (_fmt), ##__VA_ARGS__) + +/* + * Calls logErrorStrAndThrow() on `_logger` to log an error, append a + * cause to the error of the current thread, and throw an instance of + * `_exc_cls`. + */ +#define BT_CPPLOGE_STR_APPEND_CAUSE_AND_THROW_SPEC(_logger, _exc_cls, _msg) \ + (_logger).logErrorStrAndThrow(__FILE__, __func__, __LINE__, (_msg)) + +/* + * BT_CPPLOGE_STR_APPEND_CAUSE_AND_THROW_SPEC() using the default + * logger. + */ +#define BT_CPPLOGE_STR_APPEND_CAUSE_AND_THROW(_exc_cls, _msg) \ + BT_CPPLOGE_STR_APPEND_CAUSE_AND_THROW_SPEC(_BT_CPPLOG_DEF_LOGGER, _exc_cls, (_msg)) + +/* + * Calls logErrorAndRethrow() on `_logger` to log an error, append a + * cause to the error of the current thread, and throw an instance of + * `_exc_cls`. + */ +#define BT_CPPLOGE_APPEND_CAUSE_AND_RETHROW_SPEC(_logger, _fmt, ...) \ + (_logger).logErrorAndRethrow(__FILE__, __func__, __LINE__, (_fmt), ##__VA_ARGS__) + +/* + * BT_CPPLOGE_APPEND_CAUSE_AND_RETHROW_SPEC() using the default logger. + */ +#define BT_CPPLOGE_APPEND_CAUSE_AND_RETHROW(_fmt, ...) \ + BT_CPPLOGE_APPEND_CAUSE_AND_RETHROW_SPEC(_BT_CPPLOG_DEF_LOGGER, (_fmt), ##__VA_ARGS__) + +/* + * Calls logErrorStrAndRethrow() on `_logger` to log an error, append a + * cause to the error of the current thread, and throw an instance of + * `_exc_cls`. + */ +#define BT_CPPLOGE_STR_APPEND_CAUSE_AND_RETHROW_SPEC(_logger, _msg) \ + (_logger).logErrorStrAndRethrow(__FILE__, __func__, __LINE__, (_msg)) + +/* + * BT_CPPLOGE_STR_APPEND_CAUSE_AND_RETHROW_SPEC() using the default + * logger. + */ +#define BT_CPPLOGE_STR_APPEND_CAUSE_AND_RETHROW(_msg) \ + BT_CPPLOGE_STR_APPEND_CAUSE_AND_RETHROW_SPEC(_BT_CPPLOG_DEF_LOGGER, (_msg)) + +/* + * Calls logErrorErrnoAndThrow() on `_logger` to log an error, append a + * cause to the error of the current thread, and throw an instance of + * `_exc_cls`. + */ +#define BT_CPPLOGE_ERRNO_APPEND_CAUSE_AND_THROW_SPEC(_logger, _exc_cls, _init_msg, _fmt, ...) \ + (_logger).logErrorErrnoAndThrow(__FILE__, __func__, __LINE__, (_init_msg), \ + (_fmt), ##__VA_ARGS__) + +/* + * BT_CPPLOGE_ERRNO_APPEND_CAUSE_AND_THROW_SPEC() using the default + * logger. + */ +#define BT_CPPLOGE_ERRNO_APPEND_CAUSE_AND_THROW(_exc_cls, _init_msg, _fmt, ...) \ + BT_CPPLOGE_ERRNO_APPEND_CAUSE_AND_THROW_SPEC(_BT_CPPLOG_DEF_LOGGER, _exc_cls, (_init_msg), \ + (_fmt), ##__VA_ARGS__) + +/* + * Calls logErrorErrnoStrAndThrow() on `_logger` to log an error, append + * a cause to the error of the current thread, and throw an instance of + * `_exc_cls`. + */ +#define BT_CPPLOGE_ERRNO_STR_APPEND_CAUSE_AND_THROW_SPEC(_logger, _exc_cls, _init_msg, _msg) \ + (_logger).logErrorErrnoStrAndThrow(__FILE__, __func__, __LINE__, (_init_msg), \ + (_msg)) + +/* + * BT_CPPLOGE_ERRNO_STR_APPEND_CAUSE_AND_THROW_SPEC() using the default + * logger. + */ +#define BT_CPPLOGE_ERRNO_STR_APPEND_CAUSE_AND_THROW(_exc_cls, _init_msg, _msg) \ + BT_CPPLOGE_ERRNO_STR_APPEND_CAUSE_AND_THROW_SPEC(_BT_CPPLOG_DEF_LOGGER, _exc_cls, (_init_msg), \ + (_msg)) + +/* + * Calls logErrorErrnoAndRethrow() on `_logger` to log an error, append + * a cause to the error of the current thread, and throw an instance of + * `_exc_cls`. + */ +#define BT_CPPLOGE_ERRNO_APPEND_CAUSE_AND_RETHROW_SPEC(_logger, _init_msg, _fmt, ...) \ + (_logger).logErrorErrnoAndRethrow(__FILE__, __func__, __LINE__, (_init_msg), (_fmt), \ + ##__VA_ARGS__) + +/* + * BT_CPPLOGE_ERRNO_APPEND_CAUSE_AND_RETHROW_SPEC() using the default + * logger. + */ +#define BT_CPPLOGE_ERRNO_APPEND_CAUSE_AND_RETHROW(_init_msg, _fmt, ...) \ + BT_CPPLOGE_ERRNO_APPEND_CAUSE_AND_RETHROW_SPEC(_BT_CPPLOG_DEF_LOGGER, (_init_msg), (_fmt), \ + ##__VA_ARGS__) + +/* + * Calls logErrorErrnoStrAndRethrow() on `_logger` to log an error, + * append a cause to the error of the current thread, and throw an + * instance of `_exc_cls`. + */ +#define BT_CPPLOGE_ERRNO_STR_APPEND_CAUSE_AND_RETHROW_SPEC(_logger, _init_msg, _msg) \ + (_logger).logErrorErrnoStrAndRethrow(__FILE__, __func__, __LINE__, (_init_msg), (_msg)) + +/* + * BT_CPPLOGE_ERRNO_STR_APPEND_CAUSE_AND_RETHROW_SPEC() using the + * default logger. + */ +#define BT_CPPLOGE_ERRNO_STR_APPEND_CAUSE_AND_RETHROW(_init_msg, _msg) \ + BT_CPPLOGE_ERRNO_STR_APPEND_CAUSE_AND_RETHROW_SPEC(_BT_CPPLOG_DEF_LOGGER, (_init_msg), (_msg)) + +#endif /* BABELTRACE_CPP_COMMON_BT2C_LOGGING_HPP */ -- 2.34.1