Back to home page

EIC code displayed by LXR

 
 

    


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