2012-02-01 101 views
0

也許這是一個微不足道的問題,許多/大多數/所有優秀的框架都可以做到這一點,但我正在尋找一個記錄器類/框架(儘可能簡單),使可以輕鬆地讓擁有嵌套日誌輸出,像嵌套/格式化日誌記錄

[time] A::doSomething start 
[time] doing this 
[time] doing that 
[time] calling B 
[time] B::somethingElse start 
[time]  do 
[time]  re 
[time]  mi 
[time]  c::foo start 
[time]  ... 
[time]  c::foo end 
[time] B::somethingElse end 
[time] A::doSomething end 

我來同時搜索interwebs是nested diagnostic contexts in log4j最接近的一次。但a)這是爲java和b)我不知道這是否提供了我在找的東西...

還有這個「當離開上下文時,請在文檔中調用NDC.pop」。如果可能的話,我希望有更多基於堆棧的魔法。

有沒有可以做我想找的項目?

TIA

+0

我發現一個簡單的帶有宏的單例類,可以根據調試定義調用調用,如果需要創建調試定義,則最容易創建調試定義,否則只需執行項目已經完成的任務。 – 2012-02-01 13:38:21

+0

「項目」目前使用了veeery簡單的記錄器類。我已經繼承了一堆代碼,流程控制不明確,許多功能/方法有多個退出點,純粹的未經過濾的意大利麪代碼。而且現在我非常渴望用新的日誌代碼來修改代碼,至少可以知道發生了什麼:( – 2012-02-01 14:00:20

+0

@AdrianAlbrecht:方法中的多個退出點沒有問題......但是很長的方法是通常不好:) – 2012-02-01 14:09:03

回答

0

我不知道任何日誌框架,但我已經與我知道這是不是真的很難夠漂亮打印機打出。

假設一個Logger類的存在,支持pushpop操作:

class LogNester: private boost::noncopyable { 
public: 
    LogNester(Logger& l): logger(l) { logger.push(); } 
    ~LogNester() { logger.pop(); } 

private: 
    Logger& logger; 
}; 

用法:

void foo() { 
    LogNester _(GlobalLogger); 

    // do something 
} 

一個重要的一點:你需要變量,LogNester(GlobalLogger)將僅爲此語句推送和彈出(oups),而命名變量將一直存在直到範圍結束。

如果你已經厭倦了每次(這我能理解)推出新的名字,你總是可以訴諸宏:

#define NESTLOG() LogNester BOOST_PP_CAT(log, __LINE__)(GlobalLogger); 

不過,這不正是......自動爲您需要爲每種方法在輸入時定義一個LogNester對象。從理論上講,只要你不介意慢一點,你應該能夠神奇地獲得深度:使用堆棧調用信息。隨着gcc這是使用backtrace工具來完成:

#include <execinfo.h> // GNU/Linux specific header 

inline unsigned depth() { 
    void* Stack[64]; 
    return backtrace(Stack, sizeof(Stack)); 
} 

然後,增強你的日誌宏:

#define LOG(Message_) \ 
    do { \ 
    GlobalLogger.log(__FILE__, __LINE__, __FUNCTION__, depth(), Message_); \ 
    } while(0) 

當然,這取決於相當的呼籲是否內聯與否。

我個人發現__FILE____LINE____FUNCTION__已足夠滿足我的需求。