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