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

相关文章

Python如何实现读取csv文件时忽略文件的编码格式

《Python如何实现读取csv文件时忽略文件的编码格式》我们再日常读取csv文件的时候经常会发现csv文件的格式有多种,所以这篇文章为大家介绍了Python如何实现读取csv文件时忽略文件的编码格式... 目录1、背景介绍2、库的安装3、核心代码4、完整代码1、背景介绍我们再日常读取csv文件的时候经常

Golang中map缩容的实现

《Golang中map缩容的实现》本文主要介绍了Go语言中map的扩缩容机制,包括grow和hashGrow方法的处理,具有一定的参考价值,感兴趣的可以了解一下... 目录基本分析带来的隐患为什么不支持缩容基本分析在 Go 底层源码 src/runtime/map.go 中,扩缩容的处理方法是 grow

Go 1.23中Timer无buffer的实现方式详解

《Go1.23中Timer无buffer的实现方式详解》在Go1.23中,Timer的实现通常是通过time包提供的time.Timer类型来实现的,本文主要介绍了Go1.23中Timer无buff... 目录Timer 的基本实现无缓冲区的实现自定义无缓冲 Timer 实现更复杂的 Timer 实现总结在

基于Python实现多语言朗读与单词选择测验

《基于Python实现多语言朗读与单词选择测验》在数字化教育日益普及的今天,开发一款能够支持多语言朗读和单词选择测验的程序,对于语言学习者来说无疑是一个巨大的福音,下面我们就来用Python实现一个这... 目录一、项目概述二、环境准备三、实现朗读功能四、实现单词选择测验五、创建图形用户界面六、运行程序七、

Vue中动态权限到按钮的完整实现方案详解

《Vue中动态权限到按钮的完整实现方案详解》这篇文章主要为大家详细介绍了Vue如何在现有方案的基础上加入对路由的增、删、改、查权限控制,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、数据库设计扩展1.1 修改路由表(routes)1.2 修改角色与路由权限表(role_routes)二、后端接口设计

C#集成DeepSeek模型实现AI私有化的流程步骤(本地部署与API调用教程)

《C#集成DeepSeek模型实现AI私有化的流程步骤(本地部署与API调用教程)》本文主要介绍了C#集成DeepSeek模型实现AI私有化的方法,包括搭建基础环境,如安装Ollama和下载DeepS... 目录前言搭建基础环境1、安装 Ollama2、下载 DeepSeek R1 模型客户端 ChatBo

Qt实现发送HTTP请求的示例详解

《Qt实现发送HTTP请求的示例详解》这篇文章主要为大家详细介绍了如何通过Qt实现发送HTTP请求,文中的示例代码讲解详细,具有一定的借鉴价值,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1、添加network模块2、包含改头文件3、创建网络访问管理器4、创建接口5、创建网络请求对象6、创建一个回复对

C++实现回文串判断的两种高效方法

《C++实现回文串判断的两种高效方法》文章介绍了两种判断回文串的方法:解法一通过创建新字符串来处理,解法二在原字符串上直接筛选判断,两种方法都使用了双指针法,文中通过代码示例讲解的非常详细,需要的朋友... 目录一、问题描述示例二、解法一:将字母数字连接到新的 string思路代码实现代码解释复杂度分析三、

grom设置全局日志实现执行并打印sql语句

《grom设置全局日志实现执行并打印sql语句》本文主要介绍了grom设置全局日志实现执行并打印sql语句,包括设置日志级别、实现自定义Logger接口以及如何使用GORM的默认logger,通过这些... 目录gorm中的自定义日志gorm中日志的其他操作日志级别Debug自定义 Loggergorm中的

Spring Boot整合消息队列RabbitMQ的实现示例

《SpringBoot整合消息队列RabbitMQ的实现示例》本文主要介绍了SpringBoot整合消息队列RabbitMQ的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的... 目录RabbitMQ 简介与安装1. RabbitMQ 简介2. RabbitMQ 安装Spring