如何在项目中实现良好的调试/日志记录功能
How to implement a good debug/logging feature in a project
我正在做一个小项目,总共大约有3-4个人。我希望有一种稳定的方法来调试应用程序,例如通过日志。关于如何构建它等等,有什么好的资源吗?我从项目经理那里听说,好的日志记录功能对每个项目都至关重要,但我不确定如何做到这一点。
我发现多布博士的这篇文章《登录C++》对这个主题非常有用。
也论Dobb博士的: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;
}
如果您想了解日志框架并且使用C++,请查看Apache的log4cxx。理解体系结构需要一些时间,但一旦你理解了,你就会意识到它是灵活性、易用性和(正如他们所说的)性能之间的良好平衡。
log4cxx
有一个非常灵活的配置,您可以在不重新编译的情况下控制输出的位置(文件/旋转文件/控制台等)、子组件的调试级别(例如,您想专注于某个特定的类/组件,所以您将其设置为DEBUG
级别,而其余的则设置为INFO
级别)、日志项的格式等。
如果您询问关于如何进行日志记录的一般指南,我还没有看到(实际上我并没有找到)。我认为这主要是经验——你决定每个日志级别需要什么信息,比如info、DEBUG等,然后根据你和你的客户的需求进行改进(别忘了,根据你的项目,你的客户也可能是日志的客户)。
取决于"日志记录"的含义。一种形式是简单地提供一种将某个对象的内容打印到输出流的方法。对于ClassName类型的对象,这需要为类编写一个插入运算符:
std::ostream &operator<< (std::ostream &stream, const ClassName & obj) {
// Implementation elided
}
有了这个,您可以将ClassName类型的对象打印到输出流中。这可能非常有用,以至于有些组织要求每个类都实现这样的方法。
- 当回溯以零开始时,如何调试崩溃
- 在linux上调试巨大的C++项目
- 为什么使用__LINE_的代码在发布模式下在MSVC下编译,而不是在调试模式下
- 如何针对特定情况调试和修复此双自由内存损坏问题
- EvtExportLogneneneba API正在将远程计算机的事件日志保存到远程PC本身.如何将其保存到主机
- 正在VS调试器中监视映射条目
- 使用调试/崩溃报告将应用程序部署到客户端
- 执行调试日志记录的更好方法
- 从 Tableau 调用 Rcpp 函数时出错.如何解释和调试 Rserve 日志
- Poco::Logger 不记录跟踪或调试级别日志,只记录信息级别及以上
- Valgrind调试日志:大小为8的读取无效
- log4cplus在Visual Studio调试控制台中进行日志记录
- 调试日志语句的预处理器宏在C++中有一席之地吗
- NDK如何在发布时删除日志调试语句
- 我怎么能用C++在非越狱的ios设备上写调试日志呢
- windows上的c++调试日志
- 创建一个简单的窗口来输出用于调试的信息(日志样式)- wxWidgets
- Android -跨平台友好的调试/日志宏
- 如何从程序中删除日志调试语句
- 如何在项目中实现良好的调试/日志记录功能