gabime/spdlogPublic

Fast C++ logging library.

AI summary: Fast C++ logging library, available as header-only or compiled.

Stars
29.4K
+11 today
Forks
5.4K
Watchers
475
Open issues
36
Open PRs
10
Contributors
~462
Commits
4.5K
Branches
21

C++OtherCreated Nov 1, 2014Last push 14d agoLatest release v1.17.0+137 stars this week+154 this month

Star history

since Nov 2, 2014
010K20KNov 2014Sep 2018Aug 2022Aug 2026
29.4K stars as of Aug 7, 2026, tracked back to Nov 2, 2014. Historical curve reconstructed from public GitHub event archives, calibrated to the current total.

Contribution activity

commits per day, last 52 weeks
AugSepOctNovDecJanFebMarAprMayJunJulAugMonWedFri2025-08-10: 0 commits2025-08-11: 0 commits2025-08-12: 0 commits2025-08-13: 0 commits2025-08-14: 0 commits2025-08-15: 0 commits2025-08-16: 0 commits2025-08-17: 0 commits2025-08-18: 0 commits2025-08-19: 0 commits2025-08-20: 0 commits2025-08-21: 0 commits2025-08-22: 0 commits2025-08-23: 0 commits2025-08-24: 0 commits2025-08-25: 0 commits2025-08-26: 0 commits2025-08-27: 0 commits2025-08-28: 0 commits2025-08-29: 0 commits2025-08-30: 0 commits2025-08-31: 0 commits2025-09-01: 0 commits2025-09-02: 0 commits2025-09-03: 0 commits2025-09-04: 0 commits2025-09-05: 0 commits2025-09-06: 0 commits2025-09-07: 0 commits2025-09-08: 0 commits2025-09-09: 0 commits2025-09-10: 0 commits2025-09-11: 0 commits2025-09-12: 0 commits2025-09-13: 0 commits2025-09-14: 0 commits2025-09-15: 0 commits2025-09-16: 0 commits2025-09-17: 0 commits2025-09-18: 0 commits2025-09-19: 0 commits2025-09-20: 0 commits2025-09-21: 0 commits2025-09-22: 0 commits2025-09-23: 0 commits2025-09-24: 0 commits2025-09-25: 0 commits2025-09-26: 0 commits2025-09-27: 0 commits2025-09-28: 0 commits2025-09-29: 0 commits2025-09-30: 0 commits2025-10-01: 0 commits2025-10-02: 0 commits2025-10-03: 0 commits2025-10-04: 0 commits2025-10-05: 0 commits2025-10-06: 0 commits2025-10-07: 0 commits2025-10-08: 0 commits2025-10-09: 0 commits2025-10-10: 0 commits2025-10-11: 3 commits2025-10-12: 0 commits2025-10-13: 0 commits2025-10-14: 0 commits2025-10-15: 0 commits2025-10-16: 0 commits2025-10-17: 0 commits2025-10-18: 0 commits2025-10-19: 0 commits2025-10-20: 0 commits2025-10-21: 0 commits2025-10-22: 0 commits2025-10-23: 0 commits2025-10-24: 0 commits2025-10-25: 0 commits2025-10-26: 0 commits2025-10-27: 0 commits2025-10-28: 0 commits2025-10-29: 0 commits2025-10-30: 0 commits2025-10-31: 0 commits2025-11-01: 2 commits2025-11-02: 0 commits2025-11-03: 0 commits2025-11-04: 0 commits2025-11-05: 0 commits2025-11-06: 0 commits2025-11-07: 0 commits2025-11-08: 0 commits2025-11-09: 1 commit2025-11-10: 0 commits2025-11-11: 0 commits2025-11-12: 0 commits2025-11-13: 1 commit2025-11-14: 0 commits2025-11-15: 0 commits2025-11-16: 0 commits2025-11-17: 1 commit2025-11-18: 0 commits2025-11-19: 0 commits2025-11-20: 0 commits2025-11-21: 0 commits2025-11-22: 0 commits2025-11-23: 0 commits2025-11-24: 0 commits2025-11-25: 0 commits2025-11-26: 0 commits2025-11-27: 0 commits2025-11-28: 5 commits2025-11-29: 0 commits2025-11-30: 2 commits2025-12-01: 0 commits2025-12-02: 0 commits2025-12-03: 0 commits2025-12-04: 0 commits2025-12-05: 0 commits2025-12-06: 0 commits2025-12-07: 0 commits2025-12-08: 0 commits2025-12-09: 0 commits2025-12-10: 0 commits2025-12-11: 0 commits2025-12-12: 0 commits2025-12-13: 0 commits2025-12-14: 0 commits2025-12-15: 2 commits2025-12-16: 0 commits2025-12-17: 0 commits2025-12-18: 0 commits2025-12-19: 0 commits2025-12-20: 0 commits2025-12-21: 0 commits2025-12-22: 0 commits2025-12-23: 0 commits2025-12-24: 1 commit2025-12-25: 0 commits2025-12-26: 0 commits2025-12-27: 0 commits2025-12-28: 0 commits2025-12-29: 0 commits2025-12-30: 0 commits2025-12-31: 0 commits2026-01-01: 0 commits2026-01-02: 0 commits2026-01-03: 2 commits2026-01-04: 3 commits2026-01-05: 0 commits2026-01-06: 0 commits2026-01-07: 0 commits2026-01-08: 0 commits2026-01-09: 0 commits2026-01-10: 2 commits2026-01-11: 3 commits2026-01-12: 1 commit2026-01-13: 0 commits2026-01-14: 0 commits2026-01-15: 1 commit2026-01-16: 0 commits2026-01-17: 0 commits2026-01-18: 0 commits2026-01-19: 0 commits2026-01-20: 0 commits2026-01-21: 0 commits2026-01-22: 0 commits2026-01-23: 0 commits2026-01-24: 0 commits2026-01-25: 0 commits2026-01-26: 0 commits2026-01-27: 0 commits2026-01-28: 0 commits2026-01-29: 0 commits2026-01-30: 0 commits2026-01-31: 0 commits2026-02-01: 0 commits2026-02-02: 0 commits2026-02-03: 0 commits2026-02-04: 0 commits2026-02-05: 0 commits2026-02-06: 0 commits2026-02-07: 0 commits2026-02-08: 0 commits2026-02-09: 3 commits2026-02-10: 0 commits2026-02-11: 0 commits2026-02-12: 0 commits2026-02-13: 0 commits2026-02-14: 0 commits2026-02-15: 0 commits2026-02-16: 0 commits2026-02-17: 0 commits2026-02-18: 0 commits2026-02-19: 0 commits2026-02-20: 1 commit2026-02-21: 0 commits2026-02-22: 0 commits2026-02-23: 2 commits2026-02-24: 1 commit2026-02-25: 0 commits2026-02-26: 0 commits2026-02-27: 0 commits2026-02-28: 0 commits2026-03-01: 0 commits2026-03-02: 0 commits2026-03-03: 0 commits2026-03-04: 0 commits2026-03-05: 0 commits2026-03-06: 0 commits2026-03-07: 0 commits2026-03-08: 0 commits2026-03-09: 0 commits2026-03-10: 0 commits2026-03-11: 0 commits2026-03-12: 0 commits2026-03-13: 0 commits2026-03-14: 1 commit2026-03-15: 1 commit2026-03-16: 0 commits2026-03-17: 0 commits2026-03-18: 0 commits2026-03-19: 0 commits2026-03-20: 0 commits2026-03-21: 0 commits2026-03-22: 0 commits2026-03-23: 0 commits2026-03-24: 0 commits2026-03-25: 0 commits2026-03-26: 0 commits2026-03-27: 0 commits2026-03-28: 0 commits2026-03-29: 0 commits2026-03-30: 0 commits2026-03-31: 0 commits2026-04-01: 0 commits2026-04-02: 0 commits2026-04-03: 1 commit2026-04-04: 0 commits2026-04-05: 0 commits2026-04-06: 0 commits2026-04-07: 1 commit2026-04-08: 0 commits2026-04-09: 1 commit2026-04-10: 0 commits2026-04-11: 1 commit2026-04-12: 0 commits2026-04-13: 3 commits2026-04-14: 0 commits2026-04-15: 0 commits2026-04-16: 0 commits2026-04-17: 0 commits2026-04-18: 0 commits2026-04-19: 0 commits2026-04-20: 0 commits2026-04-21: 0 commits2026-04-22: 0 commits2026-04-23: 0 commits2026-04-24: 0 commits2026-04-25: 0 commits2026-04-26: 0 commits2026-04-27: 0 commits2026-04-28: 0 commits2026-04-29: 0 commits2026-04-30: 0 commits2026-05-01: 0 commits2026-05-02: 0 commits2026-05-03: 0 commits2026-05-04: 0 commits2026-05-05: 0 commits2026-05-06: 0 commits2026-05-07: 0 commits2026-05-08: 0 commits2026-05-09: 0 commits2026-05-10: 0 commits2026-05-11: 1 commit2026-05-12: 0 commits2026-05-13: 0 commits2026-05-14: 0 commits2026-05-15: 0 commits2026-05-16: 0 commits2026-05-17: 0 commits2026-05-18: 0 commits2026-05-19: 0 commits2026-05-20: 0 commits2026-05-21: 0 commits2026-05-22: 0 commits2026-05-23: 0 commits2026-05-24: 0 commits2026-05-25: 0 commits2026-05-26: 0 commits2026-05-27: 0 commits2026-05-28: 0 commits2026-05-29: 1 commit2026-05-30: 0 commits2026-05-31: 0 commits2026-06-01: 0 commits2026-06-02: 0 commits2026-06-03: 0 commits2026-06-04: 0 commits2026-06-05: 1 commit2026-06-06: 0 commits2026-06-07: 0 commits2026-06-08: 1 commit2026-06-09: 0 commits2026-06-10: 0 commits2026-06-11: 0 commits2026-06-12: 1 commit2026-06-13: 2 commits2026-06-14: 0 commits2026-06-15: 0 commits2026-06-16: 0 commits2026-06-17: 0 commits2026-06-18: 0 commits2026-06-19: 0 commits2026-06-20: 0 commits2026-06-21: 0 commits2026-06-22: 0 commits2026-06-23: 0 commits2026-06-24: 0 commits2026-06-25: 0 commits2026-06-26: 2 commits2026-06-27: 1 commit2026-06-28: 0 commits2026-06-29: 0 commits2026-06-30: 0 commits2026-07-01: 0 commits2026-07-02: 0 commits2026-07-03: 0 commits2026-07-04: 0 commits2026-07-05: 0 commits2026-07-06: 0 commits2026-07-07: 0 commits2026-07-08: 0 commits2026-07-09: 0 commits2026-07-10: 1 commit2026-07-11: 3 commits2026-07-12: 0 commits2026-07-13: 0 commits2026-07-14: 0 commits2026-07-15: 0 commits2026-07-16: 0 commits2026-07-17: 0 commits2026-07-18: 0 commits2026-07-19: 0 commits2026-07-20: 0 commits2026-07-21: 0 commits2026-07-22: 0 commits2026-07-23: 0 commits2026-07-24: 1 commit2026-07-25: 0 commits2026-07-26: 0 commits2026-07-27: 0 commits2026-07-28: 0 commits2026-07-29: 0 commits2026-07-30: 0 commits2026-07-31: 0 commits2026-08-01: 0 commits2026-08-02: 0 commits2026-08-03: 0 commits2026-08-04: 0 commits2026-08-05: 0 commits2026-08-06: 0 commits2026-08-07: 0 commits2026-08-08: 0 commits
61 commits in the last yearLessMore

Signals and awards

derived from tracked data
  • Widely adopted

    29,448 stars

  • Battle-tested

    11 years of history

  • Community-driven

    ~462 contributors

  • Continuous integration

    Automated checks passing

  • Repeat trending

    3 trending appearances

What spdlog does

spdlog is a very fast C++ logging library. It offers both header-only and compiled versions, providing developers with flexibility in how they integrate it into their build systems. The library supports asynchronous logging, custom formatting, and multiple sink targets (like files and consoles). It is designed to be highly concurrent and thread-safe, making it suitable for performance-critical applications.

spdlog is built for C++ developers building high-performance or concurrent applications. It is ideal for teams needing a reliable, fast logging framework with minimal setup overhead.

  • Header-only mode: Can be included directly into projects without needing to link against a compiled library.
  • Compiled version: Offers a compiled library option for much faster compilation times in large projects.
  • Asynchronous logging: Utilizes a lock-free queue to ensure that hot-path calls never block on I/O operations.
  • Custom formatting: Allows developers to define exact log output formats.
  • Multiple sinks: Routes log messages to various destinations simultaneously.

Where teams use it

High-Performance Applications

Game engines and real-time systems can use spdlog to record events without degrading performance.

System Daemons

Background services can log their status and errors to rotating log files for administration.

Embedded Systems

Resource-constrained environments benefit from its minimal overhead and flexible configuration.

General Purpose Logging

Any C++ application needing a robust, easy-to-integrate logging solution for debugging and monitoring.

Getting started: $ git clone https://github.com/gabime/spdlog.git

README

v1.x branch

spdlog

ci  ci  ci  Build status Release

Fast C++ logging library

Install

Header-only version

Copy the include folder to your build tree and use a C++11 compiler.

Compiled version (recommended - much faster compile times)

$ git clone https://github.com/gabime/spdlog.git
$ cd spdlog && mkdir build && cd build
$ cmake .. && cmake --build .

see example CMakeLists.txt on how to use.

Platforms

  • Linux, FreeBSD, OpenBSD, Solaris, AIX
  • Windows (msvc 2013+, cygwin)
  • macOS (clang 3.5+)
  • Android

Package managers:

  • Debian: sudo apt install libspdlog-dev
  • Homebrew: brew install spdlog
  • MacPorts: sudo port install spdlog
  • FreeBSD: pkg install spdlog
  • Fedora: dnf install spdlog
  • Gentoo: emerge dev-libs/spdlog
  • Arch Linux: pacman -S spdlog
  • openSUSE: sudo zypper in spdlog-devel
  • ALT Linux: apt-get install libspdlog-devel
  • vcpkg: vcpkg install spdlog
  • conan: conan install --requires=spdlog/[*]
  • conda: conda install -c conda-forge spdlog
  • build2: depends: spdlog ^1.8.2

Features

  • Very fast (see benchmarks below).
  • Headers only or compiled
  • Feature-rich formatting, using the excellent fmt library.
  • Asynchronous mode (optional)
  • Custom formatting.
  • Multi/Single threaded loggers.
  • Various log targets:
    • Rotating log files.
    • Daily log files.
    • Console logging (colors supported).
    • syslog.
    • Windows event log.
    • Windows debugger (OutputDebugString(..)).
    • Log to Qt widgets (example).
    • Easily extendable with custom log targets.
  • Log filtering - log levels can be modified at runtime as well as compile time.
  • Support for loading log levels from argv or environment var.
  • Backtrace support - store debug messages in a ring buffer and display them later on demand.

Usage samples

Basic usage

#include "spdlog/spdlog.h"

int main() 
{
    spdlog::info("Welcome to spdlog!");
    spdlog::error("Some error message with arg: {}", 1);
    
    spdlog::warn("Easy padding in numbers like {:08d}", 12);
    spdlog::critical("Support for int: {0:d};  hex: {0:x};  oct: {0:o}; bin: {0:b}", 42);
    spdlog::info("Support for floats {:03.2f}", 1.23456);
    spdlog::info("Positional args are {1} {0}..", "too", "supported");
    spdlog::info("{:<30}", "left aligned");
    
    spdlog::set_level(spdlog::level::debug); // Set *global* log level to debug
    spdlog::debug("This message should be displayed..");    
    
    // change log pattern
    spdlog::set_pattern("[%H:%M:%S %z] [%n] [%^---%L---%$] [thread %t] %v");
    
    // Compile time log levels
    // Note that this does not change the current log level, it will only
    // remove (depending on SPDLOG_ACTIVE_LEVEL) the call on the release code.
    SPDLOG_TRACE("Some trace message with param {}", 42);
    SPDLOG_DEBUG("Some debug message");
}

Create stdout/stderr logger object

#include "spdlog/spdlog.h"
#include "spdlog/sinks/stdout_color_sinks.h"
void stdout_example()
{
    // create a color multi-threaded logger
    auto console = spdlog::stdout_color_mt("console");    
    auto err_logger = spdlog::stderr_color_mt("stderr");    
    spdlog::get("console")->info("loggers can be retrieved from a global registry using the spdlog::get(logger_name)");
}

Basic file logger

#include "spdlog/sinks/basic_file_sink.h"
void basic_logfile_example()
{
    try 
    {
        auto logger = spdlog::basic_logger_mt("basic_logger", "logs/basic-log.txt");
    }
    catch (const spdlog::spdlog_ex &ex)
    {
        std::cout << "Log init failed: " << ex.what() << std::endl;
    }
}

Rotating files

#include "spdlog/sinks/rotating_file_sink.h"
void rotating_example()
{
    // Create a file rotating logger with 5 MB size max and 3 rotated files
    auto max_size = 1048576 * 5;
    auto max_files = 3;
    auto logger = spdlog::rotating_logger_mt("some_logger_name", "logs/rotating.txt", max_size, max_files);
}

Daily files

#include "spdlog/sinks/daily_file_sink.h"
void daily_example()
{
    // Create a daily logger - a new file is created every day at 2:30 am
    auto logger = spdlog::daily_logger_mt("daily_logger", "logs/daily.txt", 2, 30);
}

Backtrace support

// Debug messages can be stored in a ring buffer instead of being logged immediately.
// This is useful to display debug logs only when needed (e.g. when an error happens).
// When needed, call dump_backtrace() to dump them to your log.

spdlog::enable_backtrace(32); // Store the latest 32 messages in a buffer. 
// or my_logger->enable_backtrace(32)..
for(int i = 0; i < 100; i++)
{
  spdlog::debug("Backtrace message {}", i); // not logged yet..
}
// e.g. if some error happened:
spdlog::dump_backtrace(); // log them now! show the last 32 messages
// or my_logger->dump_backtrace(32)..

Periodic flush

// periodically flush all *registered* loggers every 3 seconds:
// warning: only use if all your loggers are thread-safe ("_mt" loggers)
spdlog::flush_every(std::chrono::seconds(3));

Stopwatch

// Stopwatch support for spdlog
#include "spdlog/stopwatch.h"
void stopwatch_example()
{
    spdlog::stopwatch sw;    
    spdlog::debug("Elapsed {}", sw);
    spdlog::debug("Elapsed {:.3}", sw);       
}

Log binary data in hex

// many types of std::container<char> types can be used.
// ranges are supported too.
// format flags:
// {:X} - print in uppercase.
// {:s} - don't separate each byte with space.
// {:p} - don't print the position on each line start.
// {:n} - don't split the output into lines.
// {:a} - show ASCII if :n is not set.

#include "spdlog/fmt/bin_to_hex.h"

void binary_example()
{
    auto console = spdlog::get("console");
    std::array<char, 80> buf;
    console->info("Binary example: {}", spdlog::to_hex(buf));
    console->info("Another binary example:{:n}", spdlog::to_hex(std::begin(buf), std::begin(buf) + 10));
    // more examples:
    // logger->info("uppercase: {:X}", spdlog::to_hex(buf));
    // logger->info("uppercase, no delimiters: {:Xs}", spdlog::to_hex(buf));
    // logger->info("uppercase, no delimiters, no position info: {:Xsp}", spdlog::to_hex(buf));
}

Logger with multi sinks - each with a different format and log level

// create a logger with 2 targets, with different log levels and formats.
// The console will show only warnings or errors, while the file will log all. 
void multi_sink_example()
{
    auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
    console_sink->set_level(spdlog::level::warn);
    console_sink->set_pattern("[multi_sink_example] [%^%l%$] %v");

    auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>("logs/multisink.txt", true);
    file_sink->set_level(spdlog::level::trace);

    spdlog::logger logger("multi_sink", {console_sink, file_sink});
    logger.set_level(spdlog::level::debug);
    logger.warn("this should appear in both console and file");
    logger.info("this message should not appear in the console, only in the file");
}

Register several loggers - change global level

// Creation of loggers. Set levels to all registered loggers. 
void set_level_example()
{
    auto logger1 = spdlog::basic_logger_mt("logger1", "logs/logger1.txt");
    auto logger2 = spdlog::basic_logger_mt("logger2", "logs/logger2.txt");

    spdlog::set_default_logger(logger2);
    spdlog::default_logger()->set_level(spdlog::level::trace); // set level for the default logger (logger2) to trace

    spdlog::trace("trace message to the logger2 (specified as default)");

    spdlog::set_level(spdlog::level::off) // (sic!) set level for *all* registered loggers to off (disable)
  
    logger1.warn("warn message will not appear because the level set to off");
    logger2.warn("warn message will not appear because the level set to off");
    spdlog::warn("warn message will not appear because the level set to off");
}

User-defined callbacks about log events

// create a logger with a lambda function callback, the callback will be called
// each time something is logged to the logger
void callback_example()
{
    auto callback_sink = std::make_shared<spdlog::sinks::callback_sink_mt>([](const spdlog::details::log_msg &msg) {
         // for example you can be notified by sending an email to yourself
    });
    callback_sink->set_level(spdlog::level::err);

    auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
    spdlog::logger logger("custom_callback_logger", {console_sink, callback_sink});

    logger.info("some info log");
    logger.error("critical issue"); // will notify you
}

Asynchronous logging

#include "spdlog/async.h"
#include "spdlog/sinks/basic_file_sink.h"
void async_example()
{
    // default thread pool settings can be modified *before* creating the async logger:
    // spdlog::init_thread_pool(8192, 1); // queue with 8k items and 1 backing thread.
    auto async_file = spdlog::basic_logger_mt<spdlog::async_factory>("async_file_logger", "logs/async_log.txt");
    // alternatively:
    // auto async_file = spdlog::create_async<spdlog::sinks::basic_file_sink_mt>("async_file_logger", "logs/async_log.txt");   
}

Asynchronous logger with multi sinks

#include "spdlog/async.h"
#include "spdlog/sinks/stdout_color_sinks.h"
#include "spdlog/sinks/rotating_file_sink.h"

void multi_sink_example2()
{
    spdlog::init_thread_pool(8192, 1);
    auto stdout_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt >();
    auto rotating_sink = std::make_shared<spdlog::sinks::rotating_file_sink_mt>("mylog.txt", 1024*1024*10, 3);
    std::vector<spdlog::sink_ptr> sinks {stdout_sink, rotating_sink};
    auto logger = std::make_shared<spdlog::async_logger>("loggername", sinks.begin(), sinks.end(), spdlog::thread_pool(), spdlog::async_overflow_policy::block);
    spdlog::register_logger(logger);
}

User-defined types

template<>
struct fmt::formatter<my_type> : fmt::formatter<std::string>
{
    auto format(my_type my, format_context &ctx) const -> decltype(ctx.out())
    {
        return fmt::format_to(ctx.out(), "[my_type i={}]", my.i);
    }
};

void user_defined_example()
{
    spdlog::info("user defined type: {}", my_type(14));
}

User-defined flags in the log pattern

// Log patterns can contain custom flags.
// the following example will add new flag '%*' - which will be bound to a <my_formatter_flag> instance.
#include "spdlog/pattern_formatter.h"
class my_formatter_flag : public spdlog::custom_flag_formatter
{
public:
    void format(const spdlog::details::log_msg &, const std::tm &, spdlog::memory_buf_t &dest) override
    {
        std::string some_txt = "custom-flag";
        dest.append(some_txt.data(), some_txt.data() + some_txt.size());
    }

    std::unique_ptr<custom_flag_formatter> clone() const override
    {
        return spdlog::details::make_unique<my_formatter_flag>();
    }
};

void custom_flags_example()
{    
    auto formatter = std::make_unique<spdlog::pattern_formatter>();
    formatter->add_flag<my_formatter_flag>('*').set_pattern("[%n] [%*] [%^%l%$] %v");
    spdlog::set_formatter(std::move(formatter));
}

Custom error handler

void err_handler_example()
{
    // can be set globally or per logger(logger->set_error_handler(..))
    spdlog::set_error_handler([](const std::string &msg) { spdlog::get("console")->error("*** LOGGER ERROR ***: {}", msg); });
    spdlog::get("console")->info("some invalid message to trigger an error {}{}{}{}", 3);
}

syslog

#include "spdlog/sinks/syslog_sink.h"
void syslog_example()
{
    std::string ident = "spdlog-example";
    auto syslog_logger = spdlog::syslog_logger_mt("syslog", ident, LOG_PID);
    syslog_logger->warn("This is warning that will end up in syslog.");
}

Android example

#include "spdlog/sinks/android_sink.h"
void android_example()
{
    std::string tag = "spdlog-android";
    auto android_logger = spdlog::android_logger_mt("android", tag);
    android_logger->critical("Use \"adb shell logcat\" to view this message.");
}

Load log levels from the env variable or argv

#include "spdlog/cfg/env.h"
int main (int argc, char *argv[])
{
    spdlog::cfg::load_env_levels();
    // or specify the env variable name:
    // MYAPP_LEVEL=info,mylogger=trace && ./example
    // spdlog::cfg::load_env_levels("MYAPP_LEVEL");
    // or from the command line:
    // ./example SPDLOG_LEVEL=info,mylogger=trace
    // #include "spdlog/cfg/argv.h" // for loading levels from argv
    // spdlog::cfg::load_argv_levels(argc, argv);
}

So then you can:

$ export SPDLOG_LEVEL=info,mylogger=trace
$ ./example

Log file open/close event handlers

// You can get callbacks from spdlog before/after a log file has been opened or closed. 
// This is useful for cleanup procedures or for adding something to the start/end of the log file.
void file_events_example()
{
    // pass the spdlog::file_event_handlers to file sinks for open/close log file notifications
    spdlog::file_event_handlers handlers;
    handlers.before_open = [](spdlog::filename_t filename) { spdlog::info("Before opening {}", filename); };
    handlers.after_open = [](spdlog::filename_t filename, std::FILE *fstream) { fputs("After opening\n", fstream); };
    handlers.before_close = [](spdlog::filename_t filename, std::FILE *fstream) { fputs("Before closing\n", fstream); };
    handlers.after_close = [](spdlog::filename_t filename) { spdlog::info("After closing {}", filename); };
    auto my_logger = spdlog::basic_logger_st("some_logger", "logs/events-sample.txt", true, handlers);        
}

Replace the Default Logger

void replace_default_logger_example()
{
    auto new_logger = spdlog::basic_logger_mt("new_default_logger", "logs/new-default-log.txt", true);
    spdlog::set_default_logger(new_logger);
    spdlog::info("new logger log message");
}

Log to Qt with nice colors

#include "spdlog/spdlog.h"
#include "spdlog/sinks/qt_sinks.h"
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
    setMinimumSize(640, 480);
    auto log_widget = new QTextEdit(this);
    setCentralWidget(log_widget);
    int max_lines = 500; // keep the text widget to max 500 lines. remove old lines if needed.
    auto logger = spdlog::qt_color_logger_mt("qt_logger", log_widget, max_lines);
    logger->info("Some info message");
}

Mapped Diagnostic Context

// Mapped Diagnostic Context (MDC) is a map that stores key-value pairs (string values) in thread local storage.
// Each thread maintains its own MDC, which loggers use to append diagnostic information to log outputs.
// Note: it is not supported in asynchronous mode due to its reliance on thread-local storage.
#include "spdlog/mdc.h"
void mdc_example()
{
    spdlog::mdc::put("key1", "value1");
    spdlog::mdc::put("key2", "value2");
    // if not using the default format, use the %& formatter to print mdc data
    // spdlog::set_pattern("[%H:%M:%S %z] [%^%L%$] [%&] %v");
}

Benchmarks

Below are some benchmarks done in Ubuntu 64 bit, Intel i7-4770 CPU @ 3.40GHz

Synchronous mode

[info] **************************************************************
[info] Single thread, 1,000,000 iterations
[info] **************************************************************
[info] basic_st         Elapsed: 0.17 secs        5,777,626/sec
[info] rotating_st      Elapsed: 0.18 secs        5,475,894/sec
[info] daily_st         Elapsed: 0.20 secs        5,062,659/sec
[info] empty_logger     Elapsed: 0.07 secs       14,127,300/sec
[info] **************************************************************
[info] C-string (400 bytes). Single thread, 1,000,000 iterations
[info] **************************************************************
[info] basic_st         Elapsed: 0.41 secs        2,412,483/sec
[info] rotating_st      Elapsed: 0.72 secs        1,389,196/sec
[info] daily_st         Elapsed: 0.42 secs        2,393,298/sec
[info] null_st          Elapsed: 0.04 secs       27,446,957/sec
[info] **************************************************************
[info] 10 threads, competing over the same logger object, 1,000,000 iterations
[info] **************************************************************
[info] basic_mt         Elapsed: 0.60 secs        1,659,613/sec
[info] rotating_mt      Elapsed: 0.62 secs        1,612,493/sec
[info] daily_mt         Elapsed: 0.61 secs        1,638,305/sec
[info] null_mt          Elapsed: 0.16 secs        6,272,758/sec

Asynchronous mode

[info] -------------------------------------------------
[info] Messages     : 1,000,000
[info] Threads      : 10
[info] Queue        : 8,192 slots
[info] Queue memory : 8,192 x 272 = 2,176 KB 
[info] -------------------------------------------------
[info] 
[info] *********************************
[info] Queue Overflow Policy: block
[info] *********************************
[info] Elapsed: 1.70784 secs     585,535/sec
[info] Elapsed: 1.69805 secs     588,910/sec
[info] Elapsed: 1.7026 secs      587,337/sec
[info] 
[info] *********************************
[info] Queue Overflow Policy: overrun
[info] *********************************
[info] Elapsed: 0.372816 secs    2,682,285/sec
[info] Elapsed: 0.379758 secs    2,633,255/sec
[info] Elapsed: 0.373532 secs    2,677,147/sec

Documentation

Documentation can be found in the wiki pages.


Powered by

JetBrains logo
View on GitHub

Recent activity

commits and pull requests

Recent open issues

view all

Discussions

all 201

Releases and announcements

45 total
  1. Version 1.17.0v1.17.0Jan 4, 2026

    * Bump bundled {fmt} library to 12.1.0 * Fix the **`%z` formatter** (UTC offset): * Windows: Replaced implementation for better accuracy and speed (~2.5x) by @gabime in https://github.com/gabime/spdlog/pull/3508 * FreeBSD: Fixed incorrect implementation (#3483) by @gabime in https://github.com/gabime/spdlog/pull/3491 * Fixed issue where the offset was not displaying as `+00:00` when the formatter was configured to show UTC time. * Removed unreliable fallback for Unix systems lacking `tm_gmtoff`. If compilation fails on such platforms, use `SPDLOG_NO_TZ_OFFSET=ON` (`%z` will display `+??:??` instead of compilation error). * Set `CMAKE_BUILD_TYPE` only in top-level project by @double-fault in https://github.com/gabime/spdlog/pull/3480 * Change access scope for ANSI `target_file_` from private to protected by @fab4100 in https://github.com/gabime/spdlog/pull/3486 * Fix UWP detection by @jdumas in https://github.com/gabime/spdlog/pull/3489 * Fix include `<fcntl.h>` in `tcp_client.h` to avoid compilation failures by @maordadush in https://github.com/gabime/spdlog/pull/3497 * Tests: Fix unit tests to respect default level names by @ssam18 in https://github.com/gabime/s

  2. version 1.16.0v1.16.0Oct 11, 2025

    * Bump bundled {fmt} library to 12.0.0 * Use std::getenv #3414 by @kfeng123 in https://github.com/gabime/spdlog/pull/3415 * Remove unnecessary and inconsistent "final" from color sinks by @vadz in https://github.com/gabime/spdlog/pull/3430 * Fix ringbuffer sink for zero buffer size by @gabime in https://github.com/gabime/spdlog/pull/3436 * Add option to override CMAKE_DEBUG_POSTFIX by @joshuachp in https://github.com/gabime/spdlog/pull/3433 * Update README.md by @yalov in https://github.com/gabime/spdlog/pull/3437 * Added timeout for TCP calls such as connect, send, recv by @LowLevelLore in https://github.com/gabime/spdlog/pull/3432 * Run tests in the order they are declared by @xvitaly in https://github.com/gabime/spdlog/pull/3451 * Remove the fileapi.h include in os-inl.h by @MasonAngelio in https://github.com/gabime/spdlog/pull/3444 **Full Changelog**: https://github.com/gabime/spdlog/compare/v1.15.3...v1.16.0 Special thanks to @tt4g for assisting with community questions and issues.

  3. Version 1.15.3v1.15.3May 9, 2025

    - Bumped bundled {fmt} library to 11.2.0 by @gabime in [#3399](https://github.com/gabime/spdlog/pull/3399) - Fixed incorrect behavior in `dup_filter_sink` when reporting skipped messages by @SleepingSoul in [#3390](https://github.com/gabime/spdlog/pull/3390) - Fixed MSVC C4530 warning when exceptions are disabled by @roeas in [#3393](https://github.com/gabime/spdlog/pull/3393) - Added support for modifying `max-size` and `max-files` in `rotating_file_sink` after creation by @gabime in [#3397](https://github.com/gabime/spdlog/pull/3397) - Added `spdlog::register_or_replace(new_logger)` to safely replace existing loggers in the registry by @gabime in [#3398](https://github.com/gabime/spdlog/pull/3398) - Fixed broken links to the wiki and local references by @cgringmuth in [#3377](https://github.com/gabime/spdlog/pull/3377) and [#3378](https://github.com/gabime/spdlog/pull/3378), and by @non-descriptive in [#3381](https://github.com/gabime/spdlog/pull/3381) **Full Changelog**: https://github.com/gabime/spdlog/compare/v1.15.2...v1.15.3 Special thanks to @tt4g for assisting with community questions and issues.

  4. Version 1.15.2v1.15.2Mar 29, 2025

    * Upgraded bundled {fmt} to version 11.1.4 ([faa0a7a](https://github.com/gabime/spdlog/commit/faa0a7a9c5a3550ed5461fab7d8e31c37fd1a2ef)) * Fixed [#3360](https://github.com/gabime/spdlog/issues/3360), discovered by OSS-Fuzz regarding the `%D` format flag, in [#3361](https://github.com/gabime/spdlog/pull/3361) * Fixed [#3352](https://github.com/gabime/spdlog/issues/3352): `%z` (UTC offset) on Apple and POSIX.1-2024-conforming platforms by @toh-ableton in [#3366](https://github.com/gabime/spdlog/pull/3366) * Updated README with ALT Linux installation instructions by @lubyagin in [#3338](https://github.com/gabime/spdlog/pull/3338) **Full Changelog**: https://github.com/gabime/spdlog/compare/v1.15.1...v1.15.2 Special thanks to @tt4g for assisting with community questions and issues.

  5. Version 1.15.1v1.15.1Feb 1, 2025

    * Update bundled `fmt` version to 11.1.3 by @gabime in https://github.com/gabime/spdlog/pull/3332 * Use `fwrite_unlocked()` if available by @gabime in https://github.com/gabime/spdlog/pull/3276 and https://github.com/gabime/spdlog/pull/3318 * On-demand truncation for basic file sinks by @matteodelseppia in https://github.com/gabime/spdlog/pull/3280 * Allow manual rotation of `rotating_file_sink` by @hjs-ast in https://github.com/gabime/spdlog/pull/3269 * Make `null_sink` `final` by @gabime in https://github.com/gabime/spdlog/pull/3267 * **Fix:** Add explicit `fmt::` and `std::` to avoid ambiguous calls by @LiAuTraver in https://github.com/gabime/spdlog/pull/3259 * **Fix:** Pass `/utf-8` only when the compiler is MSVC by @miyanyan in https://github.com/gabime/spdlog/pull/3260 * **Fix:** Support `bin_to_hex()` when using `std::format` by @koniarik in https://github.com/gabime/spdlog/pull/3315 * Support custom environment variables for `load_env_levels` by @ken-matsui in https://github.com/gabime/spdlog/pull/3327 * **Fix:** Added a lock to `rotate_now()` by @matteodelseppia in https://github.com/gabime/spdlog/pull/3281 * **Fix:** Update `to_string_view` function for `fmt` 11

Code frequency

additions and deletions
+1.1K-1.1KWeek of 2025-08-03: +1 linesWeek of 2025-08-03: -2 linesWeek of 2025-08-10: +0 linesWeek of 2025-08-10: -0 linesWeek of 2025-08-17: +0 linesWeek of 2025-08-17: -0 linesWeek of 2025-08-24: +0 linesWeek of 2025-08-24: -0 linesWeek of 2025-08-31: +0 linesWeek of 2025-08-31: -0 linesWeek of 2025-09-07: +0 linesWeek of 2025-09-07: -0 linesWeek of 2025-09-14: +0 linesWeek of 2025-09-14: -0 linesWeek of 2025-09-21: +0 linesWeek of 2025-09-21: -0 linesWeek of 2025-09-28: +0 linesWeek of 2025-09-28: -0 linesWeek of 2025-10-05: +1,084 linesWeek of 2025-10-05: -1,019 linesWeek of 2025-10-12: +0 linesWeek of 2025-10-12: -0 linesWeek of 2025-10-19: +0 linesWeek of 2025-10-19: -0 linesWeek of 2025-10-26: +6 linesWeek of 2025-10-26: -2 linesWeek of 2025-11-02: +0 linesWeek of 2025-11-02: -0 linesWeek of 2025-11-09: +6 linesWeek of 2025-11-09: -4 linesWeek of 2025-11-16: +2 linesWeek of 2025-11-16: -1 linesWeek of 2025-11-23: +729 linesWeek of 2025-11-23: -689 linesWeek of 2025-11-30: +1 linesWeek of 2025-11-30: -10 linesWeek of 2025-12-07: +0 linesWeek of 2025-12-07: -0 linesWeek of 2025-12-14: +4 linesWeek of 2025-12-14: -0 linesWeek of 2025-12-21: +2 linesWeek of 2025-12-21: -2 linesWeek of 2025-12-28: +16 linesWeek of 2025-12-28: -9 linesWeek of 2026-01-04: +185 linesWeek of 2026-01-04: -39 linesWeek of 2026-01-11: +35 linesWeek of 2026-01-11: -36 linesWeek of 2026-01-18: +0 linesWeek of 2026-01-18: -0 linesWeek of 2026-01-25: +0 linesWeek of 2026-01-25: -0 linesWeek of 2026-02-01: +0 linesWeek of 2026-02-01: -0 linesWeek of 2026-02-08: +62 linesWeek of 2026-02-08: -4 linesWeek of 2026-02-15: +1 linesWeek of 2026-02-15: -1 linesWeek of 2026-02-22: +196 linesWeek of 2026-02-22: -165 linesWeek of 2026-03-01: +0 linesWeek of 2026-03-01: -0 linesWeek of 2026-03-08: +5 linesWeek of 2026-03-08: -0 linesWeek of 2026-03-15: +1 linesWeek of 2026-03-15: -1 linesWeek of 2026-03-22: +0 linesWeek of 2026-03-22: -0 linesWeek of 2026-03-29: +5 linesWeek of 2026-03-29: -5 linesWeek of 2026-04-05: +7 linesWeek of 2026-04-05: -3 linesWeek of 2026-04-12: +5 linesWeek of 2026-04-12: -6 linesWeek of 2026-04-19: +0 linesWeek of 2026-04-19: -0 linesWeek of 2026-04-26: +0 linesWeek of 2026-04-26: -0 linesWeek of 2026-05-03: +0 linesWeek of 2026-05-03: -0 linesWeek of 2026-05-10: +354 linesWeek of 2026-05-10: -0 linesWeek of 2026-05-17: +0 linesWeek of 2026-05-17: -0 linesWeek of 2026-05-24: +11 linesWeek of 2026-05-24: -0 linesWeek of 2026-05-31: +491 linesWeek of 2026-05-31: -398 linesWeek of 2026-06-07: +152 linesWeek of 2026-06-07: -54 linesWeek of 2026-06-14: +0 linesWeek of 2026-06-14: -0 linesWeek of 2026-06-21: +9 linesWeek of 2026-06-21: -4 linesWeek of 2026-06-28: +0 linesWeek of 2026-06-28: -0 linesWeek of 2026-07-05: +83 linesWeek of 2026-07-05: -2 linesWeek of 2026-07-12: +0 linesWeek of 2026-07-12: -0 linesWeek of 2026-07-19: +4 linesWeek of 2026-07-19: -4 linesWeek of 2026-07-26: +0 linesWeek of 2026-07-26: -0 linesAug 3, 2025Jul 26, 2026
+3.5K lines added, -2.5K removed over the last year.

Commits per week

last 52 weeks
50Week of 2025-08-10: 0 commitsWeek of 2025-08-17: 0 commitsWeek of 2025-08-24: 0 commitsWeek of 2025-08-31: 0 commitsWeek of 2025-09-07: 0 commitsWeek of 2025-09-14: 0 commitsWeek of 2025-09-21: 0 commitsWeek of 2025-09-28: 0 commitsWeek of 2025-10-05: 3 commitsWeek of 2025-10-12: 0 commitsWeek of 2025-10-19: 0 commitsWeek of 2025-10-26: 2 commitsWeek of 2025-11-02: 0 commitsWeek of 2025-11-09: 2 commitsWeek of 2025-11-16: 1 commitsWeek of 2025-11-23: 5 commitsWeek of 2025-11-30: 2 commitsWeek of 2025-12-07: 0 commitsWeek of 2025-12-14: 2 commitsWeek of 2025-12-21: 1 commitsWeek of 2025-12-28: 2 commitsWeek of 2026-01-04: 5 commitsWeek of 2026-01-11: 5 commitsWeek of 2026-01-18: 0 commitsWeek of 2026-01-25: 0 commitsWeek of 2026-02-01: 0 commitsWeek of 2026-02-08: 3 commitsWeek of 2026-02-15: 1 commitsWeek of 2026-02-22: 3 commitsWeek of 2026-03-01: 0 commitsWeek of 2026-03-08: 1 commitsWeek of 2026-03-15: 1 commitsWeek of 2026-03-22: 0 commitsWeek of 2026-03-29: 1 commitsWeek of 2026-04-05: 3 commitsWeek of 2026-04-12: 3 commitsWeek of 2026-04-19: 0 commitsWeek of 2026-04-26: 0 commitsWeek of 2026-05-03: 0 commitsWeek of 2026-05-10: 1 commitsWeek of 2026-05-17: 0 commitsWeek of 2026-05-24: 1 commitsWeek of 2026-05-31: 1 commitsWeek of 2026-06-07: 4 commitsWeek of 2026-06-14: 0 commitsWeek of 2026-06-21: 3 commitsWeek of 2026-06-28: 0 commitsWeek of 2026-07-05: 4 commitsWeek of 2026-07-12: 0 commitsWeek of 2026-07-19: 1 commitsWeek of 2026-07-26: 0 commitsWeek of 2026-08-02: 0 commitsAug 10, 2025Aug 2, 2026
61 commits in the last 52 weeks.

When work happens

weekday and hour
SunMonTueWedThuFriSat036912151821Sun 0:00 — 100 commitsSun 1:00 — 108 commitsSun 2:00 — 59 commitsSun 3:00 — 24 commitsSun 4:00 — 11 commitsSun 5:00 — 20 commitsSun 6:00 — 24 commitsSun 7:00 — 14 commitsSun 8:00 — 5 commitsSun 9:00 — 13 commitsSun 10:00 — 11 commitsSun 11:00 — 10 commitsSun 12:00 — 15 commitsSun 13:00 — 20 commitsSun 14:00 — 16 commitsSun 15:00 — 21 commitsSun 16:00 — 34 commitsSun 17:00 — 49 commitsSun 18:00 — 45 commitsSun 19:00 — 32 commitsSun 20:00 — 28 commitsSun 21:00 — 28 commitsSun 22:00 — 19 commitsSun 23:00 — 27 commitsMon 0:00 — 32 commitsMon 1:00 — 29 commitsMon 2:00 — 23 commitsMon 3:00 — 10 commitsMon 4:00 — 3 commitsMon 5:00 — 2 commitsMon 6:00 — 1 commitsMon 7:00 — 0 commitsMon 8:00 — 2 commitsMon 9:00 — 12 commitsMon 10:00 — 11 commitsMon 11:00 — 22 commitsMon 12:00 — 46 commitsMon 13:00 — 27 commitsMon 14:00 — 30 commitsMon 15:00 — 31 commitsMon 16:00 — 35 commitsMon 17:00 — 27 commitsMon 18:00 — 19 commitsMon 19:00 — 23 commitsMon 20:00 — 14 commitsMon 21:00 — 16 commitsMon 22:00 — 25 commitsMon 23:00 — 31 commitsTue 0:00 — 46 commitsTue 1:00 — 71 commitsTue 2:00 — 39 commitsTue 3:00 — 10 commitsTue 4:00 — 6 commitsTue 5:00 — 1 commitsTue 6:00 — 0 commitsTue 7:00 — 3 commitsTue 8:00 — 6 commitsTue 9:00 — 10 commitsTue 10:00 — 13 commitsTue 11:00 — 8 commitsTue 12:00 — 29 commitsTue 13:00 — 10 commitsTue 14:00 — 22 commitsTue 15:00 — 28 commitsTue 16:00 — 24 commitsTue 17:00 — 24 commitsTue 18:00 — 17 commitsTue 19:00 — 23 commitsTue 20:00 — 20 commitsTue 21:00 — 16 commitsTue 22:00 — 15 commitsTue 23:00 — 33 commitsWed 0:00 — 63 commitsWed 1:00 — 48 commitsWed 2:00 — 16 commitsWed 3:00 — 13 commitsWed 4:00 — 6 commitsWed 5:00 — 2 commitsWed 6:00 — 4 commitsWed 7:00 — 6 commitsWed 8:00 — 7 commitsWed 9:00 — 15 commitsWed 10:00 — 17 commitsWed 11:00 — 9 commitsWed 12:00 — 13 commitsWed 13:00 — 22 commitsWed 14:00 — 22 commitsWed 15:00 — 33 commitsWed 16:00 — 36 commitsWed 17:00 — 28 commitsWed 18:00 — 23 commitsWed 19:00 — 31 commitsWed 20:00 — 11 commitsWed 21:00 — 24 commitsWed 22:00 — 18 commitsWed 23:00 — 28 commitsThu 0:00 — 36 commitsThu 1:00 — 29 commitsThu 2:00 — 16 commitsThu 3:00 — 5 commitsThu 4:00 — 2 commitsThu 5:00 — 0 commitsThu 6:00 — 3 commitsThu 7:00 — 2 commitsThu 8:00 — 9 commitsThu 9:00 — 14 commitsThu 10:00 — 15 commitsThu 11:00 — 11 commitsThu 12:00 — 23 commitsThu 13:00 — 13 commitsThu 14:00 — 22 commitsThu 15:00 — 16 commitsThu 16:00 — 27 commitsThu 17:00 — 23 commitsThu 18:00 — 38 commitsThu 19:00 — 28 commitsThu 20:00 — 21 commitsThu 21:00 — 25 commitsThu 22:00 — 22 commitsThu 23:00 — 24 commitsFri 0:00 — 34 commitsFri 1:00 — 38 commitsFri 2:00 — 25 commitsFri 3:00 — 21 commitsFri 4:00 — 9 commitsFri 5:00 — 1 commitsFri 6:00 — 0 commitsFri 7:00 — 1 commitsFri 8:00 — 6 commitsFri 9:00 — 11 commitsFri 10:00 — 19 commitsFri 11:00 — 16 commitsFri 12:00 — 48 commitsFri 13:00 — 25 commitsFri 14:00 — 55 commitsFri 15:00 — 66 commitsFri 16:00 — 73 commitsFri 17:00 — 67 commitsFri 18:00 — 54 commitsFri 19:00 — 22 commitsFri 20:00 — 22 commitsFri 21:00 — 16 commitsFri 22:00 — 18 commitsFri 23:00 — 30 commitsSat 0:00 — 22 commitsSat 1:00 — 25 commitsSat 2:00 — 19 commitsSat 3:00 — 17 commitsSat 4:00 — 6 commitsSat 5:00 — 1 commitsSat 6:00 — 0 commitsSat 7:00 — 2 commitsSat 8:00 — 2 commitsSat 9:00 — 10 commitsSat 10:00 — 12 commitsSat 11:00 — 32 commitsSat 12:00 — 24 commitsSat 13:00 — 57 commitsSat 14:00 — 43 commitsSat 15:00 — 65 commitsSat 16:00 — 45 commitsSat 17:00 — 56 commitsSat 18:00 — 46 commitsSat 19:00 — 45 commitsSat 20:00 — 36 commitsSat 21:00 — 25 commitsSat 22:00 — 26 commitsSat 23:00 — 25 commits
Commit volume by weekday and hour (UTC). Larger dots mean more commits.

Who is committing

last 52 weeks
Maintainer commits18 (28%)
Community commits46 (72%)

64 commits in total over the last year.

DateListRankStars gained
Aug 6, 2026daily#8+10
Aug 5, 2026daily#8+10
Jul 27, 2026monthly#16+455