File indexing completed on 2026-09-27 09:14:58
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
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
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
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
0061 class log_handler;
0062 namespace global {
0063 extern log_handler logger;
0064 }
0065 template <log_level level>
0066 void log(const std::string& mtitle, const std::string& mtext,
0067 log_handler& logger = global::logger);
0068 }
0069
0070
0071
0072
0073
0074
0075
0076
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
0108
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 }
0160
0161
0162
0163
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 }
0172
0173 #endif