File indexing completed on 2025-01-18 10:17:39
0001
0002
0003
0004
0005 #pragma once
0006
0007 #include <JANA/Compatibility/JStreamLog.h>
0008
0009 #include <iostream>
0010 #include <sstream>
0011 #include <chrono>
0012 #include <thread>
0013 #include <iomanip>
0014 #include <time.h>
0015 #include <mutex>
0016
0017 #ifndef JANA2_USE_LOGGER_MUTEX
0018 #define JANA2_USE_LOGGER_MUTEX 0
0019 #endif
0020
0021
0022 struct JLogger {
0023 enum class Level { TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF };
0024 Level level;
0025 std::ostream *destination;
0026 std::string group;
0027 bool show_level = true;
0028 bool show_group = false;
0029 bool show_timestamp = true;
0030 bool show_threadstamp = false;
0031
0032 explicit JLogger(JLogger::Level level = JLogger::Level::INFO,
0033 std::ostream* destination = &std::cout,
0034 std::string group = "")
0035 : level(level), destination(destination), group(std::move(group)) {};
0036
0037 JLogger(const JLogger&) = default;
0038 JLogger& operator=(const JLogger&) = default;
0039
0040 void SetGroup(std::string group) {this->group = group; }
0041 void ShowGroup(bool show) {show_group = show; }
0042 void ShowLevel(bool show) {show_level = show; }
0043 void ShowTimestamp(bool show) {show_timestamp = show; }
0044 void ShowThreadstamp(bool show) {show_threadstamp = show; }
0045
0046 [[ deprecated("Use SetGroup() instead")]]
0047 void SetTag(std::string tag) {this->group = tag; }
0048 };
0049
0050
0051
0052 inline std::ostream& operator<<(std::ostream& s, JLogger::Level l) {
0053 switch (l) {
0054 case JLogger::Level::TRACE: return s << "trace";
0055 case JLogger::Level::DEBUG: return s << "debug";
0056 case JLogger::Level::INFO: return s << "info";
0057 case JLogger::Level::WARN: return s << "warn ";
0058 case JLogger::Level::ERROR: return s << "error";
0059 case JLogger::Level::FATAL: return s << "fatal";
0060 default: return s << "off";
0061 }
0062 }
0063
0064
0065 class JLogMessage : public std::stringstream {
0066 private:
0067 std::string m_prefix;
0068 std::ostream* m_destination;
0069
0070 public:
0071 JLogMessage(const std::string& prefix="") : m_prefix(prefix), m_destination(&std::cout){
0072 }
0073
0074 JLogMessage(JLogMessage&& moved_from) : std::stringstream(std::move(moved_from)) {
0075 m_prefix = moved_from.m_prefix;
0076 m_destination = moved_from.m_destination;
0077 }
0078
0079 JLogMessage(const JLogger& logger, JLogger::Level level) {
0080 m_destination = logger.destination;
0081 std::ostringstream builder;
0082 if (logger.show_timestamp) {
0083 auto now = std::chrono::system_clock::now();
0084 std::time_t current_time = std::chrono::system_clock::to_time_t(now);
0085 tm tm_buf;
0086 localtime_r(¤t_time, &tm_buf);
0087
0088
0089 auto milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()) % 1000;
0090 builder << std::put_time(&tm_buf, "%H:%M:%S.");
0091 builder << std::setfill('0') << std::setw(3) << milliseconds.count() << std::setfill(' ') << " ";
0092 }
0093 if (logger.show_level) {
0094 switch (level) {
0095 case JLogger::Level::TRACE: builder << "[trace] "; break;
0096 case JLogger::Level::DEBUG: builder << "[debug] "; break;
0097 case JLogger::Level::INFO: builder << " [info] "; break;
0098 case JLogger::Level::WARN: builder << " [warn] "; break;
0099 case JLogger::Level::ERROR: builder << "[error] "; break;
0100 case JLogger::Level::FATAL: builder << "[fatal] "; break;
0101 default: builder << "[?????] ";
0102 }
0103 }
0104 if (logger.show_threadstamp) {
0105 builder << std::this_thread::get_id() << " ";
0106 }
0107 if (logger.show_group && !logger.group.empty()) {
0108 builder << logger.group << " > ";
0109 }
0110 m_prefix = builder.str();
0111 }
0112
0113 virtual ~JLogMessage() {
0114 #if JANA2_USE_LOGGER_MUTEX
0115 static std::mutex cout_mutex;
0116 std::lock_guard<std::mutex> lock(cout_mutex);
0117 #endif
0118 std::string line;
0119 std::ostringstream oss;
0120 while (std::getline(*this, line)) {
0121 oss << m_prefix << line << std::endl;
0122 }
0123 *m_destination << oss.str();
0124 m_destination->flush();
0125 }
0126 };
0127
0128
0129 template <typename T>
0130 JLogMessage operator<<(const JLogger& logger, T&& t) {
0131 JLogMessage message(logger, logger.level);
0132 message << t;
0133 return message;
0134 }
0135
0136 inline JLogMessage operator<<(const JLogger& logger, std::ostream& (*manip)(std::ostream&)) {
0137 JLogMessage message(logger, logger.level);
0138 message << manip;
0139 return message;
0140 }
0141
0142
0143
0144
0145 #define LOG JLogMessage()
0146
0147 #define LOG_IF(predicate) if (predicate) JLogMessage()
0148
0149 #define LOG_END std::endl
0150
0151 #define LOG_AT_LEVEL(logger, msglevel) if ((logger).level <= msglevel) JLogMessage((logger), msglevel)
0152
0153 #define LOG_FATAL(logger) LOG_AT_LEVEL(logger, JLogger::Level::FATAL)
0154 #define LOG_ERROR(logger) LOG_AT_LEVEL(logger, JLogger::Level::ERROR)
0155 #define LOG_WARN(logger) LOG_AT_LEVEL(logger, JLogger::Level::WARN)
0156 #define LOG_INFO(logger) LOG_AT_LEVEL(logger, JLogger::Level::INFO)
0157 #define LOG_DEBUG(logger) LOG_AT_LEVEL(logger, JLogger::Level::DEBUG)
0158 #define LOG_TRACE(logger) LOG_AT_LEVEL(logger, JLogger::Level::TRACE)
0159
0160
0161
0162
0163 extern JLogger jout;
0164 extern JLogger jerr;
0165 #define jendl std::endl
0166 #define default_cout_logger jout
0167 #define default_cerr_logger jerr
0168 #define _DBG_ jerr<<__FILE__<<":"<<__LINE__<<" "
0169 #define _DBG__ jerr<<__FILE__<<":"<<__LINE__<<std::endl
0170