用于QT的一个简易日志功能模块封装。算不上强大和多高的性能,但是足够简单小巧。用于记录日志到文件够用了。单独的一个文件模块,使用时直接引入源码。想要其他功能,直接改代码即可。
C++的下的日志库有很多,如log4cpp、Easylogging++,eplog,g3log,Qt下也有log4qt。
还有简单小巧的QsLog,它是一个基于Qt的轻量级开源日志库。
QsLog的git地址:https://github.com/victronenergy/QsLog
log4qt的git地址:https://github.com/devbean/log4qt
如果这些都不想用,还想更简单小巧的,可以看以下这个简易模块封装。
查看日志推荐用baretailpro工具。
使用方法
使用时只需工程文件.pro中包含模块源码即可。
include(Logger/MessageLogger.pri)
MessageLogger.pri文件内容:
#ifndef MESSAGELOGGER_H #define MESSAGELOGGER_H /** @description 用于Qt项目的一个简单的日志库,将日志存入日志文件(文本文件)中。 * 典型用法示例: * 第一个 FileLogger 将日志输出到 stderr 上。 * 第二个 FileLogger 将日志输出到文件。 * 建议将这段代码放到 main 函数的开头处,但是要在 QCoreApplication 或 QApplication 之后。 * 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(); */ #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(); /** * @brief startLogging 启动日志系统,在这之后所有的调试信息发送到对应的 FileLogger */ void startLogging(); /** * @brief attach 在日志系统中注册一个新的 FileLogger * @param m_currentLogger */ 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(QString name, LEVEL level) :m_where(false) { setFileName(name); setLogLevel(level); } 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 = "[D]"; break; case QtInfoMsg: str = "[I]"; break; case QtWarningMsg: str = "[W]"; break; case QtCriticalMsg: str = "[C]"; break; case QtFatalMsg: str = "[F]"; } 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 "mainwindow.h" #include <QApplication> #include <QSettings> #include <QString> #include <QFileInfo> #include <QTime> #include <QDir> #include "cglobal.h" #include "MessageLogger.h" #include "utils.h" int main(int argc, char *argv[]) { //自适应高分辨率(DPI),不确定是否管用 #if (QT_VERSION >= QT_VERSION_CHECK(5,9,0)) QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); #endif QApplication a(argc, argv); a.setFont(QFont("Microsoft Yahei", 9));//设置应用程序字体 a.setWindowIcon(QIcon(":/main.ico"));//设置应用程序图标 mkDirIfNotExist(); //打印日志到文件中 LoggerController logger; logger.attach(new FileLogger("stderr", FileLogger::E_DEBUG, FileLogger::E_INFO , FileLogger::E_WARNING , FileLogger::E_CRITICAL, FileLogger::E_FATAL)); QString dateTime = QDateTime::currentDateTime().toString("yyyy-MM-dd_hhmmss"); QString logName = LOG_PATH+dateTime+"_log.txt"; //日志文件输入以下级别的日志 FileLogger::LEVEL level = (FileLogger::LEVEL)(FileLogger::E_INFO | FileLogger::E_WARNING); FileLogger *lg = new FileLogger(logName,level); logger.attach(lg); logger.startLogging(); qInfo("程序启动..."); qInfo(APP_VERION); MainWindow w; w.show(); return a.exec(); } void mkDirIfNotExist(){ QDir *folder = new QDir; bool exist,ok = false; exist = folder->exists(LOG_PATH); if(!exist){ ok = folder->mkdir(LOG_PATH); if(!ok){ qDebug("Error,创建日志文件夹失败"); } } exist = folder->exists(PIC_PATH); if(!exist){ ok = folder->mkdir(PIC_PATH); if(!ok){ qDebug("Error,创建图片文件夹失败"); } } }
引用
QT 轻量级的LOG日志库_Duffy_Gallagher的博客-CSDN博客_qt日志库