# How to Log Binary Data with to_hex in spdlog: Format Flags and Examples

> Log binary data with spdlog to_hex. Convert byte buffers to hex strings using format flags for uppercase or ASCII output. Optimize your logging now.

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

---

**Use `spdlog::to_hex()` from [`spdlog/fmt/bin_to_hex.h`](https://github.com/gabime/spdlog/blob/main/spdlog/fmt/bin_to_hex.h) to convert byte buffers into formatted hexadecimal strings, then pass the result to any spdlog logger with format flags like `X` for uppercase or `a` for ASCII output.**

The gabime/spdlog library provides a header-only mechanism for logging binary data as readable hexadecimal dumps. By leveraging the **fmt** library's extension system, you can log binary data with to_hex in spdlog using simple format specifiers that control case, spacing, and ASCII representation.

## How to_hex Works Under the Hood

The implementation resides entirely in [`include/spdlog/fmt/bin_to_hex.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/fmt/bin_to_hex.h) and consists of two main components: a data holder created by `to_hex()` and a specialized fmt formatter that renders the output.

### The to_hex Helper Function

The `to_hex` function template provides three overloads (lines 61–90) that accept:

- A **container** (any type with `begin()` and `end()`)
- A **`std::span`** (when C++20 `<span>` is available)
- A **pair of iterators** (begin/end)

All variants return a `details::dump_info` object that stores the iterator range and the desired **bytes-per-line** (defaulting to 32). This object acts as a lightweight data holder with no formatting logic of its own.

### The Formatter Specialization

The actual rendering logic lives in a `fmt::formatter<dump_info<T>>` specialization (lines 101–224). The `parse()` method interprets format flags after the colon (`:`), while the `format()` method walks the byte range and writes the output.

According to the spdlog source code, the `format` function uses `fmt::format_to` to write position headers when `put_positions` is true (lines 144–222). It converts each byte to two hex characters using `hex_upper` or `hex_lower`, inserts delimiters, and optionally appends an ASCII column.

## Format Flags Reference

When logging binary data with spdlog to_hex, you can append these flags after the colon in your format string:

- **`X`** – Use uppercase hex digits (A–F) instead of lowercase
- **`s`** – Suppress the space delimiter between bytes
- **`p`** – Omit the position header (e.g., `0000:`)
- **`n`** – Produce a single line without line breaks (disables ASCII column)
- **`a`** – Show printable ASCII alongside hex (only works when line breaks are enabled)

## Complete Usage Examples

Include the header and pass `spdlog::to_hex()` to any logger:

```cpp
#include "spdlog/spdlog.h"
#include "spdlog/fmt/bin_to_hex.h"

int main() {
    // Create a logger (console sink used here)
    auto logger = spdlog::stdout_color_mt("example");

    // Sample binary buffer
    std::vector<unsigned char> buf(64);
    std::iota(buf.begin(), buf.end(), 0x00);   // 0x00,0x01,...0x3F

    // 1️⃣ Default hex dump (lower‑case, spaced, positions, ASCII)
    logger->info("Default dump: {}", spdlog::to_hex(buf));

    // 2️⃣ Upper‑case hex, no delimiters, no position column
    logger->info("Upper‑case, dense: {:Xs}", spdlog::to_hex(buf));

    // 3️⃣ Single‑line dump (no newlines, no ASCII)
    logger->info("One‑liner: {:n}", spdlog::to_hex(buf));

    // 4️⃣ Hex with ASCII column (hexdump style)
    logger->info("Hex + ASCII: {:a}", spdlog::to_hex(buf, 16));

    // 5️⃣ Custom range – only first 10 bytes, upper‑case
    logger->info("First 10 bytes: {:X}", spdlog::to_hex(buf.begin(), buf.begin() + 10));
}

```

The `to_hex` function accepts an optional second parameter to specify bytes per line (default is 32), as shown in example 4 where 16 bytes per line are used.

## Key Implementation Files

| File | Role |
|------|------|
| [`include/spdlog/fmt/bin_to_hex.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/fmt/bin_to_hex.h) | Core implementation of `to_hex` and `fmt::formatter` specialization |
| [`tests/test_bin_to_hex.cpp`](https://github.com/gabime/spdlog/blob/main/tests/test_bin_to_hex.cpp) | Unit tests demonstrating all flag combinations |
| [`example/example.cpp`](https://github.com/gabime/spdlog/blob/main/example/example.cpp) | Example usage in the repository's sample program |

## Summary

- **Include [`spdlog/fmt/bin_to_hex.h`](https://github.com/gabime/spdlog/blob/main/spdlog/fmt/bin_to_hex.h)** to access the `to_hex` function
- **Three overloads** support containers, `std::span`, and iterator pairs
- **Format flags** (`X`, `s`, `p`, `n`, `a`) control the output style when passed in the format string
- **Default configuration** uses lowercase hex, 32 bytes per line, with spaces and position headers
- **No runtime dependencies** are required; the implementation is header-only

## Frequently Asked Questions

### How do I include the to_hex functionality in my project?

Add `#include "spdlog/fmt/bin_to_hex.h"` alongside your regular spdlog headers. This header defines `spdlog::to_hex` and the necessary fmt formatter specializations. No additional linking is required because the implementation is header-only.

### Can I control the number of bytes per line when logging binary data?

Yes. Pass a second argument to `to_hex()` specifying the bytes-per-line value. For example, `spdlog::to_hex(buf, 16)` formats the output with 16 bytes per line instead of the default 32. This parameter is stored in the `dump_info` object and respected by the formatter.

### Does to_hex work with C-style arrays or only STL containers?

`to_hex` works with any contiguous memory range. You can use the iterator-pair overload for C-style arrays: `spdlog::to_hex(array, array + size)`. The container overload works with `std::vector`, `std::array`, and other STL containers that provide `begin()` and `end()` methods.

### Why is my ASCII column not showing when using the 'n' flag?

The `n` flag produces a single-line output without line breaks, which disables the ASCII column functionality. According to the implementation in [`include/spdlog/fmt/bin_to_hex.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/fmt/bin_to_hex.h), the ASCII column (`a` flag) is only rendered when line breaks are enabled because it appears alongside each line of hex output. Remove the `n` flag or use it separately from `a` to see the ASCII representation.