Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-11 08:51:34

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