Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Logger.hpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file Logger.hpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2016-2018 CERN for the benefit of the Acts project
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 
9 #pragma once
10 // STL include(s)
11 #include <cassert>
12 #include <ctime>
13 #include <exception>
14 #include <functional>
15 #include <iomanip>
16 #include <iostream>
17 #include <memory>
18 #include <optional>
19 #include <sstream>
20 #include <stdexcept>
21 #include <string>
22 #include <string_view>
23 #include <thread>
24 #include <utility>
25 
26 // clang-format off
31 // <tt>std::unique_ptr<const Acts::Logger></tt>
49 #define ACTS_LOCAL_LOGGER(log_object) \
50  struct __local_acts_logger \
51  { \
52  __local_acts_logger(std::unique_ptr<const ::Acts::Logger> logger): \
53  m_logger(std::move(logger)) \
54  {} \
55  \
56  const ::Acts::Logger& operator()() const \
57  { \
58  return *m_logger; \
59  } \
60  \
61  std::unique_ptr<const ::Acts::Logger> m_logger; \
62  }; \
63  __local_acts_logger logger(log_object);
64 
65 // Debug level agnostic implementation of the ACTS_XYZ logging macros
66 #define ACTS_LOG(level, x) \
67  if (logger().doPrint(level)) { \
68  std::ostringstream os; \
69  os << x; \
70  logger().log(level, os.str()); \
71  }
72 
83 #define ACTS_VERBOSE(x) ACTS_LOG(Acts::Logging::VERBOSE, x)
84 
95 #define ACTS_DEBUG(x) ACTS_LOG(Acts::Logging::DEBUG, x)
96 
107 #define ACTS_INFO(x) ACTS_LOG(Acts::Logging::INFO, x)
108 
119 #define ACTS_WARNING(x) ACTS_LOG(Acts::Logging::WARNING, x)
120 
131 #define ACTS_ERROR(x) ACTS_LOG(Acts::Logging::ERROR, x)
132 
143 #define ACTS_FATAL(x) ACTS_LOG(Acts::Logging::FATAL, x)
144 // clang-format on
145 
146 namespace Acts {
147 
150 namespace Logging {
155 enum Level {
156  VERBOSE = 0,
163 };
164 
165 inline std::string_view levelName(Level level) {
166  switch (level) {
167  case Level::VERBOSE:
168  return "VERBOSE";
169  case Level::DEBUG:
170  return "DEBUG";
171  case Level::INFO:
172  return "INFO";
173  case Level::WARNING:
174  return "WARNING";
175  case Level::ERROR:
176  return "ERROR";
177  case Level::FATAL:
178  return "FATAL";
179  case Level::MAX:
180  return "MAX";
181  default:
182  throw std::invalid_argument{"Unknown level"};
183  }
184 }
185 
186 #ifdef DOXYGEN
187 
188 
189 
190 
191 
192 
193 
194 
196 
197 #else
198 
199 #ifdef ACTS_ENABLE_LOG_FAILURE_THRESHOLD
200 #ifdef ACTS_LOG_FAILURE_THRESHOLD
201 // We have a fixed compile time log failure threshold
202 constexpr Level getFailureThreshold() {
203  return Level::ACTS_LOG_FAILURE_THRESHOLD;
204 }
205 #else
207 #endif
208 #else
210  // Default "NO" failure threshold
211  return Level::MAX;
212 }
213 #endif
214 
215 #endif
216 
230 
232 class ThresholdFailure : public std::runtime_error {
233  using std::runtime_error::runtime_error;
234 };
235 
241  public:
243  virtual ~OutputPrintPolicy() = default;
244 
249  virtual void flush(const Level& lvl, const std::string& input) = 0;
250 
253  virtual const std::string& name() const = 0;
254 
258  virtual std::unique_ptr<OutputPrintPolicy> clone(
259  const std::string& name) const = 0;
260 };
261 
267  public:
269  virtual ~OutputFilterPolicy() = default;
270 
277  virtual bool doPrint(const Level& lvl) const = 0;
278 
281  virtual Level level() const = 0;
282 
286  virtual std::unique_ptr<OutputFilterPolicy> clone(Level level) const = 0;
287 };
288 
294  public:
298  explicit DefaultFilterPolicy(Level lvl) : m_level(lvl) {
299  if (lvl > getFailureThreshold()) {
300  throw ThresholdFailure(
301  "Requested debug level is incompatible with "
302  "the ACTS_LOG_FAILURE_THRESHOLD=" +
304  " configuration. See "
305  "https://acts.readthedocs.io/en/latest/core/"
306  "logging.html#logging-thresholds");
307  }
308  }
309 
311  ~DefaultFilterPolicy() override = default;
312 
318  bool doPrint(const Level& lvl) const override { return m_level <= lvl; }
319 
322  Level level() const override { return m_level; }
323 
327  std::unique_ptr<OutputFilterPolicy> clone(Level level) const override {
328  return std::make_unique<DefaultFilterPolicy>(level);
329  }
330 
331  private:
334 };
335 
342  public:
347  explicit OutputDecorator(std::unique_ptr<OutputPrintPolicy> wrappee)
348  : m_wrappee(std::move(wrappee)) {}
349 
357  void flush(const Level& lvl, const std::string& input) override {
358  m_wrappee->flush(lvl, input);
359  }
360 
363  const std::string& name() const override { return m_wrappee->name(); }
364 
365  protected:
367  std::unique_ptr<OutputPrintPolicy> m_wrappee;
368 };
369 
373 class NamedOutputDecorator final : public OutputDecorator {
374  public:
380  NamedOutputDecorator(std::unique_ptr<OutputPrintPolicy> wrappee,
381  const std::string& name, unsigned int maxWidth = 15)
382  : OutputDecorator(std::move(wrappee)),
383  m_name(name),
384  m_maxWidth(maxWidth) {}
385 
393  void flush(const Level& lvl, const std::string& input) override {
394  std::ostringstream os;
395  os << std::left << std::setw(m_maxWidth) << m_name.substr(0, m_maxWidth - 3)
396  << input;
397  OutputDecorator::flush(lvl, os.str());
398  }
399 
403  std::unique_ptr<OutputPrintPolicy> clone(
404  const std::string& name) const override {
405  return std::make_unique<NamedOutputDecorator>(m_wrappee->clone(name), name,
406  m_maxWidth);
407  }
408 
411  const std::string& name() const override { return m_name; }
412 
413  private:
416 
418  unsigned int m_maxWidth;
419 };
420 
424 class TimedOutputDecorator final : public OutputDecorator {
425  public:
430  TimedOutputDecorator(std::unique_ptr<OutputPrintPolicy> wrappee,
431  const std::string& format = "%X")
432  : OutputDecorator(std::move(wrappee)), m_format(format) {}
433 
441  void flush(const Level& lvl, const std::string& input) override {
442  std::ostringstream os;
443  os << std::left << std::setw(12) << now() << input;
444  OutputDecorator::flush(lvl, os.str());
445  }
446 
450  std::unique_ptr<OutputPrintPolicy> clone(
451  const std::string& name) const override {
452  return std::make_unique<TimedOutputDecorator>(m_wrappee->clone(name),
453  m_format);
454  }
455 
456  private:
460  std::string now() const {
461  char buffer[20];
462  time_t t{};
463  std::time(&t);
464  std::strftime(buffer, sizeof(buffer), m_format.c_str(), localtime(&t));
465  return buffer;
466  }
467 
470 };
471 
476  public:
480  explicit ThreadOutputDecorator(std::unique_ptr<OutputPrintPolicy> wrappee)
481  : OutputDecorator(std::move(wrappee)) {}
482 
490  void flush(const Level& lvl, const std::string& input) override {
491  std::ostringstream os;
492  os << std::left << std::setw(20) << std::this_thread::get_id() << input;
493  OutputDecorator::flush(lvl, os.str());
494  }
495 
499  std::unique_ptr<OutputPrintPolicy> clone(
500  const std::string& name) const override {
501  return std::make_unique<ThreadOutputDecorator>(m_wrappee->clone(name));
502  }
503 };
504 
508 class LevelOutputDecorator final : public OutputDecorator {
509  public:
513  explicit LevelOutputDecorator(std::unique_ptr<OutputPrintPolicy> wrappee)
514  : OutputDecorator(std::move(wrappee)) {}
515 
523  void flush(const Level& lvl, const std::string& input) override {
524  std::ostringstream os;
525  os << std::left << std::setw(10) << toString(lvl) << input;
526  OutputDecorator::flush(lvl, os.str());
527  }
528 
532  std::unique_ptr<OutputPrintPolicy> clone(
533  const std::string& name) const override {
534  return std::make_unique<LevelOutputDecorator>(m_wrappee->clone(name));
535  }
536 
537  private:
543  std::string toString(const Level& lvl) const {
544  static const char* const buffer[] = {"VERBOSE", "DEBUG", "INFO",
545  "WARNING", "ERROR", "FATAL"};
546  return buffer[lvl];
547  }
548 };
549 
554 class DefaultPrintPolicy final : public OutputPrintPolicy {
555  public:
561  explicit DefaultPrintPolicy(std::ostream* out = &std::cout) : m_out(out) {}
562 
567  void flush(const Level& lvl, const std::string& input) final {
568  (*m_out) << input << std::endl;
569  if (lvl >= getFailureThreshold()) {
570  throw ThresholdFailure(
571  "Previous debug message exceeds the "
572  "ACTS_LOG_FAILURE_THRESHOLD=" +
574  " configuration, bailing out. See "
575  "https://acts.readthedocs.io/en/latest/core/"
576  "logging.html#logging-thresholds");
577  }
578  }
579 
586  const std::string& name() const override {
587  throw std::runtime_error{
588  "Default print policy doesn't have a name. Is there no named output in "
589  "the decorator chain?"};
590  };
591 
595  std::unique_ptr<OutputPrintPolicy> clone(
596  const std::string& name) const override {
597  (void)name;
598  return std::make_unique<DefaultPrintPolicy>(m_out);
599  };
600 
601  private:
603  std::ostream* m_out;
604 };
605 } // namespace Logging
606 
613 class Logger {
614  public:
619  Logger(std::unique_ptr<Logging::OutputPrintPolicy> pPrint,
620  std::unique_ptr<Logging::OutputFilterPolicy> pFilter)
621  : m_printPolicy(std::move(pPrint)), m_filterPolicy(std::move(pFilter)) {}
622 
628  bool doPrint(const Logging::Level& lvl) const {
629  return m_filterPolicy->doPrint(lvl);
630  }
631 
636  void log(const Logging::Level& lvl, const std::string& input) const {
637  if (doPrint(lvl)) {
638  m_printPolicy->flush(lvl, input);
639  }
640  }
641 
645  return *m_printPolicy;
646  }
647 
651  return *m_filterPolicy;
652  }
653 
656  Logging::Level level() const { return m_filterPolicy->level(); }
657 
660  const std::string& name() const { return m_printPolicy->name(); }
661 
665  std::unique_ptr<Logger> clone(
666  const std::optional<std::string>& _name = std::nullopt,
667  const std::optional<Logging::Level>& _level = std::nullopt) const {
668  return std::make_unique<Logger>(
669  m_printPolicy->clone(_name.value_or(name())),
670  m_filterPolicy->clone(_level.value_or(level())));
671  }
672 
677  std::unique_ptr<Logger> clone(Logging::Level _level) const {
678  return clone(std::nullopt, _level);
679  }
680 
685  std::unique_ptr<Logger> cloneWithSuffix(
686  const std::string& suffix,
687  std::optional<Logging::Level> _level = std::nullopt) const {
688  return clone(name() + suffix, _level.value_or(level()));
689  }
690 
693  const Logger& operator()() const { return *this; }
694 
695  private:
697  std::unique_ptr<Logging::OutputPrintPolicy> m_printPolicy;
698 
700  std::unique_ptr<Logging::OutputFilterPolicy> m_filterPolicy;
701 };
702 
716 std::unique_ptr<const Logger> getDefaultLogger(
717  const std::string& name, const Logging::Level& lvl,
718  std::ostream* log_stream = &std::cout);
719 
720 const Logger& getDummyLogger();
721 
722 } // namespace Acts