File indexing completed on 2025-09-16 08:17:09
0001
0002
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
0027
0028 class mdc_formatter_flag : public spdlog::custom_flag_formatter {
0029 public:
0030 void format(const spdlog::details::log_msg& , const std::tm& ,
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
0063
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
0081
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
0091 auto logger = spdlog::get(name);
0092 if (!logger) {
0093
0094 logger = spdlog::default_logger()->clone(name);
0095
0096
0097
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 }