2013-05-13 22 views
3

我有一個簡單的記錄器,用於我的應用程序。這裏是一個(簡化的)接口:C++:記錄器設計,線/函數信息作爲函數參數

class ILogger 
{ 
public: 

    virtual void LogUnsafe(const LogPriority& priority, const boost::format& message) = 0; 

    virtual void Log(const LogPriority& priority, const boost::format& message) 
    { 
     if (priority <= logPriority_) 
     { 
      std::unique_lock<std::mutex> lock(loggerMutex_); 
      LogUnsafe(priority, message); 
     } 
    } 

    void Log(const LogPriority& priority, const std::string& message) 
    { 
     Log(priority, boost::format(message)); 
    } 

    template<typename T, typename... Args> 
    void Log(const LogPriority& priority, boost::format &format, const T &v, Args... args) 
    { 
     Log(priority, boost::format(format) % v, args ...); 
    } 

    template<typename... Args> 
    void Log(const LogPriority& priority, const char *format, Args... args) 
    { 
     boost::format fmt(format); 
     Log(priority, fmt, args ...); 
    } 
}; 

現在我需要(爲了便於錯誤檢測)包括在每一個日誌消息線和功能信息(使用__LINE____FUNCTION__)。合理地它應該作爲函數參數傳遞。和往常一樣,我不想在每次寫日誌消息時輸入所有這些宏。所以我在這裏遇到麻煩了。我如何優雅地將它們傳遞給日誌記錄功能,而無需在每條日誌消息中明確寫入它?

在此先感謝。

+1

由於__LINE__是一個宏觀的,我認爲唯一的辦法就是讓不同的宏包含__LINE__宏。 – olevegard 2013-05-13 10:19:04

+0

@olevegard,不知道這可以幫助。你能提供一個簡單的例子來說明這個想法嗎? – maverik 2013-05-13 10:21:00

+1

您不應該使用「我」來識別您的接口。這是用戶不需要知道的實現細節。 – Dennis 2013-05-13 10:37:05

回答

4

我發現「最好」的方法是使用通過宏創建的日誌對象,如Neil上面解釋的。關於它的「好處」是封裝了網站上的所有可用信息,因此它可以傳遞給不同的記錄器。例如,您可以通過網絡發送一系列「記錄器」,將其發送到磁盤和系統監視器(如Windows事件日誌)。您也可以使用生產者 - 消費者日誌記錄線程來提升性能。

class LogEntry{ 

    LogEntry(const boost::format& traceMsg, const unsigned int lineNumber, const std::string& file){ 
     //set members 
    } 

    std::string print(){ 
     // Do print logic... 
    } 

    // Getters... Allow the logger instance build its own log from the info. 
} 

然後使用宏:

#define LOG(format) sendToLogQueue(LogEntry(format, __LINE__, std::string(__FILE__))); 
3

傳統方法是將您的日誌調用包裝在一個宏中,並且只使用代碼中的宏。

例如

#ifdef NDEBUG 
#define LOG(priority, message) \ 
    Log(priority,message) 
... 
#else 
#define LOG(priority, message) \ 
    Log(priority, message, __FILE__, __LINE__) 
... 
#endif 

void function() 
{ 
    LOG(PRI1, "Message"); 
} 

然後一直使用LOG宏。

+1

注意:即使在發佈模式下,沒有理由不包括'__FILE__'和'__LINE__'。他們可用! – 2013-05-13 11:47:04

+0

它們可用,但佔用額外的代碼/數據空間。由於缺乏內存,我們的嵌入式系統需要將它們移除以進行裝運/發佈。每一個小小的幫助:-) – Neil 2013-05-13 12:13:28

+0

啊!這是一個非常特殊的需求,儘管在服務器上工作,我們保留它們(並且實際上將'__func__'添加到組合中)。 – 2013-05-13 12:15:51