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
117namespace kiwano
118{
119
120KGE_DECLARE_SMART_PTR(LogFormater);
121KGE_DECLARE_SMART_PTR(LogProvider);
122
127enum class LogLevel
128{
129 Debug,
130 Info,
131 Notice,
132 Warning,
133 Error,
134};
135
140class KGE_API LogFormater : public ObjectBase
141{
142public:
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
154class KGE_API LogBuffer : public std::streambuf
155{
156public:
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
169protected:
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
179private:
180 Vector<char_type> buf_;
181 char_type* seek_high_;
182};
183
188class KGE_API LogProvider : public ObjectBase
189{
190public:
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
201protected:
202 LogProvider();
203
204 virtual void WriteMessage(LogLevel level, const char* msg) = 0;
205
206protected:
207 LogLevel level_;
208};
209
214class KGE_API ConsoleLogProvider : public LogProvider
215{
216public:
218
219 virtual ~ConsoleLogProvider();
220
221 void Init() override;
222
223 void Flush() override;
224
225protected:
226 void WriteMessage(LogLevel level, const char* msg) override;
227
228private:
229 typedef std::ostream&(*ConsoleColor)(std::ostream&);
230
231 ConsoleColor GetColor(LogLevel level);
232};
233
238class KGE_API FileLogProvider : public LogProvider
239{
240public:
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
249protected:
250 void WriteMessage(LogLevel level, const char* msg) override;
251
252private:
253 std::ofstream ofs_;
254};
255
260class KGE_API Logger final : public Singleton<Logger>
261{
262 friend Singleton<Logger>;
263
264public:
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
320private:
321 Logger();
322
323 std::iostream& GetFormatedStream(LogLevel level, LogBuffer* buffer);
324
325 void WriteToProviders(LogLevel level, LogBuffer* buffer);
326
327private:
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
337inline void Logger::Enable()
338{
339 enabled_ = true;
340}
341
342inline void Logger::Disable()
343{
344 enabled_ = false;
345}
346
347inline void Logger::SetFormater(LogFormaterPtr formater)
348{
349 formater_ = formater;
350}
351
352template <typename... _Args>
353inline 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
控制台日志生产者
Definition: Logger.h:215
文件日志生产者
Definition: Logger.h:239
日志流缓冲
Definition: Logger.h:155
日志格式化
Definition: Logger.h:141
日志生产者
Definition: Logger.h:189
日志记录器
Definition: Logger.h:261
void Enable()
启用日志
Definition: Logger.h:337
void SetFormater(LogFormaterPtr formater)
设置日志格式
Definition: Logger.h:347
void Disable()
禁用日志
Definition: Logger.h:342
void Log(LogLevel level, _Args &&... args)
打印日志
Definition: Logger.h:353
基础对象
Definition: ObjectBase.h:137
Definition: Singleton.h:28
时钟时间
Definition: Time.h:74