spdlog covers the logging jobs most C++ programs actually need
The spdlog README starts with a compact API: call info, warn, or error with fmt-style placeholders. Under that simple surface are console colors, basic and rotating files, daily files, syslog, Windows event log, debugger output, Android, Qt widgets, callbacks, and custom sinks. Log levels can change at runtime or compile time. The library also has a backtrace ring buffer for retaining debug messages until an error makes them useful.
This breadth is practical rather than architectural. A desktop application can write warnings to the console and full details to a file through one multi-sink logger. A service can choose an asynchronous file logger. A library can accept a logger supplied by its host. The API does not require a daemon, account, configuration server, or network connection. At 181 repository files and 1.2 MB checked out in our run, the project stays small enough to audit and vendor.
Header-only and compiled modes trade convenience for compile time
The header-only path asks users to copy the include directory and compile with C++11 or newer. That is convenient for a prototype or vendored dependency because there is no separate library artifact to ship. The README recommends the compiled path for much faster compilation. CMake builds that library normally, and packages are available through Debian, Homebrew, Fedora, vcpkg, Conan, conda, and other common native ecosystems.
Formatting comes from fmt, which spdlog can bundle or consume externally. Version 1.17.0 updated the bundled fmt copy to 12.1.0. Mixing a newer external fmt deserves a build check: issue 3631 reports deprecation warnings with fmt 12.2.0 and Visual Studio 2026, which become failures when warnings are treated as errors. Pin both dependencies together in strict builds.
What happened when we ran it
Our sandbox installed commit f5f173a in 22 seconds. The CMake build then completed in 154 seconds in a fresh unprivileged container with 3 CPUs and 8 GB of RAM. Unlike the larger agent projects in this batch, spdlog needed no service credentials, package registry login, database, or model provider to reach a built artifact. The repository included 3 CI workflow files and a dedicated tests directory.
Ctest finished in 22 seconds with 2 passing and 0 failing tests. Those are the only test-count and timing claims from our run; we did not measure message throughput or compare sink latency. The README publishes its own benchmark section on older named hardware, but that is not a substitute for testing your message size, thread count, filesystem, flush policy, and compiler flags. Logging cost is shaped by all five.
The clean result gives confidence in the documented CMake route. It does not validate every optional platform sink or async overflow choice. Our Debian container could not stand in for Windows event log, Android logcat, Qt widgets, or an unreachable TCP endpoint. Teams using those paths should add a focused smoke test on each shipping platform rather than treating the 2 ctest targets as universal coverage.
Async mode makes queue policy part of correctness
An asynchronous logger moves formatting and sink work through a shared thread pool. The README shows queue sizing, backing threads, and two overflow policies: block the caller or overrun older messages. Neither policy is universally safe. Blocking can let an unavailable destination stall application work. Overrunning can discard the exact events needed during an incident. Pick deliberately, expose dropped-message signals where possible, and test shutdown so buffered records reach their destination.
Mapped Diagnostic Context has a specific limit. The README says it is thread-local and unsupported in asynchronous mode. Applications that depend on request IDs, tenant IDs, or trace fields should avoid assuming MDC will cross that boundary. Pass fields in the message, build a custom representation, or choose a library whose async design preserves the context model you need. This is a competent-developer reason to reject spdlog for some services.
Rotation and network sinks need application-level tests
Rotating and daily file sinks reduce housekeeping code, yet retention is still part of production correctness. Issue 2553 reports that daily cleanup stops scanning at the first missing date, leaving older files behind when a day has no log file. A proposed pull request scans the directory instead, but the issue remained open when researched. Disk-budget tests should include gaps, restarts, clock changes, and manual deletion.
A network destination has a different failure mode. Issue 2682 says the TCP client can wait up to 2 minutes when a syslog server is unreachable and asks for a configurable connect timeout. That duration comes from the issue report, not our lab. A process with a strict startup or request deadline should isolate connection attempts or choose a sink with the required timeout control.
The v1 branch is maintained, even with a slower release rhythm
The latest tagged release, 1.17.0, shipped on 2026-01-04. The repository was pushed on 2026-08-08, and issues and pull requests were still receiving updates later in August. Its 50 open issues and pull requests form a modest combined queue for a 29,521-star library. The January tag alone does not indicate abandonment; current code and discussion show continued maintenance on the v1.x default branch.
The source is under the MIT license, with a notice that fmt carries its own MIT terms. Boost.Log is the alternative for a richer Boost-native attribute system, Quill for an async-first design, and Loguru for a smaller inclusion model. spdlog is the sensible first pick when common sinks and readable fmt syntax matter more than elaborate event schemas. Its clean build and test run reinforce that recommendation.

