带有文件名,行和时间戳的记录器

时间:2013-02-28 11:46:08

标签: c++ logging

我有一个自定义记录器类,其中包含调试,信息等消息的不同方法。除了日志消息,我还要打印调用记录器方法的文件的名称和行,以及时间戳。

我现在的解决方案是这样的:

m_logger.debug("some debug message", __FILE__ , __LINE__, __TIME__);

问题:有没有办法可以避免调用两个宏__FILE____LINE____TIME__,并实现一些以便调用它自动?

感谢。

5 个答案:

答案 0 :(得分:10)

也许是这样的:

#define debug_with_ft(x) debug(x, __FILE__, __TIME__)

...
m_logger.debug_with_ft("some debug message");

当然,有各种不同的方法来解决这个问题,例如:隐藏宏中的整个m_logger

#define debug_with_ft(x) m_logger.debug(x, __FILE__, __TIME__)

答案 1 :(得分:4)

__TIME__是一个预处理器宏,它将在编译时生成当前时间 。因此,它不应该在您的情况下使用,因为您可能希望在运行时访问当前时间(记录消息时)。

__FILE__也是一个预处理器宏,必须在编译前编译时进行评估,不能以其他方式实现。

您可能也对__LINE__

感兴趣

答案 2 :(得分:2)

这是宏 正确解决方案的一种情况。您 想要使用宏调用你的记录器(因为只有一个宏可以 自动插入__FILE____LINE__),您想要 以允许客户端代码传递一个或多个的方式执行此操作 消息元素,可能使用<<。通常的做法 这就像:

#define LOG() m_logger.getStream( __FILE__, __LINE__ )

,其中m_logger.getStream插入标题(使用它 参数和当前时间),并返回一个引用 到日志流,或者也是一个特殊的包装类 实现<< - 只返回对流的引用是 最简单的,但使用包装器可以捕获结束 消息(因为包装器是临时的,它将是 在完整表达结束时被破坏),释放一把锁 取自getStream(以便日志记录是线程安全的),或者 确保输出是原子的,如果是<<包装器 类似的东西:

template <typename T>
LogStream& LogStream::operator<<( T const& object )
{
    if ( myStream != NULL ) {
        *myStream << object;
    }
}

,您可以禁用日志记录,如果是,则不会进行任何转换 它被禁用了。

答案 3 :(得分:1)

为什么您认为__FILE____TIME__不好?我不确定它们本身是否真的是宏。它们是所谓的宏名称。我也认为它们是按标准定义的,因此使用它们应该是安全的。

另一方面,您似乎错过了编译时间评估和运行时间评估的概念。

在运行时如何知道源文件的名称?这就是为什么你应该使用__FILE__,因为编译器会为你评估文件名。

相反,__TIME__也是由编译器替换的宏名称。是否要记录编译或调用行的时间?如果是后者,则应使用适当的运行时函数。

我认为没有任何可能性绕过__FILE__

但是,如果您只想缩短通话时间

我使用以下代码段:

#ifndef NDEBUG
#define DEBUG_MSG(msg) do{ std::cerr << __FILE__ << "(@" << __LINE__ << "): " << msg << '\n'; } while( false )
#else
#define DEBUG_MSG(msg) do{ } while ( false )
#endif

我发现它非常便携且易于使用,但并不意味着它可以用作类方法。 您可以将其定义为

#define DEBUG_MSG(msg) debug( msg, __FILE__, __LINE__ )

并使用

m_logger.DEBUG_MSG("message");

因此宏将扩展到设计的函数调用。然而,这是非常危险的。 如果您更改了debug签名,则需要更改宏,而且几乎无法移植。

答案 4 :(得分:0)

是的,这是可能的。您可以为记录器定义一个宏,如

#define m_logger.debug( ... ) m_logger.debug(__VA_ARGS__, __FILE__, __LINE__, __TIME__ )

但请注意,如果你将* .h和* .cpp文件分开,则必须从* .cpp中排除此定义,因为宏将替换* .cpp中的函数。

通过以下方式完成:

*。CPP

#define MYLOGGER_CPP

和* .h(在底部)

#ifndef MYLOGGER_CPP
  #define m_logger.debug( ... ) m_logger.debug(__VA_ARGS__, __FILE__, __LINE__, __TIME__ )
#endif