作者寄语:用心写好每一篇文章,一起进步
前言
- 📄本文内容:实现Logger类
- 📇 所属专栏:服务器 | Linux C++高性能服务器
- 👤 作者主页:紫荆鱼
- 📆 创作时间:2021-12-28
🔙返回目录(建议收藏): Linux C++高性能服务器
日志系统框架目录
项目目录
0.为什么服务器需要日志系统
出现问题:
不一致性:对文件系统进行修改
时,这些操作可能中途被打断
,也就是说,这些操作不是“不可中断”的。如果操作被打断,就可能造成文件系统出现不一致
的状态。
解决问题:
解决不一致定:为了避免这样的错误,日志文件系统分配了一个称为日志
的区域来提前记录要对文件系统做的更改。在崩溃
后,只要读取日志重新执行
未完成的操作,文件系统就可以恢复
一致。
1.日志系统怎样设计?
- 表达日志:
LogEvent
类至少应该包含两个属性,一个是时间戳,另一个是消息本身; - 日志级别:
LogLevel
类定义了日志的级别; - 日志输出:
LogAppender
类可以输出到不同的地方,控制台、文件等,通过继承实现; - 日志信息格式化:
LogFormatter
可以引用 LogFormatter 这样就可以将 LogEvent 事件中的日志消息经过 LogFormatter 进行格式化,然后再由 LogAppender 输出; - 获取日志:
Logger
日志器。
类图:(项目整体类图)
2.命名空间angel
为什么用命名空间就是为了方式命名冲突了
namespace angel
{
//上述类都定义在这个命名空间内
}
3.LogEvent类
//日志事件类,表达日志信息的概念
class LogEvent
{
public:
typedef std::shared_ptr<LogEvent> ptr;
LogEvent(); //构造函数
private:
const char* m_file = nullptr; //文件名
int32_t m_line = 0; //行号
uint32_t m_elapse = 0; //进程启动起的毫秒数
uint32_t m_threadId = 0; //线程id
uint32_t m_fiberId =0; //携程id
uint64_t m_time = 0; //时间戳
std::string m_content;
};
LogEvent类难点:
- std::shared_ptr:一种
智能指针
(smart pointer),作用有如同指针,但会记录有多少个shared_ptrs共同指向一个对象。这便是所谓的引用计数(reference counting),一旦最后一个这样的指针被销毁,也就是一旦某个对象的引用计数变为0,这个对象会被自动删除。 - 包含两个属性,一个是
时间戳
,另一个是消息本身
。
4.LogLevel类
//日志级别类
class LogLevel
{
public:
enum Level
{
UNKNOW = 0, //未知级别
DEBUG = 1; //DEBUG级别
INFO =2; //INFO级别
WARN =3; //WARN级别
ERROR = 4; //ERROR级别
FATAL = 5; //FATAL级别
};
};
5.LogFormatter类
//日志格式器
class LogFormatter
{
public:
typedef std::shared_ptr<LogFormatter> ptr; //智能指针
std::string format(LogEvent::ptr event); //格式化写入日志内容
private:
};
6.LogAppender类及子类
基类
:
//日志输出地类
class LogAppender
{
public:
typedef std::shared_ptr<LogAppender> ptr; //智能指针
virtual ~LogAppender(){} //析构
/**
* @brief 写入日志
* @param[in] logger 日志器
* @param[in] level 日志级别
* @param[in] event 日志事件
*/
virtual void log(LogEvent::Level level,LogEvent::ptr event) = 0;
protected:
LogLevel::Level level;
};
子类
//日志输出到控制台
class StdoutLogAppender: public LogAppender
{
public:
}
//日志输出到文件
classs FileLogAppender: public LogAppender
{
}
7.Logger类
//日志器
class Logger
{
public:
std::shared_ptr<Logger> ptr; //智能指针
Logger(const std::string name = 'root');
void log(LogLevel::Level level,LogEvent::ptr event); //@brief 写日志
void debug(LogEvent::ptr event); //写不同级别的日志
void info(LogEvent::ptr event); //同上
void warn(LogEvent::ptr event);
void error(LogEvent::ptr event);
void fatal(LogEvent::ptr event);
void addAppender(LogAppender::ptr appender); //@brief 添加日志目标
void delAppender(LogAppender::ptr appender); //@brief 删除日志目标
void clearAppenders(); //@brief 清空日志目标
LogLevel::Level getLevel() const {return m_level;} //@brief 获取日志等级
void setLevel(LogLevel::level val){m_level = val;} //@brief 设置日志等级
private:
std::string name; //日志名称
LogLevel::Level m_level; //日志级别
std::list<LogAppender::ptr> m_appenders; //Appender集合
};
*第一天跟写记录
心得体会
第一次接触服务器,100%是有一点难度的,比如说Sylar中一些C++语言没看懂,比如说智能指针,stringsream库,还有被VScode惯坏的我用Vim的时候有点困难。希望自己能坚持写下去,当然也希望从中获得很多,“千里之行始于足下”,加油吧!
源码
#ifndef __ANGEL_LOG_H__
#define __ANGEL_LOG_H__
#include <string>
#include <stdint.h>
#include <memory>
#include <list>
#include <stringstream>
#include <fstream>
namespace angel
{
//日志事件类
class LogEvent
{
public:
typedef std::shared_ptr<LogEvent> ptr;
LogEvent();
private:
const char* m_file = nullptr; //文件名
int32_t m_line = 0; //行号
uint32_t m_elapse = 0; //进程启动起的毫秒数
uint32_t m_threadId = 0; //线程id
uint32_t m_fiberId =0; //携程id
uint64_t m_time = 0; //时间戳
std::string m_content;
};
//日志级别类
class LogLevel
{
public:
enum Level
{
DEBUG = 1;
INFO =2;
WARN =3;
ERROR = 4;
FATAL = 5;
};
};
//日志格式器
class LogFormatter
{
public:
typedef std::shared_ptr<LogFormatter> ptr;
std::string format(LogEvent::ptr event);
private:
};
//日志输出地类
class LogAppender
{
public:
typedef std::shared_ptr<LogAppender> ptr;
virtual ~LogAppender(){}
virtual void log(LogEvent::Level level,LogEvent::ptr event) = 0;
protected:
LogLevel::Level level;
};
//日志器
class Logger
{
public:
std::shared_ptr<Logger> ptr;
Logger(const std::string name = 'root');
void log(LogLevel::Level level,LogEvent::ptr event);
void debug(LogEvent::ptr event);
void info(LogEvent::ptr event);
void warn(LogEvent::ptr event);
void error(LogEvent::ptr event);
void fatal(LogEvent::ptr event);
void addAppender(LogAppender::ptr appender);
void delAppender(LogAppender::ptr appender);
LogLevel::Level getLevel() const {return m_level;}
void setLevel(LogLevel::level val){m_level = val;}
private:
std::string name; //日志名称
LogLevel::Level m_level; //日志级别
std::list<LogAppender::ptr> m_appenders; //Appender集合
};
//日志输出到控制台
class StdoutLogAppender: public LogAppender
{
public:
}
//日志输出到文件
classs FileLogAppender: public LogAppender
{
}
}
#endif