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
- 下一篇: 随机数的生成