File indexing completed on 2025-07-01 07:56:34
0001
0002
0003
0004
0005 #include "Log_service.h"
0006
0007 #include <JANA/JApplication.h>
0008 #include <JANA/JException.h>
0009 #include <spdlog/details/log_msg.h>
0010 #include <spdlog/formatter.h>
0011 #include <spdlog/pattern_formatter.h>
0012 #include <spdlog/spdlog.h>
0013 #include <spdlog/version.h>
0014 #if SPDLOG_VERSION >= 11400 && (!defined(SPDLOG_NO_TLS) || !SPDLOG_NO_TLS)
0015 #include <spdlog/mdc.h>
0016 #endif
0017 #include <ctime>
0018 #include <exception>
0019 #include <map>
0020 #include <string_view>
0021 #include <utility>
0022
0023 #include "extensions/spdlog/SpdlogExtensions.h"
0024
0025 #if SPDLOG_VERSION >= 11400 && (!defined(SPDLOG_NO_TLS) || !SPDLOG_NO_TLS)
0026
0027
0028
0029 class mdc_formatter_flag : public spdlog::custom_flag_formatter {
0030 public:
0031 void format(const spdlog::details::log_msg& , const std::tm& ,
0032 spdlog::memory_buf_t& dest) override {
0033 auto& mdc_map = spdlog::mdc::get_context();
0034 if (mdc_map.empty()) {
0035 return;
0036 }
0037 format_mdc(mdc_map, dest);
0038 }
0039
0040 static void format_mdc(const spdlog::mdc::mdc_map_t& mdc_map, spdlog::memory_buf_t& dest) {
0041 auto last_element = --mdc_map.end();
0042 for (auto it = mdc_map.begin(); it != mdc_map.end(); ++it) {
0043 const auto& pair = *it;
0044 const auto& key = pair.first;
0045 const auto& value = pair.second;
0046 dest.append(std::string_view{key});
0047 dest.append(std::string_view{":"});
0048 dest.append(std::string_view{value});
0049 if (it != last_element) {
0050 dest.append(std::string_view{" "});
0051 }
0052 }
0053 }
0054
0055 std::unique_ptr<custom_flag_formatter> clone() const override {
0056 return spdlog::details::make_unique<mdc_formatter_flag>();
0057 }
0058 };
0059
0060 #endif
0061
0062 Log_service::Log_service(JApplication* app) : m_application(app), m_log_level_str("info") {
0063
0064
0065
0066 m_application->SetDefaultParameter("eicrecon:LogLevel", m_log_level_str,
0067 "log_level: trace, debug, info, warn, error, critical, off");
0068 spdlog::default_logger()->set_level(eicrecon::ParseLogLevel(m_log_level_str));
0069
0070 auto formatter = std::make_unique<spdlog::pattern_formatter>();
0071 #if SPDLOG_VERSION >= 11400 && (!defined(SPDLOG_NO_TLS) || !SPDLOG_NO_TLS)
0072 formatter->add_flag<mdc_formatter_flag>('&').set_pattern("[%&] [%n] [%^%l%$] %v");
0073 #else
0074 formatter->set_pattern("[%n] [%^%l%$] %v");
0075 #endif
0076 m_application->SetDefaultParameter("eicrecon:LogFormat", m_log_level_str,
0077 "spdlog pattern string");
0078 spdlog::set_formatter(std::move(formatter));
0079 }
0080
0081
0082
0083 Log_service::~Log_service() = default;
0084
0085 std::shared_ptr<spdlog::logger> Log_service::logger(const std::string& name,
0086 const std::optional<level> default_level) {
0087
0088 try {
0089 std::lock_guard<std::recursive_mutex> locker(m_lock);
0090
0091
0092 auto logger = spdlog::get(name);
0093 if (!logger) {
0094
0095 logger = spdlog::default_logger()->clone(name);
0096
0097
0098
0099 std::string log_level_str =
0100 default_level ? eicrecon::LogLevelToString(default_level.value()) : m_log_level_str;
0101 m_application->SetDefaultParameter(name + ":LogLevel", log_level_str,
0102 "log_level for " + name +
0103 ": trace, debug, info, warn, error, critical, off");
0104 logger->set_level(eicrecon::ParseLogLevel(log_level_str));
0105 }
0106 return logger;
0107 } catch (const std::exception& exception) {
0108 throw JException(exception.what());
0109 }
0110 }
0111
0112 Log_service::level Log_service::getDefaultLevel() { return spdlog::default_logger()->level(); }
0113
0114 std::string Log_service::getDefaultLevelStr() {
0115 return eicrecon::LogLevelToString(getDefaultLevel());
0116 }