/xbmc/utils/log.h

http://github.com/xbmc/xbmc · C Header · 217 lines · 163 code · 41 blank · 13 comment · 8 complexity · 80945f7e6b7e1ed3e1e8e2f2fb02e95e MD5 · raw file

  1. /*
  2. * Copyright (C) 2005-2018 Team Kodi
  3. * This file is part of Kodi - https://kodi.tv
  4. *
  5. * SPDX-License-Identifier: GPL-2.0-or-later
  6. * See LICENSES/README.md for more information.
  7. */
  8. #pragma once
  9. // spdlog specific defines
  10. #define SPDLOG_LEVEL_NAMES {"TRACE", "DEBUG", "INFO", "WARNING", "ERROR", "FATAL", "OFF"};
  11. #include "commons/ilog.h"
  12. #include "settings/lib/ISettingCallback.h"
  13. #include "settings/lib/ISettingsHandler.h"
  14. #include "settings/lib/SettingDefinitions.h"
  15. #include "utils/IPlatformLog.h"
  16. #include "utils/StringUtils.h"
  17. #include "utils/logtypes.h"
  18. #include <string>
  19. #include <vector>
  20. #include <spdlog/spdlog.h>
  21. namespace spdlog
  22. {
  23. namespace sinks
  24. {
  25. template<typename Mutex>
  26. class basic_file_sink;
  27. template<typename Mutex>
  28. class dist_sink;
  29. } // namespace sinks
  30. } // namespace spdlog
  31. class CLog : public ISettingsHandler, public ISettingCallback
  32. {
  33. public:
  34. CLog();
  35. ~CLog() = default;
  36. // implementation of ISettingsHandler
  37. void OnSettingsLoaded() override;
  38. // implementation of ISettingCallback
  39. void OnSettingChanged(std::shared_ptr<const CSetting> setting) override;
  40. void Initialize(const std::string& path);
  41. void Uninitialize();
  42. void SetLogLevel(int level);
  43. int GetLogLevel() { return m_logLevel; }
  44. bool IsLogLevelLogged(int loglevel);
  45. bool CanLogComponent(uint32_t component) const;
  46. static void SettingOptionsLoggingComponentsFiller(std::shared_ptr<const CSetting> setting,
  47. std::vector<IntegerSettingOption>& list,
  48. int& current,
  49. void* data);
  50. Logger GetLogger(const std::string& loggerName);
  51. template<typename Char, typename... Args>
  52. static inline void Log(int level, const Char* format, Args&&... args)
  53. {
  54. Log(MapLogLevel(level), format, std::forward<Args>(args)...);
  55. }
  56. template<typename Char, typename... Args>
  57. static inline void Log(int level, uint32_t component, const Char* format, Args&&... args)
  58. {
  59. if (!GetInstance().CanLogComponent(component))
  60. return;
  61. Log(level, format, std::forward<Args>(args)...);
  62. }
  63. template<typename Char, typename... Args>
  64. static inline void Log(spdlog::level::level_enum level, const Char* format, Args&&... args)
  65. {
  66. GetInstance().FormatAndLogInternal(level, format, std::forward<Args>(args)...);
  67. }
  68. template<typename Char, typename... Args>
  69. static inline void Log(spdlog::level::level_enum level,
  70. uint32_t component,
  71. const Char* format,
  72. Args&&... args)
  73. {
  74. if (!GetInstance().CanLogComponent(component))
  75. return;
  76. Log(level, format, std::forward<Args>(args)...);
  77. }
  78. template<typename Char, typename... Args>
  79. static inline void LogFunction(int level,
  80. const char* functionName,
  81. const Char* format,
  82. Args&&... args)
  83. {
  84. LogFunction(MapLogLevel(level), functionName, format, std::forward<Args>(args)...);
  85. }
  86. template<typename Char, typename... Args>
  87. static inline void LogFunction(
  88. int level, const char* functionName, uint32_t component, const Char* format, Args&&... args)
  89. {
  90. if (!GetInstance().CanLogComponent(component))
  91. return;
  92. LogFunction(level, functionName, format, std::forward<Args>(args)...);
  93. }
  94. template<typename Char, typename... Args>
  95. static inline void LogFunction(spdlog::level::level_enum level,
  96. const char* functionName,
  97. const Char* format,
  98. Args&&... args)
  99. {
  100. if (functionName == nullptr || strlen(functionName) == 0)
  101. GetInstance().FormatAndLogInternal(level, format, std::forward<Args>(args)...);
  102. else
  103. GetInstance().FormatAndLogFunctionInternal(level, functionName, format,
  104. std::forward<Args>(args)...);
  105. }
  106. template<typename Char, typename... Args>
  107. static inline void LogFunction(spdlog::level::level_enum level,
  108. const char* functionName,
  109. uint32_t component,
  110. const Char* format,
  111. Args&&... args)
  112. {
  113. if (!GetInstance().CanLogComponent(component))
  114. return;
  115. LogFunction(level, functionName, format, std::forward<Args>(args)...);
  116. }
  117. #define LogF(level, format, ...) LogFunction((level), __FUNCTION__, (format), ##__VA_ARGS__)
  118. #define LogFC(level, component, format, ...) \
  119. LogFunction((level), __FUNCTION__, (component), (format), ##__VA_ARGS__)
  120. private:
  121. static CLog& GetInstance();
  122. static spdlog::level::level_enum MapLogLevel(int level);
  123. template<typename... Args>
  124. static inline void FormatAndLogFunctionInternal(spdlog::level::level_enum level,
  125. const char* functionName,
  126. const char* format,
  127. Args&&... args)
  128. {
  129. GetInstance().FormatAndLogInternal(
  130. level, StringUtils::Format("{0:s}: {1:s}", functionName, format).c_str(),
  131. std::forward<Args>(args)...);
  132. }
  133. template<typename... Args>
  134. static inline void FormatAndLogFunctionInternal(spdlog::level::level_enum level,
  135. const char* functionName,
  136. const wchar_t* format,
  137. Args&&... args)
  138. {
  139. GetInstance().FormatAndLogInternal(
  140. level, StringUtils::Format(L"{0:s}: {1:s}", functionName, format).c_str(),
  141. std::forward<Args>(args)...);
  142. }
  143. template<typename Char, typename... Args>
  144. inline void FormatAndLogInternal(spdlog::level::level_enum level,
  145. const Char* format,
  146. Args&&... args)
  147. {
  148. // TODO: for now we manually format the messages to support both python- and printf-style formatting.
  149. // this can be removed once all log messages have been adjusted to python-style formatting
  150. auto logString = StringUtils::Format(format, std::forward<Args>(args)...);
  151. // fixup newline alignment, number of spaces should equal prefix length
  152. StringUtils::Replace(logString, "\n", "\n ");
  153. m_defaultLogger->log(level, std::move(logString));
  154. }
  155. Logger CreateLogger(const std::string& loggerName);
  156. void SetComponentLogLevel(const std::vector<CVariant>& components);
  157. std::unique_ptr<IPlatformLog> m_platform;
  158. std::shared_ptr<spdlog::sinks::dist_sink<std::mutex>> m_sinks;
  159. Logger m_defaultLogger;
  160. std::shared_ptr<spdlog::sinks::basic_file_sink<std::mutex>> m_fileSink;
  161. int m_logLevel;
  162. bool m_componentLogEnabled;
  163. uint32_t m_componentLogLevels;
  164. };
  165. namespace XbmcUtils
  166. {
  167. class LogImplementation : public XbmcCommons::ILogger
  168. {
  169. public:
  170. ~LogImplementation() override = default;
  171. inline void log(int logLevel, IN_STRING const char* message) override
  172. {
  173. CLog::Log(logLevel, "{0:s}", message);
  174. }
  175. };
  176. } // namespace XbmcUtils