Kiwano Engine v1.3.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
116namespace kiwano
117{
118
123enum class LogLevel
124{
125 Debug,
126 Info,
127 Notice,
128 Warning,
129 Error,
130};
131
136class KGE_API LogFormater : public ObjectBase
137{
138public:
139 virtual void FormatHeader(std::ostream& out, LogLevel level, ClockTime time) = 0;
140
141 virtual void FormatFooter(std::ostream& out, LogLevel level) = 0;
142
143 String GetLevelLabel(LogLevel level) const;
144};
145
150class KGE_API LogBuffer : public std::streambuf
151{
152public:
153 LogBuffer(size_t buffer_size);
154
155 void Resize(size_t size);
156
157 void Reset();
158
159 const char* GetRaw() const;
160
161 LogBuffer(const LogBuffer&) = delete;
162
163 LogBuffer& operator=(const LogBuffer&) = delete;
164
165protected:
166 int_type overflow(int_type ch) override;
167
168 int_type underflow() override;
169
170 pos_type seekpos(pos_type sp, std::ios_base::openmode which) override;
171
172 pos_type seekoff(off_type off, std::ios_base::seekdir dir,
173 std::ios_base::openmode which = std::ios_base::in) override;
174
175private:
176 Vector<char_type> buf_;
177 char_type* seek_high_;
178};
179
184class KGE_API LogProvider : public ObjectBase
185{
186public:
187 virtual ~LogProvider();
188
189 virtual void Init();
190
191 virtual void Flush();
192
193 void Write(LogLevel level, const char* msg);
194
195 void SetLevel(LogLevel level);
196
197protected:
198 LogProvider();
199
200 virtual void WriteMessage(LogLevel level, const char* msg) = 0;
201
202protected:
203 LogLevel level_;
204};
205
210class KGE_API ConsoleLogProvider : public LogProvider
211{
212public:
214
215 virtual ~ConsoleLogProvider();
216
217 void Init() override;
218
219 void Flush() override;
220
221protected:
222 void WriteMessage(LogLevel level, const char* msg) override;
223
224private:
225 typedef std::ostream& (*ConsoleColor)(std::ostream&);
226
227 ConsoleColor GetColor(LogLevel level);
228};
229
234class KGE_API FileLogProvider : public LogProvider
235{
236public:
237 FileLogProvider(StringView filepath, std::ios_base::openmode mode = std::ios_base::out);
238
239 virtual ~FileLogProvider();
240
241 void Init() override;
242
243 void Flush() override;
244
245protected:
246 void WriteMessage(LogLevel level, const char* msg) override;
247
248private:
249 std::ofstream ofs_;
250};
251
256class KGE_API Logger final : public Singleton<Logger>
257{
258 friend Singleton<Logger>;
259
260public:
265 void Logf(LogLevel level, const char* format, ...);
266
271 template <typename... _Args>
272 void Log(LogLevel level, _Args&&... args);
273
276 void Flush();
277
280 void Enable();
281
284 void Disable();
285
288 void SetLevel(LogLevel level);
289
293 void AddProvider(RefPtr<LogProvider> provider);
294
298 void SetFormater(RefPtr<LogFormater> formater);
299
303 RefPtr<LogFormater> GetFormater();
304
308 void ResizeBuffer(size_t buffer_size);
309
312 void ShowConsole(bool show);
313
314 virtual ~Logger();
315
316private:
317 Logger();
318
319 std::iostream& GetFormatedStream(LogLevel level, LogBuffer* buffer);
320
321 void WriteToProviders(LogLevel level, LogBuffer* buffer);
322
323private:
324 bool enabled_;
325 LogLevel level_;
326 RefPtr<LogFormater> formater_;
327 LogBuffer buffer_;
328 std::iostream stream_;
329 Vector<RefPtr<LogProvider>> providers_;
330 std::mutex mutex_;
331};
332
333inline void Logger::Enable()
334{
335 enabled_ = true;
336}
337
338inline void Logger::Disable()
339{
340 enabled_ = false;
341}
342
344{
345 formater_ = formater;
346}
347
348template <typename... _Args>
349inline void Logger::Log(LogLevel level, _Args&&... args)
350{
351 if (!enabled_)
352 return;
353
354 if (level < level_)
355 return;
356
357 std::lock_guard<std::mutex> lock(mutex_);
358
359 // build message
360 auto& stream = this->GetFormatedStream(level, &this->buffer_);
361 (void)std::initializer_list<int>{ ((stream << ' ' << args), 0)... };
362
363 // write message
364 this->WriteToProviders(level, &this->buffer_);
365}
366
367} // namespace kiwano
控制台日志生产者
Definition: Logger.h:211
文件日志生产者
Definition: Logger.h:235
日志流缓冲
Definition: Logger.h:151
日志格式化
Definition: Logger.h:137
日志生产者
Definition: Logger.h:185
日志记录器
Definition: Logger.h:257
void Enable()
启用日志
Definition: Logger.h:333
void SetFormater(RefPtr< LogFormater > formater)
设置日志格式
Definition: Logger.h:343
void Disable()
禁用日志
Definition: Logger.h:338
void Log(LogLevel level, _Args &&... args)
打印日志
Definition: Logger.h:349
基础对象
Definition: ObjectBase.h:138
引用计数智能指针
Definition: RefBasePtr.hpp:35
Definition: Singleton.h:28
时钟时间
Definition: Time.h:74