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