Warning, /acts/docs/core/misc/logging.md is written in an unsupported language. File is not indexed.
0001 # Logging
0002
0003 The ACTS logging facility supports several severity levels which allow you to
0004 control the amount of information displayed at run-time. Logger objects can
0005 easily be created using the {func}`Acts::getDefaultLogger` function which
0006 should be sufficient to get you started. In case you need more customized debug
0007 output, you can make use of the output decorators defined in
0008 `Acts::Logging` or even write your own implementation of
0009 {class}`Acts::Logging::OutputDecorator`. In order to add debug messages to your
0010 program, you should use the provided macros for the different severity levels:
0011
0012 ```cpp
0013 ACTS_VERBOSE(...);
0014 ACTS_DEBUG(...);
0015 ACTS_INFO(...);
0016 ACTS_WARNING(...);
0017 ACTS_ERROR(...);
0018 ACTS_FATAL(...);
0019 ```
0020
0021 These macros correspond to the available log levels:
0022
0023 :::{doxygenenum} Acts::Logging::Level
0024 :outline:
0025 :::
0026
0027
0028 The macros require that a function `logger` returning a {class}`Acts::Logger`
0029 object is available in the scope in which the macros are used:
0030
0031 ```cpp
0032 const Logger& logger() const;
0033 ```
0034
0035 Inside classes
0036 containing an {class}`Acts::Logger` object as member variable, this could be
0037 achieved by providing a private class method called `logger()` (for an example
0038 see e.g. {func}`Acts::CylinderVolumeBuilder::logger`). Inside free functions
0039 or member methods with local logger objects, the macros are also usable, since
0040 {class}`Acts::Logger` is callable and returns a reference to itself.
0041
0042 Code example illustrating the usage:
0043
0044 :::{doxygenfunction} Acts::getDefaultLogger
0045 :::
0046
0047 ```cpp
0048 #include <fstream>
0049 #include <memory>
0050
0051 #include "Acts/Utilities/Logger.hpp"
0052
0053 void myFunction() {
0054 // open the logfile
0055 std::ofstream logfile("log.txt");
0056 // set up a logger instance for >= INFO messages, streaming into the log file
0057 std::unique_ptr<const Acts::Logger> logger
0058 = Acts::getDefaultLogger("MyLogger", Acts::Logging::INFO, &logfile);
0059 // make sure the ACTS debug macros can work with your logger
0060 ACTS_VERBOSE("This message will not appear in the logfile.");
0061 ACTS_INFO("But this one will: Hello World!");
0062 // do not forget to close the logfile
0063 logfile.close();
0064 }
0065 ```
0066
0067 ## Logger integration
0068
0069 In case you are using ACTS in another framework which comes with its own
0070 logging facility (e.g. Gaudi) you can pipe the logging output from ACTS
0071 tools and algorithms to your framework's logging system by supplying different
0072 implementations of:
0073
0074 - {class}`Acts::Logging::OutputFilterPolicy` (for mapping logging levels)
0075 - {class}`Acts::Logging::OutputPrintPolicy` (for passing the Acts output
0076 to your internal logging system)
0077
0078 There are two approaches to logger integration:
0079
0080 1. [](override_deflog).
0081 This has the downside that log levels cannot be controlled from top-level
0082 experiment specific code. This means that it is non-trivial to steer the log
0083 level of an e.g. Gaudi algorithm via the `OutputLevel` property, and have
0084 the ACTS code respect this log level. It is therefore now **discouraged** to
0085 use this approach.
0086
0087 :::{note}
0088 ACTS code has iteratively moved to not construct loggers via
0089 {func}`Acts::getDefaultLogger` as much as possible, in favor of using a
0090 const-reference to {class}`Acts::Logger`. The latter can be defaulted to a
0091 dummy logger using {func}`Acts::getDummyLogger`. It is more suitable to
0092 pass into functions that might be called from other ACTS functions (rather
0093 than construction a local logger via `getDefaultLogger`, or creating logger
0094 instances on the fly).
0095 :::
0096
0097 2. Passing logger instances to high level components, and rely on ACTS code to
0098 pass them into lower level classes / functions.
0099
0100
0101 (override_deflog)=
0102 ### Overriding `Acts::getDefaultLogger`
0103
0104 :::{attention}
0105 Using this mechanism is now **discouraged** for integration with an experiment
0106 framework.
0107 :::
0108
0109 Since ACTS makes extensive use of {func}`Acts::getDefaultLogger` to provide
0110 sufficient information for debugging, you might want to provide a modified
0111 implementation of this function (using your output filter and printing
0112 policies) to also pipe this output to your framework. You can use the following
0113 approach using the possibility to inject custom code by preloading shared
0114 libraries with `LD_PRELOAD`. You need to provide an appropriate implementation
0115 for a function of the following signature into a separate source file and
0116 compile it in a shared library
0117
0118
0119 ```cpp
0120 namespace Acts {
0121 std::unique_ptr<const Logger> getDefaultLogger(const std::string&,
0122 const Logging::Level&,
0123 std::ostream*);
0124 }
0125 ```
0126
0127 Then you can run your executable, which uses ACTS tools and algorithms, in
0128 the following way (tested under Unix)
0129
0130 ```console
0131 $ LD_PRELOAD=<YOUR_SHARED_LIBRARY> path/to/your/executable
0132 ```
0133
0134 ## Logging thresholds
0135
0136 Generally, log levels in ACTS are only of informative value: even
0137 {enumerator}`Acts::Logging::Level::ERROR` and {enumerator}`Acts::Logging::Level::FATAL` will only print a
0138 messages, **and not terminate execution**.
0139
0140 This is desirable in an experiment context, where jobs should not immediately
0141 terminate when ACTS encounters something that is logged as an error. In a test
0142 context, however, this behavior is not optimal: the tests should ensure in
0143 known configurations errors do not occur, or only in specific circumstances. To
0144 solve this, ACTS implements an optional log *threshold* mechanism.
0145
0146 The threshold mechanism is steered via two CMake options:
0147 `ACTS_ENABLE_LOG_FAILURE_THRESHOLD` and `ACTS_LOG_FAILURE_THRESHOLD`. Depending
0148 on their configuration, the logging can operate in three modes:
0149
0150 1. **No log failure threshold** exists, log levels are informative only. This is
0151 the default behavior.
0152 2. A **compile-time log failure threshold** is set. If
0153 `ACTS_ENABLE_LOG_FAILURE_THRESHOLD=ON` and
0154 `ACTS_LOG_FAILURE_THRESHOLD=<LEVEL>` are set, the logger code will compile
0155 in a fixed check if the log level of a particular message exceeds `<LEVEL>`.
0156 If that is the case, an exception of type {class}`Acts::Logging::ThresholdFailure` is
0157 thrown.
0158 3. A **runtime log failure threshold** is set. If only
0159 `ACTS_ENABLE_LOG_FAILURE_THRESHOLD=ON` and no fixed threshold level is set,
0160 the logger code will compile in a check of a global runtime threshold
0161 variable.
0162
0163 :::{note}
0164 If only `ACTS_LOG_FAILURE_THRESHOLD` is set,
0165 `ACTS_ENABLE_LOG_FAILURE_THRESHOLD` will be set automatically, i.e. a
0166 compile-time threshold will be set
0167 :::
0168
0169 Two functions exist to interact with the failure threshold:
0170
0171 :::{doxygenfunction} Acts::Logging::getFailureThreshold
0172 :::
0173
0174 :::{doxygenfunction} Acts::Logging::setFailureThreshold
0175 :::