logger.cpp
1 // logger.cpp : Defines the functions for the static library. 2 // 3 #include "pch.h" 4 #include "framework.h" 5 #include "logger.h" 6 #include <unordered_map> 7 #include <spdlog/sinks/daily_file_sink.h> 8 #include <spdlog/sinks/msvc_sink.h> 9 #include <spdlog/sinks/null_sink.h> 10 #include <spdlog/sinks/stdout_color_sinks-inl.h> 11 #include <iostream> 12 13 using spdlog::sinks_init_list; 14 using spdlog::level::level_enum; 15 using spdlog::sinks::daily_file_sink_mt; 16 using spdlog::sinks::msvc_sink_mt; 17 using std::make_shared; 18 19 namespace 20 { 21 const std::unordered_map<std::wstring, level_enum> logLevelMapping = { 22 { L"trace", level_enum::trace }, 23 { L"debug", level_enum::debug }, 24 { L"info", level_enum::info }, 25 { L"warn", level_enum::warn }, 26 { L"err", level_enum::err }, 27 { L"critical", level_enum::critical }, 28 { L"off", level_enum::off }, 29 }; 30 } 31 32 level_enum getLogLevel(std::wstring_view logSettingsPath) 33 { 34 auto logLevel = get_log_settings(logSettingsPath).logLevel; 35 if (auto it = logLevelMapping.find(logLevel); it != logLevelMapping.end()) 36 { 37 return it->second; 38 } 39 40 if (auto it = logLevelMapping.find(LogSettings::defaultLogLevel); it != logLevelMapping.end()) 41 { 42 return it->second; 43 } 44 return level_enum::trace; 45 } 46 47 std::shared_ptr<spdlog::logger> Logger::logger = spdlog::null_logger_mt("null"); 48 49 bool Logger::wasLogFailedShown() 50 { 51 wchar_t* pValue; 52 size_t len; 53 _wdupenv_s(&pValue, &len, logFailedShown.c_str()); 54 delete[] pValue; 55 return len; 56 } 57 58 void Logger::init(std::string loggerName, std::wstring logFilePath, std::wstring_view logSettingsPath) 59 { 60 auto logLevel = getLogLevel(logSettingsPath); 61 bool newLoggerCreated = false; 62 try 63 { 64 logger = spdlog::get(loggerName); 65 if (logger == nullptr) 66 { 67 auto sink = make_shared<daily_file_sink_mt>(logFilePath, 0, 0, false, LogSettings::retention); 68 if (IsDebuggerPresent()) 69 { 70 auto msvc_sink = make_shared<msvc_sink_mt>(); 71 msvc_sink->set_pattern("[%Y-%m-%d %H:%M:%S.%f] [%n] [t-%t] [%l] %v"); 72 logger = make_shared<spdlog::logger>(loggerName, sinks_init_list{ sink, msvc_sink }); 73 } 74 else 75 { 76 logger = make_shared<spdlog::logger>(loggerName, sink); 77 } 78 newLoggerCreated = true; 79 } 80 } 81 catch (...) 82 { 83 logger = spdlog::null_logger_mt(loggerName); 84 if (!wasLogFailedShown()) 85 { 86 // todo: that message should be shown from init caller and strings should be localized 87 MessageBoxW(NULL, 88 L"Logger cannot be initialized", 89 L"PowerToys", 90 MB_OK | MB_ICONERROR); 91 92 SetEnvironmentVariable(logFailedShown.c_str(), L"yes"); 93 } 94 95 return; 96 } 97 98 if (newLoggerCreated) 99 { 100 logger->set_level(logLevel); 101 logger->set_pattern("[%Y-%m-%d %H:%M:%S.%f] [p-%P] [t-%t] [%l] %v"); 102 logger->flush_on(logLevel); // Auto flush on every log message. 103 spdlog::register_logger(logger); 104 } 105 106 logger->info("{} logger is initialized", loggerName); 107 } 108 109 void Logger::init(std::vector<spdlog::sink_ptr> sinks) 110 { 111 auto init_logger = std::make_shared<spdlog::logger>("", begin(sinks), end(sinks)); 112 if (!init_logger) 113 { 114 return; 115 } 116 117 Logger::logger = init_logger; 118 }