一个用于 Qt 项目的简单的日志库
来源:互联网 发布:三千元手机推荐知乎 编辑:程序博客网 时间:2024/05/17 22:41
一个用于 Qt 项目的简单的日志库
在写 Qt 程序时,经常会用到 qDebug 输出一些调试信息。但是正式发布时这些信息就看不到了,这时就很需要有个日志系统,可以把程序输出的一些关键性的信息记录下来。
上网查找了一番,是有个开源项目叫 log4qt 的。不过这个项目许久都不更新了。看了看这个项目还挺复杂的,感觉用不到这么多功能。所以就自己山寨了个简单的日志库。
Qt 中有个 qInstallMessageHandler 函数,可以注册自己的处理函数,之后 qDebug、qInfo 一类的信息就可以按照自己的需要输出到文件或者其他地方了。
在 Qt 中,调试信息分为 5 级,分别如下:
QtDebugMsg -> qDebug()
QtInfoMsg -> qInfo()
QtWarningMsg -> qWarning()
QtCriticalMsg -> qCritical()
QtFatalMsg -> qFatal()
qt 帮助文件中给的例子如下:
#include <qapplication.h> #include <stdio.h> #include <stdlib.h> void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg) { QByteArray localMsg = msg.toLocal8Bit(); switch (type) { case QtDebugMsg: fprintf(stderr, "Debug: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function); break; case QtInfoMsg: fprintf(stderr, "Info: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function); break; case QtWarningMsg: fprintf(stderr, "Warning: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function); break; case QtCriticalMsg: fprintf(stderr, "Critical: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function); break; case QtFatalMsg: fprintf(stderr, "Fatal: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function); abort(); } } int main(int argc, char **argv) { qInstallMessageHandler(myMessageOutput); QApplication app(argc, argv); ... return app.exec(); }
qt 自带的这个例子很简单,但是也基本上说明清楚了如何用这个函数了。
我自己的实现上又做了些扩展,首先是日志应该可以输出到多个地方,比如同时输出到 console 和 文件中。
另外就是哪几个级别的日志是要输出的也应该可以控制。为此,设计了两个类:
- FileLogger 一个 FileLogger 代表一个具体的日志存储方式,比如输出到 console 或存储到一个特定的文件。当然也可以输出到其他的地方,只要写个类继承自 FileLogger ,重新实现个 writeLog 方法就行了。
- LoggerController 用来注册具体的 FileLogger,一个 LoggerController可以注册多个 FileLogger。
下面是代码:
#ifndef MESSAGELOGGER_H#define MESSAGELOGGER_H#include <QtCore/QString>#include <QtCore/QFile>#include <QtCore/QList>#include <QtCore/QMap>#include <QtCore/QDebug>#include <QtCore/QMessageLogContext>class FileLogger{public: enum LEVEL{E_DEBUG = 1, E_INFO = 2, E_WARNING = 4, E_CRITICAL = 8, E_FATAL = 16}; FileLogger(QString name, LEVEL level); FileLogger(QString name = "stderr", bool debug = false, bool info = true, bool warning = true, bool critical= true, bool fatal = true); virtual ~FileLogger(); /** * @brief setFileName 设置日志存储的文件名 * @param name 日志存储的文件名,如果为 "stderr" 则输出到 stderr * @return */ bool setFileName(QString name = "stderr"); /** * @brief setLogLevel 设置哪些级别的信息要输出到文件 * @param level 可以为 E_DEBUG、E_INFO、E_WARNING、E_CRITICAL、E_FATAL 或者这些项的组合(bit or) * 没有设置的 level 则不输出日志 */ void setLogLevel(LEVEL level); /** * @brief setLogLevel 设置哪些级别的信息要输出到文件 * @param debug true 表示 qDebug 信息输出到日志 * @param info true 表示 qInfo 信息输出到日志 * @param warning true 表示 qWarning 信息输出到日志 * @param critical true 表示 qCritical 信息输出到日志 * @param fatal true 表示 qFatal 信息输出到日志 */ void setLogLevel(bool debug = false, bool info = true, bool warning = true, bool critical= true, bool fatal = true); virtual void writeLog(QtMsgType type, const QMessageLogContext &context, const QString &msg);private: QString messageType(QtMsgType type); FileLogger(FileLogger &f) {Q_UNUSED(f);} // 不能被拷贝 FileLogger& operator=( FileLogger &f) {Q_UNUSED(f);} // 不能被拷贝private: QFile m_file; QMap<QtMsgType, bool> m_level; bool m_where;};class LoggerController{public: LoggerController(){} ~LoggerController(); void startLogging(); void attach(FileLogger *m_currentLogger); void detach(FileLogger *m_currentLogger);private: static void writeLog(QtMsgType type, const QMessageLogContext &context, const QString &msg); static LoggerController * m_currentLogger; QList<FileLogger *> m_list;};#endif // MESSAGELOGGER_H
#include "MessageLogger.h"#include <QtCore/QDateTime>#include <QtCore/QTextStream>FileLogger::FileLogger(QString name, bool debug, bool info, bool warning, bool critical, bool fatal) :m_where(true){ setFileName(name); setLogLevel(debug, info, warning, critical, fatal);}FileLogger::~FileLogger(){ m_file.close();}bool FileLogger::setFileName(QString name){ m_file.close(); if(name == "stderr") { return m_file.open(stderr, QIODevice::WriteOnly); } else { m_file.setFileName(name); return m_file.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text); }}void FileLogger::setLogLevel(LEVEL level){ m_level[QtDebugMsg] = static_cast<bool> (level | E_DEBUG); m_level[QtInfoMsg] = static_cast<bool> (level | E_INFO); m_level[QtWarningMsg] = static_cast<bool> (level | E_WARNING); m_level[QtCriticalMsg] = static_cast<bool> (level | E_CRITICAL); m_level[QtFatalMsg] = static_cast<bool> (level | E_FATAL);}void FileLogger::setLogLevel(bool debug, bool info, bool warning, bool critical, bool fatal){ m_level[QtDebugMsg] = debug; m_level[QtInfoMsg] = info; m_level[QtWarningMsg] = warning; m_level[QtCriticalMsg] = critical; m_level[QtFatalMsg] = fatal;}void FileLogger::writeLog(QtMsgType type, const QMessageLogContext &context, const QString &msg){ if(!m_level[type]) { return; } QString strTime = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"); QTextStream logfile(&m_file); logfile << strTime << ", "; logfile << messageType(type) << ", "; logfile << msg; if(context.file && m_where) { logfile << ", (" << context.file << ":" << context.line << ", " << context.function << ")\n"; } else { logfile << endl; } if(type == QtFatalMsg) { abort(); }}QString FileLogger::messageType(QtMsgType type){ QString str; switch (type) { case QtDebugMsg: str = "[Debug] "; break; case QtInfoMsg: str = "[Info] "; break; case QtWarningMsg: str = "[Warning] "; break; case QtCriticalMsg: str = "[Critical]"; break; case QtFatalMsg: str = "[Fatal] "; } return str;}void LoggerController::attach(FileLogger *logger){ m_list.append(logger);}void LoggerController::detach(FileLogger *logger){ if(logger) { m_list.removeOne(logger); delete logger; }}void LoggerController::startLogging(){ m_currentLogger = this; qInstallMessageHandler(LoggerController::writeLog);}LoggerController::~LoggerController(){ qDeleteAll(m_list);}LoggerController* LoggerController::m_currentLogger = nullptr;void LoggerController::writeLog(QtMsgType type, const QMessageLogContext &context, const QString &msg){ if( m_currentLogger ) { QList<FileLogger *> &list = m_currentLogger->m_list; QList<FileLogger *>::const_iterator i; for (i = list.cbegin(); i != list.cend(); ++i) { (*i)->writeLog(type, context, msg); } }}
#include <QCoreApplication>#include "MessageLogger.h"int main(int argc, char *argv[]){ QCoreApplication a(argc, argv); LoggerController logger; logger.attach(new FileLogger("stderr", FileLogger::E_DEBUG | FileLogger::E_INFO | FileLogger::E_WARNING | FileLogger::E_CRITICAL | FileLogger::E_FATAL)); logger.attach(new FileLogger("d:/log2.txt")); logger.startLogging(); qDebug() << "this is a debug message" ; qInfo() << "this is a info message"; qWarning() << "this is a warning message"; qCritical() << "this is a critical message"; return a.exec();}
项目文件我放到了 code.csdn.net 上了,网址如下:
https://code.csdn.net/liyuanbhu/qtlogger.git
这个日志库我还会继续维护,增加新的功能。希望最后能成为一个比较完善功能的日志库。
阅读全文
2 0
- 一个用于 Qt 项目的简单的日志库
- 一个很简单的日志类ZPLog, 用于输出日志
- 一个简单的Qt日志类 使用方便
- Mondrian用于web项目的一个简单搭建实验
- bunyan(一个用于node.js服务的JSON日志库)
- 一个简单的用于嵌入式Linux开发的C调试日志打印接口
- 一个Qt线程的例子,用于说明QWaitCondition的作用
- 一个简单的日志类
- 一个简单的日志类
- 一个简单的日志收集
- 一个简单的日志module
- 一个简单的日志收集
- Qt中简单的日志文件实现
- QT 简单的写日志功能
- 简单易用的Qt日志模块
- qt 下的一个小日志系统
- 一个项目多建一个tmocat(用于图片的存取)
- 用于Linux的日志文件系统
- <meta http-equiv="" content="">详解
- 多表查询----连接查询
- Unity之简易定时器Timer
- HDU-2017 多校训练赛2-1008-To my boyfriend
- 51nod 1717 好数
- 一个用于 Qt 项目的简单的日志库
- ZOJ 3804 YY's Minions(搜索+模拟)
- 4、C程序 数组排序之[选择排序法]
- 数据结构-最小完美哈希和保序最小完美哈希函数
- 防止过拟合的方法
- 浅谈栈帧
- nginx(负载均衡基本配置)
- 用maven命令在命令行中create创建项目出现错误
- BlockingQueue深入分析