Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-19 09:23:41

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