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

Use spdlog::to_hex() from 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 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:

#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 Core implementation of to_hex and fmt::formatter specialization
tests/test_bin_to_hex.cpp Unit tests demonstrating all flag combinations
example/example.cpp Example usage in the repository's sample program

Summary

  • Include 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, 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →