本文主要是介绍Qt spdlog日志模块的使用详解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
《Qtspdlog日志模块的使用详解》在Qt应用程序开发中,良好的日志系统至关重要,本文将介绍如何使用spdlog1.5.0创建满足以下要求的日志系统,感兴趣的朋友一起看看吧...
版本
spdlog版本:1.5.0
采用1.5.0版本主要基于以下考虑:兼容Qt5.9.X版本和兼容C++11。
spdlog 1.5.0下载地址:https://github.com/gabime/spdlog/releases/tag/v1.5.0
摘要
在Qt应用程序开发中,良好的日志系统至关重要。本文将介绍如何使用spdlog 1.5.0创建满足以下要求的日php志系统:
- 自定义文件名格式:yyyyMMdd_hhmmss_毫秒.log,不使用spdlog提供的日志轮转功能
spdlog::sinks::rotating_file_sink_mt,采用自定义custom_rotating_file_sink;
- 保留最近10个日志文件,每个日志文件大小限制为1MB。
例子
logmanager.h文件
#ifndef LOGMANAGER_H #djsefine LOGMANAGER_H #include <QObject> #include <memory> #include <spdlog/spdlog.h> class LogManager : public QObject { Q_OBJECT public: static LogManager& instance(); void initialize(const QString& logDir = "logs", const QString& appName = "app", size_t maxFileSize = 1024 * 1024, // 1MB size_t maxFiles = 10); void shutdown(); template<typename... Args> static void log(spdlog::level::level_enum level, const QString& message, Args... args) { if (instance().m_logger) { instance().m_logger->log(level, message.toStdString().c_str(), args...); } } // 便捷方法 static void trace(const QString& message) { log(spdlog::level::trace, message); } static void debug(const QString& message) { log(spdlog::level::debug, message); } static void info(const QString& message) { log(spdlog::level::info, message); } static void warn(const QString& message) { log(spdlog::level::warn, message); } static void error(const QString& message) { log(spdlog::level::err, message); } static void critical(const QString& message) { log(spdlog::level::critical, message); } private: LogManager(QObject* parent = nullptr); ~LogManager(); std::shared_ptr<spdlog::logger> createCustomLogger(const std::string& base_filename, size_t max_size, size_t max_files); std::shared_ptr<spdlog::logger> m_logger; std::atomic<bool> m_shuttingDown{false}; signals: void aboutToShutdown(); private slots: void onAboutToQuit(); }; // 日志宏定义 #define LOG_TRACE(...) LogManager::log(spdlog::level::trace, __VA_ARGS__) #define LOG_DEBUG(...) LogManager::log(spdlog::level::debug, __VA_ARGS__) #define LOG_INFO(...) LogManager::log(spdlog::level::info, __VA_ARGS__) #define LOG_WARN(...) LogManager::log(spdlog::level::warn, __VA_ARGS__) #define LOG_ERROR(...) LogManager::log(spdlog::level::err, __VA_ARGS__) #define LOG_CRITICAL(...) LogManager::log(spdlog::level::critical, __VA_ARGS__) #endif // LOGMANAGER_H
logmanager.cpp文件
#include "logmanager.h" #include <spdlog/sinks/base_sink.h> #include <spdlog/details/file_helper.h> #include <mutex> #include <chrono> #include <iomanip> #include <sstream> #include <vector> #include <algorithm> #include <QDir> #include <QFileInfo> #include <QDateTime> #include <QCoreApplication> #include <csignal> #include <QDebug> // 替换 std::filesystem 的 C++11 兼容实现 namespace spdlog { class custom_rotating_file_sink : public spdlog::sinks::base_sink<std::mutex> { public: custom_rotating_file_sink(const std::string& base_filename, std::size_t max_size, std::size_t max_files) : base_filename_(base_filename), max_size_(max_size), max_files_(max_files) { file_helper_.open(gen_filename()); } prowww.chinasem.cntected: void sink_it_(const spdlog::details::log_msg& msg) override { spdlog::memory_buf_t formatted; formatter_->format(msg, formatted); if (file_helper_.size() + formatted.size() > max_size_) { rotate_(); } file_helper_.write(formatted); } void flush_() override { file_helper_.flush(); } private: std::string gen_filename() { QDateTime now = QDateTime::currentDateTime(); QString timeStr = now.toString("yyyyMMddhhmmss"); // 添加毫秒部分(3位) int ms = now.time().msec(); timeStr += QString("_%1").arg(ms, 3, 10, QLatin1Char('0')); return base_filename_ + "_" + timeStr.toStdString() + ".log"; } void rotate_() { file_helper_.close(); cleanup_old_files(); file_helper_.open(gen_filename()); } void cleanup_old_files() { if (max_files_ == 0) return; QFileInfo base_info(QString::fromStdString(base_filename_)); QDir dir = base_info.absoluteDir(); QString base_name = base_info.fileName(); QFileInfoList files = dir.entryInfoList(QStringList() << (base_name + "_*.log"), QDir::Files, QDir::Time); // 删除最旧的文件 while (files.size() >= static_cast<int>(max_files_)) { QFile::remove(files.last().absoluteFilePath()); files.removeLast(); } } std::string base_filename_; std::size_t max_size_; std::size_t max_files_; spdlog::details::file_helper file_helper_; }; } // namespace LogManager::LogManager(QObject* parent) : QObject(parent) { // 连接Qt退出信号 connect(qApp, &QCoreApplication::aboutToQuit, this, &LogManager::onAboutToQuit); // 处理异常信号 static auto handleSignal = [](int) { LogManager::instance().shutdown(); std::_Exit(1); }; std::signal(SIGTERM, handleSignal); std::signal(SIGSEGV, handleSignal); std::signal(SIGINT, handleSignal); std::sjavascriptignal(SIGABRT, handleSignal); } LogManager::~LogManager() { shutdown(); } LogManager& LogManager::instance() { static LogManager instance; return instance; } void LogManager::initialize(const QString& logDir, const QString& appName, size_t maxFileSize, size_t maxFiles) { if (m_logger) { return; } // 确保日志目录存在 QDir().mkpath(logDir); std::string base_filename = QDir(logDir).absoluteFilePath(appName).toStdString(); m_logger = createCustomLogger(base_filename, maxFileSize, maxFiles); // 设置默认日志格式 m_logger->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%l] [thread %t] %v"); m_logger->set_level(spdlog::level::trace); spdlog::register_logger(m_logger); spdlog::set_default_logger(m_logger); } void LogManager::shutdown() { /* if (m_logger) { spdlog::drop(m_logger->name()); m_logger.reset(); } spdlog::shutdown(); */ if (m_shuttingDown) return; m_shuttingDown = true; emit aboutToShutdown(); try { javascript if (m_logger) { m_logger->flush(); spdlog::drop(m_logger->name()); } spdlog::shutdown(); m_logger.reset(); } catch (const spdlog::spdlog_ex& ex) { qCritical() << "Log shutdown error:" << ex.what(); } } void LogManager::onAboutToQuit() { shutdown(); } std::shared_ptr<spdlog::logger> LogManager::createCustomLogger(const std::string& base_filename, size_t max_size, size_t max_files) { auto sink = std::make_shared<spdlog::custom_rotating_file_sink>(base_filename, max_size, max_files); auto logger = std::make_shared<spdlog::logger>("qt_logger", sink); return logger; }
main.cpp文件
#include <QCoreApplication> #include "logmanager.h" #include <QTimer> #include <QDebug> int main(int argc, char* argv[]) { QCoreApplication a(argc, argv); // 初始化日志系统 LogManager::instance().initialize("logs", "MyAppTest"); // 连接关闭信号进行额外清理 QObject::connect(&LogManager::instance(), &LogManager::aboutToShutdown, []() { LOG_INFO("Performing final cleanup before shutdown..."); }); for (int i = 0; i < 5000; ++i) { LOG_INFO("This is a test message to fill up the log file. Iteration: {}", i); } return a.exec(); }
到此这篇关于Qt spdlog日志模块的使用的文章就介绍到这了,更多相关Qt spdlog日志模块内容请搜索China编程(www.chinasem.cn)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程China编程(www.chinasem.cn)!
这篇关于Qt spdlog日志模块的使用详解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!