如何在项目中实现良好的调试/日志记录功能

时间:2011-05-29 13:55:18

标签: c++ c debugging logging

我正在做一个小项目,总共约3-4人。我希望有一个可靠的方法来调试应用程序,例如日志。是否有任何关于如何构建它的好资源?我从项目经理那里听到很多好的日志记录功能对每个项目都很重要,但我不知道该怎么做。

3 个答案:

答案 0 :(得分:16)

我发现Dobb博士的文章Logging In C++对这个主题非常有用。

同样在Dobb博士身上:A Highly Configurable Logging Framework In C++

如果你想要的只是一个死的简单线程安全日志记录类,它总是输出到stderr那么你可以使用我写的这个类:

#ifndef _LOGGER_HPP_
#define _LOGGER_HPP_

#include <iostream>
#include <sstream>

/* consider adding boost thread id since we'll want to know whose writting and
 * won't want to repeat it for every single call */

/* consider adding policy class to allow users to redirect logging to specific
 * files via the command line
 */

enum loglevel_e
    {logERROR, logWARNING, logINFO, logDEBUG, logDEBUG1, logDEBUG2, logDEBUG3, logDEBUG4};

class logIt
{
public:
    logIt(loglevel_e _loglevel = logERROR) {
        _buffer << _loglevel << " :" 
            << std::string(
                _loglevel > logDEBUG 
                ? (_loglevel - logDEBUG) * 4 
                : 1
                , ' ');
    }

    template <typename T>
    logIt & operator<<(T const & value)
    {
        _buffer << value;
        return *this;
    }

    ~logIt()
    {
        _buffer << std::endl;
        // This is atomic according to the POSIX standard
        // http://www.gnu.org/s/libc/manual/html_node/Streams-and-Threads.html
        std::cerr << _buffer.str();
    }

private:
    std::ostringstream _buffer;
};

extern loglevel_e loglevel;

#define log(level) \
if (level > loglevel) ; \
else logIt(level)

#endif

像这样使用:

// define and turn off for the rest of the test suite
loglevel_e loglevel = logERROR;

void logTest(void) {
    loglevel_e loglevel_save = loglevel;

    loglevel = logDEBUG4;

    log(logINFO) << "foo " << "bar " << "baz";

    int count = 3;
    log(logDEBUG) << "A loop with "    << count << " iterations";
    for (int i = 0; i != count; ++i)
    {
        log(logDEBUG1) << "the counter i = " << i;
        log(logDEBUG2) << "the counter i = " << i;
    }

    loglevel = loglevel_save;
}

答案 1 :(得分:3)

如果您询问日志记录框架并且您使用的是C ++,请查看Apache的log4cxx。需要一些时间才能理解架构,但是一旦你做到了,你会发现它在灵活性,易用性和(正如他们所说)性能方面取得了很好的平衡。

log4cxx有一个非常灵活的配置,你可以控制,无需重新编译,输出到哪里(文件/旋转文件/控制台/等),子组件的调试级别(例如你想要关注)在特定的类/组件上,所以你将它设置为DEBUG级别,其余的是INFO),日志条目的格式等。

如果您询问关于如何记录的一般指南,我还没有看到(不是我实际查找过的)。我认为这主要是经验性的 - 您决定在每个日志级别上需要哪些信息,如INFO,DEBUG等,并根据您和您客户的需求进行优化(不要忘记您的客户也可以是客户的记录,具体取决于您的项目。)

答案 2 :(得分:2)

取决于“记录”的含义。一种形式是简单地提供用于将某个对象的内容打印到输出流的方法。对于ClassName类型的对象,这需要为类编写插入运算符:

std::ostream &operator<< (std::ostream &stream, const ClassName & obj) {
   // Implementation elided
}

有了这个,您可以将ClassName类型的对象打印到输出流。这非常有用,非常有用,有些组织要求每个类都实现这样的方法。