Skip to content

Repository files navigation

spdlite

Linux macOS Windows

A small, header-only C++20 logger - the lite version of spdlog, simpler, smaller, fewer features.

Use spdlite if you want a tiny, fast, capable logger.

Install

Copy the include/spdlite/ folder into your build tree — header-only, no build step. Or via CMake (find_package, FetchContent, or add_subdirectory), link spdlite::spdlite.

Quick start

#include "spdlite/logger.h"
#include "spdlite/sinks/console_sink.h"

int main() {
    using namespace spdlite;
    logger<console_sink> log("app", console_sink{});

    log.info("Hello {}", "world");
    log.info("Value: {}", 42);
    log.warn("Something happened");
    log.error("Failed with code {}", -1);
}

Output:

[2026-04-11 10:30:45.123] [app] [INF] Hello world
[2026-04-11 10:30:45.123] [app] [INF] Value: 42
[2026-04-11 10:30:45.123] [app] [WRN] Something happened
[2026-04-11 10:30:45.123] [app] [ERR] Failed with code -1

See include/spdlite/logger.h for the full API and include/spdlite/sinks/ for the available sinks.

Thread safety

logger is thread-safe by default — it uses a std::mutex to serialize format and dispatch per call, so multiple threads can write through the same instance safely.

If you don't require thread safety, you can use logger_st which skips the lock entirely:

spdlite::logger<console_sink>    loogger("app", console_sink{});  // std::mutex
spdlite::logger_st<console_sink> logger("app", console_sink{});  // no locking

Both share the same API; only the mutex type differs.

Formatter options

The default header is [YYYY-MM-DD HH:MM:SS.mmm] [name] [LVL] payload. Reconfigure via format_options:

log.format_options({.utc = true});
log.format_options({.precision = time_precision::ns});
log.format_options({.show_date = false, .precision = time_precision::none});

See the table below for all available fields:

Field Default Effect
utc false Use gmtime instead of localtime.
show_date true Include the YYYY-MM-DD prefix.
show_thread_id false Include a 6-digit thread id after the timestamp.
precision time_precision::ms Fractional digits: none, ms (3), us (6), or ns (9).

Compile-time level gating

Strip log calls below a chosen severity from the binary entirely — no format string, no argument evaluation, no symbol — via the SPDLITE_* macros:

#define SPDLITE_ACTIVE_LEVEL SPDLITE_LEVEL_INFO  // before the include
#include "spdlite/logger.h"

void hot_path(spdlite::logger<spdlite::console_sink>& log) {
    SPDLITE_DEBUG(log, "value={}", expensive_to_compute());  // gone — args not evaluated
    SPDLITE_INFO(log,  "did the thing");                     // stays
}

Macros: SPDLITE_TRACE, SPDLITE_DEBUG, SPDLITE_INFO, SPDLITE_WARN, SPDLITE_ERROR, SPDLITE_CRITICAL. Levels: SPDLITE_LEVEL_TRACE (0) ... SPDLITE_LEVEL_OFF (6). Per-TU setting; default is SPDLITE_LEVEL_TRACE (no elision). The compile-time gate is independent of the runtime set_log_level() — a call emits only when both gates pass.

Compile times

Most of a logging TU's compile cost is the bundled fmt headers. To cut it:

  • Gate out cold log calls — see Compile-time level gating above; elided calls cost nothing, at compile time and runtime.
  • Compile fmt once-DSPDLITE_COMPILED_FMT=ON builds fmt's implementation into a small static lib instead of header-only, so logging TUs compile much faster (~60% per TU) with no runtime cost and identical output. Worth it from ~2 logging TUs up; gives up pure header-only (consumers link the lib — automatic via spdlite::spdlite).
  • Use std::format-DSPDLITE_USE_STD_FORMAT=ON drops the bundled fmt headers and compiles ~20% faster per TU, but it is a compile-time-for-runtime trade: libstdc++'s std::format is ~1.3–2× slower than bundled fmt on typical messages, so fmt stays the default. Needs a modern stdlib (libstdc++ 13+, libc++ 17+, MSVC 19.29+).

Build options

CMake isn't required to use spdlite — copy the headers and you're done. The flags below only apply if you build the bundled example, tests, or benchmarks with the provided CMakeLists.txt.

Option Default Effect
SPDLITE_BUILD_EXAMPLE ON Build the example executable.
SPDLITE_BUILD_TESTS OFF Build the doctest-based unit tests.
SPDLITE_BUILD_BENCH OFF Build the benchmarks (fetches Google Benchmark automatically).
SPDLITE_USE_STD_FORMAT OFF CMake option: use <format> instead of bundled fmt — drop fmt/ from the install. Pass via -DSPDLITE_USE_STD_FORMAT=ON.
SPDLITE_COMPILED_FMT OFF Compile bundled fmt once into a static lib (not header-only) — faster builds, links spdlite_fmt. Mutually exclusive with SPDLITE_USE_STD_FORMAT.

Benchmarks

Build and run:

$ cmake -B build -DSPDLITE_BUILD_BENCH=ON .
$ cmake --build build
$ ./build/latency           # quick set
$ ./build/latency full      # adds multi-threaded + file I/O

License

MIT

About

Minimal, header-only C++ logging library. Lite version of spdlog.

Resources

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages