# How to Integrate spdlog with Qt Applications Using the qt_sink

> Integrate spdlog with Qt using qt_sink to send logs to Qt widgets. Utilize spdlog::qt_logger_mt or spdlog::qt_logger_st for thread-safe UI updates via Qt's meta-object system.

- Repository: [Gabi Melman/spdlog](https://github.com/gabime/spdlog)
- Tags: how-to-guide
- Published: 2026-07-17

---

**Use `spdlog::qt_logger_mt` or `spdlog::qt_logger_st` to forward log messages to any Qt widget that exposes a slot accepting `QString`, leveraging Qt's meta-object system for thread-safe UI updates.**

The **gabime/spdlog** library provides dedicated Qt sinks that bridge high-performance C++ logging with Qt's GUI framework. To integrate **spdlog with Qt applications**, you use the `qt_sink` or `qt_color_sink` classes defined in [`include/spdlog/sinks/qt_sinks.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/sinks/qt_sinks.h). These sinks marshal log entries across thread boundaries using Qt's `QMetaObject::invokeMethod`, ensuring your UI updates safely even when logging occurs from background worker threads.

## Understanding the Qt-Specific Sinks

The spdlog Qt integration centers on two sink types that derive from `spdlog::sinks::base_sink<Mutex>`, inheriting the same thread-safety policies as standard spdlog sinks.

### qt_sink for Plain Text Output

The **qt_sink** forwards formatted log messages as plain text to any `QObject` that implements a compatible Qt slot. You typically target `QPlainTextEdit` or `QTextEdit` widgets using their `append(const QString&)` slot. Because the sink stores a raw pointer to the Qt object, it performs a null check in the constructor and throws `spdlog_ex` if the widget pointer is invalid.

### qt_color_sink for Styled Output

The **qt_color_sink** extends this functionality to support per-log-level color customization in `QTextEdit` widgets. It maintains an internal mapping of `spdlog::level` to `QTextCharFormat`, allowing you to set foreground colors, background colors, and font styles via the `set_color()` method.

## Implementing spdlog Qt Integration Step by Step

### Include the Header

Add the Qt sinks header to your source file. This header declares both sink classes and the convenience factory functions.

```cpp
#include <spdlog/sinks/qt_sinks.h>

```

### Create the Logger

Instantiate a logger using one of the factory functions that match your thread-safety requirements:

- **`spdlog::qt_logger_mt(name, qt_object, meta_method)`** – Creates a multi-threaded logger safe for concurrent access.
- **`spdlog::qt_logger_st(name, qt_object, meta_method)`** – Creates a single-threaded logger for use in one thread only.

The `meta_method` parameter must be the fully-qualified Qt slot signature, such as `"append(const QString&)"`.

```cpp
QPlainTextEdit *logView = new QPlainTextEdit(parent);
auto logger = spdlog::qt_logger_mt("qt_ui_logger", logView, "append(const QString&)");
logger->info("Application started successfully");

```

### Configure Color Formatting (Optional)

For colored output, instantiate `qt_color_logger_mt` instead, then customize the appearance:

```cpp
QTextEdit *colorLogView = new QTextEdit(parent);
auto color_logger = spdlog::qt_color_logger_mt("color_logger", colorLogView, 1000);

// Customize warning level to appear in dark yellow
QTextCharFormat warnFmt;
warnFmt.setForeground(Qt::darkYellow);
color_logger->set_color(spdlog::level::warn, warnFmt);

```

## Thread Safety and Lifetime Management

Under the hood, both sinks use **Qt::AutoConnection** when calling `QMetaObject::invokeMethod`. This automatically queues the log message onto the widget's owning thread if the logger runs in a different context, preventing race conditions during GUI updates.

Because the sink holds a raw pointer (`QObject*`) and does not manage the widget's lifetime, you must ensure the logger is destroyed or reset before the target widget is deleted. Failure to do so results in dangling pointer dereferences. Tie the logger's scope to the widget's parent or explicitly call `spdlog::drop()` in your widget destructor.

## Complete Code Examples

The following examples demonstrate practical implementation patterns found in the [`example/qt_example.cpp`](https://github.com/gabime/spdlog/blob/main/example/qt_example.cpp) file of the spdlog repository.

**Plain Text Logger with QPlainTextEdit:**

```cpp
#include <QPlainTextEdit>
#include <spdlog/sinks/qt_sinks.h>

// ... inside your MainWindow or Widget constructor
QPlainTextEdit *logView = new QPlainTextEdit(this);
auto logger = spdlog::qt_logger_mt("qt_logger", logView, "append(const QString&)");
logger->set_level(spdlog::level::debug);
logger->info("spdlog integrated with Qt!");

```

**Colored Logger with QTextEdit:**

```cpp
#include <QTextEdit>
#include <spdlog/sinks/qt_sinks.h>

QTextEdit *colorLogView = new QTextEdit(this);
auto color_logger = spdlog::qt_color_logger_mt("qt_color_logger", colorLogView, 1000);
color_logger->set_level(spdlog::level::trace);

// Custom formatting for warnings
QTextCharFormat warnFmt;
warnFmt.setForeground(Qt::darkYellow);
color_logger->set_color(spdlog::level::warn, warnFmt);

color_logger->warn("This warning appears in yellow!");

```

## Summary

- **Include** [`include/spdlog/sinks/qt_sinks.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/sinks/qt_sinks.h) to access Qt-specific logging functionality.
- **Choose** between `qt_sink` for plain text or `qt_color_sink` for per-level color customization.
- **Instantiate** using `spdlog::qt_logger_mt()` or `spdlog::qt_logger_st()` with the target widget and slot signature.
- **Manage lifetimes** carefully: destroy the logger before destroying the target QWidget to avoid dangling pointers.
- **Rely** on Qt's meta-object system via `QMetaObject::invokeMethod` with `Qt::AutoConnection` for automatic thread marshalling.

## Frequently Asked Questions

### What Qt widgets can receive spdlog messages?

Any `QObject` that exposes a slot accepting `const QString&` can receive messages, but `QPlainTextEdit` and `QTextEdit` are the most common targets using their native `append(const QString&)` slots.

### Is spdlog's qt_sink thread-safe?

Yes. The `*_mt` variants use mutex-protected base sinks, and internally the sink calls `QMetaObject::invokeMethod` with `Qt::AutoConnection`, which safely marshals calls to the GUI thread if logging occurs from a background thread.

### How do I prevent crashes when closing my Qt application?

Reset or drop the spdlog logger in your widget destructor before deleting the Qt widget. The sink validates the `QObject*` pointer at construction but does not track widget destruction; logging to a destroyed widget causes undefined behavior.

### Can I use custom colors for different log levels with qt_sink?

Only `qt_color_sink` supports color customization via `set_color(spdlog::level, QTextCharFormat)`. The standard `qt_sink` forwards plain text without formatting. Use `spdlog::qt_color_logger_mt()` to instantiate the colored variant.