/ src / common / logger / logger.cpp
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  }