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

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

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

同样在Dr. Dobb上: C ++中的高度可配置日志框架

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

 #ifndef _LOGGER_HPP_ #define _LOGGER_HPP_ #include  #include  /* 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  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; } 

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

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

如果你问的是关于如何记录的一般指导原则 ,我还没有看到这样的(不是我真正想要的)。 我认为这主要是经验性的 – 您决定在每个日志级别上需要哪些信息,如INFO,DEBUG等,并根据您和您客户的需求进行优化(不要忘记您的客户也可以是客户的日志,取决于您的项目)。

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

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

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