Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:17:39

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 <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(&current_time, &tm_buf);
0087 
0088             // Extract milliseconds by calculating the duration since the last whole second
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 /// Macros
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 /// Backwards compatibility with JANA1 logger
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