概述
添加TabFormatItem类 用来输出tab,并在 s_format_items 中添加对应的映射关系%T
再添加FiberIdFormatItem类用来输出纤程ID,并添加上对应的映射关系%F
新建util.h 与util.cpp
添加函数 pid_t getThreadId(),利用systemcall(SYS_gettid)
返回线程号
添加工具方法 uint32_t getFiberId() 暂且只让它返回0
编辑CMakeList,将新增的文件添加进去
修改LogEvent
:
添加shared_ptr<Logger> m_logger
、LogEvent m_level
字段,以及相应的get方法。并在构造函数中加入这两个字段。
添加LogEventWrap
类(为了不直接使用智能指针LogEvent::ptr)
class LogEventWrap {
public :
LogEventWrap(LogEvent::ptr e); //传入一个LogEvent给m_event赋值
~LogEventWrap();
std::stringstream& getSS(); //返回logevnet的getSS()
private:
LogEvent::ptr m_event;
}
编写~LogEventWrap()
获取m_event
本身的m_logger
,用m_event
的级别m_level
和自身作为参数,调用该事件所属的Logger的log()
方法
添加void format( const char* fmt , .... )
装载变长参数va_start( va_list, 变长形参的首个固定参数 )、释放变长参数va_end()
添加 void format( const char* fmt , va_list al )
主要服务于上一个format() ,va_list al
接收了变长参数,交给vasprintf(char指针地址char** buf,格式字符串,va_list) 将格式化后的字符串写入buf字符串中,最后将其写入到 getSS() <<
定义宏使得日志模块更加易用
1、
先定义一个基础宏 LOG_LEVEL(logger,level)
只要当前等级>=logger中的日志等级,就创建一个新的LogEvent
并用它来初始化一个LogEventWrap
,并调用getSS()
来返回其内容流。
用这个基础宏来定义等级分别为 LOG_debug LOG_warn … 的其它宏,使得:
输入:logger对象
输出:所创建事件的内容流(&stringstream)
使用方式:LOG_XXX(logger) << "日志内容"
2、
logEvent中新增的两个format方法主要是为了让我们能用格式字符串的方式来输入日志信息:即允许在日志内容中出现%x
来进行格式化输出
同样,先定义一个基础宏:
LOG_FMT_LEVEL(logger , level , fmt , ... )
只要当前输入等级>=logger中的内置级别,就创建一个新的LogEvent,并用它来初始化一个LogEventWrap,并用新增的format()设置其中的LogEvent
的内容getSS()
这个宏的主要难点是如何表示变长参数列表,这需要借助一个宏__VA_AR GS__
来表示...
再用这个基础宏去定义当前格式化输出的日志级别分别是 debug 、info … 的宏LOG_FMT_XXXX(logger, “日志内容 %A %B ”,“aaa”,“bbb”)
修改LogAppender
:
增加 setLevel()
、getLevel()
方法
创建日志管理器(为了简化logger的使用)
新增类 LogMannger
数据:
map<string名称,Logger::ptr> m_logger
,用来存放所有logger
m_root
默认使用的logger
方法:
init()
之后会和配置文件联合使用,加载配置产生logger
class LoggerManager(){
public:
LoggerManager(); //设置缺省logger:m_root中包含仅一个输出地:stdLogAppender
Logger::ptr getLogger(const std::string& name); 调用find按名字找对应的logger,没找到则返回默认的日志器m_root
void init();//之后会从配置文件中直接加载我们要使用的logger
private:
Logger::ptr m_root;
map<std::string,Logger::ptr> m_loggers;
}
新建Singleton.h
在其中加入两个模板类
单例类:
template<class T , class X = void ,int N = 0> //N用来区分同类型的多个不同实例
class Singleton{
public :
static T* getInstance(){
static T v;
return &v;
}
}
单例指针:
template<class T , class X = void ,int N = 0>
class SingletonPtr{
public :
static std::shared_ptr<T> getInstance(){
static std::shared_ptr<T> v(new T);
return v;
}
}
应用单例类来创建唯一一个 LogManager
定义新类型 LoggerMgr
typedef sylar::Singleton<LoggerManager> LoggerMgr
使用方式:
auto my_logger = sylar::LoggerMgr::getInstance()->getLogger("logger名称");
LOG_INFO(my_logger) << "日志内容";
注:
class{}后面要记得加分号!!
命名空间::要加上!!
std::shared_ptr<XX>.reset() 这里要用`.`!!
shared_ptr<XX>.reset(new XX ) 调用原来所指向对象的析构函数(即释放掉旧对象),并将指针指向新对象new XX
map.find() 后返回的是KV对,因此类型一般用auto
取出KV对中的“V”用 `->second()`
static 表示该变量仅此一份,不会随作用域的退出而销毁。
vim :vs XX 垂直分屏 打开文件
最后
以上就是鳗鱼钢笔为你收集整理的【sylar服务器框架】完善日志系统的全部内容,希望文章能够帮你解决【sylar服务器框架】完善日志系统所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复