# How to Integrate spdlog with Qt Using qt_sinks: A Complete Guide

> Integrate spdlog with Qt using qt_sinks for thread-safe logging to UI widgets. Ensure correct thread updates with QMetaObject invokeMethod for seamless background worker integration.

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

---

**Use spdlog's [`qt_sinks.h`](https://github.com/gabime/spdlog/blob/main/qt_sinks.h) header to create thread-safe loggers that forward messages to Qt widgets via `QMetaObject::invokeMethod`, ensuring UI updates occur on the correct thread even when logging from background workers.**

The `gabime/spdlog` library provides dedicated Qt integration through the `qt_sinks` module, allowing you to stream high-performance log output directly into `QPlainTextEdit` or `QTextEdit` widgets. This integration leverages Qt's meta-object system to marshal log calls across threads safely, making it straightforward to integrate spdlog with Qt using qt_sinks while maintaining responsive user interfaces.

## Prerequisites and Header Inclusion

To begin, include the Qt-specific sink header in your source file. This header declares both sink types and the convenience factory functions for logger creation.

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

```

Ensure your build system links against Qt (typically Qt5 or Qt6) and that the `spdlog` include directory is in your compiler's search path.

## Understanding qt_sinks Types

The [`include/spdlog/sinks/qt_sinks.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/sinks/qt_sinks.h) file defines two specialized sinks that derive from `spdlog::sinks::base_sink<Mutex>`, inheriting the same thread-safety policies as standard spdlog sinks.

### qt_sink for Plain Text Widgets

The **qt_sink** writes plain text to any `QObject` that implements a compatible Qt slot. This sink works with `QPlainTextEdit` through its `append(const QString&)` slot, or any custom `QObject` exposing a similar signature.

### qt_color_sink for Rich Text Output

The **qt_color_sink** targets `QTextEdit` widgets and supports per-log-level color customization. It inserts colored text using `QTextCharFormat` objects, allowing you to visually distinguish between debug, warning, and error messages in the same widget.

## Creating a Qt Logger

### Factory Function Signatures

Create loggers using the multi-threaded (`*_mt`) or single-threaded (`*_st`) convenience factory functions:

- `spdlog::qt_logger_mt(name, qt_object, meta_method)` – Creates a thread-safe logger using `qt_sink` with mutex protection.
- `spdlog::qt_logger_st(name, qt_object, meta_method)` – Creates a single-threaded logger without mutex overhead.
- `spdlog::qt_color_logger_mt(name, qt_object, max_logs)` – Creates a colored logger for `QTextEdit` with a maximum log buffer size.

The `qt_object` parameter accepts a pointer to your target widget (e.g., `QPlainTextEdit*`), while `meta_method` must be the fully-qualified Qt slot signature as a string, such as `"append(const QString&)"`.

### Connecting to Widget Slots

The sink stores the `QObject*` pointer and method name internally. When a log entry arrives, it builds the formatted message using the configured spdlog formatter and invokes the slot via `Qt::invokeMethod`. This mechanism ensures that even if you log from a background thread, the UI update executes on the main thread that owns the widget.

## Thread Safety and Cross-Thread Logging

Both `qt_sink` and `qt_color_sink` use **Qt::AutoConnection** when calling `QMetaObject::invokeMethod`. This automatically queues the call if the logging thread differs from the widget's thread, preventing race conditions during UI updates. Because the sinks inherit from `base_sink<Mutex>`, the `*_mt` variants provide thread-safe logging through standard mutex locking, while `*_st` variants offer higher performance when logging exclusively from the main thread.

## Customizing Colors in qt_color_sink

Customize the appearance of log levels by creating `QTextCharFormat` objects and applying them to specific levels:

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

QTextCharFormat warnFmt;
warnFmt.setForeground(Qt::darkYellow);
color_logger->set_color(spdlog::level::warn, warnFmt);

```

The `set_color(level, QTextCharFormat)` method updates the internal format map used when inserting text into the `QTextEdit`.

## Lifetime Management and Safety

The sink constructor includes a guard clause: `if (!qt_object_) throw_spdlog_ex(...)`. If you pass a null pointer or if the widget is destroyed before the logger, the sink throws a `spdlog_ex` exception. Because the sink stores a raw pointer rather than a `QPointer` or hard reference, you must ensure the logger's lifetime is tied to the widget's lifetime, or explicitly reset the logger (e.g., call `spdlog::drop("logger_name")`) before destroying the target widget to avoid dangling pointers.

## Complete Implementation Examples

### Basic Plain-Text Integration

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

// Create widget and logger
QPlainTextEdit *logView = new QPlainTextEdit(parent);
auto logger = spdlog::qt_logger_mt("qt_logger", logView, "append(const QString&)");

logger->set_level(spdlog::level::debug);
logger->info("Application started successfully");

```

### Colored Logging with Custom Formatting

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

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

// Configure custom warning color
QTextCharFormat warnFmt;
warnFmt.setForeground(Qt::darkYellow);
warnFmt.setFontWeight(QFont::Bold);
color_logger->set_color(spdlog::level::warn, warnFmt);

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

```

## Summary

- **Include** [`spdlog/sinks/qt_sinks.h`](https://github.com/gabime/spdlog/blob/main/spdlog/sinks/qt_sinks.h) to access Qt-specific logging functionality.
- **Choose** between `qt_sink` for plain text and `qt_color_sink` for colored output in `QTextEdit` widgets.
- **Create** loggers using `qt_logger_mt` or `qt_color_logger_mt` for thread-safe operation, passing the widget pointer and slot signature.
- **Leverage** `QMetaObject::invokeMethod` with `Qt::AutoConnection` to automatically marshal log calls to the UI thread.
- **Manage** object lifetimes carefully to prevent `spdlog_ex` exceptions when widgets are destroyed.
- **Customize** log appearance using `set_color` with `QTextCharFormat` for visual log level distinction.

## Frequently Asked Questions

### What Qt widgets are compatible with qt_sinks?

The `qt_sink` works with any `QObject` exposing a slot that accepts a `QString` parameter, most commonly `QPlainTextEdit` and `QTextEdit`. The `qt_color_sink` specifically requires `QTextEdit` because it manipulates `QTextCharFormat` and rich text cursors.

### How does spdlog ensure thread safety when updating Qt GUI elements?

The sinks use `QMetaObject::invokeMethod` with `Qt::AutoConnection`, which automatically detects if the logging thread differs from the widget's thread. If a different thread is detected, Qt queues the method call to execute on the widget's owning thread, preventing direct manipulation of GUI elements from worker threads.

### Can I use custom slot signatures other than append(const QString&)?

Yes. The `meta_method` parameter in `qt_logger_mt` accepts any Qt slot signature that matches your widget's implementation. For example, if you have a custom `QObject` with a slot `void addLogEntry(const QString& text)`, you would pass `"addLogEntry(const QString&)"` as the third parameter to the factory function.

### Why does my application throw a spdlog_ex when creating the logger?

This exception occurs in the sink constructor if the `qt_object` pointer is null or if the specified `meta_method` does not exist on the object. Verify that your widget pointer is valid and that the slot signature exactly matches the Qt meta-object signature, including `const` qualifiers and reference symbols.