Back to home page

EIC code displayed by LXR

 
 

    


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 // Copyright 2020, Jefferson Science Associates, LLC.
0003 // Subject to the terms in the LICENSE file found in the top-level directory.
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(&current_time, &tm_buf);
0093 
0094             // Extract milliseconds by calculating the duration since the last whole second
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 /// Macros
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 /// Backwards compatibility with JANA1 logger
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