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

相关文章

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount

Kubernetes PodSecurityPolicy:PSP能实现的5种主要安全策略

Kubernetes PodSecurityPolicy:PSP能实现的5种主要安全策略 1. 特权模式限制2. 宿主机资源隔离3. 用户和组管理4. 权限提升控制5. SELinux配置 💖The Begin💖点点关注,收藏不迷路💖 Kubernetes的PodSecurityPolicy(PSP)是一个关键的安全特性,它在Pod创建之前实施安全策略,确保P

工厂ERP管理系统实现源码(JAVA)

工厂进销存管理系统是一个集采购管理、仓库管理、生产管理和销售管理于一体的综合解决方案。该系统旨在帮助企业优化流程、提高效率、降低成本,并实时掌握各环节的运营状况。 在采购管理方面,系统能够处理采购订单、供应商管理和采购入库等流程,确保采购过程的透明和高效。仓库管理方面,实现库存的精准管理,包括入库、出库、盘点等操作,确保库存数据的准确性和实时性。 生产管理模块则涵盖了生产计划制定、物料需求计划、

C++——stack、queue的实现及deque的介绍

目录 1.stack与queue的实现 1.1stack的实现  1.2 queue的实现 2.重温vector、list、stack、queue的介绍 2.1 STL标准库中stack和queue的底层结构  3.deque的简单介绍 3.1为什么选择deque作为stack和queue的底层默认容器  3.2 STL中对stack与queue的模拟实现 ①stack模拟实现

基于51单片机的自动转向修复系统的设计与实现

文章目录 前言资料获取设计介绍功能介绍设计清单具体实现截图参考文献设计获取 前言 💗博主介绍:✌全网粉丝10W+,CSDN特邀作者、博客专家、CSDN新星计划导师,一名热衷于单片机技术探索与分享的博主、专注于 精通51/STM32/MSP430/AVR等单片机设计 主要对象是咱们电子相关专业的大学生,希望您们都共创辉煌!✌💗 👇🏻 精彩专栏 推荐订阅👇🏻 单片机