日韩性视频-久久久蜜桃-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的全部內容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 欢乐谷在线观看免费播放高清 | 中文在线字幕免费观看电 | 婷婷五月综合久久中文字幕 | 日韩亚洲欧美综合 | 久久中文字幕在线观看 | 国产精品网页 | 在线观看亚洲欧美 | 快播av在线 | 中文字幕人妻一区二区在线视频 | 久草视频中文在线 | 欧美视频在线观看一区二区 | 欧美理伦片在线播放 | 日韩一区不卡 | 日韩精品成人 | 美女黄色小视频 | 日韩高清在线观看一区 | 国产一区二区欧美日韩 | 日本aⅴ视频 | av中文字幕在线免费观看 | 一本大道久久a久久综合婷婷 | xxxwww国产 | 欧美精品成人一区二区三区四区 | 国产又粗又长又黄的视频 | 超碰老司机 | 小泽玛丽亚在线观看 | 人人澡人人澡人人澡 | 日本xxxwww| 亚洲一级片网站 | 特及毛片| 91av日本| 一级做a爱片久久毛片 | 伊人激情在线 | 亚洲精品久久久久久久久久久久久 | 黄色刺激视频 | 婷婷综合色 | 99免费观看 | 亚洲精品在线视频观看 | 国产毛片基地 | 成人在线免费视频播放 | 免费黄色大片 | 99久久久无码国产精品免费蜜柚 | 一区二区三区波多野结衣 | 黄色大片免费网站 | 狠狠插狠狠操 | 丰满熟妇被猛烈进入高清片 | 99久久久无码国产精品性 | 欧美精品一区二区三区四区 | 欧美日本亚洲 | 大粗鳮巴久久久久久久久 | 日本人的性生活视频 | 欧美顶级毛片在线播放 | 亚洲av无码国产精品永久一区 | 日本熟妇一区二区三区四区 | 国产情侣露脸自拍 | 欧美一二三区视频 | 国产乱码精品一区二三赶尸艳谈 | 成年人视频在线观看免费 | 欧美一级片黄色 | aa爱做片免费 | 日韩一级黄色 | 天堂аⅴ在线最新版在线 | 国产在线视频在线观看 | 漂亮人妻洗澡被公强 日日躁 | 日本免费一二三区 | 久久综合中文字幕 | 精品欧美| 无码国产精品一区二区免费16 | 免费成人美女女 | 香蕉国产片 | 亚洲a成人 | 国产毛片a级 | 自拍偷拍麻豆 | 日本精品久久久久久 | 美女的隐私免费看 | 中文字幕在线观看网址 | jizz中文字幕 | 久久久黄色片 | 俄罗斯精品一区二区三区 | 成年人免费看的视频 | 97毛片| 狠狠爱夜夜 | 日本 奴役 捆绑 受虐狂xxxx | 在线免费一区二区 | 亚洲欧洲日本国产 | 免费成人av在线播放 | 国产精品久久久久影院老司 | 免费成人激情视频 | www.国产视频.com | 成人手机在线观看 | 午夜神马影院 | 国产剧情精品 | 精品美女视频 | 亚洲a成人 | 在线视频国产一区 | 97精品久久 | 国产精品三级电影 | 久久爱综合| 亚洲中文一区二区三区 | 男人久久|