前言
日志是一个程序最核心的一个模块,此日志程序模仿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