中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁 > news >正文

wordpress修改注冊表班級優(yōu)化大師學(xué)生版

wordpress修改注冊表,班級優(yōu)化大師學(xué)生版,溫州甌北做網(wǎng)站,怎么把自己做的網(wǎng)站放到百度上spdlog Loggers:是 Spdlog 最基本的組件,負(fù)責(zé)記錄日志消息。在 Spdlog 中,一個(gè) Logger 對象代表著一個(gè)日志記錄器,應(yīng)用程序可以使用 Logger 對象記錄不同級別的日志消息Sinks:決定了日志消息的輸出位置。在 Spdlog 中&…

spdlog

請?zhí)砑訄D片描述

  • Loggers:是 Spdlog 最基本的組件,負(fù)責(zé)記錄日志消息。在 Spdlog 中,一個(gè) Logger 對象代表著一個(gè)日志記錄器,應(yīng)用程序可以使用 Logger 對象記錄不同級別的日志消息
  • Sinks:決定了日志消息的輸出位置。在 Spdlog 中,一個(gè) Sink 對象代表著一個(gè)輸出位置,例如控制臺、文件、網(wǎng)絡(luò)等。應(yīng)用程序可以將不同的日志消息發(fā)送到不同的 Sink 中
  • Formatters:負(fù)責(zé)將日志消息轉(zhuǎn)換為特定格式。在 Spdlog 中,一個(gè) Formatter 對象代表著一個(gè)消息格式器,應(yīng)用程序可以使用不同的 Formatter 對象將日志消息轉(zhuǎn)換為不同的格式
  • Async Logger:是 Spdlog 的異步記錄器,它負(fù)責(zé)將日志消息異步地寫入到目標(biāo) Sink 中。當(dāng)應(yīng)用程序調(diào)用 Logger 對象記錄一個(gè)日志消息時(shí),該消息會被加入到一個(gè)隊(duì)列中,然后異步地寫入目標(biāo) Sink 中。這樣可以避免多個(gè)線程同時(shí)訪問 Sink,從而確保線程安全性
  • Registry:用于管理 Spdlog 的所有組件。在 Spdlog 中,所有的 Loggers、Sinks、Formatters 和 Async Logger 都在一個(gè)全局注冊表中注冊,Registry 用于管理這些組件

spdlog 記錄日志的流程

當(dāng)應(yīng)用程序調(diào)用spdlog 記錄日志時(shí),spdlog 的調(diào)用流程如下:

  1. 獲取一個(gè) Logger 對象
  2. 使用該 Logger 對象記錄一個(gè)日志消息,該消息包括日志級別、時(shí)間戳、線程 ID、文件名和行號等信息
  3. 將日志消息傳遞給 Formatter,將消息轉(zhuǎn)換為特定格式
  4. 將格式化后的消息傳遞給 Async Logger
  5. Async Logger 將消息寫入目標(biāo) Sink,完成日志記錄。

源碼結(jié)構(gòu)

.
├── CMakeLists.txt
├── bench
├── cmake
├── example
│   ├── CMakeLists.txt
│   └── example.cpp
├── include
│   └── spdlog
│       ├── async.h       // *.h 異步模式,日志庫接口等實(shí)現(xiàn)
│       ├── async_logger-inl.h
│       ├── async_logger.h
│       ├── cfg
│       ├── common-inl.h
│       ├── common.h
│       ├── details         // 功能函數(shù)目錄
│       │   ├── registry-inl.h
│       │   ├── registry.h  // 管理所有l(wèi)ogger的獲取、創(chuàng)建、銷毀等
│       │   ├── mpmc_blocking_q.h //  多生產(chǎn)多消費(fèi)者隊(duì)列
│       │   ├── circular_q.h  // 循環(huán)隊(duì)列
│       │   ├── thread_pool-inl.h 
│       │   ├── thread_pool.h // 線程池
│       │   └── synchronous_factory.h
│       ├── fmt             // {fmt} 庫目錄
│       ├── formatter.h
│       ├── fwd.h
│       ├── logger-inl.h
│       ├── logger.h
│       ├── mdc.h
│       ├── pattern_formatter-inl.h
│       ├── pattern_formatter.h
│       ├── sinks         // 落地文件格式實(shí)現(xiàn)
│       │   ├── android_sink.h
│       │   ├── ansicolor_sink-inl.h
│       │   ├── ansicolor_sink.h
│       │   ├── base_sink-inl.h
│       │   ├── base_sink.h
│       │   ├── basic_file_sink-inl.h
│       │   ├── basic_file_sink.h
│       │   ├── callback_sink.h
│       │   ├── daily_file_sink.h
│       │   ├── dist_sink.h
│       │   ├── dup_filter_sink.h
│       │   ├── hourly_file_sink.h
│       │   ├── kafka_sink.h
│       │   ├── mongo_sink.h
│       │   ├── msvc_sink.h
│       │   ├── null_sink.h
│       │   ├── ostream_sink.h
│       │   ├── qt_sinks.h
│       │   ├── ringbuffer_sink.h
│       │   ├── rotating_file_sink-inl.h
│       │   ├── rotating_file_sink.h
│       │   ├── sink-inl.h
│       │   ├── sink.h      // 所有sink的基類
│       │   ├── stdout_color_sinks-inl.h
│       │   ├── stdout_color_sinks.h
│       │   ├── stdout_sinks-inl.h
│       │   ├── stdout_sinks.h
│       │   ├── syslog_sink.h
│       │   ├── systemd_sink.h
│       │   ├── tcp_sink.h
│       │   ├── udp_sink.h
│       │   ├── win_eventlog_sink.h
│       │   ├── wincolor_sink-inl.h
│       │   └── wincolor_sink.h
│       ├── spdlog-inl.h
│       ├── spdlog.h
│       ├── stopwatch.h
│       ├── tweakme.h      
│       └── version.h
├── src
│   ├── async.cpp         // .cpp 文件,組成編譯模塊生成靜態(tài)庫使用
│   ├── bundled_fmtlib_format.cpp
│   ├── cfg.cpp
│   ├── color_sinks.cpp
│   ├── file_sinks.cpp
│   ├── spdlog.cpp
│   └── stdout_sinks.cpp
└── tests             // 測試代碼

其中:

  • spdlog/spdlog.h 為日志庫接口,提供日志宏的屬性控制函數(shù)
  • spdlog/logger.h 為日志管理器,為前后端連接的樞紐
  • spdlog/async.h 為異步模式接口
  • spdlog/sinks/base_sink.h 為日志文件格式基類,后面所有的日志文件格式都是繼承該類來實(shí)現(xiàn)不同功能
  • spdlog/sinks/registry.h 用于注冊所有的logger,及一些默認(rèn)的屬性,如日志格式、日志寫入等級

spdlog編譯方式

spdlog的源碼被分在xxx.hxxx-inl.h文件中,其中xxx.h只有函數(shù)和類的聲明,而實(shí)現(xiàn)都以inline的方式寫在了xxx-inl.h中。spdlog提供了header-only versioncompiled version2種方式, 通過SPDLOG_HEADER_ONLY宏定義,可以調(diào)節(jié).h文件中是否包含了其實(shí)現(xiàn)的代碼,如果包含了那就是header-only version。如果不包含,那它就是compiled version中普通的頭文件。如果是compiled version形式,則其源碼中包含xxx-inl.h實(shí)現(xiàn)就可以了。SPDLOG_COMPILED_LIBSPDLOG_HEADER_ONLY宏定義:

// spdlog/common.h
#ifdef SPDLOG_COMPILED_LIB#undef SPDLOG_HEADER_ONLY#define SPDLOG_INLINE
#else  // !defined(SPDLOG_COMPILED_LIB)#define SPDLOG_API#define SPDLOG_HEADER_ONLY#define SPDLOG_INLINE inline
#endif  // #ifdef SPDLOG_COMPILED_LIB
// async.cpp
#ifndef SPDLOG_COMPILED_LIB#error Please define SPDLOG_COMPILED_LIB to compile this file.
#endif#include <spdlog/async.h> // 正常async頭文件,包含類和接口聲明
// xxx-inl.h 具體實(shí)現(xiàn)
#include <spdlog/async_logger-inl.h>
#include <spdlog/details/periodic_worker-inl.h>
#include <spdlog/details/thread_pool-inl.h>// cfg.cpp
#ifndef SPDLOG_COMPILED_LIB#error Please define SPDLOG_COMPILED_LIB to compile this file.
#endif
#include <spdlog/cfg/helpers-inl.h>

spdlog 接口

  • spdlog::debug(), 默認(rèn)的日志對象,使用默認(rèn)的日志信息格式,輸出至 stdout
  • logger->debug(), 指定日志對象進(jìn)行日志記錄,輸出至該日志對象對應(yīng)的文件中
  • SPDLOG_LOGGER_DEBUG(logger), SPDLOG_DEBUG(), 使用宏對以上兩種接口進(jìn)行包裝,產(chǎn)生的日志格式包含 文件、函數(shù)、行
    • 支持的文件類型:
      • 標(biāo)準(zhǔn)輸出
      • 帶顏色的標(biāo)準(zhǔn)輸出(默認(rèn))
      • 基本文件
      • 可設(shè)定時(shí)間的滾動文件
      • 可設(shè)定大小的滾動文件
      • 過濾重復(fù)的日志
      • syslog 日志

spdlog 默認(rèn)使用同步模式,也可以設(shè)置異步模式,異步模式會創(chuàng)建一個(gè)線程池,線程池大小可以自行設(shè)置,默認(rèn)為1,該線程池所有者為 details::registry::instance(). 后臺的大小可以設(shè)置的 多生產(chǎn)者多消費(fèi)者隊(duì)列 默認(rèn)為阻塞模式,也可以設(shè)置為非阻塞。

sync-logger 的調(diào)用過程

// 調(diào)用例如spdlog::info("Welcome to spdlog!"); 
// 或者spdlog::info(num);
template <typename T> void info(const T &msg)
{ log(level::info, msg); }   // 1. 確定log等級為info// 調(diào)用例如spdlog::info("Support for floats {:03.2f}", 1.23456);
// 或者spdlog::info("Positional args are {1} {0}..", "too", "supported");
template <typename... Args> void info(format_string_t<Args...> fmt, Args &&...args)
{ log(level::info, fmt, std::forward<Args>(args)...); }  // 1. 確定log等級為infotemplate <typename T> void log(level::level_enum lvl, const T &msg)
{ log(source_loc{}, lvl, msg); }  // 2. 確定日志調(diào)用的位置(文件、函數(shù)名、行號)template <typename... Args>
void log(level::level_enum lvl, format_string_t<Args...> fmt, Args &&...args)
{ log(source_loc{}, lvl, fmt, std::forward<Args>(args)...); }  // 2. 確定日志調(diào)用的位置(文件、函數(shù)名、行號)template <typename T> void log(source_loc loc, level::level_enum lvl, const T &msg)
{ log(loc, lvl, "{}", msg); } // spdlog::info(num);可以等價(jià)為spdlog::info("{}", num);這里加了一個(gè)“{}”template <typename... Args>
void log(source_loc loc, level::level_enum lvl, format_string_t<Args...> fmt, Args &&...args)
{ log_(loc, lvl, details::to_string_view(fmt), std::forward<Args>(args)...); }  // 3. log_日志輸出// 4. 
template <typename... Args>
void log_(source_loc loc, level::level_enum lvl, string_view_t fmt, Args &&...args) {bool log_enabled = should_log(lvl); // 是否需要記錄日志bool traceback_enabled = tracer_.enabled(); // 是否需要tracebackif (!log_enabled && !traceback_enabled) { return; } memory_buf_t buf;// 使用第三方的fmt庫做格式化,例如將("num {:.2f}", 1.23456) 格式化成 "num 1.23"fmt::vformat_to(fmt::appender(buf), fmt, fmt::make_format_args(args...));details::log_msg log_msg(loc, name_, lvl, string_view_t(buf.data(), buf.size()));// log_it_(log_msg, log_enabled, traceback_enabled);
}// 5. 
void logger::log_it_(const spdlog::details::log_msg &log_msg,bool log_enabled,bool traceback_enabled) {if (log_enabled) { sink_it_(log_msg); }if (traceback_enabled) { tracer_.push_back(log_msg); }
}
// 6. 
void logger::sink_it_(const details::log_msg &msg) {// 遍歷sinks_中的所有sink并把msg交給每個(gè)sink去處理for (auto &sink : sinks_) {if (sink->should_log(msg.level)) { sink->log(msg); }}// should_flush_: 通過判斷msg的等級和flush_level_的關(guān)系來決定是不是立即將msg寫到文件或終端if (should_flush_(msg)) { flush_(); }
}
// 7. 讓所有sink都進(jìn)行一次flush操作
void logger::flush_() {for (auto &sink : sinks_) { sink->flush(); // 將緩沖區(qū)的內(nèi)容進(jìn)一步寫入到文件或者控制臺等最終目的地}
}

async-logger 的調(diào)用過程

async-logger的代碼在asyn_logger.h和async_looger-inl.h中,對應(yīng)async_logger類。async_logger繼承自logger,前面關(guān)于接受日志內(nèi)容整理log_msg對象中的工作照常做,將對sink的調(diào)用(包括sink->log(msg)和sink->flush())都交由線程池去執(zhí)行了,由此便實(shí)現(xiàn)了異步。代碼如下:

void spdlog::async_logger::sink_it_(const details::log_msg &msg)
{if (auto pool_ptr = thread_pool_.lock()) {pool_ptr->post_log(shared_from_this(), msg, overflow_policy_);}else {throw_spdlog_ex("async log: thread pool doesn't exist anymore");}
}
// thread_pool_ 的聲明
std::weak_ptr<details::thread_pool> thread_pool_;

線程池里面要有一個(gè)多生產(chǎn)多消費(fèi)的線程安全隊(duì)列,用來存放日志內(nèi)容??梢杂卸鄠€(gè)async_logger(即生產(chǎn)者)向里面生產(chǎn)日志,又同時(shí)又多個(gè)線程(即消費(fèi)者)從里面消費(fèi)日志。這個(gè)隊(duì)列的容量應(yīng)該是有限的,當(dāng)隊(duì)列滿了之后向里面生產(chǎn)日志可以有不同的策略,spdlog提供了三種策略:阻塞、丟棄新日志丟棄舊日志。為方便實(shí)現(xiàn)這個(gè)需求,用循環(huán)隊(duì)列來實(shí)現(xiàn)

循環(huán)隊(duì)列

循環(huán)隊(duì)列的代碼在circular_q.h中實(shí)現(xiàn):

  • circular_q應(yīng)設(shè)計(jì)成類模板,使其能夠支持各種數(shù)據(jù)類型;
  • circular_q中實(shí)際存數(shù)據(jù)的std::vector<T> vec_的大小應(yīng)該比circular_q能存的數(shù)據(jù)大小多一個(gè),這樣才能隊(duì)列是滿的還是空的

多生產(chǎn)多消費(fèi)的線程安全隊(duì)列

template <typename T>
class mpmc_blocking_queue {...// try to enqueue and block if no room leftvoid enqueue(T &&item) {std::unique_lock<std::mutex> lock(queue_mutex_);pop_cv_.wait(lock, [this] { return !this->q_.full(); }); // 阻塞式等待,直到q_非滿狀態(tài)q_.push_back(std::move(item));push_cv_.notify_one();}// blocking dequeue without a timeout.void dequeue(T &popped_item) {std::unique_lock<std::mutex> lock(queue_mutex_);push_cv_.wait(lock, [this] { return !this->q_.empty(); }); // 阻塞式等待popped_item = std::move(q_.front());q_.pop_front();pop_cv_.notify_one();}private:std::mutex queue_mutex_;std::condition_variable push_cv_;std::condition_variable pop_cv_;spdlog::details::circular_q<T> q_;std::atomic<size_t> discard_counter_{0};
}

spdlog線程池

thread_pool使用了mpmc_blocking_queue(多生產(chǎn)者-多消費(fèi)者阻塞隊(duì)列)來緩存日志消息。這個(gè)隊(duì)列允許多個(gè)前端線程(生產(chǎn)者)同時(shí)向隊(duì)列中添加日志消息,也允許多個(gè)后端線程(消費(fèi)者)同時(shí)從隊(duì)列中取出消息。前端線程是指用戶調(diào)用日志記錄功能的線程。當(dāng)用戶調(diào)用異步日志記錄方法時(shí),日志消息會被封裝成 async_msg 對象,并放入 mpmc_blocking_queue 隊(duì)列中。thread_pool 內(nèi)部維護(hù)了一組后端線程,這些線程從 mpmc_blocking_queue 隊(duì)列中取出日志消息并進(jìn)行處理。實(shí)際上是調(diào)用 async_logger::backend_sink_it_ 方法,將日志消息寫入到預(yù)先注冊的 sink(日志輸出目標(biāo),如文件、控制臺等)

log_msg
+string_view_t logger_name
+level::level_enum level
+log_clock::time_point time
+size_t thread_id
+source_loc source;
+string_view_t payload;
+mutable size_t color_range_start
+mutable size_t color_range_end
+log_msg(log_clock::time_point log_time, source_loc loc,string_view_t logger_name,level::level_enum lvl, string_view_t msg)
+log_msg(source_loc loc, string_view_t logger_name, level::level_enum lvl, string_view_t msg)
+log_msg(string_view_t logger_name, level::level_enum lvl, string_view_t msg)
log_msg_buffer
-memory_buf_t buffer
+log_msg_buffer()
+explicit log_msg_buffer(const log_msg &orig_msg)
+log_msg_buffer(const log_msg_buffer &other)
+log_msg_buffer(log_msg_buffer &&other)
+log_msg_buffer &operator=(const log_msg_buffer &other)
+log_msg_buffer &operator=(log_msg_buffer &&other)
-void update_string_views()
async_msg
+async_msg_type msg_type
+async_logger_ptr worker_ptr
+std::promise flush_promise
+async_msg()
+~async_msg()
+async_msg(const async_msg &)
+async_msg(async_logger_ptr &&worker, async_msg_type the_type, const details::log_msg &m)
+async_msg(async_logger_ptr &&worker, async_msg_type the_type)
+async_msg(async_logger_ptr &&worker, async_msg_type the_type, std::promise &&promise)
+explicit async_msg(async_msg_type the_type)
thread_pool
-q_type q_
-std::vector threads_
+thread_pool(size_t q_max_items, size_t threads_n, std::function on_thread_start, std::function on_thread_stop)
+thread_pool(size_t q_max_items, size_t threads_n, std::function on_thread_start)
+thread_pool(size_t q_max_items, size_t threads_n)
+void post_log(async_logger_ptr &&worker_ptr, const details::log_msg &msg, async_overflow_policy overflow_policy)
+std::future post_flush(async_logger_ptr &&worker_ptr, async_overflow_policy overflow_policy)
+size_t overrun_counter()
+void reset_overrun_counter()
+size_t discard_counter()
+void reset_discard_counter()
+size_t queue_size()
-void post_async_msg_(async_msg &&new_msg, async_overflow_policy overflow_policy)
-void worker_loop_()
-bool process_next_msg_()
SPDLOG_INLINE thread_pool::thread_pool(size_t q_max_items,size_t threads_n,std::function<void()> on_thread_start,std::function<void()> on_thread_stop): q_(q_max_items) {if (threads_n == 0 || threads_n > 1000) {throw_spdlog_ex("spdlog::thread_pool(): invalid threads_n param (valid range is 1-1000)");}for (size_t i = 0; i < threads_n; i++) {threads_.emplace_back([this, on_thread_start, on_thread_stop] {on_thread_start();this->thread_pool::worker_loop_();on_thread_stop();});}
}
SPDLOG_INLINE thread_pool::thread_pool(size_t q_max_items,size_t threads_n,std::function<void()> on_thread_start): thread_pool(q_max_items, threads_n, on_thread_start, [] {}) {}
SPDLOG_INLINE thread_pool::thread_pool(size_t q_max_items, size_t threads_n): thread_pool(q_max_items, threads_n, [] {}, [] {}) {}void SPDLOG_INLINE thread_pool::worker_loop_() {while (process_next_msg_()) {}
}// process next message in the queue, return true if this thread should 
// still be active (while no terminate msg was received)
bool SPDLOG_INLINE thread_pool::process_next_msg_() {async_msg incoming_async_msg;q_.dequeue(incoming_async_msg);switch (incoming_async_msg.msg_type) {case async_msg_type::log: {incoming_async_msg.worker_ptr->backend_sink_it_(incoming_async_msg);return true;}case async_msg_type::flush: {incoming_async_msg.worker_ptr->backend_flush_();incoming_async_msg.flush_promise.set_value();return true;}case async_msg_type::terminate: {return false;}default: {assert(false);}}return true;
}std::future<void> SPDLOG_INLINE thread_pool::post_flush(async_logger_ptr &&worker_ptr,async_overflow_policy overflow_policy) {std::promise<void> promise;std::future<void> future = promise.get_future();post_async_msg_(async_msg(std::move(worker_ptr), async_msg_type::flush, std::move(promise)), overflow_policy);return future;
}
void SPDLOG_INLINE thread_pool::post_async_msg_(async_msg &&new_msg, async_overflow_policy overflow_policy) {if (overflow_policy == async_overflow_policy::block) {q_.enqueue(std::move(new_msg));} else if (overflow_policy == async_overflow_policy::overrun_oldest) {q_.enqueue_nowait(std::move(new_msg));} else {assert(overflow_policy == async_overflow_policy::discard_new);q_.enqueue_if_have_room(std::move(new_msg));}
}

spdlog sink

sink接收log_msg對象,并通過formatter將對象中所含有的信息轉(zhuǎn)換成字符串,最后將字符串輸出到指定的地方,例如控制臺、文件等,甚至通過tcp/udp將字符串發(fā)送到指定的地方

sink 類圖

sink
#level_t level_ = level::trace;
+virtual void log(const details::log_msg &msg)
+virtual void flush()
+virtual void set_pattern(const std::string &pattern)
+virtual void set_formatter(std::unique_ptr sink_formatter)
+void set_level(level::level_enum log_level)
+level::level_enum level()
+bool should_log(level::level_enum msg_level)
base_sink<Mutex>
#std::unique_ptr formatter_
#Mutex mutex_
+void log(const details::log_msg &msg)
+void flush()
+void set_pattern(const std::string &pattern)
+void set_formatter(std::unique_ptr sink_formatter)
#virtual void sink_it_(const details::log_msg &msg)
#virtual void flush_()
#virtual void set_pattern_(const std::string &pattern)
#virtual void set_formatter_(std::unique_ptr sink_formatter)
basic_file_sink<Mutex>
-details::file_helper file_helper_
#void sink_it_(const details::log_msg &msg)
#void flush_()
daily_file_sink<Mutex、FileNameCalc>
-filename_t base_filename_;
-int rotation_h_;
-int rotation_m_;
-log_clock::time_point rotation_tp_;
-details::file_helper file_helper_;
-bool truncate_;
-uint16_t max_files_;
-details::circular_q filenames_q_;
+daily_file_sink(filename_t base_filename, int rotation_hour, int rotation_minute, bool truncate = false, uint16_t max_files = 0, const file_event_handlers &event_handlers)
+filename_t filename()
#void sink_it_(const details::log_msg &msg)
#void flush_()
-void init_filenames_q_()
-tm now_tm(log_clock::time_point tp)
-log_clock::time_point next_rotation_tp_()
-void delete_old_()
hourly_file_sink<Mutex、FileNameCalc>
-filename_t base_filename_;
-log_clock::time_point rotation_tp_;
-details::file_helper file_helper_;
-bool truncate_;
-uint16_t max_files_;
-details::circular_q filenames_q_;
-bool remove_init_file_;
+hourly_file_sink(filename_t base_filename, bool truncate = false, uint16_t max_files = 0, const file_event_handlers &event_handlers)
+filename_t filename()
#void sink_it_(const details::log_msg &msg)
#void flush_()
-void init_filenames_q_()
-tm now_tm(log_clock::time_point tp)
-log_clock::time_point next_rotation_tp_()
-void delete_old_()
rotating_file_sink<Mutex>
-filename_t base_filename_;
-std::size_t max_size_;
-std::size_t max_files_;
-std::size_t current_size_;
-details::file_helper file_helper_;
+rotating_file_sink(filename_t base_filename, std::size_t max_size,std::size_t max_files,bool rotate_on_open = false,const +file_event_handlers &event_handlers)
+filename_t calc_filename(const filename_t &filename, std::size_t index)
+filename_t filename()
#void sink_it_(const details::log_msg &msg)
#void flush_()
-void rotate_()
-bool rename_file_(const filename_t &src_filename, const filename_t &target_filename)
dist_sink<Mutex>
#std::vector> sinks_
+explicit dist_sink(std::vector> sinks)
+void add_sink(std::shared_ptr sub_sink)
+void remove_sink(std::shared_ptr sub_sink)
+void set_sinks(std::vector> sinks)
+std::vector> &sinks()
#void sink_it_(const details::log_msg &msg)
#void flush_()
#void set_pattern_(const std::string &pattern)
#void set_formatter_(std::unique_ptr sink_formatter)
dup_filter_sink<Mutex>
#std::chrono::microseconds max_skip_duration_;
#log_clock::time_point last_msg_time_;
#std::string last_msg_payload_;
#size_t skip_counter_ = 0;
#level::level_enum log_level_;
+explicit dup_filter_sink~Rep,Period~(std::chrono::duration max_skip_duration, level::level_enum notification_level = level::info)
#void sink_it_(const details::log_msg &msg)
#bool filter_(const details::log_msg &msg)
stdout_sink_base<ConsoleMutex>
#mutex_t &mutex_;
#FILE *file_;
#std::unique_ptr formatter_;
+explicit stdout_sink_base(FILE *file)
+void log(const details::log_msg &msg)
+void flush()
+void set_pattern(const std::string &pattern)
+void set_formatter(std::unique_ptr sink_formatter)
stdout_sink<ConsoleMutex>
+stdout_sink()
stderr_sink<ConsoleMutex>
+stderr_sink()

源碼剖析

logger factory

// synchronous_factory.h 
// Default logger factory-  creates synchronous loggers
struct synchronous_factory {template <typename Sink, typename... SinkArgs>static std::shared_ptr<spdlog::logger> create(std::string logger_name, SinkArgs &&...args) {auto sink = std::make_shared<Sink>(std::forward<SinkArgs>(args)...);auto new_logger = std::make_shared<spdlog::logger>(std::move(logger_name), std::move(sink));details::registry::instance().initialize_logger(new_logger);return new_logger;}
};// stdout_sinks factory
template <typename Factory = spdlog::synchronous_factory>
std::shared_ptr<logger> stdout_logger_mt(const std::string &logger_name);template <typename Factory = spdlog::synchronous_factory>
std::shared_ptr<logger> stdout_logger_st(const std::string &logger_name);template <typename Factory = spdlog::synchronous_factory>
std::shared_ptr<logger> stderr_logger_mt(const std::string &logger_name);template <typename Factory = spdlog::synchronous_factory>
std::shared_ptr<logger> stderr_logger_st(const std::string &logger_name);// stdout_color_sinks
// stdout_color_mt: 多線程(mult thread)   stdout_color_st: 單線程(single thread)
template <typename Factory>
SPDLOG_INLINE std::shared_ptr<logger> stdout_color_mt(const std::string &logger_name, color_mode mode) {return Factory::template create<sinks::stdout_color_sink_mt>(logger_name, mode);
}template <typename Factory>
SPDLOG_INLINE std::shared_ptr<logger> stdout_color_st(const std::string &logger_name, color_mode mode) {return Factory::template create<sinks::stdout_color_sink_st>(logger_name, mode);
}template <typename Factory>
SPDLOG_INLINE std::shared_ptr<logger> stderr_color_mt(const std::string &logger_name, color_mode mode) {return Factory::template create<sinks::stderr_color_sink_mt>(logger_name, mode);
}template <typename Factory>
SPDLOG_INLINE std::shared_ptr<logger> stderr_color_st(const std::string &logger_name, color_mode mode) {return Factory::template create<sinks::stderr_color_sink_st>(logger_name, mode);
}// basic_file_sink factory
template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> basic_logger_mt(const std::string &logger_name,const filename_t &filename,bool truncate = false,const file_event_handlers &event_handlers = {}) {return Factory::template create<sinks::basic_file_sink_mt>(logger_name, filename, truncate, event_handlers);
}template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> basic_logger_st(const std::string &logger_name,const filename_t &filename,bool truncate = false,const file_event_handlers &event_handlers = {}) {return Factory::template create<sinks::basic_file_sink_st>(logger_name, filename, truncate, event_handlers);
}// daily_file_sink factory
template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> daily_logger_mt(const std::string &logger_name,const filename_t &filename,int hour = 0,int minute = 0,bool truncate = false,uint16_t max_files = 0,const file_event_handlers &event_handlers = {}) {return Factory::template create<sinks::daily_file_sink_mt>(logger_name, filename, hour, minute, truncate, max_files, event_handlers);
}template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> daily_logger_format_mt(const std::string &logger_name,const filename_t &filename,int hour = 0,int minute = 0,bool truncate = false,uint16_t max_files = 0,const file_event_handlers &event_handlers = {}) {return Factory::template create<sinks::daily_file_format_sink_mt>(logger_name, filename, hour, minute, truncate, max_files, event_handlers);
}template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> daily_logger_st(const std::string &logger_name,const filename_t &filename,int hour = 0,int minute = 0,bool truncate = false,uint16_t max_files = 0,const file_event_handlers &event_handlers = {}) {return Factory::template create<sinks::daily_file_sink_st>(logger_name, filename, hour, minute, truncate, max_files, event_handlers);
}template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> daily_logger_format_st(const std::string &logger_name,const filename_t &filename,int hour = 0,int minute = 0,bool truncate = false,uint16_t max_files = 0,const file_event_handlers &event_handlers = {}) {return Factory::template create<sinks::daily_file_format_sink_st>(logger_name, filename, hour, minute, truncate, max_files, event_handlers);
}// hourly_file_sink
template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> hourly_logger_mt(const std::string &logger_name,const filename_t &filename,bool truncate = false,uint16_t max_files = 0,const file_event_handlers &event_handlers = {}) {return Factory::template create<sinks::hourly_file_sink_mt>(logger_name, filename, truncate, max_files, event_handlers);
}template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> hourly_logger_st(const std::string &logger_name,const filename_t &filename,bool truncate = false,uint16_t max_files = 0,const file_event_handlers &event_handlers = {}) {return Factory::template create<sinks::hourly_file_sink_st>(logger_name, filename, truncate, max_files, event_handlers);
}
// rotating_file_sink
template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> rotating_logger_mt(const std::string &logger_name,const filename_t &filename,size_t max_file_size,size_t max_files,bool rotate_on_open = false,const file_event_handlers &event_handlers = {}) {return Factory::template create<sinks::rotating_file_sink_mt>(logger_name, filename, max_file_size, max_files, rotate_on_open, event_handlers);
}template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> rotating_logger_st(const std::string &logger_name,const filename_t &filename,size_t max_file_size,size_t max_files,bool rotate_on_open = false,const file_event_handlers &event_handlers = {}) {return Factory::template create<sinks::rotating_file_sink_st>(logger_name, filename, max_file_size, max_files, rotate_on_open, event_handlers);
}
以stdout_logger為例看整個(gè)logger創(chuàng)建過程
using stdout_sink_mt = stdout_sink<details::console_mutex>;     // 有鎖對應(yīng)多線程版本
using stdout_sink_st = stdout_sink<details::console_nullmutex>; // 無鎖對應(yīng)單線程版本// 1. 調(diào)用工廠方法
template <typename Factory>
SPDLOG_INLINE std::shared_ptr<logger> stdout_logger_mt(const std::string &logger_name) {return Factory::template create<sinks::stdout_sink_mt>(logger_name);
}
// 2. 創(chuàng)建logger之后將其注冊進(jìn)registry并返回logger
struct synchronous_factory {template <typename Sink, typename... SinkArgs>static std::shared_ptr<spdlog::logger> create(std::string logger_name, SinkArgs &&...args) {auto sink = std::make_shared<Sink>(std::forward<SinkArgs>(args)...);auto new_logger = std::make_shared<spdlog::logger>(std::move(logger_name), std::move(sink)); // 1. 構(gòu)造loggerdetails::registry::instance().initialize_logger(new_logger);  // 2. 調(diào)用registry的initialize_logger方法中return new_logger;}
};
// 3.
SPDLOG_INLINE void registry::initialize_logger(std::shared_ptr<logger> new_logger) {std::lock_guard<std::mutex> lock(logger_map_mutex_);new_logger->set_formatter(formatter_->clone());if (err_handler_) {new_logger->set_error_handler(err_handler_);}// set new level according to previously configured level or default levelauto it = log_levels_.find(new_logger->name());auto new_level = it != log_levels_.end() ? it->second : global_log_level_;new_logger->set_level(new_level);new_logger->flush_on(flush_level_);if (backtrace_n_messages_ > 0) {new_logger->enable_backtrace(backtrace_n_messages_);}if (automatic_registration_) {register_logger_(std::move(new_logger));}
}

registry

Loggers registry of unique name->logger pointer. An attempt to create a logger with an already existing name will result
with spdlog_ex exception.If user requests a non existing logger, nullptr will be returned. This class is thread safe

// std::unordered_map<std::string, std::shared_ptr<logger>> loggers_;// create default logger (ansicolor_stdout_sink_mt)
registry::registry() : formatter_(new pattern_formatter()) {auto color_sink = std::make_shared<sinks::ansicolor_stdout_sink_mt>();const char *default_logger_name = "";default_logger_ = std::make_shared<spdlog::logger>(default_logger_name, std::move(color_sink));loggers_[default_logger_name] = default_logger_;
spdlog::info(“Welcome to spdlog!”)調(diào)用分析
// spdlog/spdlog.h
template <typename... Args>
inline void info(format_string_t<Args...> fmt, Args &&...args) {default_logger_raw()->info(fmt, std::forward<Args>(args)...);
}spdlog::logger *default_logger_raw() {return details::registry::instance().get_default_raw();
}// spdlog/details/register-inl.h
registry &registry::instance() {static registry s_instance;return s_instance;
}// spdlog/details/register-inl.h
logger *registry::get_default_raw() { return default_logger_.get();  // default_logger_ 由registry模塊初始化
}

附件

超詳細(xì)!spdlog源碼解析(上)
spdlog源碼解讀(三)

http://www.risenshineclean.com/news/38242.html

相關(guān)文章:

  • 做網(wǎng)絡(luò) 批發(fā)的網(wǎng)站seo運(yùn)營推廣
  • 安卓網(wǎng)站開發(fā)平臺東莞百度seo電話
  • 網(wǎng)站開發(fā)主要用什么語言武漢seo關(guān)鍵詞排名優(yōu)化
  • 服務(wù)器 無法訪問網(wǎng)站上海網(wǎng)絡(luò)推廣外包公司
  • 深圳建筑工程招聘信息凱里seo排名優(yōu)化
  • 最好的自助建站系統(tǒng)店鋪運(yùn)營方案策劃
  • 網(wǎng)站建設(shè)開發(fā)的條件軟文營銷實(shí)施背景
  • 在北京做網(wǎng)站制作一個(gè)月多少錢百度快照收錄入口
  • 東莞汽車網(wǎng)站建設(shè)百度指數(shù)排名
  • 網(wǎng)站建設(shè)實(shí)力滴滴友鏈
  • 深圳市招聘信息網(wǎng)站佛山網(wǎng)絡(luò)排名優(yōu)化
  • 網(wǎng)站建設(shè)包含哪些方面刷關(guān)鍵詞排名軟件有用嗎
  • 深度網(wǎng)營銷型網(wǎng)站建設(shè)公司怎么樣seo網(wǎng)站優(yōu)化
  • 東莞網(wǎng)站設(shè)計(jì)電話網(wǎng)址查詢服務(wù)中心
  • 重慶廣告網(wǎng)站推廣seo結(jié)算系統(tǒng)
  • 高端網(wǎng)站建設(shè)公司價(jià)格關(guān)鍵詞優(yōu)化價(jià)格
  • 免費(fèi)咨詢律師不收費(fèi)的平臺長治seo顧問
  • 阿里巴巴招聘官網(wǎng)西安關(guān)鍵詞優(yōu)化平臺
  • 做特殊單頁的網(wǎng)站怎樣建立一個(gè)網(wǎng)絡(luò)銷售平臺
  • 自己做靜態(tài)網(wǎng)站的步驟百度搜索技巧
  • 建站寶盒做的網(wǎng)站十大免費(fèi)excel網(wǎng)站
  • 公司做網(wǎng)站之前要準(zhǔn)備什么軟件廣點(diǎn)通廣告投放平臺登錄
  • 什么網(wǎng)站做電氣自動化兼職做優(yōu)化的網(wǎng)站
  • 做博物館網(wǎng)站最重要性seo視頻教學(xué)網(wǎng)站
  • 深圳做網(wǎng)站有哪些指數(shù)函數(shù)
  • 設(shè)計(jì)師做網(wǎng)站的流程西安網(wǎng)站建設(shè)哪家好
  • 怎么設(shè)計(jì)自己的網(wǎng)站知乎小說推廣對接平臺
  • 專業(yè)汽車網(wǎng)站seo日常工作都做什么的
  • 做網(wǎng)站百度推廣多少錢客戶關(guān)系管理系統(tǒng)
  • 設(shè)計(jì)做網(wǎng)站哪家公司好短期培訓(xùn)班學(xué)什么好