Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-27 09:14:58

0001 // lAger: General Purpose l/A-event Generator
0002 // Copyright (C) 2016-2021 Sylvester Joosten <sjoosten@anl.gov>
0003 // 
0004 // This file is part of lAger.
0005 // 
0006 // lAger is free software: you can redistribute it and/or modify
0007 // it under the terms of the GNU General Public License as published by
0008 // the Free Shoftware Foundation, either version 3 of the License, or
0009 // (at your option) any later version.
0010 // 
0011 // lAger is distributed in the hope that it will be useful,
0012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
0013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0014 // GNU General Public License for more details.
0015 // 
0016 // You should have received a copy of the GNU General Public License
0017 // along with lAger.  If not, see <https://www.gnu.org/licenses/>.
0018 // 
0019 
0020 #ifndef LAGER_CORE_LOGGER_LOADED
0021 #define LAGER_CORE_LOGGER_LOADED
0022 
0023 #include <array>
0024 #include <ctime>
0025 #include <iostream>
0026 #include <mutex>
0027 #include <ostream>
0028 #include <string>
0029 
0030 // =============================================================================
0031 // default global logger
0032 // =============================================================================
0033 
0034 // =============================================================================
0035 // Global logger, logging levels and functions.
0036 //
0037 // Actual logging should happen through the preprocessor macros
0038 //   * LOG_CRITICAL(title, text)
0039 //   * LOG_ERROR(title, text)
0040 //   * LOG_WARNING(title, text)
0041 //   * LOG_INFO(title, text)
0042 //   * LOG_DEBUG(title, text)
0043 //   * LOG_DEBUG2(title, text)
0044 // =============================================================================
0045 namespace lager {
0046 enum class log_level : unsigned {
0047   NOTHING = 0,
0048   CRITICAL = 1,
0049   ERROR = 2,
0050   WARNING = 3,
0051   INFO = 4,
0052   DEBUG = 5,
0053   JUNK = 6,
0054   JUNK2 = 7
0055 };
0056 constexpr std::array<const char*, 8> LOG_LEVEL_NAMES{
0057     "nothing", "critical", "error", "warning",
0058     "info",    "debug",    "junk",  "junk2"};
0059 
0060 // the global logger
0061 class log_handler;
0062 namespace global {
0063 extern log_handler logger;
0064 } // ns global
0065 template <log_level level>
0066 void log(const std::string& mtitle, const std::string& mtext,
0067          log_handler& logger = global::logger);
0068 } // ns lager
0069 
0070 // PREPROCESSOR macros to actually call the logger.
0071 // Strongly prefered over calling the logger function directly, as in the
0072 // macros,
0073 // mtitle and mtext (which might be complex expressions) are only evaluated
0074 // *after* the log_level check.
0075 // This is *significantly* (orders of magnitude!) faster than calling
0076 // log<LEVEL>(mtitle, mtext) directly in the code.
0077 #define LOG_CRITICAL(mtitle, mtext)                                            \
0078   if (lager::global::logger.level() >= log_level::CRITICAL) {                  \
0079     lager::log<lager::log_level::CRITICAL>((mtitle), (mtext));                 \
0080   }
0081 #define LOG_ERROR(mtitle, mtext)                                               \
0082   if (lager::global::logger.level() >= log_level::ERROR) {                     \
0083     lager::log<lager::log_level::ERROR>((mtitle), (mtext));                    \
0084   }
0085 #define LOG_WARNING(mtitle, mtext)                                             \
0086   if (lager::global::logger.level() >= log_level::WARNING) {                   \
0087     lager::log<lager::log_level::WARNING>((mtitle), (mtext));                  \
0088   }
0089 #define LOG_INFO(mtitle, mtext)                                                \
0090   if (lager::global::logger.level() >= log_level::INFO) {                      \
0091     lager::log<lager::log_level::INFO>((mtitle), (mtext));                     \
0092   }
0093 #define LOG_DEBUG(mtitle, mtext)                                               \
0094   if (lager::global::logger.level() >= log_level::DEBUG) {                     \
0095     lager::log<lager::log_level::DEBUG>((mtitle), (mtext));                    \
0096   }
0097 #define LOG_JUNK(mtitle, mtext)                                                \
0098   if (lager::global::logger.level() >= log_level::JUNK) {                      \
0099     lager::log<lager::log_level::JUNK>((mtitle), (mtext));                     \
0100   }
0101 #define LOG_JUNK2(mtitle, mtext)                                               \
0102   if (lager::global::logger.level() >= log_level::JUNK2) {                     \
0103     lager::log<lager::log_level::JUNK2>((mtitle), (mtext));                    \
0104   }
0105 
0106 // =============================================================================
0107 // log_handler class designed for global usage,
0108 // threading secure
0109 // =============================================================================
0110 namespace lager {
0111 class log_handler {
0112 private:
0113   typedef std::mutex mutex_type;
0114   typedef std::lock_guard<mutex_type> lock_type;
0115 
0116 public:
0117   log_handler(const log_level level = log_level::INFO,
0118               std::ostream& sink = std::cout);
0119 
0120   log_level level() const {
0121     lock_type lock{mutex_};
0122     return level_;
0123   }
0124 
0125   void set_level(const log_level level);
0126   void set_level(unsigned ulevel);
0127   void set_output(std::ostream& sink) { sink_ = &sink; }
0128 
0129   void operator()(const log_level mlevel, const std::string& mtitle,
0130                   const std::string& mtext) {
0131     lock_type lock{mutex_};
0132     if (mlevel > level_) {
0133       return;
0134     }
0135     time_t rt;
0136     time(&rt);
0137 
0138     std::ostream* sink =
0139         (mlevel == log_level::ERROR || mlevel == log_level::CRITICAL)
0140             ? &std::cerr
0141             : sink_;
0142 
0143     if (sink != &std::cout) {
0144       (*sink) << "[" << rt << ", " << mtitle << ", "
0145               << LOG_LEVEL_NAMES[static_cast<unsigned>(mlevel)] << "] " << mtext
0146               << std::endl;
0147     }
0148 
0149     std::cout << "[" << rt << ", " << mtitle << ", "
0150               << LOG_LEVEL_NAMES[static_cast<unsigned>(mlevel)] << "] " << mtext
0151               << std::endl;
0152   }
0153 
0154 private:
0155   log_level level_;
0156   std::ostream* sink_;
0157   mutable mutex_type mutex_;
0158 };
0159 } // ns lager
0160 
0161 // =============================================================================
0162 // global logger function
0163 // threading seutil
0164 // =============================================================================
0165 namespace lager {
0166 template <log_level level>
0167 void log(const std::string& mtitle, const std::string& mtext,
0168          log_handler& logger) {
0169   logger(level, mtitle, mtext);
0170 }
0171 } // ns lager
0172 
0173 #endif