cpp-common: add `logging.hpp` (`bt2c::Logger` and BT_CPPLOG*() macros)
authorPhilippe Proulx <eeppeliteloop@gmail.com>
Tue, 14 Nov 2023 19:25:39 +0000 (14:25 -0500)
committerSimon Marchi <simon.marchi@efficios.com>
Thu, 14 Dec 2023 15:57:04 +0000 (10:57 -0500)
commit7a72f18a55652b7166fb4adec37431c892e37fc9
tree43652be4d2bdf6c5f5df029532e107dbbb6578fc
parent7f66516e9046d905f08f55575fe801d5646745d5
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 <eeppeliteloop@gmail.com>
Change-Id: Iacb4c26e42c868f27e3a85b9fe163acac870624f
Reviewed-on: https://review.lttng.org/c/babeltrace/+/11388
Reviewed-by: Simon Marchi <simon.marchi@efficios.com>
Tested-by: jenkins <jenkins@lttng.org>
CI-Build: Simon Marchi <simon.marchi@efficios.com>
src/Makefile.am
src/cpp-common/bt2c/logging.hpp [new file with mode: 0644]
This page took 0.024192 seconds and 4 git commands to generate.