如何在需要时添加易于打开的日志并关闭而无需生产开销?

时间:2013-04-24 15:57:12

标签: c++

在我的C#项目中,我喜欢使用ConditionalAttribute并发现它非常有用。我有很多用于日志记录的类,只需重新编译并设置相应的条件属性或取消设置我可以打开或关闭日志记录(没有开销)。

// this code likely is not good as HedgerControllerLogger better to be singleton
// please ignore that

public class HedgerControllerLogger
{
    private StreamWriter swLog;

    public HedgerControllerLogger()
    {
        swLog = new StreamWriter("logsGeneral/logHedgerController.txt") { AutoFlush = true };
    }

    [Conditional("LOG_HEDGER_CONTROLLER")]
    public void Log(string message)
    {
        swLog.WriteLine(DateTimePrecise.Instance.CurDateTime().ToString("H:mm:ss:ffffff") + ' ' + message);
    }

}

如何对c ++产生同样的效果?我应该使用类似的东西吗?可能一些现有的日志库已经具有相同的功能,可能是boost?谢谢!

2 个答案:

答案 0 :(得分:1)

您可以使用预处理器:

#ifdef ENABLE_LOGGING
  void log(const std::string& message) { /* do logging*/}
#else
  void log(const std::string&){}
#endif

您也可以使用模板执行类似操作,但为什么会使事情过于复杂?

答案 1 :(得分:0)

我建议看看如何提供TRACE/ATLTRACE和类似的宏(如果我是正确的,你使用的是Visual Studio)。一般来说,它们归结为在DEBUG构建中进行跟踪调用,以及在RELEASE构建中进行无操作。这是一个例子:

struct CTrace
{
    static void CTrace::Trace(LPCTSTR lpszFormat, ...)
    {
        va_list args;
        va_start(args, lpszFormat);
        TCHAR szBuffer[1024];
        int nSize = sizeof(szBuffer)/sizeof(szBuffer[0]);
        int nBuf = _vsntprintf(szBuffer, nSize, lpszFormat, args);          
        OutputDebugString(szBuffer); // write to debug output
        va_end(args);
    }    
};

#ifdef _DEBUG   
#define TRACE               CTrace::Trace
#else  
#define TRACE               true ? (void)0 : CTrace::Trace
#endif // _DEBUG

然后在代码中你有类似的东西:

TRACE("value is %d", 34);

在DEBUG构建中,这会被编译为:

CTrace::Trace("value is %d", 34);

在发布版本中,它转向:

true ? (void)0 : CTrace::Trace("value is %d", 34);

然后由编译器优化掉。您可以通过检查生成的代码来验证它。