PageRenderTime 52ms CodeModel.GetById 12ms app.highlight 36ms RepoModel.GetById 1ms app.codeStats 0ms

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