【日至组件】日至前端

本节将研究日至组件的前端,并给出C++实现;

日至

说明几点

(1)日至前端有多个,而日至后端只有一个,整个程序共用一个后端;前端作为生产者,无阻塞,将打印内容存入日至内存即可;后端作为消费者,当日至内存足够多时,要定期、定量将日至内存刷新到日至文件中;当日至文件超过一定的大小,还要更换日至文件;

(2)日至库支持的打印级别分别是TRACE、DEBUG、 INFO、 WARN、 ERROR、 SYSERR;一般日至库的默认打印级别是INFO,因此默认情况下TRACE、DEBUG两种级别,日至是不会打印的,节省日至打印的内容;

(3)日至的格式为20150327 07:31:52.835744132 8113 TRACE EventLoop.cc:48 EventLoop – eventfd fd: 10,打印内容依次是时间(精确到纳秒)、线程id、打印级别、文件名,文件行、函数名(文件名,文件行、函数名总大小受限制为30个字节对齐)、打印内容;这样每一个日至行还是相对比较对齐,整洁的;

(4)日志前端打印的风格,类似cout,如LOG_INFO << "123" << " " << 456;stream支持重载<<来支持常见的类型;LOG_INFO使用宏定义,这样当当前输出的日至级别高于语句的级别时,宏替换后是一个简单的if判断,便可忽略当前的打印;

test.cc

#include <iostream>using namespace std;int currentLevel = 1;int logLevel = 2;#define LOG if (logLevel > currentLevel) coutint main(void){ LOG << "123" << "456" << endl;}使用sykpour@sykpour:~/Desktop$ g++ -E -o test.i test2.cc查看宏替换后的文件的最后几行为:# 2 "test2.cc" 2using namespace std;int currentLevel = 1;int logLevel = 2;int main(void){ if (logLevel > currentLevel) cout << "123" << "456" << endl;}我们发现当currentLevel大于等于logLevel时,cout是不会执行的;(5)日至前端整体示意图如下:

说明几点:

(5.1)Logger只是对用户的一层包装,提供用户LOG_INFO、LOG_ERROR这样的用户接口;而真正构造日至信息的是LogProxy类,由它使用LogStream将日至内容存放到StreamBuffer;而AsyncLogger只是间接使用到StreamBuffer的日至内容,写入到自身的空StreamBuffer列表中,然后来刷新到日至文件中;

(5.2)LogStream中的StreamBuffer可以刷入到后端,默认是刷新到控制台输出;

(5.3)AsyncLogger中_asyncLogger()将会将汇集的日至刷入到日至文件中,详细请见下一个博客介绍日至后端的;

StreamBuffertemplate <size_t size>class StreamBuffer final{public: StreamBuffer():_curr(_buffer),_used(0),_avail(size) {} void append(const void* buf, size_t len) {if (avail() >= len){::memcpy(_curr, buf, len);_avail -= len;_used += len;_curr += len;} } char* curr() const {return curr; } void reset() {_curr = _buffer;_used = 0;_avail = size; } size_t avail() const {return _avail; } size_t used() const {return _used; } const char* buffer() const {return _buffer; } char* buffer() {return _buffer; }private: char _buffer[size]; char* _curr; size_t _used; size_t _avail;};const size_t cSmallBufferSize = 4 * 1024;const size_t cLargeBufferSize = 4 * 1024 * 1024;typedef StreamBuffer<cSmallBufferSize> SmallBuffer;typedef StreamBuffer<cLargeBufferSize> LargeBuffer;

说明几点:

(1)StreamBuffer分别支持的日至大小是4k和4M,一般是使用4k大小,如果某一次日至行大小超过4k,4k以后的字节大小将会丢失;

LogStreamLogStream的声明class LogStream final{public: LogStream& operator=(const LogStream&) = delete; LogStream(const LogStream&) = delete; LogStream() = default; LogStream& operator<<(char value) {_buffer.append(&value, 1);return *this; } LogStream& operator<<(int value); LogStream& operator<<(short value) {return operator<<(static_cast<int>(value)); } LogStream& operator<<(long value) {return operator<<(static_cast<int>(value)); } LogStream& operator<<(size_t value) {return operator<<(static_cast<int>(value)); }LogStream& operator<<(long long value);LogStream& operator<<(unsigned long long value) {return operator<<(static_cast<long long>(value)); } LogStream& operator<<(const char* buf); LogStream& operator<<(const void* address);LogStream& operator<<(const std::string& s) {append(s.c_str(), s.size());return *this; } void append(const void* buf, size_t len) {_buffer.append(buf, len); } void fflush();private: StreamBuffer<cSmallBufferSize> _buffer;};typedef std::function<void(const char*, size_t)> OutputFflushFunc;void setDefualtFunc(const OutputFflushFunc& func);

说明几点:

(1)setDefualtFunc可以设置OutputFflushFunc的后端的输出类型,在LogStream.cc中定义的g_outFflushFunc默认为输出后端为控制台;

(2)LogStream支持多种类型的输出,使用<<重载,包括const char* buf,const void* address,const std::string s,double,int,double等;

曾经拥有的不要忘记,难以得到的更要珍惜,

【日至组件】日至前端

相关文章:

你感兴趣的文章:

标签云: