# How to Use enable_backtrace and dump_backtrace in spdlog

> Learn how to use spdlog's enable_backtrace and dump_backtrace functions. Capture and replay recent log messages to diagnose errors effectively.

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

---

**spdlog's backtrace facility stores the last N log messages in a circular buffer and replays them through `dump_backtrace()` to help diagnose the state leading up to an error.**

The gabime/spdlog library provides a lightweight, thread-safe mechanism for capturing recent log history without impacting runtime performance. By using `enable_backtrace` and `dump_backtrace` in spdlog, you can maintain a sliding window of formatted log messages that can be emitted on demand when critical errors occur, making debugging production issues significantly easier.

## How spdlog Backtracing Works

The backtrace system operates as a circular message buffer attached to individual loggers or the global registry. When enabled, every log call pushes a copy of the formatted `log_msg` into a `circular_q<log_msg_buffer>` before the message is dispatched to sinks. This capture happens in [`include/spdlog/details/backtracer.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/details/backtracer.h), where the `details::backtracer` class manages an `std::atomic<bool> enabled_` flag and protects the queue with an `std::mutex` for thread safety.

The architecture separates global convenience functions from per-logger control:

- **Global API** ([`include/spdlog/spdlog.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/spdlog.h) and [`spdlog-inl.h`](https://github.com/gabime/spdlog/blob/main/spdlog-inl.h)): Forwards calls to `details::registry::instance()`, propagating settings to all existing loggers.
- **Per-Logger API** ([`include/spdlog/logger.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/logger.h) and [`logger-inl.h`](https://github.com/gabime/spdlog/blob/main/logger-inl.h)): Each `logger` instance owns a `details::backtracer tracer_` member for isolated message capture.

## Enabling Backtraces Globally vs Per-Logger

You can activate backtracing across your entire application or limit it to specific loggers that handle critical subsystems.

### Global Registry Configuration

Use the global helpers when you want uniform backtrace behavior across all loggers. According to [`include/spdlog/spdlog-inl.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/spdlog-inl.h), these functions forward to the registry which iterates through all registered loggers:

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

// Store the last 32 messages in every logger's circular buffer
spdlog::enable_backtrace(32);

// Later, dump the backtrace using the default logger
spdlog::dump_backtrace();

// Disable and clear all backtrace buffers globally
spdlog::disable_backtrace();

```

### Per-Logger Configuration

For finer control, enable backtracing on individual logger instances. This is defined in [`include/spdlog/logger-inl.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/logger-inl.h) and isolates the buffer to that specific logger's sinks:

```cpp
auto logger = spdlog::stdout_color_mt("critical_component");
logger->enable_backtrace(10);  // Keep only the last 10 messages for this component

// When an error is detected in this subsystem
logger->dump_backtrace();
logger->disable_backtrace();

```

## Implementation Details of the Backtracer Class

The underlying mechanism resides in [`include/spdlog/details/backtracer.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/details/backtracer.h) and its implementation in [`backtracer-inl.h`](https://github.com/gabime/spdlog/blob/main/backtracer-inl.h). The `backtracer` class template uses a fixed-size circular queue that overwrites old messages when full (FIFO order).

Key implementation aspects:

- **Message Storage**: The `push_back(const log_msg&)` method stores a `log_msg_buffer` (a copy of the formatted message) to ensure the data persists even if the original log context changes.
- **Thread Safety**: An `std::mutex` guards the circular queue during push operations and when iterating via `foreach_pop`.
- **Dumping**: The `foreach_pop` method iterates over stored messages in order, invoking a callback that writes them to the logger's sinks. This is called internally by `logger::dump_backtrace()`.

## Practical Code Examples

### Basic Global Backtrace Workflow

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

int main() {
    auto file_logger = spdlog::basic_logger_mt("file_logger", "app.log");
    
    // Enable global backtrace of last 10 messages
    spdlog::enable_backtrace(10);
    
    file_logger->info("Application started");
    file_logger->debug("Config loaded: {}", 42);
    file_logger->warn("Resource threshold at 80%");
    
    // Simulate error detection
    try {
        throw std::runtime_error("Critical failure");
    } catch (...) {
        // Dump the last 10 messages to see what led to the error
        spdlog::dump_backtrace();  // Writes to default logger's sinks
    }
    
    spdlog::disable_backtrace();
}

```

### Isolated Component Backtrace

```cpp
auto network_logger = spdlog::stdout_color_mt("network");
network_logger->enable_backtrace(5);

// Simulated network operations
network_logger->info("Connecting to host...");
network_logger->debug("Sent packet: {}", 1024);
network_logger->error("Connection timeout");

// Dump only this logger's history to diagnose the network issue
network_logger->dump_backtrace();  // Prints the 5 most recent lines
network_logger->disable_backtrace();

```

## Summary

- **Global vs Local**: Use `spdlog::enable_backtrace()` in [`spdlog.h`](https://github.com/gabime/spdlog/blob/main/spdlog.h) to capture across all loggers, or `logger->enable_backtrace()` for isolated component tracking.
- **Dumping**: Call `dump_backtrace()` on the default logger via `spdlog::dump_backtrace()` or on specific logger instances to replay buffered messages to their sinks.
- **Implementation**: The `details::backtracer` class in [`backtracer.h`](https://github.com/gabime/spdlog/blob/main/backtracer.h) uses a thread-safe `circular_q<log_msg_buffer>` managed by `std::mutex` to store formatted message copies.
- **Cleanup**: Invoke `disable_backtrace()` to atomically disable tracing and clear the circular buffer without dumping contents.

## Frequently Asked Questions

### What is the performance impact of enabling backtraces in spdlog?

The overhead is minimal but non-zero. Each log call performs an atomic check on `enabled_`, locks a mutex, and pushes a copy of the formatted message into the circular queue. For high-frequency logging (millions of messages per second), consider using per-logger backtraces only on critical subsystems rather than the global registry.

### How do I clear the backtrace buffer without dumping the messages?

Call `disable_backtrace()` on the logger or the global registry. In [`include/spdlog/details/backtracer-inl.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/details/backtracer-inl.h), the `disable()` method clears the `circular_q` and sets the atomic flag to false, effectively dropping all stored messages without writing them to sinks.

### Is the spdlog backtrace buffer thread-safe?

Yes. The `details::backtracer` class uses an `std::atomic<bool>` for the enabled state and an `std::mutex` to protect the `circular_q<log_msg_buffer>` during concurrent push and pop operations. Multiple threads can log simultaneously while the backtrace is enabled.

### What happens when the backtrace buffer reaches its capacity?

The circular queue overwrites the oldest messages in FIFO order. When `push_back()` is called on a full buffer, the implementation in [`backtracer-inl.h`](https://github.com/gabime/spdlog/blob/main/backtracer-inl.h) replaces the oldest entry, maintaining exactly the last *N* messages specified in the `enable_backtrace(size_t n_messages)` call.