日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

muduo之Logger

發布時間:2025/6/15 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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_H

Logging.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的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: www99热| 国产精品毛片一区二区三区 | 欧美一卡二卡三卡 | 国产精品久久成人 | 激情久久网站 | 女同hd系列中文字幕 | 亚洲精品人妻无码 | 日韩影院在线 | 国产交换配乱淫视频免费 | 午夜理伦三级理论 | 亚洲调教| 婷婷色五 | 日韩理论视频 | 色婷婷久久综合中文久久蜜桃av | 成年人观看视频 | 国产精品高潮呻吟久久久久久 | 一级伦理片| 欧美三级三级三级爽爽爽 | 午夜国产精品视频 | 色鬼久久 | 中文字幕欧美视频 | 看av在线 | 黑人与日本少妇 | 亚洲欧美天堂网 | 欧美黑人做爰爽爽爽 | 99久久一区 | 日本一级片在线观看 | 爱爱激情网 | 日本免费黄色大片 | 91在线精品入口 | 中文字幕中文在线 | 成年人午夜免费视频 | 福利一区福利二区 | 麻豆国产免费 | 男人的天堂久久久 | 欧美精品一二 | 免费无码不卡视频在线观看 | 国产三级成人 | 欧美三级图片 | 欧美xx在线 | 淫片一级国产 | 日本精品久久久久久久 | 中文日韩av | 在线观看国产日韩 | 色77777| av免费在线观看不卡 | 毛片在线免费观看网站 | 蜜桃av在线| 成人一级生活片 | 女人做爰全过程免费观看美女 | 亚洲综合一二三区 | 夜夜嗨av一区二区三区免费区 | 久久久久久久国产 | 精品香蕉一区二区三区 | 黄色特级大片 | 黄色一级影片 | 日产毛片 | 草草视频在线观看 | 免费a视频| 激情久久久久久久 | 日本黄色免费在线观看 | 亚洲无线观看 | 九九日韩| 日本在线观看视频网站 | 狠狠人妻久久久久久综合 | 欧美性生活xxx| 色a视频| 亚洲v在线| 可以免费看污视频的网站 | 免费av网址在线观看 | 夜夜操狠狠干 | 久久久久久毛片 | 久久综合伊人77777麻豆最新章节 | 亚洲一级免费视频 | 亚洲宗人网 | 澳门色网 | 国产成人精品亚洲线观看 | 国产在线区| 天天看天天摸 | 亚洲欧美一区二区三区四区五区 | 成人免费在线观看av | 九色porny自拍视频 | 成人高潮片免费网站 | 夜夜导航 | 久久精品一区二区 | 香蕉视频911 | 欧美在线一级视频 | 精品国产午夜福利在线观看 | 免费在线观看成年人视频 | 亚洲精品永久免费 | 网站免费黄色 | 亚洲av无码国产精品久久 | 欧美14sex性hd摘花 | 亚欧美日韩 | 欧美内谢 | 欧美精品video | 日本a大片| 夜av| 超碰在线最新地址 |