liunx服务器-日志模块设计


前言

日志是一个程序最核心的一个模块,此日志程序模仿log4j日志,日志具有5个级别,
DEBUG 指出细粒度信息事件对调试应用程序是非常有帮助的。
INFO 表明 消息在粗粒度级别上突出强调应用程序的运行过程。
WARN 表明会出现潜在错误的情形。
ERROR 指出虽然发生错误事件,但仍然不影响系统的继续运行。
FATAL 指出每个严重的错误事件将会导致应用程序的退出。
在这里插入图片描述
分别对应 系统时间 协程id 线程id 日志级别 用户名 文件 行号 内容


一、日志是什么?

运行日志是程序最核心的模块之一,许多应用程序需要记录它们的活动。系统程序经常需要向控制台或日志文件写消息。这些消息可能指示错误、警告或是与系统状态有关的一般信息,便于快速排查问题。

二、代码实现

1.日志级别

//日志级别
	class LogLevel {
	public:
		enum Level {
			UNKNOW = 0,
			DEBUG = 1,
			INFO = 2,
			WARN = 3,
			ERROR = 4,
			FATAL = 5
		};

		static const char * ToString(LogLevel::Level level);
	};

2.日志事件

//日志事件
	class LogEvent {
	public:
		typedef std::shared_ptr<LogEvent> ptr;

		LogEvent(std::shared_ptr<Logger> logger, LogLevel::Level level ,const char * file, int32_t line, \
			uint32_t elapse, uint32_t thread_id, uint32_t fiber_id, uint64_t time);

		const char * getFile() const { return m_file; } //获得文件
		int32_t getLine() const { return m_line; }      //获得行号
		uint32_t getElapse() const { return m_elapase; }//程序启动到现在运行了多长时间
		uint32_t getTheadId() const { return m_threadId; }//线程id
		uint32_t getFiberId() const { return m_fiberId; } //协程id
		uint64_t getTime() const { return m_time; } //获得时间
		std::string getContent() const { return m_ss.str(); } //获得文件内容
		std::stringstream & getSS() { return m_ss; } //
		std::shared_ptr<Logger> getLogger() const { return m_logger; }
		LogLevel::Level getLevel() const { return m_level; }

	private:
		const char * m_file = nullptr;      //文件名
		int32_t m_line = 0;					//行号
		uint32_t m_elapase = 0;				//程序启动到现在的毫秒数
		uint32_t m_threadId = 0;			//线程id
		uint32_t m_fiberId = 0;				//协程id
		uint64_t m_time;					//时间戳
		std::stringstream m_ss;				//文件内容
		std::shared_ptr<Logger> m_logger;	//日志器
		LogLevel::Level m_level;            //日志级别
	};

3.日志包装器

//日志包装器
	class LogEventWrap
	{
	public:
		LogEventWrap(LogEvent::ptr e);

		std::stringstream & getSS();

		~LogEventWrap();

	private:
		LogEvent::ptr m_event;
	};

4.日志格式器

//日志格式器
	class LogFormatter {
	public:
		typedef std::shared_ptr<LogFormatter> ptr;

		LogFormatter(const std::string & pattern);

		std::string format(std::shared_ptr<Logger> logger, LogLevel::Level level, LogEvent::ptr event);

	public:
		class FormatItem {
		public:
			typedef std::shared_ptr<FormatItem> ptr;
			FormatItem(const std::string & fmt = "") {};
			virtual ~FormatItem() {}
			virtual void format(std::ostream & os, std::shared_ptr<Logger> logger, LogLevel::Level level, LogEvent::ptr event) = 0;
		};

		void init();
	private:
		std::string m_pattern;
		std::vector<FormatItem::ptr> m_items;
	};

5.日志输出地

//日志输出地
	class LogAppender {
	public:
		typedef std::shared_ptr<LogAppender> ptr;

		virtual ~LogAppender() {};

		virtual void log(std::shared_ptr<Logger> logger, LogLevel::Level level, LogEvent::ptr event) = 0;  /* 纯虚函数 父类不做实现 */

		//%d{%Y-%m-%d %H:%M:%S}%T%t%T%F%T[%p]%T[%c]%T%f:%l%T%m%n
		//时间 线程id 协成id 日志级别 用户名 文件名 行号 文件内容 回车符
		void setFormatter(LogFormatter::ptr val) { m_formatter = val; } //设置输出格式
		LogFormatter::ptr getFormatter() const { return m_formatter; }

	protected:
		LogLevel::Level m_level;
		LogFormatter::ptr m_formatter;
	};

6.日志器

//日志器  
	class Logger : public std::enable_shared_from_this<Logger>{
	public:
		typedef 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);

		/* 添加和删除Appender */
		void addAppender(LogAppender::ptr event);
		void delAppender(LogAppender::ptr event);

		/* 获得level和设置level */
		LogLevel::Level getLevel() const { return m_level; }
		void setLevel(LogLevel::Level val) { m_level = val; }

		std::string getName() const { return m_name; }
	private:
		std::string m_name;							//日志名字
		LogLevel::Level m_level;					//日志级别
		std::list<LogAppender::ptr> m_appenders;	//Appender集合
		LogFormatter::ptr m_formatter;				//初始化formatter
	};

7.输出到控制台

//输出到控制台
	class StdoutLogAppender : public LogAppender {
	public:
		typedef std::shared_ptr<StdoutLogAppender> ptr;
		void log(Logger::ptr logger, LogLevel::Level level, LogEvent::ptr event) override;  /* 父类继承重载实现 */
	};

8.输出到文件

//输出到文件
	class FileLogAppender : public LogAppender {
	public:
		typedef std::shared_ptr<FileLogAppender> ptr;

		FileLogAppender(const std::string & filename);

		void log(Logger::ptr logger, LogLevel::Level level, LogEvent::ptr event) override;  /* 父类继承重载实现 */

		bool reopen();
	private:
		std::string m_filename;
		std::ofstream m_filestream; //写文件
	};

三、测试代码

sylar::Logger::ptr logger(new sylar::Logger);

	logger->addAppender(sylar::LogAppender::ptr(new sylar::StdoutLogAppender));
	SYLAR_LOG_DEBUG(logger) << "zcy";
	SYLAR_LOG_INFO(logger) << "zcy";
	SYLAR_LOG_WARN(logger) << "zcy";
	SYLAR_LOG_ERROR(logger) << "zcy";
	SYLAR_LOG_FATAL(logger) << "zcy";
#define SYLAR_LOG_LEVEL(logger,level) \
	if(logger->getLevel() <= level) \
		zcy::LogEventWrap(zcy::LogEvent::ptr(new zcy::LogEvent(logger,level,\
			__FILE__, __LINE__, 0, 1, 2, time(0)))).getSS()

#define SYLAR_LOG_DEBUG(logger) SYLAR_LOG_LEVEL(logger, zcy::LogLevel::DEBUG)
#define SYLAR_LOG_INFO(logger) SYLAR_LOG_LEVEL(logger, zcy::LogLevel::INFO)
#define SYLAR_LOG_WARN(logger) SYLAR_LOG_LEVEL(logger, zcy::LogLevel::WARN)
#define SYLAR_LOG_ERROR(logger) SYLAR_LOG_LEVEL(logger,zcy::LogLevel::ERROR)
#define SYLAR_LOG_FATAL(logger) SYLAR_LOG_LEVEL(logger,zcy::LogLevel::FATAL)

在这里插入图片描述
完整代码链接
提取码: a3b3

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值