cyber
之前,apollo的LOG模塊是直接用google的glog
的。最多就把人家的LOG(INFO)
改名為AINFO
。cyber
中,終於發現他們做了自己的Logger了,主要多了log格式的優化跟性能上的考慮。而他們自己的Logger是實作了google::base::Logger
,所以用法跟以前一樣 LOG(INFO) << "xxyy"
而Logger模塊中,主要有LogFileObject
,AsyncLogger
跟Logger
3個class, 下邊是他們的關係圖.
LogFileObject
負責跟文件打交道,是真正寫檔案,對log message做格式統一的地方。glog
本身也有一個LogFileObject
,應該是直接用了glog
的一部份代碼,再改了改AsyncLogger
是負責找出對應的LogFileObject
,調用其去把數據寫到文件。而AsyncLogger
另外提供了double-buffering
,即是當log message來到的時候並不會立刻做寫操作,而是先放到一個buffer。而在背景有另一個thread,定期把buffer換到真正的write buffer, 再一次過寫到文件,減少io blockingLogger
跟AsyncLogger
差不多,但沒有double-buffering
,而是message一來就寫.Logger
和AsyncLogger
都是要管理多個LogFileObject
的。會以log message的內容去決定用那一個LogFileObject
// Wrapper for a glog Logger which asynchronously writes log messages.
// This class starts a new thread responsible for forwarding the messages
// to the logger, and performs double buffering. Writers append to the
// current buffer and then wake up the logger thread. The logger swaps in
// a new buffer and writes any accumulated messages to the wrapped
// Logger.
//
// This double-buffering design dramatically improves performance, especially
// for logging messages which require flushing the underlying file (i.e WARNING
// and above for default). The flush can take a couple of milliseconds, and in
// some cases can even block for hundreds of milliseconds or more. With the
// double-buffered approach, threads can proceed with useful work while the IO
// thread blocks.
//
// The semantics provided by this wrapper are slightly weaker than the default
// glog semantics. By default, glog will immediately (synchronously) flush
// WARNING
// and above to the underlying file, whereas here we are deferring that flush to
// a separate thread. This means that a crash just after a 'LOG_WARN' would
// may be missing the message in the logs, but the perf benefit is probably
// worth it. We do take care that a glog FATAL message flushes all buffered log
// messages before exiting.
//
// NOTE: the logger limits the total amount of buffer space, so if the
// underlying
// log blocks for too long, eventually the threads generating the log messages
// will block as well. This prevents runaway memory usage.
Logger
用到glog
中cyber/init.cc
// Init glog
google::InitGoogleLogging(binary_name);
google::SetLogDestination(google::ERROR, "");
google::SetLogDestination(google::WARNING, "");
google::SetLogDestination(google::FATAL, "");
// Init async logger
async_logger = new ::apollo::cyber::logger::AsyncLogger(
google::base::GetLogger(FLAGS_minloglevel), 2 * 1024 * 1024);
google::base::SetLogger(FLAGS_minloglevel, async_logger);
async_logger->Start();
glog
已經提供了接口,調用google::base::SetLogger
便可以更改為自定義logger。inner thread
,所以要async_logger->Start();
去啟動