ZLToolkit的日志模块。
#include "Util/logger.h"
int main()
{
Logger::Instance().add(std::make_shared());
Logger::Instance().setWriter(std::make_shared());
TraceL<< "int"<< (int)1<< endl;
PrintT("this is a %s test:%d", "printf trace", 124);
LogT(1, "+", "2", '=', 3);
return 0;
}
源码分析
类图源码分析使用如下:
void Logger::writeChannels(const LogContextPtr &ctx) {
if (ctx->_line == _last_log->_line && ctx->_file == _last_log->_file && ctx->str() == _last_log->str()) {
//重复的日志每隔500ms打印一次,过滤频繁的重复日志
++_last_log->_repeat;
if (timevalDiff(_last_log->_tv, ctx->_tv) >500) { //超过500ms,打印一条
ctx->_repeat = _last_log->_repeat; //ctx->_repeat要继承过来
writeChannels_l(ctx);
}
return;
}
if (_last_log->_repeat) { //上一条日志短时间内一直重复,没有打印出来,最后打印一下
writeChannels_l(_last_log);
}
writeChannels_l(ctx);
}
Logger
单例,核心类,所有的重要操作几乎都是由这个类完成。
LogChannel
日志通道,负责格式化日志并打印到输出流
void format(const Logger &logger, std::ostream &ost, const LogContextPtr &ctx, bool enable_color, bool enable_detail)函数负责将LogContex的内容进行格式化并输出ost中。
LogWriter/AsyncLogWriter
LogWriter只是作为一个基类,几乎没有实现。AsyncLogWriter是一个使用率很高的类,这个类开启了一个线程用于写日志。
write函数用于将日志暂存进_pending对象,并唤醒阻塞的信号量刷新日志。
** flushAll**函数用于刷新日志。
void AsyncLogWriter::flushAll() {
decltype(_pending) tmp;
{
lock_guardlock(_mutex);
tmp.swap(_pending);
}
tmp.for_each([&](std::pair&pr) {
pr.second->writeChannels(pr.first);
});
}
这个函数将_pending的日志先交换到tmp对象再进行打印。可以优先减少锁的时间,提高效率。
LogContextCapture
每次打印的时候会生成该类的临时对象,在构造时生成LogContext对象并与logger对象进行关联,结束后主要是生成LogContext对象并将logger对象于其进行关联。比较有意思的是LogContextCapture &operator<<(std::ostream &(*f)(std::ostream &))这个函数,会在参数为std::endl(回车符)的时候是调用,这个函数会调用_logger.write(_ctx)将日志立即输出。
LoggerWrapper包装类
这个类用于支持printf和可变参数格式。实现比较简单,但是对模板的使用很巧妙。
templatestatic inline void printLogArray(Logger &logger, LogLevel level, const char *file, const char *function, int line, First &&first, ARGS &&...args) {
LogContextCapture log(logger, level, file, function, line);
log<< std::forward(first);
appendLog(log, std::forward(args)...);
}
templatestatic inline void appendLog(Log &out, First &&first, ARGS &&...args) {
out<< std::forward(first);
appendLog(out, std::forward(args)...);
}
templatestatic inline void appendLog(Log &out) {}
将第一个参数用First &&first和其余参数区分开。First &&first和std::forward(first)是完美转发,不改变first的左值或者右值属性。printLogArray创建了一个LogContextCapture对象,交给appendLog进行<<处理,直到最后一次空调用。
//禁止拷贝基类
class noncopyable {
protected:
noncopyable() {}
~noncopyable() {}
private:
//禁止拷贝
noncopyable(const noncopyable &that) = delete;
noncopyable(noncopyable &&that) = delete;
noncopyable &operator=(const noncopyable &that) = delete;
noncopyable &operator=(noncopyable &&that) = delete;
};
将拷贝函数声明为delete,当你尝试调用这些函数时,编译器会抛出一个错误, 而且派生类不能重写这个函数。
default也是可以简化开发。
class MyClass {
public:
MyClass() = default; // 提供缺省的构造函数
MyClass(const MyClass& other) = default; // 提供缺省的拷贝构造函数
MyClass& operator=(const MyClass& other) = default; // 提供缺省的拷贝赋值运算符
// 其他成员函数
private:
int x;
};
enable_shared_from_this说明:
若一个类T继承了std::enable_shared_from_this,则会为该类T提供成员函数:shared_from_this.当T类型对象t被一个为名为 pt的std::shared_ptr 类对象管理时,调用 T::shared_from_this 成员函数,将会返回一个新的std::shared_ptr 对象,它与pt共享t的所有权。
示例:
class A : public std::enable_shared_from_this
{
public:
std::shared_ptr getptr() {
return shared_from_this();
}
~A() { std::cout<< "A::~A() called"<< std::endl; }
};
int main()
{
{
std::shared_ptr a1(new A());
std::shared_ptr a2 = a1->getptr();
std::cout<< "a1.use_count() = "<< a1.use_count()<< std::endl; //2
std::cout<< "a2.use_count() = "<< a2.use_count()<< std::endl; //2
}
}
使用场景:
在异步调用中,存在一个保活机制,异步函数执行的时间点我们是无法确定的,然而异步函数可能会使用到异步调用之前就存在的变量。为了保证该变量在异步函数执期间一直有效,我们可以传递一个指向自身的share_ptr给异步函数,这样在异步函数执行期间share_ptr所管理的对象就不会析构,所使用的变量也会一直有效了(保活)。
templateclass List : public std::list{
public:
templateList(ARGS &&...args) : std::list(std::forward(args)...) {};
~List() = default;
void append(List&other) {
if (other.empty()) {
return;
}
this->insert(this->end(), other.begin(), other.end());
other.clear();
}
templatevoid for_each(FUNC &&func) {
for (auto &t : *this) {
func(t);
}
}
templatevoid for_each(FUNC &&func) const { //const List& listRef = list; const List* listPtr = &list调用的版本
for (auto &t : *this) {
func(t);
}
}
};
你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧