我是靠谱客的博主 鳗鱼钢笔,最近开发中收集的这篇文章主要介绍【sylar服务器框架】完善日志系统,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

添加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_loggerLogEvent 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服务器框架】完善日志系统所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(45)

评论列表共有 0 条评论

立即
投稿
返回
顶部