LogSystem beta 1.4
This is a logging system project
 
载入中...
搜索中...
未找到
format.hpp
浏览该文件的文档.
1
8#pragma once
9
10#include "level.hpp"
11#include "message.hpp"
12#include <ctime>
13#include <vector>
14#include <cassert>
15#include <sstream>
16#include <memory>
17namespace Xulog
18{
23 {
24 public:
25 using ptr = std::shared_ptr<FormatItem>;
31 virtual void format(std::ostream &out, LogMsg &msg) = 0;
32 };
37 {
38 public:
44 void format(std::ostream &out, LogMsg &msg) override
45 {
46 out << msg._payload;
47 }
48 };
53 {
54 public:
60 void format(std::ostream &out, LogMsg &msg) override
61 {
62 out << LogLevel::toString(msg._level);
63 }
64 };
69 {
70 public:
75 TimeFormatItem(const std::string &fmt = "%H:%M:%S")
76 : _time_fmt(fmt)
77 {
78 }
84 void format(std::ostream &out, LogMsg &msg) override
85 {
86 struct tm st;
87 localtime_r(&msg._ctime, &st);
88 char tmp[32] = {0};
89 strftime(tmp, 31, _time_fmt.c_str(), &st);
90 out << tmp;
91 }
92
93 private:
94 std::string _time_fmt;
95 };
100 {
101 public:
107 void format(std::ostream &out, LogMsg &msg) override
108 {
109 out << msg._file;
110 }
111 };
116 {
117 public:
123 void format(std::ostream &out, LogMsg &msg) override
124 {
125 out << msg._line;
126 }
127 };
132 {
133 public:
139 void format(std::ostream &out, LogMsg &msg) override
140 {
141 out << msg._tid;
142 }
143 };
148 {
149 public:
155 void format(std::ostream &out, LogMsg &msg) override
156 {
157 out << msg._logger;
158 }
159 };
164 {
165 public:
171 void format(std::ostream &out, LogMsg &msg) override
172 {
173 out << "\t";
174 }
175 };
180 {
181 public:
187 void format(std::ostream &out, LogMsg &msg) override
188 {
189 out << "\n";
190 }
191 };
196 {
197 public:
202 OtherFormatItem(const std::string &str)
203 : _str(str)
204 {
205 }
211 void format(std::ostream &out, LogMsg &msg) override
212 {
213 out << _str;
214 }
215
216 private:
217 std::string _str;
218 };
219
220 /*
221 %d 日期,子格式{%H:%M:%S}
222 %T 缩进
223 %t 线程ID
224 %p 日志级别
225 %c 日志器名称
226 %f 文件名
227 %l 行号
228 %m 日志消息
229 %n 换行
230 */
231
236 {
237 public:
238 using ptr = std::shared_ptr<Formatter>;
253 Formatter(const std::string &pattern = "[%d{%y-%m-%d|%H:%M:%S}][%t][%c][%f:%l][%p]%T%m%n")
254 : _pattern(pattern)
255 {
256 assert(parsePattern());
257 }
263 std::string Format(LogMsg &msg)
264 {
265 std::stringstream ss;
266 Format(ss, msg);
267 return ss.str();
268 }
274 void Format(std::ostream &out, LogMsg &msg)
275 {
276 for (auto &item : _items)
277 {
278 item->format(out, msg);
279 }
280 }
281 // 对格式化内容进行解析
282 /*
283 1. 没有以%起始的字符都是原始字符串
284 2. 遇到%则是原始字符串的结束
285 3. %%表示原始的%
286 4. 如果遇到{则说明这是格式化字符的子格式,遇到}结束
287 */
288
291 std::string getPattern()
292 {
293 return _pattern;
294 }
295
296 private:
302 {
303 std::vector<std::pair<std::string, std::string>> fmt_order;
304 size_t pos = 0;
305 std::string key, val;
306
307 // 字符串解析
308 while (pos < _pattern.size())
309 {
310 if (_pattern[pos] != '%')
311 {
312 val.push_back(_pattern[pos++]);
313 continue;
314 }
315 if (pos + 1 < _pattern.size() && _pattern[pos + 1] == '%')
316 {
317 val.push_back('%');
318 pos += 2;
319 continue;
320 }
321 // 原始字符串处理完毕
322 if (val.empty() == false)
323 {
324 fmt_order.push_back(std::make_pair("", val));
325 val.clear();
326 }
327
328 if (pos >= _pattern.size())
329 {
330 std::cout << "%后没有有效字符" << std::endl;
331 return false;
332 }
333 pos += 1;
334 key = _pattern[pos];
335 if (pos + 1 < _pattern.size() && _pattern[pos + 1] == '{')
336 {
337 pos += 2;
338 while (pos < _pattern.size() && _pattern[pos] != '}')
339 {
340 val.push_back(_pattern[pos++]);
341 }
342 if (pos >= _pattern.size())
343 {
344 std::cout << "规则中{}匹配出错" << std::endl;
345 return false;
346 }
347 }
348
349 fmt_order.push_back(std::make_pair(key, val));
350 pos++;
351 key.clear();
352 val.clear();
353 }
354
355 // 初始化成员
356 for (auto &it : fmt_order)
357 {
358 _items.push_back(createItem(it.first, it.second));
359 }
360 return true;
361 }
368 FormatItem::ptr createItem(const std::string &key, const std::string &value)
369 {
370 if (key == "d")
371 return std::make_shared<TimeFormatItem>(value);
372 if (key == "t")
373 return std::make_shared<ThreadFormatItem>();
374 if (key == "c")
375 return std::make_shared<LoggerFormatItem>();
376 if (key == "f")
377 return std::make_shared<FileFormatItem>();
378 if (key == "l")
379 return std::make_shared<LineFormatItem>();
380 if (key == "p")
381 return std::make_shared<LevelFormatItem>();
382 if (key == "T")
383 return std::make_shared<TabFormatItem>();
384 if (key == "m")
385 return std::make_shared<MsgFormatItem>();
386 if (key == "n")
387 return std::make_shared<NLineFormatItem>();
388 if (key.empty())
389 return std::make_shared<OtherFormatItem>(value);
390 std::cout << "没有对应的格式化字符:'%" << key << "'\n";
391 exit(1);
392 return FormatItem::ptr();
393 }
394
395 private:
396 std::string _pattern;
397 std::vector<FormatItem::ptr> _items;
398 };
399}
文件名格式化子项
Definition format.hpp:100
void format(std::ostream &out, LogMsg &msg) override
格式化文件名
Definition format.hpp:107
抽象格式化子项的基类
Definition format.hpp:23
std::shared_ptr< FormatItem > ptr
Definition format.hpp:25
virtual void format(std::ostream &out, LogMsg &msg)=0
格式化日志消息
格式化器类,负责将日志消息格式化为字符串
Definition format.hpp:236
std::string getPattern()
获取格式化字符串
Definition format.hpp:291
Formatter(const std::string &pattern="[%d{%y-%m-%d|%H:%M:%S}][%t][%c][%f:%l][%p]%T%m%n")
构造格式化器
Definition format.hpp:253
std::vector< FormatItem::ptr > _items
格式化子项集合
Definition format.hpp:397
std::shared_ptr< Formatter > ptr
Definition format.hpp:238
bool parsePattern()
解析格式化规则字符串
Definition format.hpp:301
FormatItem::ptr createItem(const std::string &key, const std::string &value)
根据格式化字符创建格式化子项对象
Definition format.hpp:368
std::string _pattern
格式化规则字符串
Definition format.hpp:396
std::string Format(LogMsg &msg)
对日志消息进行格式化
Definition format.hpp:263
void Format(std::ostream &out, LogMsg &msg)
对日志消息进行格式化,并输出到指定流
Definition format.hpp:274
日志级别格式化子项
Definition format.hpp:53
void format(std::ostream &out, LogMsg &msg) override
格式化日志级别
Definition format.hpp:60
行号格式化子项
Definition format.hpp:116
void format(std::ostream &out, LogMsg &msg) override
格式化行号
Definition format.hpp:123
static const char * toString(LogLevel::value level)
将日志等级转换为对应的字符串
Definition level.hpp:44
日志器名称格式化子项
Definition format.hpp:148
void format(std::ostream &out, LogMsg &msg) override
格式化日志器名称
Definition format.hpp:155
消息格式化子项
Definition format.hpp:37
void format(std::ostream &out, LogMsg &msg) override
格式化消息
Definition format.hpp:44
换行符格式化子项
Definition format.hpp:180
void format(std::ostream &out, LogMsg &msg) override
格式化换行符
Definition format.hpp:187
其他格式化子项
Definition format.hpp:196
OtherFormatItem(const std::string &str)
构造其他格式化子项
Definition format.hpp:202
void format(std::ostream &out, LogMsg &msg) override
格式化其他字符串
Definition format.hpp:211
std::string _str
格式化字符串
Definition format.hpp:217
制表符格式化子项
Definition format.hpp:164
void format(std::ostream &out, LogMsg &msg) override
格式化制表符
Definition format.hpp:171
线程ID格式化子项
Definition format.hpp:132
void format(std::ostream &out, LogMsg &msg) override
格式化线程ID
Definition format.hpp:139
时间格式化子项
Definition format.hpp:69
std::string _time_fmt
时间格式
Definition format.hpp:94
void format(std::ostream &out, LogMsg &msg) override
格式化时间
Definition format.hpp:84
TimeFormatItem(const std::string &fmt="%H:%M:%S")
构造时间格式化子项
Definition format.hpp:75
日志等级类的定义和实现
日志消息类的实现
Definition buffer.hpp:12
日志消息结构体
Definition message.hpp:24
size_t _line
行号
Definition message.hpp:26
std::string _payload
有效载荷数据
Definition message.hpp:31
time_t _ctime
日志产生的时间戳
Definition message.hpp:25
std::string _file
源文件名称
Definition message.hpp:29
std::string _logger
日志器
Definition message.hpp:30
std::thread::id _tid
线程ID
Definition message.hpp:27
LogLevel::value _level
日志等级
Definition message.hpp:28