muduo之Logger
生活随笔
收集整理的这篇文章主要介绍了
muduo之Logger
小编觉得挺不错的,现在分享给大家,帮大家做个参考.
Logger用来记录和分析日志。
Logging.h
// Use of this source code is governed by a BSD-style license // that can be found in the License file. // // Author: Shuo Chen (chenshuo at chenshuo dot com)#ifndef MUDUO_BASE_LOGGING_H #define MUDUO_BASE_LOGGING_H#include "muduo/base/LogStream.h" #include "muduo/base/Timestamp.h"namespace muduo {class TimeZone;class Logger //记录分析日志 {public:enum LogLevel//用来设置不同的日志级别{TRACE,DEBUG,INFO,WARN,ERROR,FATAL,NUM_LOG_LEVELS,//级别个数};// compile time calculation of basename of source fileclass SourceFile// help to get the name of a file 嵌套类{public:template<int N>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();//return he reference of a LogStream Object。LogStream重载了<<运算符,因此可以直接使用LogStream& stream() { return impl_.stream_; }//static成员函数static LogLevel logLevel();static void setLogLevel(LogLevel level);typedef void (*OutputFunc)(const char* msg, int len);typedef void (*FlushFunc)();static void setOutput(OutputFunc);//设置输出函数static void setFlush(FlushFunc);//清空缓冲static void setTimeZone(const TimeZone& tz);private: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_;//LogStream对象LogLevel level_;int line_;//行号SourceFile basename_; };Impl impl_;//实现对象};extern Logger::LogLevel g_logLevel; inline Logger::LogLevel Logger::logLevel() {return g_logLevel; }// // CAUTION: do not write: // // if (good) // LOG_INFO << "Good news"; // else // LOG_WARN << "Bad news"; // // this expends to // // if (good) // if (logging_INFO) // logInfoStream << "Good news"; // else // logWarnStream << "Bad news"; // //使用宏来定义匿名对象,LogStream重载了<<,因此可以使用 LOG_REACE<<"日志"<< #define LOG_TRACE if (muduo::Logger::logLevel() <= muduo::Logger::TRACE) \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; }} // namespace muduo#endif // MUDUO_BASE_LOGGING_HLogging.cc
// Use of this source code is governed by a BSD-style license // that can be found in the License file. // // Author: Shuo Chen (chenshuo at chenshuo dot com)#include "muduo/base/Logging.h"#include "muduo/base/CurrentThread.h" #include "muduo/base/Timestamp.h" #include "muduo/base/TimeZone.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变量,和线程存储相关 __thread char t_errnobuf[512]; __thread char t_time[64]; __thread time_t t_lastSecond;const char* strerror_tl(int savedErrno) {return strerror_r(savedErrno, t_errnobuf, sizeof t_errnobuf); }Logger::LogLevel initLogLevel()//全局函数,返回类型为Logger::LogLevel {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();//日志级别的string形式,方便输出到缓存 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; }void defaultOutput(const char* msg, int len) {size_t n = fwrite(msg, 1, len, stdout);//默认输出到stdout//FIXME check n(void)n; }void defaultFlush() {fflush(stdout);//默认输出到stdout }Logger::OutputFunc g_output = defaultOutput; //output函数指针 Logger::FlushFunc g_flush = defaultFlush; //flush函数指针 TimeZone g_logTimeZone;} // namespace muduo//上面是一个namespace,下面使用上面的namespace 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) {//日志格式:时间---线程ID---日志级别formatTime();//时间CurrentThread::tid();//线程ID//把线程ID和log level输入到日志中stream_ << T(CurrentThread::tidString(), CurrentThread::tidStringLength());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 / Timestamp::kMicroSecondsPerSecond);int microseconds = static_cast<int>(microSecondsSinceEpoch % Timestamp::kMicroSecondsPerSecond);if (seconds != t_lastSecond){t_lastSecond = seconds;struct tm tm_time;if (g_logTimeZone.valid()){tm_time = g_logTimeZone.toLocalTime(seconds);}else{::gmtime_r(&seconds, &tm_time); // FIXME TimeZone::fromUtcTime}int 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;}if (g_logTimeZone.valid()){Fmt us(".%06d ", microseconds);assert(us.length() == 8);stream_ << T(t_time, 17) << T(us.data(), 8);}else{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';//这里的basename_调用前面的重载 }Logger::Logger(SourceFile file, int line) //Logger构造函数: impl_(INFO, 0, file, line) { }Logger::Logger(SourceFile file, int line, LogLevel level, const char* func) //Logger构造函数: impl_(level, 0, file, line) {impl_.stream_ << func << ' '; }Logger::Logger(SourceFile file, int line, LogLevel level) //Logger构造函数: impl_(level, 0, file, line) { }Logger::Logger(SourceFile file, int line, bool toAbort) //Logger构造函数: impl_(toAbort?FATAL:ERROR, errno, file, line) { }Logger::~Logger()//在析构函数输出缓存 {impl_.finish();//给buffer缓冲去添加'/0'const LogStream::Buffer& buf(stream().buffer());//返回bufferg_output(buf.data(), buf.length());if (impl_.level_ == FATAL){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; }void Logger::setTimeZone(const TimeZone& tz) {g_logTimeZone = tz; }《新程序员》:云原生和全面数字化实践50位技术专家共同创作,文字、视频、音频交互阅读
总结
以上是生活随笔为你收集整理的muduo之Logger的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: muduo之Atomic
- 下一篇: 随机数的生成