C++ 如何在项目中实现良好的调试/日志记录功能
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6168107/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to implement a good debug/logging feature in a project
提问by KaiserJohaan
I am making a smallish project, total of about 3-4 people. I want to have a solid way of debugging the application, by logs for example. Are there any good resources on how to structure it and such? I've heard a lot from project managers that a good logging feature is critical to each project, but I'm not sure how to do it.
我正在做一个小项目,总共大约 3-4 人。我想要一种可靠的调试应用程序的方法,例如通过日志。是否有关于如何构建它等的好的资源?我从项目经理那里听到很多说好的日志功能对每个项目都至关重要,但我不知道如何去做。
回答by Robert S. Barnes
I found this Dr. Dobb's article, Logging In C++, very useful regarding this subject.
我发现 Dobb 博士的这篇文章Logging In C++对这个主题非常有用。
Also on Dr. Dobb's: A Highly Configurable Logging Framework In C++
也在 Dr. Dobb's: 一个高度可配置的 C++ 日志框架
If all you want is a dead simple thread safe logging class which always outputs to stderr
then you could use this class I wrote:
如果你想要的只是一个简单的线程安全日志类,它总是输出到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
Use it like this:
像这样使用它:
// 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;
}
回答by davka
If you are asking about logging frameworksand you work in C++, check out Apache's log4cxx. It takes a few moments to understand the architecture, but once you did, you realize that it is a good balance of flexibility, ease of use and (as they say) performance.
如果您询问日志框架并且您使用 C++,请查看 Apache 的log4cxx。理解架构需要一些时间,但是一旦你理解了,你就会意识到它是灵活性、易用性和(正如他们所说的)性能之间的良好平衡。
log4cxx
has a very flexible configuration by witch you can control, without recompiling, where the output goes to (file / rotating file / console/etc.), the debugging level of subcomponents (e.g. you want to focus on a particular class / component so you set it to DEBUG
level while the rest is on INFO
), format of log entries etc.
log4cxx
有一个非常灵活的配置,你可以控制,无需重新编译,输出去哪里(文件/旋转文件/控制台/等),子组件的调试级别(例如,你想专注于一个特定的类/组件,所以你DEBUG
在其余部分打开时将其设置为级别INFO
),日志条目的格式等。
If you are asking about general guidelineson how do logging, I haven't seen such (not that I actually looked for). I think this is mainly empiric - you decide what info is needed on each logging level like INFO, DEBUG etc., and you refine it according to your and your client's needs (don't forget that your client could also be a customer of the log, depending on your project).
如果您询问有关如何进行日志记录的一般准则,我还没有看到这样的(不是我实际寻找的)。我认为这主要是经验性的 - 您决定在每个日志记录级别(如 INFO、DEBUG 等)上需要哪些信息,然后根据您和您客户的需求对其进行优化(不要忘记您的客户也可能是日志,具体取决于您的项目)。
回答by David Hammen
Depends on what you mean by "logging". One form is simply to provide a method for printing the contents of some object to an output stream. For an object of type ClassName this entails writing an insertion operator for the class:
取决于您所说的“记录”是什么意思。一种形式是简单地提供一种将某个对象的内容打印到输出流的方法。对于 ClassName 类型的对象,这需要为该类编写一个插入运算符:
std::ostream &operator<< (std::ostream &stream, const ClassName & obj) {
// Implementation elided
}
With this at hand you can print an object of type ClassName to an output stream. This can be quite useful, so useful that some organizations require that every class implement such a method.
有了这个,您可以将 ClassName 类型的对象打印到输出流。这可能非常有用,非常有用,以至于某些组织要求每个类都实现这样的方法。