本文主要是介绍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日志实现类的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!