|
|
|||
File indexing completed on 2026-09-19 08:27:44
0001 // This file is part of the ACTS project. 0002 // 0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project 0004 // 0005 // This Source Code Form is subject to the terms of the Mozilla Public 0006 // License, v. 2.0. If a copy of the MPL was not distributed with this 0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/. 0008 0009 #pragma once 0010 0011 // STL include(s) 0012 #include <ctime> 0013 #include <iomanip> 0014 #include <iostream> 0015 #include <memory> 0016 #include <mutex> 0017 #include <optional> 0018 #include <sstream> 0019 #include <stdexcept> 0020 #include <string> 0021 #include <string_view> 0022 #include <thread> 0023 #include <utility> 0024 0025 /// @addtogroup logging 0026 /// @{ 0027 0028 /// @defgroup logging_macros Logging Macros 0029 /// @ingroup logging 0030 /// @brief Helper macros for logging with @ref Acts::Logger 0031 /// 0032 /// When a logger accessible via the `logger()` method, see @ref logging_patterns, 0033 /// use these macros to perform the actual logging: 0034 /// 0035 /// @snippet{trimleft} examples/logging.cpp Logging Macros 0036 /// 0037 /// The macros support stream-style formatting with `<<` operators. 0038 /// @{ 0039 0040 /// @brief Macro to use a local Acts::Logger object 0041 /// 0042 /// @param log_object logger instance of type 0043 // `std::unique_ptr<const Acts::Logger>` 0044 /// 0045 /// @pre In the current scope, the symbol @c logger is not yet defined. 0046 /// @post The ownership of the given @c log_object is transferred and 0047 /// @c log_object should not be used directly any more. 0048 /// 0049 /// This macro allows to use a locally defined logging object with the ACTS_* 0050 /// logging macros. The envisaged usage is the following: 0051 /// 0052 /// @snippet{trimleft} examples/logging.cpp Local logger macro 0053 #define ACTS_LOCAL_LOGGER(log_object) \ 0054 struct __local_acts_logger { \ 0055 explicit __local_acts_logger(std::unique_ptr<const ::Acts::Logger> logger) \ 0056 : m_logger(std::move(logger)) {} \ 0057 \ 0058 const ::Acts::Logger& operator()() const { return *m_logger; } \ 0059 \ 0060 std::unique_ptr<const ::Acts::Logger> m_logger; \ 0061 }; \ 0062 __local_acts_logger logger(log_object); 0063 0064 /// Log a message at the specified level with an explicit logger instance 0065 /// @param lgr The logger instance (must be a Acts::Logger reference) 0066 /// @param level The logging level 0067 /// @param x The message to log 0068 #define ACTS_LOG_WITH_LOGGER(lgr, level, x) \ 0069 do { \ 0070 if ((lgr).doPrint(level)) { \ 0071 std::ostringstream os; \ 0072 os << x; \ 0073 (lgr).log(level, os.str()); \ 0074 } \ 0075 } while (0) 0076 0077 /// Log a message at the specified level 0078 /// @param level The logging level 0079 /// @param x The message to log 0080 #define ACTS_LOG(level, x) ACTS_LOG_WITH_LOGGER(logger(), level, x) 0081 0082 /// @brief macro for verbose debug output 0083 /// 0084 /// @param x debug message 0085 /// 0086 /// @pre @c logger() must be a valid expression in the scope where this 0087 /// macro is used and it must return a Acts::Logger object. 0088 /// 0089 /// The debug message is printed if the current Acts::Logging::Level <= 0090 /// Acts::Logging::VERBOSE. 0091 #define ACTS_VERBOSE(x) ACTS_LOG(Acts::Logging::VERBOSE, x) 0092 0093 /// @brief macro for debug debug output 0094 /// 0095 /// @param x debug message 0096 /// 0097 /// @pre @c logger() must be a valid expression in the scope where this 0098 /// macro is used and it must return a Acts::Logger object. 0099 /// 0100 /// The debug message is printed if the current Acts::Logging::Level <= 0101 /// Acts::Logging::DEBUG. 0102 #define ACTS_DEBUG(x) ACTS_LOG(Acts::Logging::DEBUG, x) 0103 0104 /// @brief macro for info debug output 0105 /// 0106 /// @param x debug message 0107 /// 0108 /// @pre @c logger() must be a valid expression in the scope where this 0109 /// macro is used and it must return a Acts::Logger object. 0110 /// 0111 /// The debug message is printed if the current Acts::Logging::Level <= 0112 /// Acts::Logging::INFO. 0113 #define ACTS_INFO(x) ACTS_LOG(Acts::Logging::INFO, x) 0114 0115 /// @brief macro for warning debug output 0116 /// 0117 /// @param x debug message 0118 /// 0119 /// @pre @c logger() must be a valid expression in the scope where this 0120 /// macro is used and it must return a Acts::Logger object. 0121 /// 0122 /// The debug message is printed if the current Acts::Logging::Level <= 0123 /// Acts::Logging::WARNING. 0124 #define ACTS_WARNING(x) ACTS_LOG(Acts::Logging::WARNING, x) 0125 0126 /// @brief macro for error debug output 0127 /// 0128 /// @param x debug message 0129 /// 0130 /// @pre @c logger() must be a valid expression in the scope where this 0131 /// macro is used and it must return a Acts::Logger object. 0132 /// 0133 /// The debug message is printed if the current Acts::Logging::Level <= 0134 /// Acts::Logging::ERROR. 0135 #define ACTS_ERROR(x) ACTS_LOG(Acts::Logging::ERROR, x) 0136 0137 /// @brief macro for fatal debug output 0138 /// 0139 /// @param x debug message 0140 /// 0141 /// @pre @c logger() must be a valid expression in the scope where this 0142 /// macro is used and it must return a Acts::Logger object. 0143 /// 0144 /// The debug message is printed if the current Acts::Logging::Level <= 0145 /// Acts::Logging::FATAL. 0146 #define ACTS_FATAL(x) ACTS_LOG(Acts::Logging::FATAL, x) 0147 0148 /// @} 0149 /// @} 0150 0151 namespace Acts { 0152 0153 namespace Logging { 0154 0155 /// @addtogroup logging 0156 /// @{ 0157 0158 /// @brief constants steering the debug output 0159 /// 0160 /// All messages with a debug level equal or higher than the currently set 0161 /// debug output level will be printed. 0162 enum Level { 0163 VERBOSE = 0, ///< Detailed diagnostic trace information 0164 DEBUG, ///< Debug information during development 0165 INFO, ///< General information messages 0166 WARNING, ///< Non-critical error conditions 0167 ERROR, ///< Error conditions which require follow-up 0168 FATAL, ///< Unrecoverable error conditions 0169 MAX ///< Filler level 0170 }; 0171 0172 /// @brief Get the string name for a logging level 0173 /// @param level The logging level 0174 /// @return String representation of the logging level 0175 inline std::string_view levelName(Level level) { 0176 switch (level) { 0177 case Level::VERBOSE: 0178 return "VERBOSE"; 0179 case Level::DEBUG: 0180 return "DEBUG"; 0181 case Level::INFO: 0182 return "INFO"; 0183 case Level::WARNING: 0184 return "WARNING"; 0185 case Level::ERROR: 0186 return "ERROR"; 0187 case Level::FATAL: 0188 return "FATAL"; 0189 case Level::MAX: 0190 return "MAX"; 0191 default: 0192 throw std::invalid_argument{"Unknown level"}; 0193 } 0194 } 0195 0196 /// @defgroup logging_thresholds Logging Thresholds 0197 /// @ingroup logging 0198 /// @brief Functions and classes to manage logging failure thresholds 0199 /// 0200 /// Generally, log levels in ACTS are only of informative value: even 0201 /// @ref Acts::Logging::Level::ERROR and @ref Acts::Logging::Level::FATAL will only print 0202 /// messages, **and not terminate execution**. 0203 /// 0204 /// This is desirable in an experiment context, where jobs should not 0205 /// immediately terminate when ACTS encounters something that is logged as an 0206 /// error. In a test context, however, this behavior is not optimal: the tests 0207 /// should ensure in known configurations errors do not occur, or only in 0208 /// specific circumstances. To solve this, ACTS implements an optional log 0209 /// *threshold* mechanism. 0210 /// 0211 /// The threshold mechanism is steered via the CMake option 0212 /// `ACTS_ENABLE_LOG_FAILURE_THRESHOLD`, so the logging operates in one of two 0213 /// modes: 0214 /// 0215 /// 1. **No log failure threshold** exists, log levels are informative only. 0216 /// This is the default behavior. 0217 /// 2. A **runtime log failure threshold** is available. With 0218 /// `ACTS_ENABLE_LOG_FAILURE_THRESHOLD=ON` the logger code compiles in a 0219 /// check against a global threshold variable, seeded from the 0220 /// `ACTS_LOG_FAILURE_THRESHOLD` environment variable and settable with 0221 /// @ref Acts::Logging::setFailureThreshold. A message at or above it raises 0222 /// @ref Acts::Logging::ThresholdFailure after it has been emitted. The 0223 /// threshold defaults to @ref Acts::Logging::Level::MAX, so an enabled build 0224 /// with no threshold set behaves like a disabled one. 0225 /// 0226 /// @{ 0227 0228 #ifdef DOXYGEN 0229 /// @brief Get debug level above which an exception will be thrown after logging 0230 /// 0231 /// All messages with a debug level equal or higher than the return value of 0232 /// this function will cause an exception to be thrown after log emission. 0233 /// 0234 /// @note Depending on the preprocessor setting @c ACTS_ENABLE_LOG_FAILURE_THRESHOLD 0235 /// this operation is either constexpr or a runtime operation. 0236 /// @return The log level threshold for failure 0237 Level getFailureThreshold(); 0238 0239 #else 0240 0241 #ifdef ACTS_ENABLE_LOG_FAILURE_THRESHOLD 0242 Level getFailureThreshold(); 0243 #else 0244 constexpr Level getFailureThreshold() { 0245 // Default "NO" failure threshold 0246 return Level::MAX; 0247 } 0248 #endif 0249 0250 #endif 0251 0252 /// @brief Set debug level above which an exception will be thrown after logging 0253 /// 0254 /// All messages with a debug level equal or higher than @p level will 0255 /// cause an exception to be thrown after log emission. 0256 /// 0257 /// @warning The runtime log failure threshold is **global state**, therefore 0258 /// this function is **not threadsafe**. The intention is that this 0259 /// level is set once, before multi-threaded execution begins, and then 0260 /// not modified before the end of the job. 0261 /// @note This function is only available if @c ACTS_ENABLE_LOG_FAILURE_THRESHOLD 0262 /// is set. Otherwise an exception is thrown. 0263 /// @param level Log level above which exceptions will be thrown 0264 void setFailureThreshold(Level level); 0265 0266 /// Custom exception class so threshold failures can be caught 0267 class ThresholdFailure : public std::runtime_error { 0268 using std::runtime_error::runtime_error; 0269 }; 0270 0271 /// Helper class that changes the failure threshold for the duration of its 0272 /// lifetime. 0273 class ScopedFailureThreshold { 0274 public: 0275 /// Constructor that sets the failure threshold for the scope 0276 /// @param level The logging level to set as failure threshold 0277 explicit ScopedFailureThreshold(Level level) { setFailureThreshold(level); } 0278 ScopedFailureThreshold(const ScopedFailureThreshold&) = delete; 0279 ScopedFailureThreshold& operator=(const ScopedFailureThreshold&) = delete; 0280 ScopedFailureThreshold(ScopedFailureThreshold&&) = delete; 0281 ScopedFailureThreshold& operator=(ScopedFailureThreshold&&) = delete; 0282 0283 ~ScopedFailureThreshold() noexcept; 0284 0285 private: 0286 Level m_previousLevel{getFailureThreshold()}; 0287 }; 0288 0289 /// @} 0290 0291 /// @brief abstract base class for printing debug output 0292 /// 0293 /// Implementations of this interface need to define how and where to @a print 0294 /// debug messages (e.g. to a file, to a stream into a database etc). 0295 class OutputPrintPolicy { 0296 public: 0297 /// virtual default destructor 0298 virtual ~OutputPrintPolicy() = default; 0299 0300 /// @brief handle output of debug message 0301 /// 0302 /// @param [in] lvl debug output level of message 0303 /// @param [in] input text of debug message 0304 virtual void flush(const Level& lvl, const std::string& input) = 0; 0305 0306 /// Return the name of the print policy 0307 /// @return the name 0308 virtual const std::string& name() const = 0; 0309 0310 /// Make a copy of this print policy with a new name 0311 /// @param name the new name 0312 /// @return the copy 0313 virtual std::unique_ptr<OutputPrintPolicy> clone( 0314 const std::string& name) const = 0; 0315 }; 0316 0317 /// @brief abstract base class for filtering debug output 0318 /// 0319 /// Implementations of this interface need to define whether a debug message 0320 /// with a certain debug level is processed or filtered out. 0321 class OutputFilterPolicy { 0322 public: 0323 /// virtual default destructor 0324 virtual ~OutputFilterPolicy() = default; 0325 0326 /// @brief decide whether a debug message should be processed 0327 /// 0328 /// @param [in] lvl debug level of debug message 0329 /// 0330 /// @return @c true of debug message should be processed, @c false if debug 0331 /// message should be skipped 0332 virtual bool doPrint(const Level& lvl) const = 0; 0333 0334 /// Get the level of this filter policy 0335 /// @return the levele 0336 virtual Level level() const = 0; 0337 0338 /// Make a copy of this filter policy with a new level 0339 /// @param level the new level 0340 /// @return the new copy 0341 virtual std::unique_ptr<OutputFilterPolicy> clone(Level level) const = 0; 0342 }; 0343 0344 /// @brief default filter policy for debug messages 0345 /// 0346 /// All debug messages with a debug level equal or larger to the specified 0347 /// threshold level are processed. 0348 class DefaultFilterPolicy final : public OutputFilterPolicy { 0349 public: 0350 /// @brief constructor 0351 /// 0352 /// @param [in] lvl threshold debug level 0353 explicit DefaultFilterPolicy(Level lvl) : m_level(lvl) { 0354 if (lvl > getFailureThreshold()) { 0355 throw ThresholdFailure( 0356 "Requested debug level is incompatible with " 0357 "the ACTS_LOG_FAILURE_THRESHOLD=" + 0358 std::string{levelName(getFailureThreshold())} + 0359 " configuration. See " 0360 "https://cern.ch/acts-log-thresh"); 0361 } 0362 } 0363 0364 /// virtual default destructor 0365 ~DefaultFilterPolicy() override = default; 0366 0367 /// @brief decide whether a debug message should be processed 0368 /// 0369 /// @param [in] lvl debug level of debug message 0370 /// 0371 /// @return @c true if @p lvl >= #m_level, otherwise @c false 0372 bool doPrint(const Level& lvl) const override { return m_level <= lvl; } 0373 0374 /// Get the level of this filter policy 0375 /// @return the levele 0376 Level level() const override { return m_level; } 0377 0378 /// Make a copy of this filter policy with a new level 0379 /// @param level the new level 0380 /// @return the new copy 0381 std::unique_ptr<OutputFilterPolicy> clone(Level level) const override { 0382 return std::make_unique<DefaultFilterPolicy>(level); 0383 } 0384 0385 private: 0386 /// threshold debug level for messages to be processed 0387 Level m_level; 0388 }; 0389 0390 /// @brief base class for decorating the debug output 0391 /// 0392 /// Derived classes may augment the debug message with additional information. 0393 /// Chaining different decorators is possible to customize the output to your 0394 /// needs. 0395 class OutputDecorator : public OutputPrintPolicy { 0396 public: 0397 /// @brief constructor wrapping actual output print policy 0398 /// 0399 /// @param [in] wrappee output print policy object which is wrapped by this 0400 /// decorator object 0401 explicit OutputDecorator(std::unique_ptr<OutputPrintPolicy> wrappee) 0402 : m_wrappee(std::move(wrappee)) {} 0403 0404 /// @brief flush the debug message to the destination stream 0405 /// 0406 /// @param [in] lvl debug level of debug message 0407 /// @param [in] input text of debug message 0408 /// 0409 /// This function delegates the flushing of the debug message to its wrapped 0410 /// object. 0411 void flush(const Level& lvl, const std::string& input) override { 0412 m_wrappee->flush(lvl, input); 0413 } 0414 0415 /// Return the name of the output decorator (forwards to wrappee) 0416 /// @return the name 0417 const std::string& name() const override { return m_wrappee->name(); } 0418 0419 protected: 0420 /// wrapped object for printing the debug message 0421 std::unique_ptr<OutputPrintPolicy> m_wrappee; 0422 }; 0423 0424 /// @brief decorate debug message with a name 0425 /// 0426 /// The debug message is complemented with a name. 0427 class NamedOutputDecorator final : public OutputDecorator { 0428 public: 0429 /// @brief constructor 0430 /// 0431 /// @param [in] wrappee output print policy object to be wrapped 0432 /// @param [in] name name to be added to debug message 0433 /// @param [in] maxWidth maximum width of field used for name 0434 NamedOutputDecorator(std::unique_ptr<OutputPrintPolicy> wrappee, 0435 const std::string& name, unsigned int maxWidth = 15) 0436 : OutputDecorator(std::move(wrappee)), 0437 m_name(name), 0438 m_maxWidth(maxWidth) {} 0439 0440 /// @brief flush the debug message to the destination stream 0441 /// 0442 /// @param [in] lvl debug level of debug message 0443 /// @param [in] input text of debug message 0444 /// 0445 /// This function prepends the given name to the debug message and then 0446 /// delegates the flushing of the whole message to its wrapped object. 0447 void flush(const Level& lvl, const std::string& input) override { 0448 std::ostringstream os; 0449 os << std::left << std::setw(static_cast<int>(m_maxWidth)) 0450 << m_name.substr(0, m_maxWidth - 3) << input; 0451 OutputDecorator::flush(lvl, os.str()); 0452 } 0453 0454 /// Make a copy of this print policy with a new name 0455 /// @param name the new name 0456 /// @return the copy 0457 std::unique_ptr<OutputPrintPolicy> clone( 0458 const std::string& name) const override { 0459 return std::make_unique<NamedOutputDecorator>(m_wrappee->clone(name), name, 0460 m_maxWidth); 0461 } 0462 0463 /// Get this named output decorators name 0464 /// @return the name 0465 const std::string& name() const override { return m_name; } 0466 0467 private: 0468 /// name to be prepended 0469 std::string m_name; 0470 0471 /// maximum width of field for printing the name 0472 unsigned int m_maxWidth; 0473 }; 0474 0475 /// @brief decorate debug message with a time stamp 0476 /// 0477 /// The debug message is complemented with a time stamp. 0478 class TimedOutputDecorator final : public OutputDecorator { 0479 public: 0480 /// @brief constructor 0481 /// 0482 /// @param [in] wrappee output print policy object to be wrapped 0483 /// @param [in] format format of time stamp (see std::strftime) 0484 explicit TimedOutputDecorator(std::unique_ptr<OutputPrintPolicy> wrappee, 0485 const std::string& format = "%X") 0486 : OutputDecorator(std::move(wrappee)), m_format(format) {} 0487 0488 /// @brief flush the debug message to the destination stream 0489 /// 0490 /// @param [in] lvl debug level of debug message 0491 /// @param [in] input text of debug message 0492 /// 0493 /// This function prepends a time stamp to the debug message and then 0494 /// delegates the flushing of the whole message to its wrapped object. 0495 void flush(const Level& lvl, const std::string& input) override { 0496 std::ostringstream os; 0497 os << std::left << std::setw(12) << now() << input; 0498 OutputDecorator::flush(lvl, os.str()); 0499 } 0500 0501 /// Make a copy of this print policy with a new name 0502 /// @param name the new name 0503 /// @return the copy 0504 std::unique_ptr<OutputPrintPolicy> clone( 0505 const std::string& name) const override { 0506 return std::make_unique<TimedOutputDecorator>(m_wrappee->clone(name), 0507 m_format); 0508 } 0509 0510 private: 0511 /// @brief get current time stamp 0512 /// 0513 /// @return current time stamp as string 0514 std::string now() const { 0515 char buffer[20]; 0516 time_t t{}; 0517 std::time(&t); 0518 struct tm tbuf{}; 0519 std::strftime(buffer, sizeof(buffer), m_format.c_str(), 0520 localtime_r(&t, &tbuf)); 0521 return buffer; 0522 } 0523 0524 /// format of the time stamp (see std::strftime for details) 0525 std::string m_format; 0526 }; 0527 0528 /// @brief decorate debug message with a thread ID 0529 /// 0530 /// The debug message is complemented with a thread ID. 0531 class ThreadOutputDecorator final : public OutputDecorator { 0532 public: 0533 /// @brief constructor 0534 /// 0535 /// @param [in] wrappee output print policy object to be wrapped 0536 explicit ThreadOutputDecorator(std::unique_ptr<OutputPrintPolicy> wrappee) 0537 : OutputDecorator(std::move(wrappee)) {} 0538 0539 /// @brief flush the debug message to the destination stream 0540 /// 0541 /// @param [in] lvl debug level of debug message 0542 /// @param [in] input text of debug message 0543 /// 0544 /// This function prepends the thread ID to the debug message and then 0545 /// delegates the flushing of the whole message to its wrapped object. 0546 void flush(const Level& lvl, const std::string& input) override { 0547 std::ostringstream os; 0548 os << std::left << std::setw(20) << std::this_thread::get_id() << input; 0549 OutputDecorator::flush(lvl, os.str()); 0550 } 0551 0552 /// Make a copy of this print policy with a new name 0553 /// @param name the new name 0554 /// @return the copy 0555 std::unique_ptr<OutputPrintPolicy> clone( 0556 const std::string& name) const override { 0557 return std::make_unique<ThreadOutputDecorator>(m_wrappee->clone(name)); 0558 } 0559 }; 0560 0561 /// @brief decorate debug message with its debug level 0562 /// 0563 /// The debug message is complemented with its debug level. 0564 class LevelOutputDecorator final : public OutputDecorator { 0565 public: 0566 /// @brief constructor 0567 /// 0568 /// @param [in] wrappee output print policy object to be wrapped 0569 explicit LevelOutputDecorator(std::unique_ptr<OutputPrintPolicy> wrappee) 0570 : OutputDecorator(std::move(wrappee)) {} 0571 0572 /// @brief flush the debug message to the destination stream 0573 /// 0574 /// @param [in] lvl debug level of debug message 0575 /// @param [in] input text of debug message 0576 /// 0577 /// This function prepends the debug level to the debug message and then 0578 /// delegates the flushing of the whole message to its wrapped object. 0579 void flush(const Level& lvl, const std::string& input) override { 0580 std::ostringstream os; 0581 os << std::left << std::setw(10) << toString(lvl) << input; 0582 OutputDecorator::flush(lvl, os.str()); 0583 } 0584 0585 /// Make a copy of this print policy with a new name 0586 /// @param name the new name 0587 /// @return the copy 0588 std::unique_ptr<OutputPrintPolicy> clone( 0589 const std::string& name) const override { 0590 return std::make_unique<LevelOutputDecorator>(m_wrappee->clone(name)); 0591 } 0592 0593 private: 0594 /// @brief convert debug level to string 0595 /// 0596 /// @param [in] lvl debug level 0597 /// 0598 /// @return string representation of debug level 0599 std::string toString(const Level& lvl) const { 0600 static const char* const buffer[] = {"VERBOSE", "DEBUG", "INFO", 0601 "WARNING", "ERROR", "FATAL"}; 0602 return buffer[lvl]; 0603 } 0604 }; 0605 0606 /// @brief default print policy for debug messages 0607 /// 0608 /// This class allows to print debug messages without further modifications to 0609 /// a specified output stream. 0610 class DefaultPrintPolicy final : public OutputPrintPolicy { 0611 public: 0612 /// @brief constructor 0613 /// 0614 /// @param [in] out pointer to output stream object 0615 /// 0616 /// @pre @p out is non-zero 0617 explicit DefaultPrintPolicy(std::ostream* out = &std::cout) : m_out(out) {} 0618 0619 /// @brief flush the debug message to the destination stream 0620 /// 0621 /// @param [in] lvl debug level of debug message 0622 /// @param [in] input text of debug message 0623 void flush(const Level& lvl, const std::string& input) final { 0624 // Mutex to serialize access to std::cout 0625 static std::mutex s_stdoutMutex; 0626 std::unique_lock lock{s_stdoutMutex, 0627 std::defer_lock}; // prep empty, we might not need it 0628 0629 if (m_out == &std::cout) { 0630 lock.lock(); // lock only if we are printing to std::cout 0631 } 0632 0633 (*m_out) << input << std::endl; 0634 if (lvl >= getFailureThreshold()) { 0635 throw ThresholdFailure( 0636 "Previous debug message exceeds the " 0637 "ACTS_LOG_FAILURE_THRESHOLD=" + 0638 std::string{levelName(getFailureThreshold())} + 0639 " configuration, bailing out. See " 0640 "https://acts.readthedocs.io/en/latest/core/misc/" 0641 "logging.html#logging-thresholds"); 0642 } 0643 } 0644 0645 /// Fulfill @c OutputPrintPolicy interface. This policy doesn't actually have a 0646 /// name, so the assumption is that somewhere in the decorator hierarchy, 0647 /// there is something that returns a name without delegating to a wrappee, 0648 /// before reaching this overload. 0649 /// @note This method will throw an exception 0650 /// @return the name, but it never returns 0651 const std::string& name() const override { 0652 throw std::runtime_error{ 0653 "Default print policy doesn't have a name. Is there no named output in " 0654 "the decorator chain?"}; 0655 }; 0656 0657 /// Make a copy of this print policy with a new name 0658 /// @return the copy 0659 std::unique_ptr<OutputPrintPolicy> clone( 0660 const std::string& /*name*/) const override { 0661 return std::make_unique<DefaultPrintPolicy>(m_out); 0662 }; 0663 0664 private: 0665 /// pointer to destination output stream 0666 std::ostream* m_out; 0667 }; 0668 0669 /// @} 0670 0671 } // namespace Logging 0672 0673 /// @brief class for printing debug output 0674 /// @ingroup logging 0675 /// 0676 /// This class provides the user interface for printing debug messages with 0677 /// different levels of severity. 0678 /// 0679 class Logger { 0680 public: 0681 /// @brief construct from output print and filter policy 0682 /// 0683 /// @param [in] pPrint policy for printing debug messages 0684 /// @param [in] pFilter policy for filtering debug messages 0685 Logger(std::unique_ptr<Logging::OutputPrintPolicy> pPrint, 0686 std::unique_ptr<Logging::OutputFilterPolicy> pFilter) 0687 : m_printPolicy(std::move(pPrint)), m_filterPolicy(std::move(pFilter)) {} 0688 0689 /// @brief decide whether a message with a given debug level has to be printed 0690 /// 0691 /// @param [in] lvl debug level of debug message 0692 /// 0693 /// @return @c true if debug message should be printed, otherwise @c false 0694 bool doPrint(const Logging::Level& lvl) const { 0695 return m_filterPolicy->doPrint(lvl); 0696 } 0697 0698 /// @brief log a debug message 0699 /// 0700 /// @param [in] lvl debug level of debug message 0701 /// @param [in] input text of debug message 0702 void log(const Logging::Level& lvl, const std::string& input) const { 0703 if (doPrint(lvl)) { 0704 m_printPolicy->flush(lvl, input); 0705 } 0706 } 0707 0708 /// Return the print policy for this logger 0709 /// @return the print policy 0710 const Logging::OutputPrintPolicy& printPolicy() const { 0711 return *m_printPolicy; 0712 } 0713 0714 /// Return the filter policy for this logger 0715 /// @return the filter policy 0716 const Logging::OutputFilterPolicy& filterPolicy() const { 0717 return *m_filterPolicy; 0718 } 0719 0720 /// Return the level of the filter policy of this logger 0721 /// @return the level 0722 Logging::Level level() const { return m_filterPolicy->level(); } 0723 0724 /// Return the name of the print policy of this logger 0725 /// @return the name 0726 const std::string& name() const { return m_printPolicy->name(); } 0727 0728 /// Make a copy of this logger, optionally changing the name or the level 0729 /// @param _name the optional new name 0730 /// @param _level the optional new level 0731 /// @return Unique pointer to a cloned logger 0732 std::unique_ptr<Logger> clone( 0733 const std::optional<std::string>& _name = std::nullopt, 0734 const std::optional<Logging::Level>& _level = std::nullopt) const { 0735 return std::make_unique<Logger>( 0736 m_printPolicy->clone(_name.value_or(name())), 0737 m_filterPolicy->clone(_level.value_or(level()))); 0738 } 0739 0740 /// Make a copy of the logger, with a new level. Convenience function for 0741 /// if you only want to change the level but not the name. 0742 /// @param _level the new level 0743 /// @return the new logger 0744 std::unique_ptr<Logger> clone(Logging::Level _level) const { 0745 return clone(std::nullopt, _level); 0746 } 0747 0748 /// Make a copy of the logger, with a suffix added to the end of it's 0749 /// name. You can also optionally supply a new level 0750 /// @param suffix the suffix to add to the end of the name 0751 /// @param _level the optional new level 0752 /// @return Unique pointer to a cloned logger with modified name 0753 std::unique_ptr<Logger> cloneWithSuffix( 0754 const std::string& suffix, 0755 std::optional<Logging::Level> _level = std::nullopt) const { 0756 return clone(name() + suffix, _level.value_or(level())); 0757 } 0758 0759 /// Helper function so a logger reference can be used as is with the logging 0760 /// macros 0761 /// @return Reference to this logger 0762 const Logger& operator()() const { return *this; } 0763 0764 private: 0765 /// policy object for printing debug messages 0766 std::unique_ptr<Logging::OutputPrintPolicy> m_printPolicy; 0767 0768 /// policy object for filtering debug messages 0769 std::unique_ptr<Logging::OutputFilterPolicy> m_filterPolicy; 0770 }; 0771 0772 /// @brief get default debug output logger 0773 /// 0774 /// @param [in] name name of the logger instance 0775 /// @param [in] lvl debug threshold level 0776 /// @param [in] log_stream output stream used for printing debug messages 0777 /// 0778 /// This function returns a pointer to a Logger instance with the following 0779 /// decorations enabled: 0780 /// - time stamps 0781 /// - name of logging instance 0782 /// - debug level 0783 /// 0784 /// @return pointer to logging instance 0785 std::unique_ptr<const Logger> getDefaultLogger( 0786 const std::string& name, const Logging::Level& lvl, 0787 std::ostream* log_stream = &std::cout); 0788 0789 /// Get a dummy logger that discards all output 0790 /// @return Reference to dummy logger instance 0791 const Logger& getDummyLogger(); 0792 0793 } // namespace Acts
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|