还有使用样例代码
和扩展样例代码(test.cc以及写的很详细了,后续补充)
以及性能测试代码
// #include "func.hpp"
// #include "log_level.hpp"
// #include "my_format.hpp"
// #include "my_message.hpp"
// #include "log_sink.hpp"
// #include "lrt_logger.hpp"
// #include "buffer.hpp"
// #include "looper.hpp"
#include "lrt_log.h"
void global_log_test2()
{
lrtlog::lrt_logger::ptr logger_p=lrtlog::logger_manager::get_instance().get_logger("异步全局日志器");
if (logger_p == nullptr)
{
std::cout << "l1 fail";
return;
}
for (int i = 0; i < 3000; i++) // 经过极限测试,是线程安全的
{
logger_p->debug("%s", "测试日志");
logger_p->info( "%s:%d", "测试日志", i);
logger_p->warn( "%s", "测试日志");
logger_p->error( "%s", "测试日志");
logger_p->fatal( "%s", "测试日志");
}
for (int i = 0; i < 3000; i++) // 经过极限测试,是线程安全的
{
DEBUG( "%s", "测试日志");
INFO( "%s:%d", "测试日志", i);
WARN( "%s:%d", "测试日志", i);
ERROR( "%s:%d", "测试日志", i);
FATAL( "%s:%d", "测试日志", i);
}
}
// void global_log_test()
// {
// lrtlog::lrt_logger::ptr logger_p =lrtlog::logger_manager::get_instance().get_rootlogger();
// if (logger_p == nullptr)
// {
// std::cout << "l1 fail";
// return;
// }
// for (int i = 0; i < 3000; i++) // 经过极限测试,是线程安全的
// {
// logger_p->debug( "%s", "测试日志");
// logger_p->info( "%s:%d", "测试日志", i);
// logger_p->warn( "%s", "测试日志");
// logger_p->error( "%s", "测试日志");
// logger_p->fatal( "%s", "测试日志");
// }
// lrtlog::lrt_logger::ptr logger_p2 =lrtlog::logger_manager::get_instance().get_logger("异步全局日志器");
// if (logger_p2 == nullptr)
// {
// std::cout << "l2 fail" << std::endl;
// return;
// }
// for (int i = 0; i < 3000; i++) // 经过极限测试,是线程安全的
// {
// logger_p2->debug( "%s", "测试日志");
// logger_p2->info( "%s:%d", "测试日志", i);
// logger_p2->warn( "%s", "测试日志");
// logger_p2->error( "%s", "测试日志");
// logger_p2->fatal( "%s", "测试日志");
// }
// }
int main()
{
// 全局日志器建造者模式测试
std::unique_ptr logger_build(new lrtlog::global_logger_build());
logger_build->name_build("异步全局日志器");
logger_build->level_build(lrtlog::log_level::DEBUG); // 输出debug及其以上的信息
logger_build->formatter_build("[%d][%C][%p]%T[%f:%l tid:%t]:[%m]%n");
logger_build->type_build(lrtlog::logger_type::ASY_LOGGER);
logger_build->sinks_build();
logger_build->sinks_build("./logfile/filetest");
logger_build->unsafe_build(lrtlog::AsyncType::ASYN_UNSAFE);
logger_build->sinks_build("./logfile/rolltest", 1024 * 1024);
// std::cout << "begin" << std::endl;
logger_build->build();
global_log_test2();
// //局部日志器建造者模式测试
// std::unique_ptr logger_build(new lrtlog::local_logger_build());
// logger_build->name_build("异步日志器");
// logger_build->level_build(lrtlog::log_level::DEBUG);//输出debug及其以上的信息
// logger_build->formatter_build("[%d][%C][%p]%T[%f:%l tid:%t]:[%m]%n");
// logger_build->type_build(lrtlog::logger_type::ASY_LOGGER);
// //logger_build->sinks_build();
// logger_build->sinks_build("./logfile/filetest");
// logger_build->unsafe_build(lrtlog::AsyncType::ASYN_UNSAFE);
// logger_build->sinks_build("./logfile/rolltest", 1024 * 1024);
// // std::cout << "begin" << std::endl;
// lrtlog::lrt_logger::ptr logger_p = logger_build->build();
// for(int i = 0 ;i<30000;i++)//经过极限测试,是线程安全的
// {
// logger_p->debug( "%s", "测试日志");
// logger_p->info( "%s:%d", "测试日志",i);
// logger_p->warn( "%s", "测试日志");
// logger_p->error( "%s", "测试日志");
// logger_p->fatal( "%s", "测试日志");
// }
// std::cout << "END" << std::endl;
//sleep(10);
// lrtlog::func::File::creat_directory("./logfile/");
// std::ifstream ifs("./logfile/rolltest-124214-172420.log-1",std::ios::binary);
// if (ifs.is_open() == false)
// {
// std::cout << "fail ";
// return 0;
// }
// ifs.seekg(0,std::ios::end);//读写位置跳转到文件末尾
// size_t fsize = ifs.tellg();//获取当前读写位置相对起始位置的偏移量
// ifs.seekg(0,std::ios::beg);//重新跳转到起始位置
// std::string body;
// body.resize(fsize);
// ifs.read(&body[0],fsize);
// if(ifs.good() == false){
// std::cout << "read error";
// }
// ifs.close();
// lrtlog::Buffer buffer;
// for(int i=0;i logger_build(new lrtlog::local_logger_build());
// logger_build->name_build("同步日志器");
// logger_build->level_build(lrtlog::log_level::DEBUG);
// logger_build->formatter_build("[%d][%C][%p]%T[%f:%l tid:%t]%m%n");
// logger_build->type_build(lrtlog::logger_type::SYN_LOGGER);
// //logger_build->sinks_build();
// logger_build->sinks_build("./logfile/filetest");
// logger_build->sinks_build("./logfile/rolltest", 1024 * 1024);
// lrtlog::lrt_logger::ptr logger_p = logger_build->build();
// for(int i = 0 ;i<1000;i++)
// {
// logger_p->debug( "%s", "测试日志");
// logger_p->info( "%s", "测试日志");
// logger_p->warn( "%s", "测试日志");
// logger_p->error( "%s", "测试日志");
// logger_p->fatal( "%s", "测试日志");
// }
// 日志器各基础接口的测试
// std::string logger_name = "lrt_syn_logger";
// lrtlog::log_level::level level=lrtlog::log_level::level::DEBUG;
// lrtlog::formatter::ptr formatter(new lrtlog::formatter("[%d][%C][%p]%T[%f:%l tid:%t]%m%n"));
// std::vector sinks;
// lrtlog::log_sink::ptr stdout_p = lrtlog::sink_factory::create();
// lrtlog::log_sink::ptr file_p = lrtlog::sink_factory::create("./logfile/filetest");
// lrtlog::log_sink::ptr roll_p = lrtlog::sink_factory::create("./logfile/rolltest", 1024 * 1024);
// sinks = {stdout_p,file_p,roll_p};
// std::string str="----";
// lrtlog::lrt_logger::ptr logger_p(new lrtlog::synchronous_logger(logger_name,level,formatter,sinks));
// //lrtlog::lrt_logger::ptr logger_p(std::make_shared(logger_name,level,formatter,sinks));
// logger_p->debug(__FILE__,__LINE__,"%s","测试日志");
// logger_p->info(__FILE__,__LINE__,"%s","测试日志");
// logger_p->warn(__FILE__,__LINE__,"%s","测试日志");
// logger_p->error(__FILE__,__LINE__,"%s","测试日志");
// logger_p->fatal(__FILE__,__LINE__,"%s","测试日志");
// int i = 0;
// for (int cur = 0; cur < 1024 * 1024 * 10; cur += str.size())
// {
// usleep(100000);
// std::string s = str + std::to_string(i++);
// }
// lrtlog::log_message msg(lrtlog::log_level::INFO, (size_t)50, (size_t)1000, "root", "格式化日志信息功能的测试", "1111...");
// lrtlog::formatter fmt;
// std::string str = fmt.format(msg);
// //std::cout << str << std::endl;
// //lrtlog::log_sink::ptr stdout_p = lrtlog::sink_factory::create();
// //lrtlog::log_sink::ptr file_p = lrtlog::sink_factory::create("./logfile/filetest");
// lrtlog::log_sink::ptr roll_p = lrtlog::sink_factory::create("./logfile/rolltest", 1024 * 1024);
// // stdout_p->log(str.c_str(), str.size());
// //file_p->log(str.c_str(), str.size());
// int i = 0;
// for (int cur = 0; cur < 1024 * 1024 * 10; cur += str.size())
// {
// std::string s = str + std::to_string(i++);
// roll_p->log(s.c_str(), str.size());
// }
// lrtlog::log_message msg(lrtlog::log_level::INFO,(size_t)50,(size_t)1000,"root","格式化日志信息功能的测试","1111...");
// lrtlog::formatter fmt;
// std::string str = fmt.format(msg);
// std::cout <
#ifndef MY_FUNC
#define MY_FUNC
#include
#include
#include
//#include
#include
namespace lrtlog{
namespace func{
class Date{
public:
static size_t get_time()
{
return (size_t)time(nullptr);
}
};
//全部创建的是文件夹而不会把最后一个文件创建成文本因此通过open自动创建,唉唉唉。
class File{
public:
static bool is_exist(const std::string &pathname)
{
struct stat st;
if (stat(pathname.c_str(),&st) < 0 )
{
return false;
}
return true;
//return (access(pathname.c_str(),F_OK)==0);//不支持跨平台
}
static std::string path(const std::string &pathname){
size_t pos=0;
pos=pathname.find_last_of("/\\");
if (pos==std::string::npos) return ".";
return pathname.substr(0,pos+1);//第二个参数是长度
}
static void creat_directory(const std::string &pathname){
size_t idx=0,pos=0;
std::string parent_dir;
while(pos < pathname.size() ){
pos=pathname.find_first_of("/\\",idx);//idx表示从哪里开始找
if(pos == std::string::npos){
mkdir(pathname.c_str(),0755);
}
parent_dir=pathname.substr(0,pos+1);
if(is_exist(parent_dir)==false) mkdir(parent_dir.c_str(),0755);
idx=pos+1;
}
}
};
}
}
#endif
#ifndef LOG_LEVEL
#define LOG_LEVEL
namespace lrtlog{
class log_level{
public:
enum level
{
UNKNOW = 0,
DEBUG,
INFO,
WARN,
ERROR,
FATAL,
OFF
};
static const char* to_string(log_level::level level){
switch (level)
{
case log_level::level::DEBUG : return "DEBUG";break;
case log_level::level::INFO : return "INFO";break;
case log_level::level::WARN : return "WARN";break;
case log_level::level::ERROR : return "ERROR";break;
case log_level::level::FATAL : return "FATAL";break;
case log_level::level::OFF : return "OFF";break;
default: return "UNKNOW"; break;
}
}
};
}
#endif
#ifndef MY_FORMAT
#define MY_FORMAT
#include "log_level.hpp"
#include "my_message.hpp"
#include
#include
#include
#include
#include
namespace lrtlog
{
class format_item
{
public:
using ptr = std::shared_ptr;
virtual void format(std::ostream &out, log_message &msg) = 0;
};
class level_format_item : public format_item
{
public:
void format(std::ostream &out,log_message &msg) override
{
out << log_level::to_string(msg._level);
}
};
class payload_format_item : public format_item
{
public:
virtual void format(std::ostream &out, log_message &msg) override
{
out << msg._payload;
}
};
class name_format_item : public format_item
{
public:
void format(std::ostream &out, log_message &msg) override
{
out << msg._name;
}
};
class tid_format_item : public format_item
{
public:
void format(std::ostream &out, log_message &msg) override
{
//没找到什么好的办法把thread_id转换成int
//std::string s((int)(msg._tid));
//auto * i = &(msg._tid);
//std::stringstream ss;
//ss << msg._tid;
//std::cout <;
formatter(const std::string &pattern = "[%d][%C][%p]%T[%f:%l tid:%t]%m%n") : _pattern(pattern) //[%d]{%H:%M:%S}
{
parsePatter();
//std::cout << "hhhh";
//assert(parsePatter());
}
// 格式化msg
private:
void format(std::ostream &out, log_message &msg)
{
for (auto &item : _item)
{
item->format(out, msg);
}
//item->format(out,msg._ctime);
}
public:
//外界调用的不需要传入字符串流
std::string format(log_message &msg)
{
std::stringstream ss;
format(ss, msg);
return ss.str();
}
// 解析格式化字符串
bool parsePatter()
{
// aaa%%%ww[%d{%H:%M:%S}][%P]%t%M%n
size_t pos = 0;
std::vector> tmp_format;
std::string key;
std::string val;
while (pos < _pattern.size())
{
// 1.不是%,说明是other,处理完进行下一次循环
if (_pattern[pos] != '%')
{
val.push_back(_pattern[pos++]);
continue;
}
// 双%特别处理,%%处理为一个%
if ((pos + 1) < _pattern.size() && _pattern[pos + 1] == '%')
{
// val.push_back(_pattern[pos])
val.push_back('%');
pos += 2;
continue;
}
// other处理完毕,先进行添加
if (val.empty() == false)
{
tmp_format.push_back(std::make_pair("", val));
val.clear();
}
pos += 1;
if (pos == _pattern.size())
{
std::cout << "%tail not have enoug payload";
return false;
}
// 记录类型
key = _pattern[pos];
// if (pos < _pattern.size() && _pattern[pos] == '{')
// {
// pos += 1;
// while (pos < _pattern.size() && _pattern[pos] == '}')
// {
// val.push_back(_pattern[pos++]);
// }
// if (pos >= _pattern.size())
// {
// std::cout << "{} error";
// return false;
// }
// // 走出 }
// pos += 1;
// }
if(_pattern[pos-1] == '%') pos++;//防止添加类型进val
tmp_format.push_back(std::make_pair(key, val));
key.clear();
val.clear();
}
for (auto& it : tmp_format)
{
//std::cout<< it.first;
_item.push_back(_creat_all_item(it.first, it.second));
}
return true;
}
private:
std::string _pattern;
std::vector _item;
private:
// 由传入的格式化字符串创建不同的格式化子项 ,也就是上面继承的一群类
format_item::ptr _creat_all_item(const std::string &fc, const std::string &val)
{
if (fc == "m")
return std::make_shared();
if (fc == "p")
return std::make_shared();
if (fc == "C")
return std::make_shared();
if (fc == "t")
return std::make_shared();
if (fc == "n")
return std::make_shared();
if (fc == "d")
return std::make_shared();//子格式的传入、有问题
if (fc == "f")
return std::make_shared();
if (fc == "l")
return std::make_shared();
if (fc == "T")
return std::make_shared();
if (fc == "")
return std::make_shared(val);
//std::cout <<"unknow format" <("");
}
};
}
#endif
#ifndef MY_MESSAGE
#define MY_MESSAGE
#include "func.hpp"
#include "log_level.hpp"
#include
#include
namespace lrtlog{
struct log_message
{
using ptr =std::shared_ptr;
size_t _line;
time_t _ctime;
size_t _tid;
const std::string _name;
const std::string _file;
const std::string _payload;
const log_level::level _level;
log_message(
log_level::level level,
size_t line,
size_t tid,
const std::string name,
const std::string file,
const std::string payload):
_name(name),
_file(file),
_ctime(func::Date::get_time()),
_payload(payload),
_level(level),
_line(line),
_tid(tid) {}
};
}
#endif
#ifndef __LOG_SINK__
#define __LOG_SINK__
#include
#include
#include
#include
#include "func.hpp"
namespace lrtlog{
class log_sink{
public:
using ptr=std::shared_ptr;
log_sink() {}
// log_sink(lrtlog::log_sink::ptr p)
// {
// ptr=p;
// }
virtual ~log_sink(){}
virtual void log(const char* data,size_t len) =0;
};
//落地方向一:标准输出
class stdout_sink : public log_sink {
public:
//将日志写到标准输出
void log(const char* data,size_t len) override
{
std::cout.write(data,len);
}
};
//落地方向二:文件输出
class file_sink :public log_sink{
public:
file_sink(const std::string& name)
:_name(name)
{
func::File::creat_directory(func::File::path(name));//需要嵌套
_ofs.open(_name, std::ios::binary | std::ios::app);
assert(_ofs.is_open());
}
//将日志消息写到标准输出
void log(const char* data,size_t len) override
{
_ofs.write(data,len);
assert(_ofs.good());
}
private:
std::string _name;
std::ofstream _ofs;
};
//落地方向三 滚动文件输出
class rolly_by_size_sink: public log_sink
{
public:
rolly_by_size_sink(const std::string& name,size_t max_size) // 构造并打开文件,并通过_ofs管理
:_base_name(name),
_max_size(max_size),
_cur_size(0),
_name_count(1)
{
std::string pathname=_creat_new_file();
func::File::creat_directory(func::File::path(name)); //貌似不需要先创建parent——path吧
_ofs.open(pathname,std::ios::binary | std::ios::app);
assert(_ofs.good());
}
// 超过就切换文件
void log(const char *data, size_t len) override
{
if (_cur_size >= _max_size)
{
_ofs.close();
std::string pathname = _creat_new_file();
//func::File::creat_directory(pathname);
_ofs.open(pathname, std::ios::binary | std::ios::app);
assert(_ofs.is_open());
_cur_size = 0;//切换清零
}
_ofs.write(data, len);
assert(_ofs.good());
_cur_size += len; // 注意需要追加
}
private:
std::string _base_name; // 通过基础加扩展文件名生成输出文件
std::ofstream _ofs;
size_t _max_size;
size_t _cur_size;
size_t _name_count;
private:
std::string _creat_new_file(){
time_t t=func::Date::get_time();
struct tm lt;
localtime_r(&t,<);
std::stringstream filename;
filename << _base_name.c_str();
filename << "-";
filename <
static log_sink::ptr create(Args &&...args)
{
// 展开参数包,采用了模板成员函数,遵循开闭原则,易于拓展
return std::make_shared(std::forward(args)...); // 注意语法
}
};
}
#endif
#ifndef __LOOPER__
#define __LOOPER__
#include "buffer.hpp"
#include
#include
#include
#include
#include
// conditional
// 在 C++ 中,std::conditional 不是一个变量,而是一个模板类,
// 位于 头文件中。它提供了条件式选择功能,根据给定的条件在编译时选择类型。
//#include
#include //条件变量
namespace lrtlog{
using Functor = std::function;
enum AsyncType
{
ASYN_SAFE,
ASYN_UNSAFE
};
class Asynlooper{
public:
~Asynlooper() { stop(); }//漏了会报位置错误,因为有未知的线程没了
using ptr = std::shared_ptr;
// 启动了一个名为 _thread 的线程,线程入口是 thread_entry 函数,而 this 指针作为参数传递给 thread_entry
// 函数。这样,在异步线程中,thread_entry 函数就能够访问到
// 当前对象的成员变量和成员函数,因为它们都属于当前对象的范围。
Asynlooper(const Functor& cb)//
:_stop(false),
_thread(std::thread(&lrtlog::Asynlooper::thread_entry,this)),
_call_back(cb)
{
//std::cout << "3" < lock(_mutex);
// 一个可调用的对象或函数,它不带任何参数,
// 并返回一个可以计算为布尔值的值。
// 重复调用此值,直到其计算结果为 true。
if(_looper_type == AsyncType::ASYN_SAFE)
_cond_pro.wait(lock,[&](){return (_pro_buf.write_able_size() > len);});//避免资源耗尽型的安全模式
_pro_buf.push(data,len);
//唤醒消费者处理缓冲区的数据
_cond_con.notify_all();
}
void change_type(AsyncType looper_type){
_looper_type = looper_type;
}
// 对消费缓冲区的数据进行处理,处理完毕后,交换缓冲区
void thread_entry() // 线程入口
{
while (_stop != true)
{
std::unique_lock lock(_mutex);
if (_stop && _pro_buf.empty())
break; // 防止阻塞
if (_looper_type == AsyncType::ASYN_SAFE)
_cond_con.wait(lock, [&]()
{ return !_stop || !_pro_buf.empty(); }); // 有则交换,进行数据消费或者要退出了就刷新缓冲区
_con_buf.swap(_pro_buf);
_cond_pro.notify_all();//换完了就快点去干活
//std::cout << "准备干活";
_call_back(_con_buf);
_con_buf.reset();
}
}
private:
//双缓冲区异步
AsyncType _looper_type;
std::atomic _stop;//停止标志
Buffer _pro_buf; //生产者
Buffer _con_buf; //消费者
std::mutex _mutex;
std::condition_variable _cond_pro;
std::condition_variable _cond_con;
std::thread _thread;//工作器对应的线程
lrtlog::Functor _call_back;
};
}
#endif
#ifndef __BUFFER__
#define __BUFFER__
#include
#include
#include
#define DEFAULT_BUFFER_SIZE (1*1024*1024)//注意加括号
#define THRESHOLD_BUFFER_SIZE (10*1024*1024)
#define INCREAS_BUFFER_SIZE (10*1024*1024)
namespace lrtlog{
class Buffer {
public:
Buffer()
{
_len=1024*10;
_reader_idx = _write_idx = 0;
_buffer.resize(_len);
}
//向缓冲写
void push(const char* data,size_t len)
{
while( len > write_able_size() )//扩容
{
if (_len < THRESHOLD_BUFFER_SIZE)
{
_len = _len * 2;
_buffer.resize(_len);
}
else
{
_len = _len + INCREAS_BUFFER_SIZE;
_buffer.resize(_len);
}
}
std::copy(data,data+len,&_buffer[_write_idx]);
move_writer_idx(len);
}
//可读数据起始
const char* begin()
{
// a =&_buffer[_reader_idx];
//_read_p = &_buffer[_reader_idx];
return &_buffer[_reader_idx];
}
size_t read_able_size()
{
return _write_idx - _reader_idx;
}
size_t write_able_size()
{
return _buffer.size() -_write_idx;
}
//移动读写指针
void move_reader_idx(size_t len)
{
assert(len <= read_able_size());//相等是可以的
_reader_idx+=len;
}
void move_writer_idx(size_t len)
{
assert(len <= write_able_size());
_write_idx+=len;
}
//重置读写位置,初始化缓冲区
void reset()
{
_write_idx = _reader_idx = 0;
}
//buffer互相交换管理的指针
void swap(Buffer& buffer)
{
_buffer.swap(buffer._buffer);
std::swap(_reader_idx,buffer._reader_idx);
std::swap(_write_idx,buffer._write_idx);
}
bool empty()
{
if(read_able_size() == 0) return true;
return false;
}
private:
size_t _reader_idx;
size_t _write_idx;
size_t _len;
const char* _read_p;
std::vector _buffer;
};
}
#endif
#ifndef __LRT_LOGGER__
#define __LRT_LOGGER__
#include "log_level.hpp"
#include "log_sink.hpp"
#include "func.hpp"
#include "my_format.hpp"
#include "my_message.hpp"
#include "looper.hpp"
#include
#include
#include
#include
namespace lrtlog{
class lrt_logger{
public:
using ptr = std::shared_ptr;
lrt_logger(std::string& logger_name,log_level::level level,formatter::ptr& formatter,std::vector& sinks):
_logger_name(logger_name),
_limit_level(level),
_fmt(formatter),
_sinks(sinks)
{}
virtual void final_log(const std::string& s) = 0 ;
const std::string& get_name()
{
return _logger_name;
}
void debug(const std::string &file, size_t line, const std::string &fmt, ...)
{
// 1. 判断当前的日志是否达到了输出等级
if (log_level::level::DEBUG < _limit_level)
{
//std::cout << "debug log output fail" < _limit_level;//保证原子操作,避免访问一个小整形而频繁的加锁
formatter::ptr _fmt;
std::vector _sinks;//多个落地方向
std::string log_init(log_level::level level,const std::string& file,size_t line,const std::string& fmt, va_list& vl )
{
char* buf;
std::string msg;
int ret = vasprintf(&buf,fmt.c_str(),vl);
if(ret < 0)
{
std::cout << "vasprintf fail";
abort();
}
//替换msg中的内容
msg.assign(buf,ret);
free(buf);
//格式化消息
log_message lm(level,line,1000,_logger_name,file,msg);
std::string str;
str = _fmt->format(lm);
//std::cout << str ;
return str;
}
};
class synchronous_logger:public lrt_logger{
public:
synchronous_logger(std::string& logger_name, log_level::level level, formatter::ptr &formatter, std::vector& sinks)
: lrt_logger(logger_name, level, formatter, sinks)
{
//std::cout << "syn logger";
}
void final_log(const std::string& s) override
{
std::unique_lock lock(_mutex);
if(_sinks.empty())
{
std::cout << "_sink empty";
return;
}
for(auto& sink: _sinks)
{
sink->log(s.c_str(),s.size());
}
}
};
enum logger_type
{
SYN_LOGGER,
ASY_LOGGER
};
class logger_builder{
public:
using ptr = std::shared_ptr;
logger_builder():
_logger_type(logger_type::SYN_LOGGER),
_limit_level(log_level::level::DEBUG),
_looper_type(AsyncType::ASYN_SAFE){}
public:
void type_build(logger_type logger_type){ _logger_type = logger_type;}
void name_build(const std::string &logger_name) { _logger_name = logger_name; }
void unsafe_build(AsyncType looper_type){ _looper_type = looper_type;}
void level_build(lrtlog::log_level::level level) { _limit_level = level; }
void formatter_build(const std::string &pattern)
{
_formatter = std::make_shared(pattern);
}
template
void sinks_build(Args &&...args)
{
log_sink::ptr sink_p = sink_factory::create(std::forward(args)...);
_sinks.push_back(sink_p);
}
virtual lrt_logger::ptr build() = 0;
protected:
std::string _logger_name;
logger_type _logger_type;
log_level::level _limit_level;
formatter::ptr _formatter;
std::vector _sinks;
lrtlog::AsyncType _looper_type;
};
class asynchronous_logger :public lrt_logger
{
public:
asynchronous_logger(std::string& logger_name,
log_level::level level,
formatter::ptr& formatter,
std::vector &sinks,
AsyncType looper_type) : lrt_logger(logger_name, level, formatter, sinks),
_looper(std::make_shared(std::bind(&asynchronous_logger::reallog, this, std::placeholders::_1)))
{
//_looper->change_type(looper_type);
//std::cout<< "2";
}
void final_log(const std::string& s){
_looper->push(s.c_str(),s.size());
}
void reallog(Buffer& buffer)
{
//std:: cout << "4" ;
if(_sinks.empty())
{
std::cout << "asyn _sink empty";
return;
}
for(auto& sink: _sinks)
{
sink->log(buffer.begin(),buffer.read_able_size());
}
}
private:
Asynlooper::ptr _looper;
};
//忘记加public就会出现父类public函数的情况
class local_logger_build :public logger_builder{
public:
lrt_logger::ptr build() override
{
//std::cout << "254 line";
//assert(_logger_name.empty()==false);
if(_formatter.get()==nullptr) _formatter = std::make_shared();
if(_sinks.empty()) sinks_build();
if(_logger_type == logger_type::SYN_LOGGER){
std::cout << std::endl;
return std::make_shared(_logger_name,_limit_level,_formatter,_sinks);
}
else
{
std::cout << "asyc" <(_logger_name,_limit_level,_formatter,_sinks,_looper_type);//传给looper了,所以asynchronous_logger可以没有looper_type,也体现了此处已经解耦
}
std::cout << "nullptr "<< std::endl;
return nullptr;
}
};
class logger_manager{
public:
static logger_manager& get_instance()
{
static logger_manager eton;//单例对象
return eton;
}
void add_logger(lrt_logger::ptr& logger)
{
if(hash_logger(logger->get_name()) == true) return;//已经存在则不创建
std::unique_lock lock(_mutex);
_loggers.insert(std::make_pair(logger->get_name(),logger));//对象放在堆上,就要用指针,也就是对象指针->函数;放在栈上,就对象.函数
}
bool hash_logger(const std::string& name)
{
std::unique_lock lock(_mutex);
auto it = _loggers.find(name);
if( it == _loggers.end())
{
return false;
}
return true;
}
lrt_logger::ptr get_logger(std::string logger_name)//失败返回空
{
std::unique_lock lock(_mutex);
std::cout << "OK,IN 306" << std::endl;
auto it = _loggers.find(logger_name);
if (it == _loggers.end())
{
return nullptr;
}
return it->second;
}
lrt_logger::ptr get_rootlogger()
{
return _root_logger;
}
private:
logger_manager()
{
std::unique_ptr logger_build(new lrtlog::local_logger_build());//不可使用全局的建造者
logger_build->name_build("root_logger");
_root_logger = logger_build->build();
_loggers.insert(std::make_pair(_root_logger->get_name(),_root_logger));
}
private:
lrt_logger::ptr _root_logger;
std::mutex _mutex;
std::unordered_map _loggers;
};
class global_logger_build :public logger_builder{
public:
lrt_logger::ptr build() override
{
lrt_logger::ptr logger;
//std::cout << "254 line";
//assert(_logger_name.empty()==false);
if(_formatter.get()==nullptr) _formatter = std::make_shared();
if(_sinks.empty()) sinks_build();
if(_logger_type == logger_type::SYN_LOGGER){
std::cout << std::endl;
logger = std::make_shared(_logger_name,_limit_level,_formatter,_sinks);
}
else
{
std::cout << "asyc" <(_logger_name,_limit_level,_formatter,_sinks,_looper_type);//传给looper了,所以asynchronous_logger可以没有looper_type,也体现了此处已经解耦
}
logger_manager::get_instance().add_logger(logger);//添加到单例对象进行管理
//std::cout << "nullptr "<< std::endl;
return logger;
}
};
}
#endif
#ifndef __LRT_LOG__
#define __LRT_LOG__
#include "lrt_logger.hpp"
#define debug(fmt, ...) debug(__FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define info(fmt, ...) info(__FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define warn(fmt, ...) warn(__FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define error(fmt, ...) error(__FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define fatal(fmt, ...) fatal(__FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define DEBUG(fmt, ...) lrtlog::get_rootlogger()->debug(fmt, ##__VA_ARGS__)
#define INFO(fmt, ...) lrtlog::get_rootlogger()->info(fmt, ##__VA_ARGS__)
#define WARN(fmt, ...) lrtlog::get_rootlogger()->warn(fmt, ##__VA_ARGS__)
#define ERROR(fmt, ...) lrtlog::get_rootlogger()->error(fmt, ##__VA_ARGS__)
#define FATAL(fmt, ...) lrtlog::get_rootlogger()->fatal(fmt, ##__VA_ARGS__)
namespace lrtlog{
lrt_logger::ptr get_logger(const std::string& name)
{
return lrtlog::logger_manager::get_instance().get_logger(name);
}
lrt_logger::ptr get_rootlogger()
{
return lrtlog::logger_manager::get_instance().get_rootlogger();
}
}
#endif