1. Obtaining spdlog Source Files
Download the spdlog repository from GitHub and extract vertion 1.15.3. Copy the include and src directories into a third_party/spdlog folder within your Qt project.
Project structure:
qt_app/
├── qt_app.pro
├── main.cpp
├── ...
└── third_party/
└── spdlog/
├── include/
│ └── spdlog/
└── src/
2. Updating the .pro File
Add the following configuration to your .pro file:
CONFIG += c++11
INCLUDEPATH += $$PWD/third_party/spdlog/include
DEFINES += SPDLOG_COMPILED_LIB
SOURCES += \
third_party/spdlog/src/async.cpp \
third_party/spdlog/src/bundled_fmtlib_format.cpp \
third_party/spdlog/src/cfg.cpp \
third_party/spdlog/src/color_sinks.cpp \
third_party/spdlog/src/file_sinks.cpp \
third_party/spdlog/src/spdlog.cpp \
third_party/spdlog/src/stdout_sinks.cpp \
3. Implementing the Logging Service
3.1 LoggerHeader.h
#ifndef LOGGERHEADER_H
#define LOGGERHEADER_H
#include <QString>
#include <spdlog/spdlog.h>
class LoggerHeader
{
public:
LoggerHeader();
void initialize();
void cleanup();
inline void trace(const QString &msg)
{
spdlog::trace(msg.toStdString().c_str());
}
inline void debug(const QString &msg)
{
spdlog::debug(msg.toStdString().c_str());
}
inline void info(const QString &msg)
{
spdlog::info(msg.toStdString().c_str());
}
inline void warn(const QString &msg)
{
spdlog::warn(msg.toStdString().c_str());
}
inline void error(const QString &msg)
{
spdlog::error(msg.toStdString().c_str());
}
inline void critical(const QString &msg)
{
spdlog::critical(msg.toStdString().c_str());
}
};
#endif // LOGGERHEADER_H
3.2 LoggerHeader.cpp
#include <QDir>
#include <QMessageBox>
#include <QString>
#include <spdlog/spdlog.h>
#include <spdlog/sinks/rotating_file_sink.h>
#include <spdlog/sinks/stdout_color_sinks.h>
#include <spdlog/async.h>
#include "LoggerHeader.h"
LoggerHeader::LoggerHeader()
{
}
void LoggerHeader::initialize()
{
try
{
// Ensure log directory exists
QDir logDirectory("logs");
if (!logDirectory.exists() && !logDirectory.mkpath("."))
{
QMessageBox::critical(nullptr, "Logging Error", "Failed to create logs directory");
return;
}
// Configure thread pool for async operations
spdlog::init_thread_pool(8192, 1);
// Auto-flush every 5 seconds
spdlog::flush_every(std::chrono::seconds(5));
// Initialize rotating file sink (5MB max per file, 100 files retained)
auto rotatingSink = std::make_shared<spdlog::sinks::rotating_file_sink_mt>(
"logs/application.log", 1024 * 1024 * 5, 100);
// Initialize colored console output
auto consoleSink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
// Combine both sinks
std::vector<spdlog::sink_ptr> allSinks{rotatingSink, consoleSink};
// Create async logger with combined sinks
auto asyncLogger = std::make_shared<spdlog::async_logger>(
"app_logger",
allSinks.begin(),
allSinks.end(),
spdlog::thread_pool(),
spdlog::async_overflow_policy::block
);
// Set timestamp format
asyncLogger->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%^%l%$] [thread %t] %v");
// Register as default logger
spdlog::set_default_logger(asyncLogger);
// Set log level based on build configuration
#ifdef QT_DEBUG
spdlog::set_level(spdlog::level::debug);
#else
spdlog::set_level(spdlog::level::info);
#endif
// Force immediate write on errors
asyncLogger->flush_on(spdlog::level::err);
spdlog::info("====== Application startup ======");
spdlog::debug("Debug logging is enabled");
// Display Qt version
spdlog::info("Current Qt version: {}", qVersion());
// Display spdlog version
auto libraryVersion = QString("%1.%2.%3")
.arg(QString::number(SPDLOG_VER_MAJOR),
QString::number(SPDLOG_VER_MINOR),
QString::number(SPDLOG_VER_PATCH))
.toStdString();
spdlog::info("Current spdlog version: {}", libraryVersion.c_str());
}
catch (const spdlog::spdlog_ex &ex)
{
QMessageBox::critical(nullptr, "Initialization Error",
QString("Failed to initialize logging system: %1").arg(ex.what()));
}
}
void LoggerHeader::cleanup()
{
spdlog::info("====== Application shutdown ======");
spdlog::shutdown();
}
4. Consuming the Logging Service
4.1 PrimaryWindow.h
#ifndef PRIMARYWINDOW_H
#define PRIMARYWINDOW_H
#include <QMainWindow>
#include "LoggerHeader.h"
class PrimaryWindow : public QMainWindow
{
Q_OBJECT
public:
PrimaryWindow(QWidget *parent = nullptr);
~PrimaryWindow();
private:
LoggerHeader *m_logger;
};
#endif // PRIMARYWINDOW_H
4.2 PrimaryWindow.cpp
#include "primarywindow.h"
PrimaryWindow::PrimaryWindow(QWidget *parent)
: QMainWindow(parent)
{
m_logger = new LoggerHeader();
m_logger->initialize();
}
PrimaryWindow::~PrimaryWindow()
{
m_logger->cleanup();
delete m_logger;
}
Notes
- spdlog requires C++11 or latter. Ensure your
.profile specifies the appropriate standard. - The
SPDLOG_COMPILED_LIBdefine must be set when using source compilation rather than header-only mode. - Async logging prevents I/O operations from blocking the main thread.
- Log files are automatically rotated when reaching the 5MB threshold, with up to 100 backup files retained.