Convert Figma logo to code with AI

gabime logospdlog

Fast C++ logging library.

23,832
4,469
23,832
56

Top Related Projects

20,408

A modern formatting library

6,992

C++ implementation of the Google logging module

log4cplus is a simple to use C++ logging API providing thread-safe, flexible, and arbitrarily granular control over log management and configuration. It is modelled after the Java log4j API.

8,063

A C++ library for interacting with JSON.

42,154

JSON for Modern C++

Quick Overview

spdlog is a fast, header-only C++ logging library. It's designed to be very fast, feature-rich, and easy to use. spdlog supports various log targets including console, files, syslog, and custom sinks.

Pros

  • Very fast performance, especially when using asynchronous logging
  • Header-only library, making it easy to integrate into projects
  • Supports various log targets and customizable formatting
  • Thread-safe and provides support for multi/single threaded loggers

Cons

  • Can be complex to set up for advanced use cases
  • Limited built-in support for log rotation (though can be implemented with custom sinks)
  • May have a steeper learning curve for beginners compared to simpler logging libraries

Code Examples

  1. Basic console logging:
#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);
}
  1. Creating a file logger:
#include "spdlog/spdlog.h"
#include "spdlog/sinks/basic_file_sink.h"

int main() {
    auto logger = spdlog::basic_logger_mt("file_logger", "logs/mylogfile.txt");
    logger->info("This message will be written to the file");
    spdlog::info("This message will be written to the console");
}
  1. Using asynchronous logging:
#include "spdlog/async.h"
#include "spdlog/sinks/basic_file_sink.h"

int main() {
    auto async_file = spdlog::basic_logger_mt<spdlog::async_factory>("async_file_logger", "logs/async_log.txt");
    for (int i = 0; i < 100; ++i) {
        async_file->info("Async message #{}", i);
    }
}

Getting Started

To use spdlog in your project, follow these steps:

  1. Download the spdlog repository or use a package manager like vcpkg or Conan.
  2. Include the spdlog headers in your project.
  3. Add the following to your C++ file:
#include "spdlog/spdlog.h"

int main() {
    spdlog::info("Hello, {}!", "World");
    return 0;
}
  1. Compile your project with C++11 or later.

Make sure to link against the necessary threading libraries if you're using asynchronous logging or custom thread pool.

Competitor Comparisons

20,408

A modern formatting library

Pros of fmt

  • More focused on formatting, offering a wider range of formatting options
  • Generally faster performance for string formatting operations
  • Provides a simpler API for basic formatting tasks

Cons of fmt

  • Lacks built-in logging functionality
  • Doesn't include features like asynchronous logging or log rotation
  • May require additional setup for use as a full-fledged logging solution

Code Comparison

fmt:

#include <fmt/core.h>

std::string message = fmt::format("Hello, {}!", name);
fmt::print("Formatted message: {}\n", message);

spdlog:

#include <spdlog/spdlog.h>

spdlog::info("Hello, {}!", name);
spdlog::debug("Formatted message: {}", message);

Summary

fmt is a powerful formatting library that excels in string manipulation and formatting tasks. It offers better performance and a more straightforward API for basic formatting needs. However, spdlog is designed specifically for logging and includes features like asynchronous logging and log rotation out of the box. While fmt can be used for logging, it may require additional setup and doesn't provide the same level of logging-specific functionality as spdlog. The choice between the two depends on whether you need a dedicated logging solution (spdlog) or a more general-purpose formatting library (fmt).

6,992

C++ implementation of the Google logging module

Pros of glog

  • Well-established and widely used in Google projects
  • Supports conditional logging and custom log levels
  • Offers extensive configuration options and flexibility

Cons of glog

  • Heavier and slower compared to spdlog
  • Less actively maintained, with fewer recent updates
  • More complex setup and usage

Code Comparison

spdlog:

#include "spdlog/spdlog.h"

int main() {
    spdlog::info("Welcome to spdlog!");
    spdlog::error("An error message with arg: {}", 42);
}

glog:

#include <glog/logging.h>

int main(int argc, char* argv[]) {
    google::InitGoogleLogging(argv[0]);
    LOG(INFO) << "Welcome to glog!";
    LOG(ERROR) << "An error message with arg: " << 42;
}

Both libraries offer similar functionality, but spdlog has a more modern and streamlined API. glog requires initialization and uses macro-based logging, while spdlog uses a simpler function-based approach. spdlog also provides better support for formatting, making it easier to include variables in log messages.

log4cplus is a simple to use C++ logging API providing thread-safe, flexible, and arbitrarily granular control over log management and configuration. It is modelled after the Java log4j API.

Pros of log4cplus

  • More mature and established project with a longer history
  • Supports a wider range of platforms, including older systems
  • Offers more configuration options and flexibility

Cons of log4cplus

  • Generally slower performance compared to spdlog
  • More complex setup and configuration process
  • Larger codebase and memory footprint

Code Comparison

log4cplus:

#include <log4cplus/logger.h>
#include <log4cplus/loggingmacros.h>

log4cplus::Logger logger = log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("main"));
LOG4CPLUS_INFO(logger, "Hello, World!");

spdlog:

#include "spdlog/spdlog.h"

auto logger = spdlog::stdout_color_mt("console");
logger->info("Hello, World!");

Both libraries provide similar functionality for logging, but spdlog offers a more streamlined and modern API. log4cplus follows a more traditional approach with its configuration and usage patterns.

spdlog is generally preferred for new projects due to its simplicity and performance, while log4cplus might be chosen for its extensive feature set and compatibility with older systems. The choice between the two often depends on specific project requirements and constraints.

8,063

A C++ library for interacting with JSON.

Pros of JsonCpp

  • Specialized for JSON parsing and manipulation
  • Extensive documentation and examples
  • Supports both reader and writer functionality

Cons of JsonCpp

  • Limited to JSON processing, not a general-purpose logging library
  • May have higher memory usage for large JSON structures
  • Less frequent updates compared to spdlog

Code Comparison

spdlog:

#include "spdlog/spdlog.h"

int main() {
    spdlog::info("Welcome to spdlog!");
    spdlog::error("An error message with format: {}", 42);
}

JsonCpp:

#include <json/json.h>

int main() {
    Json::Value root;
    root["message"] = "Welcome to JsonCpp!";
    root["error"] = "An error message with value: 42";
    std::cout << root.toStyledString() << std::endl;
}

Summary

spdlog is a fast logging library for C++, while JsonCpp focuses on JSON parsing and manipulation. spdlog offers broader functionality for general logging purposes, whereas JsonCpp excels in JSON-specific tasks. The choice between them depends on the project's requirements: logging (spdlog) or JSON handling (JsonCpp).

42,154

JSON for Modern C++

Pros of json

  • Extensive JSON manipulation capabilities, including parsing, serialization, and schema validation
  • Header-only library, simplifying integration into projects
  • Supports modern C++ features and idioms, enhancing type safety and ease of use

Cons of json

  • Focused solely on JSON processing, lacking logging functionality
  • May have a steeper learning curve for developers unfamiliar with template metaprogramming

Code Comparison

json:

#include <nlohmann/json.hpp>
using json = nlohmann::json;

json j = {
  {"name", "John Doe"},
  {"age", 30},
  {"city", "New York"}
};
std::string serialized = j.dump();

spdlog:

#include "spdlog/spdlog.h"

spdlog::info("User {} is {} years old and lives in {}",
             "John Doe", 30, "New York");

While json excels at JSON data manipulation, spdlog is designed for efficient logging. json offers powerful JSON processing capabilities but lacks logging features. spdlog provides fast and flexible logging but doesn't handle JSON directly. The choice between them depends on whether your project primarily needs JSON handling or logging functionality.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

spdlog

Very fast, header-only/compiled, C++ logging library. ci  Build status Release

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 .. && make -j

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
  • vcpkg: vcpkg install spdlog
  • conan: spdlog/[>=1.4.1]
  • 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");
}

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 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 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.


Thanks to JetBrains for donating product licenses to help develop spdlog