2013-05-13 29 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