base11. Logger日志类和Impl日志实现类

2024-03-10 21:58
文章标签 实现 日志 logger impl base11

本文主要是介绍base11. Logger日志类和Impl日志实现类,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

muduo库通过这几个宏的日志输出,既可以输出到标准输出,又可以输出到宏
__FILE__是这一行代码所在的文件名,__LINE__是这一行代码所在的行号

#define LOG_TRACE if (muduo::Logger::logLevel() <= muduo::Logger::TRACE) \//构造匿名对象,在调用完Logger.stream()之后,会自动调用析构用函数// // 匿名对象只存在于该行代码,离开这行代码后立即调用析构函数muduo::Logger(__FILE__, __LINE__, muduo::Logger::TRACE, __func__).stream()
#define LOG_DEBUG if (muduo::Logger::logLevel() <= muduo::Logger::DEBUG) \muduo::Logger(__FILE__, __LINE__, muduo::Logger::DEBUG, __func__).stream()
#define LOG_INFO if (muduo::Logger::logLevel() <= muduo::Logger::INFO) \muduo::Logger(__FILE__, __LINE__).stream()
#define LOG_WARN muduo::Logger(__FILE__, __LINE__, muduo::Logger::WARN).stream()
#define LOG_ERROR muduo::Logger(__FILE__, __LINE__, muduo::Logger::ERROR).stream()
#define LOG_FATAL muduo::Logger(__FILE__, __LINE__, muduo::Logger::FATAL).stream()
#define LOG_SYSERR muduo::Logger(__FILE__, __LINE__, false).stream()
#define LOG_SYSFATAL muduo::Logger(__FILE__, __LINE__, true).stream()

Logger类图在这里插入图片描述
数据成员:

Impl impl_:一个Impl类型的impl_对象,impl_包含日志的实现以及格式化
enum LogLevel:枚举类LogLevel

typedef

typedef void (OutputFunc)(const char msg, int len)
typedef void (*FlushFunc)()

成员函数:

Logger(SourceFile file, int line):构造函数
Logger(SourceFile file, int line, LogLevel level):构造函数
Logger(SourceFile file, int line, LogLevel level, const char* func):构造函数
Logger(SourceFile file, int line, bool toAbort):构造函数
~Logger():析构函数,调用impl_.finish(),是输出的最后一步
LogStream& stream():返回LogStream类型的stream_对象
static LogLevel logLevel():
static void setLogLevel(LogLevel level):设置日志等级
static void setOutput(OutputFunc):用来更改默认输出设备
static void setFlush(FlushFunc):用来更改默认输出设备的冲洗

Impl类图
Impl类包含日志的实现以及格式化
在这里插入图片描述
数据成员:

Timestamp time_:一个Timestamp类型的时间戳time_
LogStream stream_:一个类型为LogStream的stream_对象,用来输出信息到缓冲区FixedBuffer
LogLevel level_:一个LogLevel枚举类型的日志等级level_
int line_:一个line_对象
SourceFile basename_:日志文件的basename_

typedef

typedef Logger::LogLevel LogLevel

成员函数:

Impl(LogLevel level, int old_errno, const SourceFile& file, int line):构造函数
void formatTime():格式化函数
void finish():输出的最后一步

Logging.h

#ifndef MUDUO_BASE_LOGGING_H
#define MUDUO_BASE_LOGGING_H#include <muduo/base/LogStream.h>
#include <muduo/base/Timestamp.h>namespace muduo
{
//最外层日志类Logger类,负责日志的级别
class Logger
{public:enum LogLevel{TRACE,DEBUG,INFO,WARN,ERROR,FATAL,NUM_LOG_LEVELS,};// compile time calculation of basename of source fileclass SourceFile{public:template<int N>inline SourceFile(const char (&arr)[N]): data_(arr),size_(N-1){const char* slash = strrchr(data_, '/'); // builtin functionif (slash){data_ = slash + 1;size_ -= static_cast<int>(data_ - arr);}}explicit SourceFile(const char* filename): data_(filename){const char* slash = strrchr(filename, '/');if (slash){data_ = slash + 1;}size_ = static_cast<int>(strlen(data_));}const char* data_;int size_;};Logger(SourceFile file, int line);Logger(SourceFile file, int line, LogLevel level);Logger(SourceFile file, int line, LogLevel level, const char* func);Logger(SourceFile file, int line, bool toAbort);~Logger();//返回LogStream类型的stream_对象LogStream& stream() { return impl_.stream_; }//static LogLevel logLevel();//设置日志等级static void setLogLevel(LogLevel level);typedef void (*OutputFunc)(const char* msg, int len);typedef void (*FlushFunc)();//setOutput()、setFlush()用来更改默认输出设备以及默认输出设备的冲洗static void setOutput(OutputFunc);static void setFlush(FlushFunc);private:
//Logger类内部包装了一个Impl类,包含日志的实现以及格式化
class Impl
{public:typedef Logger::LogLevel LogLevel;Impl(LogLevel level, int old_errno, const SourceFile& file, int line);void formatTime();void finish();Timestamp time_;//一个类型为LogStream的stream_对象,用来输出信息到缓冲区FixedBufferLogStream stream_;LogLevel level_;int line_;SourceFile basename_;
};Impl impl_;};extern Logger::LogLevel g_logLevel;inline Logger::LogLevel Logger::logLevel()
{return g_logLevel;
}//muduo库通过这几个宏的日志输出,既可以输出到标准输出,又可以输出到宏
//__FILE__是这一行代码所在的文件名,__LINE__是这一行代码所在的行号
#define LOG_TRACE if (muduo::Logger::logLevel() <= muduo::Logger::TRACE) \//构造匿名对象,在调用完Logger.stream()之后,会自动调用析构用函数// // 匿名对象只存在于该行代码,离开这行代码后立即调用析构函数muduo::Logger(__FILE__, __LINE__, muduo::Logger::TRACE, __func__).stream()
#define LOG_DEBUG if (muduo::Logger::logLevel() <= muduo::Logger::DEBUG) \muduo::Logger(__FILE__, __LINE__, muduo::Logger::DEBUG, __func__).stream()
#define LOG_INFO if (muduo::Logger::logLevel() <= muduo::Logger::INFO) \muduo::Logger(__FILE__, __LINE__).stream()
#define LOG_WARN muduo::Logger(__FILE__, __LINE__, muduo::Logger::WARN).stream()
#define LOG_ERROR muduo::Logger(__FILE__, __LINE__, muduo::Logger::ERROR).stream()
#define LOG_FATAL muduo::Logger(__FILE__, __LINE__, muduo::Logger::FATAL).stream()
#define LOG_SYSERR muduo::Logger(__FILE__, __LINE__, false).stream()
#define LOG_SYSFATAL muduo::Logger(__FILE__, __LINE__, true).stream()const char* strerror_tl(int savedErrno);// Taken from glog/logging.h
//
// Check that the input is non NULL.  This very useful in constructor
// initializer lists.#define CHECK_NOTNULL(val) \::muduo::CheckNotNull(__FILE__, __LINE__, "'" #val "' Must be non NULL", (val))// A small helper for CHECK_NOTNULL().
template <typename T>
T* CheckNotNull(Logger::SourceFile file, int line, const char *names, T* ptr) {if (ptr == NULL) {Logger(file, line, Logger::FATAL).stream() << names;}return ptr;
}}#endif  // MUDUO_BASE_LOGGING_H

Logging.cc

#include <muduo/base/Logging.h>#include <muduo/base/CurrentThread.h>
#include <muduo/base/StringPiece.h>
#include <muduo/base/Timestamp.h>#include <errno.h>
#include <stdio.h>
#include <string.h>#include <sstream>namespace muduo
{/*
class LoggerImpl
{public:typedef Logger::LogLevel LogLevel;LoggerImpl(LogLevel level, int old_errno, const char* file, int line);void finish();Timestamp time_;LogStream stream_;LogLevel level_;int line_;const char* fullname_;const char* basename_;
};
*/__thread char t_errnobuf[512];
__thread char t_time[32];
__thread time_t t_lastSecond;const char* strerror_tl(int savedErrno)
{return strerror_r(savedErrno, t_errnobuf, sizeof t_errnobuf);
}Logger::LogLevel initLogLevel()
{return Logger::TRACE;/*if (::getenv("MUDUO_LOG_TRACE"))return Logger::TRACE;else if (::getenv("MUDUO_LOG_DEBUG"))return Logger::DEBUG;elsereturn Logger::INFO;*/
}Logger::LogLevel g_logLevel = initLogLevel();const char* LogLevelName[Logger::NUM_LOG_LEVELS] =
{"TRACE ","DEBUG ","INFO  ","WARN  ","ERROR ","FATAL ",
};// helper class for known string length at compile time
class T
{public:T(const char* str, unsigned len):str_(str),len_(len){assert(strlen(str) == len_);}const char* str_;const unsigned len_;
};inline LogStream& operator<<(LogStream& s, T v)
{s.append(v.str_, v.len_);return s;
}inline LogStream& operator<<(LogStream& s, const Logger::SourceFile& v)
{s.append(v.data_, v.size_);return s;
}
//默认输出函数defaultOutput()输出到标准输出stdout
void defaultOutput(const char* msg, int len)
{size_t n = fwrite(msg, 1, len, stdout);//FIXME check n(void)n;
}
//默认冲洗函数defaultFlush()冲洗stdout
void defaultFlush()
{fflush(stdout);
}
//g_output()默认调用defaultOutput()
Logger::OutputFunc g_output = defaultOutput;
//g_flush()默认调用defaultFlush()
Logger::FlushFunc g_flush = defaultFlush;}using namespace muduo;Logger::Impl::Impl(LogLevel level, int savedErrno, const SourceFile& file, int line): time_(Timestamp::now()),stream_(),level_(level),line_(line),basename_(file)
{formatTime();CurrentThread::tid();stream_ << T(CurrentThread::tidString(), 6);stream_ << T(LogLevelName[level], 6);if (savedErrno != 0){stream_ << strerror_tl(savedErrno) << " (errno=" << savedErrno << ") ";}
}void Logger::Impl::formatTime()
{int64_t microSecondsSinceEpoch = time_.microSecondsSinceEpoch();time_t seconds = static_cast<time_t>(microSecondsSinceEpoch / 1000000);int microseconds = static_cast<int>(microSecondsSinceEpoch % 1000000);if (seconds != t_lastSecond){t_lastSecond = seconds;struct tm tm_time;::gmtime_r(&seconds, &tm_time); // FIXME TimeZone::fromUtcTimeint len = snprintf(t_time, sizeof(t_time), "%4d%02d%02d %02d:%02d:%02d",tm_time.tm_year + 1900, tm_time.tm_mon + 1, tm_time.tm_mday,tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec);assert(len == 17); (void)len;}Fmt us(".%06dZ ", microseconds);assert(us.length() == 9);stream_ << T(t_time, 17) << T(us.data(), 9);
}void Logger::Impl::finish()
{stream_ << " - " << basename_ << ':' << line_ << '\n';
}Logger::Logger(SourceFile file, int line): impl_(INFO, 0, file, line)
{
}Logger::Logger(SourceFile file, int line, LogLevel level, const char* func): impl_(level, 0, file, line)
{impl_.stream_ << func << ' ';
}Logger::Logger(SourceFile file, int line, LogLevel level): impl_(level, 0, file, line)
{
}Logger::Logger(SourceFile file, int line, bool toAbort): impl_(toAbort?FATAL:ERROR, errno, file, line)
{
}//无名对象销毁时调用析构函数,把存于缓冲区(FixedBuffer类)中的数据利用g_output()输出
Logger::~Logger()
{impl_.finish();const LogStream::Buffer& buf(stream().buffer());//g_output()输出缓冲区的数据g_output(buf.data(), buf.length());//impl_.level_ == FATAL时终止程序,在终止程序之前,需要冲洗缓冲区if (impl_.level_ == FATAL){//调用g_flush()冲洗缓冲区g_flush();abort();}
}void Logger::setLogLevel(Logger::LogLevel level)
{g_logLevel = level;
}void Logger::setOutput(OutputFunc out)
{g_output = out;
}void Logger::setFlush(FlushFunc flush)
{g_flush = flush;
}

这篇关于base11. Logger日志类和Impl日志实现类的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/795653

相关文章

SpringBoot3实现Gzip压缩优化的技术指南

《SpringBoot3实现Gzip压缩优化的技术指南》随着Web应用的用户量和数据量增加,网络带宽和页面加载速度逐渐成为瓶颈,为了减少数据传输量,提高用户体验,我们可以使用Gzip压缩HTTP响应,... 目录1、简述2、配置2.1 添加依赖2.2 配置 Gzip 压缩3、服务端应用4、前端应用4.1 N

SpringBoot实现数据库读写分离的3种方法小结

《SpringBoot实现数据库读写分离的3种方法小结》为了提高系统的读写性能和可用性,读写分离是一种经典的数据库架构模式,在SpringBoot应用中,有多种方式可以实现数据库读写分离,本文将介绍三... 目录一、数据库读写分离概述二、方案一:基于AbstractRoutingDataSource实现动态

Python FastAPI+Celery+RabbitMQ实现分布式图片水印处理系统

《PythonFastAPI+Celery+RabbitMQ实现分布式图片水印处理系统》这篇文章主要为大家详细介绍了PythonFastAPI如何结合Celery以及RabbitMQ实现简单的分布式... 实现思路FastAPI 服务器Celery 任务队列RabbitMQ 作为消息代理定时任务处理完整

Java枚举类实现Key-Value映射的多种实现方式

《Java枚举类实现Key-Value映射的多种实现方式》在Java开发中,枚举(Enum)是一种特殊的类,本文将详细介绍Java枚举类实现key-value映射的多种方式,有需要的小伙伴可以根据需要... 目录前言一、基础实现方式1.1 为枚举添加属性和构造方法二、http://www.cppcns.co

使用Python实现快速搭建本地HTTP服务器

《使用Python实现快速搭建本地HTTP服务器》:本文主要介绍如何使用Python快速搭建本地HTTP服务器,轻松实现一键HTTP文件共享,同时结合二维码技术,让访问更简单,感兴趣的小伙伴可以了... 目录1. 概述2. 快速搭建 HTTP 文件共享服务2.1 核心思路2.2 代码实现2.3 代码解读3.

MySQL双主搭建+keepalived高可用的实现

《MySQL双主搭建+keepalived高可用的实现》本文主要介绍了MySQL双主搭建+keepalived高可用的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,... 目录一、测试环境准备二、主从搭建1.创建复制用户2.创建复制关系3.开启复制,确认复制是否成功4.同

Java实现文件图片的预览和下载功能

《Java实现文件图片的预览和下载功能》这篇文章主要为大家详细介绍了如何使用Java实现文件图片的预览和下载功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... Java实现文件(图片)的预览和下载 @ApiOperation("访问文件") @GetMapping("

使用Sentinel自定义返回和实现区分来源方式

《使用Sentinel自定义返回和实现区分来源方式》:本文主要介绍使用Sentinel自定义返回和实现区分来源方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Sentinel自定义返回和实现区分来源1. 自定义错误返回2. 实现区分来源总结Sentinel自定

Java实现时间与字符串互相转换详解

《Java实现时间与字符串互相转换详解》这篇文章主要为大家详细介绍了Java中实现时间与字符串互相转换的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、日期格式化为字符串(一)使用预定义格式(二)自定义格式二、字符串解析为日期(一)解析ISO格式字符串(二)解析自定义

opencv图像处理之指纹验证的实现

《opencv图像处理之指纹验证的实现》本文主要介绍了opencv图像处理之指纹验证的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学... 目录一、简介二、具体案例实现1. 图像显示函数2. 指纹验证函数3. 主函数4、运行结果三、总结一、