Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-16 08:17:09

0001 // Copyright 2022, Dmitry Romanov
0002 // Subject to the terms in the LICENSE file found in the top-level directory.
0003 //
0004 //
0005 #include "Log_service.h"
0006 
0007 #include <JANA/JApplication.h>
0008 #include <JANA/JException.h>
0009 #include <spdlog/formatter.h>
0010 #include <spdlog/pattern_formatter.h>
0011 #include <spdlog/spdlog.h>
0012 #include <spdlog/version.h>
0013 #if SPDLOG_VERSION >= 11400 && (!defined(SPDLOG_NO_TLS) || !SPDLOG_NO_TLS)
0014 #include <spdlog/mdc.h>
0015 #endif
0016 #include <ctime>
0017 #include <exception>
0018 #include <map>
0019 #include <string_view>
0020 #include <utility>
0021 
0022 #include "extensions/spdlog/SpdlogExtensions.h"
0023 
0024 #if SPDLOG_VERSION >= 11400 && (!defined(SPDLOG_NO_TLS) || !SPDLOG_NO_TLS)
0025 
0026 // Define our own MDC formatter since the one in libspdlog.so does not
0027 // function correctly under some compilers
0028 class mdc_formatter_flag : public spdlog::custom_flag_formatter {
0029 public:
0030   void format(const spdlog::details::log_msg& /*msg*/, const std::tm& /*tm_time*/,
0031               spdlog::memory_buf_t& dest) override {
0032     auto& mdc_map = spdlog::mdc::get_context();
0033     if (mdc_map.empty()) {
0034       return;
0035     }
0036     format_mdc(mdc_map, dest);
0037   }
0038 
0039   static void format_mdc(const spdlog::mdc::mdc_map_t& mdc_map, spdlog::memory_buf_t& dest) {
0040     auto last_element = --mdc_map.end();
0041     for (auto it = mdc_map.begin(); it != mdc_map.end(); ++it) {
0042       const auto& pair  = *it;
0043       const auto& key   = pair.first;
0044       const auto& value = pair.second;
0045       dest.append(std::string_view{key});
0046       dest.append(std::string_view{":"});
0047       dest.append(std::string_view{value});
0048       if (it != last_element) {
0049         dest.append(std::string_view{" "});
0050       }
0051     }
0052   }
0053 
0054   std::unique_ptr<custom_flag_formatter> clone() const override {
0055     return spdlog::details::make_unique<mdc_formatter_flag>();
0056   }
0057 };
0058 
0059 #endif
0060 
0061 Log_service::Log_service(JApplication* app) : m_application(app), m_log_level_str("info") {
0062   // Here one could add centralized documentation for spdlog::default_logger()
0063   // All subsequent loggers are cloned from the spdlog::default_logger()
0064 
0065   m_application->SetDefaultParameter("eicrecon:LogLevel", m_log_level_str,
0066                                      "log_level: trace, debug, info, warn, error, critical, off");
0067   spdlog::default_logger()->set_level(eicrecon::ParseLogLevel(m_log_level_str));
0068 
0069   auto formatter = std::make_unique<spdlog::pattern_formatter>();
0070 #if SPDLOG_VERSION >= 11400 && (!defined(SPDLOG_NO_TLS) || !SPDLOG_NO_TLS)
0071   formatter->add_flag<mdc_formatter_flag>('&').set_pattern("[%&] [%n] [%^%l%$] %v");
0072 #else
0073   formatter->set_pattern("[%n] [%^%l%$] %v");
0074 #endif
0075   m_application->SetDefaultParameter("eicrecon:LogFormat", m_log_level_str,
0076                                      "spdlog pattern string");
0077   spdlog::set_formatter(std::move(formatter));
0078 }
0079 
0080 // Virtual destructor implementation to pin vtable and typeinfo to this
0081 // translation unit
0082 Log_service::~Log_service() = default;
0083 
0084 std::shared_ptr<spdlog::logger> Log_service::logger(const std::string& name,
0085                                                     const std::optional<level> default_level) {
0086 
0087   try {
0088     std::lock_guard<std::recursive_mutex> locker(m_lock);
0089 
0090     // Try to get existing logger
0091     auto logger = spdlog::get(name);
0092     if (!logger) {
0093       // or create a new one with current configuration
0094       logger = spdlog::default_logger()->clone(name);
0095 
0096       // Set log level for this named logger allowing user to specify as config. parameter
0097       // e.g. EcalEndcapPRecHits:LogLevel
0098       std::string log_level_str =
0099           default_level ? eicrecon::LogLevelToString(default_level.value()) : m_log_level_str;
0100       m_application->SetDefaultParameter(name + ":LogLevel", log_level_str,
0101                                          "log_level for " + name +
0102                                              ": trace, debug, info, warn, error, critical, off");
0103       logger->set_level(eicrecon::ParseLogLevel(log_level_str));
0104     }
0105     return logger;
0106   } catch (const std::exception& exception) {
0107     throw JException(exception.what());
0108   }
0109 }
0110 
0111 Log_service::level Log_service::getDefaultLevel() { return spdlog::default_logger()->level(); }
0112 
0113 std::string Log_service::getDefaultLevelStr() {
0114   return eicrecon::LogLevelToString(getDefaultLevel());
0115 }