Kiwano Engine  v1.2.x
Logger.h
1 // Copyright (c) 2016-2018 Kiwano - Nomango
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a copy
4 // of this software and associated documentation files (the "Software"), to deal
5 // in the Software without restriction, including without limitation the rights
6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 // copies of the Software, and to permit persons to whom the Software is
8 // furnished to do so, subject to the following conditions:
9 //
10 // The above copyright notice and this permission notice shall be included in
11 // all copies or substantial portions of the Software.
12 //
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 // THE SOFTWARE.
20 
21 #pragma once
22 #include <mutex>
23 #include <iomanip>
24 #include <streambuf>
25 #include <fstream>
26 #include <kiwano/core/Common.h>
27 #include <kiwano/core/Time.h>
28 #include <kiwano/base/ObjectBase.h>
29 
30 #ifndef KGE_DEBUG_LOG
31 #ifdef KGE_DEBUG
32 #define KGE_DEBUG_LOG(...) ::kiwano::Logger::GetInstance().Log(::kiwano::LogLevel::Debug, __VA_ARGS__)
33 #else
34 #define KGE_DEBUG_LOG __noop
35 #endif
36 #endif
37 
38 #ifndef KGE_LOG
39 #define KGE_LOG(...) ::kiwano::Logger::GetInstance().Log(::kiwano::LogLevel::Info, __VA_ARGS__)
40 #endif
41 
42 #ifndef KGE_NOTICE
43 #define KGE_NOTICE(...) ::kiwano::Logger::GetInstance().Log(::kiwano::LogLevel::Notice, __VA_ARGS__)
44 #endif
45 
46 #ifndef KGE_WARN
47 #define KGE_WARN(...) ::kiwano::Logger::GetInstance().Log(::kiwano::LogLevel::Warning, __VA_ARGS__)
48 #endif
49 
50 #ifndef KGE_ERROR
51 #define KGE_ERROR(...) ::kiwano::Logger::GetInstance().Log(::kiwano::LogLevel::Error, __VA_ARGS__)
52 #endif
53 
54 #ifndef KGE_DEBUG_LOGF
55 #ifdef KGE_DEBUG
56 #define KGE_DEBUG_LOGF(FORMAT, ...) ::kiwano::Logger::GetInstance().Logf(::kiwano::LogLevel::Debug, FORMAT, __VA_ARGS__)
57 #else
58 #define KGE_DEBUG_LOGF __noop
59 #endif
60 #endif
61 
62 #ifndef KGE_LOGF
63 #define KGE_LOGF(FORMAT, ...) ::kiwano::Logger::GetInstance().Logf(::kiwano::LogLevel::Info, FORMAT, __VA_ARGS__)
64 #endif
65 
66 #ifndef KGE_NOTICEF
67 #define KGE_NOTICEF(FORMAT, ...) ::kiwano::Logger::GetInstance().Logf(::kiwano::LogLevel::Notice, FORMAT, __VA_ARGS__)
68 #endif
69 
70 #ifndef KGE_WARNF
71 #define KGE_WARNF(FORMAT, ...) ::kiwano::Logger::GetInstance().Logf(::kiwano::LogLevel::Warning, FORMAT, __VA_ARGS__)
72 #endif
73 
74 #ifndef KGE_ERRORF
75 #define KGE_ERRORF(FORMAT, ...) ::kiwano::Logger::GetInstance().Logf(::kiwano::LogLevel::Error, FORMAT, __VA_ARGS__)
76 #endif
77 
78 #ifndef KGE_THROW
79 #define KGE_THROW(MESSAGE) \
80  do \
81  { \
82  KGE_ERRORF("An exception occurred: %s", MESSAGE); \
83  kiwano::StackTracer().Print(); \
84  throw kiwano::RuntimeError(MESSAGE); \
85  } while (0)
86 #endif
87 
88 #ifndef KGE_THROW_IF
89 #define KGE_THROW_IF(EXPRESSION, MESSAGE) \
90  if (EXPRESSION) \
91  { \
92  KGE_THROW(MESSAGE); \
93  }
94 #endif
95 
96 #ifndef KGE_THROW_SYSTEM_ERROR
97 #define KGE_THROW_SYSTEM_ERROR(ERRCODE, MESSAGE) \
98  do \
99  { \
100  KGE_ERRORF("An exception occurred (%#x): %s", ERRCODE, MESSAGE); \
101  kiwano::StackTracer().Print(); \
102  throw kiwano::SystemError(std::error_code(kiwano::error_enum(ERRCODE)), MESSAGE); \
103  } while (0)
104 #endif
105 
106 #ifdef KGE_PLATFORM_WINDOWS
107 #ifndef KGE_THROW_IF_FAILED
108 #define KGE_THROW_IF_FAILED(HR, MESSAGE) \
109  if (FAILED(HR)) \
110  { \
111  KGE_THROW_SYSTEM_ERROR(HR, MESSAGE); \
112  }
113 #endif
114 #endif // KGE_PLATFORM_WINDOWS
115 
116 
117 namespace kiwano
118 {
119 
120 KGE_DECLARE_SMART_PTR(LogFormater);
121 KGE_DECLARE_SMART_PTR(LogProvider);
122 
127 enum class LogLevel
128 {
129  Debug,
130  Info,
131  Notice,
132  Warning,
133  Error,
134 };
135 
140 class KGE_API LogFormater : public ObjectBase
141 {
142 public:
143  virtual void FormatHeader(std::ostream& out, LogLevel level, ClockTime time) = 0;
144 
145  virtual void FormatFooter(std::ostream& out, LogLevel level) = 0;
146 
147  String GetLevelLabel(LogLevel level) const;
148 };
149 
154 class KGE_API LogBuffer : public std::streambuf
155 {
156 public:
157  LogBuffer(size_t buffer_size);
158 
159  void Resize(size_t size);
160 
161  void Reset();
162 
163  const char* GetRaw() const;
164 
165  LogBuffer(const LogBuffer&) = delete;
166 
167  LogBuffer& operator=(const LogBuffer&) = delete;
168 
169 protected:
170  int_type overflow(int_type ch) override;
171 
172  int_type underflow() override;
173 
174  pos_type seekpos(pos_type sp, std::ios_base::openmode which) override;
175 
176  pos_type seekoff(off_type off, std::ios_base::seekdir dir,
177  std::ios_base::openmode which = std::ios_base::in) override;
178 
179 private:
180  Vector<char_type> buf_;
181  char_type* seek_high_;
182 };
183 
188 class KGE_API LogProvider : public ObjectBase
189 {
190 public:
191  virtual ~LogProvider();
192 
193  virtual void Init();
194 
195  virtual void Flush();
196 
197  void Write(LogLevel level, const char* msg);
198 
199  void SetLevel(LogLevel level);
200 
201 protected:
202  LogProvider();
203 
204  virtual void WriteMessage(LogLevel level, const char* msg) = 0;
205 
206 protected:
207  LogLevel level_;
208 };
209 
214 class KGE_API ConsoleLogProvider : public LogProvider
215 {
216 public:
218 
219  virtual ~ConsoleLogProvider();
220 
221  void Init() override;
222 
223  void Flush() override;
224 
225 protected:
226  void WriteMessage(LogLevel level, const char* msg) override;
227 
228 private:
229  typedef std::ostream&(*ConsoleColor)(std::ostream&);
230 
231  ConsoleColor GetColor(LogLevel level);
232 };
233 
238 class KGE_API FileLogProvider : public LogProvider
239 {
240 public:
241  FileLogProvider(const String& filepath, std::ios_base::openmode mode = std::ios_base::out);
242 
243  virtual ~FileLogProvider();
244 
245  void Init() override;
246 
247  void Flush() override;
248 
249 protected:
250  void WriteMessage(LogLevel level, const char* msg) override;
251 
252 private:
253  std::ofstream ofs_;
254 };
255 
260 class KGE_API Logger final : public Singleton<Logger>
261 {
262  friend Singleton<Logger>;
263 
264 public:
269  void Logf(LogLevel level, const char* format, ...);
270 
275  template <typename... _Args>
276  void Log(LogLevel level, _Args&&... args);
277 
280  void Flush();
281 
284  void Enable();
285 
288  void Disable();
289 
292  void SetLevel(LogLevel level);
293 
297  void AddProvider(LogProviderPtr provider);
298 
302  void SetFormater(LogFormaterPtr formater);
303 
307  LogFormaterPtr GetFormater();
308 
312  void ResizeBuffer(size_t buffer_size);
313 
316  void ShowConsole(bool show);
317 
318  virtual ~Logger();
319 
320 private:
321  Logger();
322 
323  std::iostream& GetFormatedStream(LogLevel level, LogBuffer* buffer);
324 
325  void WriteToProviders(LogLevel level, LogBuffer* buffer);
326 
327 private:
328  bool enabled_;
329  LogLevel level_;
330  LogFormaterPtr formater_;
331  LogBuffer buffer_;
332  std::iostream stream_;
333  Vector<LogProviderPtr> providers_;
334  std::mutex mutex_;
335 };
336 
337 inline void Logger::Enable()
338 {
339  enabled_ = true;
340 }
341 
342 inline void Logger::Disable()
343 {
344  enabled_ = false;
345 }
346 
347 inline void Logger::SetFormater(LogFormaterPtr formater)
348 {
349  formater_ = formater;
350 }
351 
352 template <typename... _Args>
353 inline void Logger::Log(LogLevel level, _Args&&... args)
354 {
355  if (!enabled_)
356  return;
357 
358  if (level < level_)
359  return;
360 
361  std::lock_guard<std::mutex> lock(mutex_);
362 
363  // build message
364  auto& stream = this->GetFormatedStream(level, &this->buffer_);
365  (void)std::initializer_list<int>{ ((stream << ' ' << args), 0)... };
366 
367  // write message
368  this->WriteToProviders(level, &this->buffer_);
369 }
370 
371 } // namespace kiwano
void Disable()
禁用日志
Definition: Logger.h:342
日志流缓冲
Definition: Logger.h:154
日志生产者
Definition: Logger.h:188
void Log(LogLevel level, _Args &&...args)
打印日志
Definition: Logger.h:353
Definition: Singleton.h:27
Definition: Actor.cpp:26
控制台日志生产者
Definition: Logger.h:214
时钟时间
Definition: Time.h:73
日志记录器
Definition: Logger.h:260
void Enable()
启用日志
Definition: Logger.h:337
日志格式化
Definition: Logger.h:140
void SetFormater(LogFormaterPtr formater)
设置日志格式
Definition: Logger.h:347
基础对象
Definition: ObjectBase.h:134
文件日志生产者
Definition: Logger.h:238