Apollo 3.5 Cyber Logger模塊簡單分析

2019-04-13 16:00发布

Apollo 3.5 Cyber Logger模塊簡單分析

Logger模塊

cyber之前,apollo的LOG模塊是直接用google的glog的。最多就把人家的LOG(INFO)改名為AINFO
而在cyber中,終於發現他們做了自己的Logger了,主要多了log格式的優化跟性能上的考慮。而他們自己的Logger是實作了google::base::Logger,所以用法跟以前一樣 LOG(INFO) << "xxyy" 而Logger模塊中,主要有LogFileObject,AsyncLoggerLogger3個class, 下邊是他們的關係圖. 在这里插入图片描述
  1. LogFileObject負責跟文件打交道,是真正寫檔案,對log message做格式統一的地方。glog本身也有一個LogFileObject,應該是直接用了glog的一部份代碼,再改了改
  2. AsyncLogger是負責找出對應的LogFileObject,調用其去把數據寫到文件。而AsyncLogger另外提供了double-buffering,即是當log message來到的時候並不會立刻做寫操作,而是先放到一個buffer。而在背景有另一個thread,定期把buffer換到真正的write buffer, 再一次過寫到文件,減少io blocking
  3. LoggerAsyncLogger差不多,但沒有double-buffering,而是message一來就寫.
  4. LoggerAsyncLogger都是要管理多個LogFileObject的。會以log message的內容去決定用那一個LogFileObject

AsyncLogger 中的comment

其實代碼中有仔細comment, 有介紹為甚麼這樣改 // 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.

如何把cyber自定的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。
而async_logger因為用到了另外一個inner thread,所以要async_logger->Start();去啟動