Fast C++ logging library.

spdlog

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

Install

Header only version

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

Static lib 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:

  • Homebrew: brew install spdlog
  • MacPorts: sudo port install spdlog
  • FreeBSD: cd /usr/ports/devel/spdlog/ && make install clean
  • Fedora: dnf install spdlog
  • Gentoo: emerge dev-libs/spdlog
  • Arch Linux: pacman -S spdlog
  • vcpkg: vcpkg install spdlog
  • conan: spdlog/[>=1.4.1]
  • conda: conda install -c conda-forge spdlog

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 debugger (OutputDebugString(..))
    • Easily extendable with custom log targets (just implement a single function in the sink interface).
  • Log filtering - log levels can be modified in runtime as well as in compile time.
  • Support for loading log levels from argv or from environment var.
  • Backtrace support - store debug messages in a ring buffer and display 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
    // define SPDLOG_ACTIVE_LEVEL to desired level
    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 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 5mb 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 on 2:30am
    auto logger = spdlog::daily_logger_mt("daily_logger", "logs/daily.txt", 2, 30);
}

Backtrace support

// Loggers can store in a ring buffer all messages (including debug/trace) and display later on demand.
// When needed, call dump_backtrace() to see them

spdlog::enable_backtrace(32); // Store the latest 32 messages in a buffer. Older messages will be dropped.
// 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 to 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 different format and log level

// create 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");
}

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

// user defined types logging by implementing operator<<
#include "spdlog/fmt/ostr.h" // must be included
struct my_type
{
    int i;
    template<typename OStream>
    friend OStream &operator<<(OStream &os, const my_type &c)
    {
        return os << "[my_type i=" << c.i << "]";
    }
};

void user_defined_example()
{
    spdlog::get("console")->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 env variable or from argv

#include "spdlog/cfg/env.h"
int main (int argc, char *argv[])
{
    spdlog::cfg::load_env_levels();
    // or from 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

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

Comments
  • Provide option to use spdlog as a (static) library

    Provide option to use spdlog as a (static) library

    For a reasonable sized project, the logger is very likely to be all over the place.

    Rebuilding the whole project because an implementation detail changed would be a pain.

    Could we have a compile-time option (eg SPDLOG_LIBRARY or SPDLOG_HEADER_ONLY) that would allow somebody to choose between header-only or precompiled?

    I noticed cppformat uses a similar approach and I'd really appreciate that option.

    I can provide that if you're up for it.

  • Can you comment on this test by the maker of g3log?

    Can you comment on this test by the maker of g3log?

    https://kjellkod.wordpress.com/2015/06/30/the-worlds-fastest-logger-vs-g3log/

    He makes an interesting point that could lead to further optimisation of g3log.

  • spdlog 1.8.5 fails to build with libfmt 8.0.0

    spdlog 1.8.5 fails to build with libfmt 8.0.0

    Trying to build spdlog 1.8.5 with libfmt 8.0.0 fails with this error:

    ninja -v -j5 -l0
    [1/8] /usr/lib/ccache/bin/x86_64-pc-linux-gnu-g++ -DFMT_LOCALE -DFMT_SHARED -DSPDLOG_COMPILED_LIB -DSPDLOG_FMT_EXTERNAL -DSPDLOG_SHARED_LIB -Dspdlog_EXPORTS -I/var/tmp/portage/dev-libs/spdlog-1.8.5/work/spdlog-1.8.5/include  -O2 -march=native -pipe -fuse-linker-plugin -flto -Wl,-flto -ftree-vectorize -falign-functions=32 -fgraphite-identity -floop-nest-optimize -fno-common -fPIC -std=c++11 -MD -MT CMakeFiles/spdlog.dir/src/file_sinks.cpp.o -MF CMakeFiles/spdlog.dir/src/file_sinks.cpp.o.d -o CMakeFiles/spdlog.dir/src/file_sinks.cpp.o -c /var/tmp/portage/dev-libs/spdlog-1.8.5/work/spdlog-1.8.5/src/file_sinks.cpp
    [2/8] /usr/lib/ccache/bin/x86_64-pc-linux-gnu-g++ -DFMT_LOCALE -DFMT_SHARED -DSPDLOG_COMPILED_LIB -DSPDLOG_FMT_EXTERNAL -DSPDLOG_SHARED_LIB -Dspdlog_EXPORTS -I/var/tmp/portage/dev-libs/spdlog-1.8.5/work/spdlog-1.8.5/include  -O2 -march=native -pipe -fuse-linker-plugin -flto -Wl,-flto -ftree-vectorize -falign-functions=32 -fgraphite-identity -floop-nest-optimize -fno-common -fPIC -std=c++11 -MD -MT CMakeFiles/spdlog.dir/src/async.cpp.o -MF CMakeFiles/spdlog.dir/src/async.cpp.o.d -o CMakeFiles/spdlog.dir/src/async.cpp.o -c /var/tmp/portage/dev-libs/spdlog-1.8.5/work/spdlog-1.8.5/src/async.cpp
    [3/8] /usr/lib/ccache/bin/x86_64-pc-linux-gnu-g++ -DFMT_LOCALE -DFMT_SHARED -DSPDLOG_COMPILED_LIB -DSPDLOG_FMT_EXTERNAL -DSPDLOG_SHARED_LIB -Dspdlog_EXPORTS -I/var/tmp/portage/dev-libs/spdlog-1.8.5/work/spdlog-1.8.5/include  -O2 -march=native -pipe -fuse-linker-plugin -flto -Wl,-flto -ftree-vectorize -falign-functions=32 -fgraphite-identity -floop-nest-optimize -fno-common -fPIC -std=c++11 -MD -MT CMakeFiles/spdlog.dir/src/stdout_sinks.cpp.o -MF CMakeFiles/spdlog.dir/src/stdout_sinks.cpp.o.d -o CMakeFiles/spdlog.dir/src/stdout_sinks.cpp.o -c /var/tmp/portage/dev-libs/spdlog-1.8.5/work/spdlog-1.8.5/src/stdout_sinks.cpp
    [4/8] /usr/lib/ccache/bin/x86_64-pc-linux-gnu-g++ -DFMT_LOCALE -DFMT_SHARED -DSPDLOG_COMPILED_LIB -DSPDLOG_FMT_EXTERNAL -DSPDLOG_SHARED_LIB -Dspdlog_EXPORTS -I/var/tmp/portage/dev-libs/spdlog-1.8.5/work/spdlog-1.8.5/include  -O2 -march=native -pipe -fuse-linker-plugin -flto -Wl,-flto -ftree-vectorize -falign-functions=32 -fgraphite-identity -floop-nest-optimize -fno-common -fPIC -std=c++11 -MD -MT CMakeFiles/spdlog.dir/src/color_sinks.cpp.o -MF CMakeFiles/spdlog.dir/src/color_sinks.cpp.o.d -o CMakeFiles/spdlog.dir/src/color_sinks.cpp.o -c /var/tmp/portage/dev-libs/spdlog-1.8.5/work/spdlog-1.8.5/src/color_sinks.cpp
    [5/8] /usr/lib/ccache/bin/x86_64-pc-linux-gnu-g++ -DFMT_LOCALE -DFMT_SHARED -DSPDLOG_COMPILED_LIB -DSPDLOG_FMT_EXTERNAL -DSPDLOG_SHARED_LIB -Dspdlog_EXPORTS -I/var/tmp/portage/dev-libs/spdlog-1.8.5/work/spdlog-1.8.5/include  -O2 -march=native -pipe -fuse-linker-plugin -flto -Wl,-flto -ftree-vectorize -falign-functions=32 -fgraphite-identity -floop-nest-optimize -fno-common -fPIC -std=c++11 -MD -MT CMakeFiles/spdlog.dir/src/cfg.cpp.o -MF CMakeFiles/spdlog.dir/src/cfg.cpp.o.d -o CMakeFiles/spdlog.dir/src/cfg.cpp.o -c /var/tmp/portage/dev-libs/spdlog-1.8.5/work/spdlog-1.8.5/src/cfg.cpp
    [6/8] /usr/lib/ccache/bin/x86_64-pc-linux-gnu-g++ -DFMT_LOCALE -DFMT_SHARED -DSPDLOG_COMPILED_LIB -DSPDLOG_FMT_EXTERNAL -DSPDLOG_SHARED_LIB -Dspdlog_EXPORTS -I/var/tmp/portage/dev-libs/spdlog-1.8.5/work/spdlog-1.8.5/include  -O2 -march=native -pipe -fuse-linker-plugin -flto -Wl,-flto -ftree-vectorize -falign-functions=32 -fgraphite-identity -floop-nest-optimize -fno-common -fPIC -std=c++11 -MD -MT CMakeFiles/spdlog.dir/src/spdlog.cpp.o -MF CMakeFiles/spdlog.dir/src/spdlog.cpp.o.d -o CMakeFiles/spdlog.dir/src/spdlog.cpp.o -c /var/tmp/portage/dev-libs/spdlog-1.8.5/work/spdlog-1.8.5/src/spdlog.cpp
    FAILED: CMakeFiles/spdlog.dir/src/spdlog.cpp.o 
    /usr/lib/ccache/bin/x86_64-pc-linux-gnu-g++ -DFMT_LOCALE -DFMT_SHARED -DSPDLOG_COMPILED_LIB -DSPDLOG_FMT_EXTERNAL -DSPDLOG_SHARED_LIB -Dspdlog_EXPORTS -I/var/tmp/portage/dev-libs/spdlog-1.8.5/work/spdlog-1.8.5/include  -O2 -march=native -pipe -fuse-linker-plugin -flto -Wl,-flto -ftree-vectorize -falign-functions=32 -fgraphite-identity -floop-nest-optimize -fno-common -fPIC -std=c++11 -MD -MT CMakeFiles/spdlog.dir/src/spdlog.cpp.o -MF CMakeFiles/spdlog.dir/src/spdlog.cpp.o.d -o CMakeFiles/spdlog.dir/src/spdlog.cpp.o -c /var/tmp/portage/dev-libs/spdlog-1.8.5/work/spdlog-1.8.5/src/spdlog.cpp
    In file included from /var/tmp/portage/dev-libs/spdlog-1.8.5/work/spdlog-1.8.5/src/spdlog.cpp:9:
    /var/tmp/portage/dev-libs/spdlog-1.8.5/work/spdlog-1.8.5/include/spdlog/common-inl.h: In constructor ‘spdlog::spdlog_ex::spdlog_ex(const string&, int)’:
    /var/tmp/portage/dev-libs/spdlog-1.8.5/work/spdlog-1.8.5/include/spdlog/common-inl.h:63:50: error: cannot convert ‘const string’ {aka ‘const std::__cxx11::basic_string<char>’} to ‘const char*’
       63 |     fmt::format_system_error(outbuf, last_errno, msg);
          |                                                  ^~~
          |                                                  |
          |                                                  const string {aka const std::__cxx11::basic_string<char>}
    In file included from /var/tmp/portage/dev-libs/spdlog-1.8.5/work/spdlog-1.8.5/include/spdlog/fmt/fmt.h:26,
                     from /var/tmp/portage/dev-libs/spdlog-1.8.5/work/spdlog-1.8.5/include/spdlog/common.h:36,
                     from /var/tmp/portage/dev-libs/spdlog-1.8.5/work/spdlog-1.8.5/include/spdlog/spdlog.h:12,
                     from /var/tmp/portage/dev-libs/spdlog-1.8.5/work/spdlog-1.8.5/include/spdlog/spdlog-inl.h:7,
                     from /var/tmp/portage/dev-libs/spdlog-1.8.5/work/spdlog-1.8.5/src/spdlog.cpp:8:
    /usr/include/fmt/format.h:2262:46: note:   initializing argument 3 of ‘void fmt::v7::format_system_error(fmt::v7::detail::buffer<char>&, int, const char*)’
     2262 |                                  const char* message) FMT_NOEXCEPT;
          |                                  ~~~~~~~~~~~~^~~~~~~
    In file included from /var/tmp/portage/dev-libs/spdlog-1.8.5/work/spdlog-1.8.5/include/spdlog/pattern_formatter-inl.h:10,
                     from /var/tmp/portage/dev-libs/spdlog-1.8.5/work/spdlog-1.8.5/src/spdlog.cpp:13:
    /var/tmp/portage/dev-libs/spdlog-1.8.5/work/spdlog-1.8.5/include/spdlog/details/fmt_helper.h: In function ‘void spdlog::details::fmt_helper::pad2(int, spdlog::memory_buf_t&)’:
    /var/tmp/portage/dev-libs/spdlog-1.8.5/work/spdlog-1.8.5/include/spdlog/details/fmt_helper.h:57:23: warning: ‘fmt::v7::appender fmt::v7::format_to(fmt::v7::basic_memory_buffer<char, SIZE, Allocator>&, fmt::v7::format_string<T ...>, T&& ...) [with T = {int&}; long unsigned int SIZE = 250; Allocator = std::allocator<char>; fmt::v7::format_string<T ...> = fmt::v7::basic_format_string<char, int&>]’ is deprecated [-Wdeprecated-declarations]
       57 |         fmt::format_to(dest, "{:02}", n);
          |         ~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~
    In file included from /var/tmp/portage/dev-libs/spdlog-1.8.5/work/spdlog-1.8.5/include/spdlog/fmt/fmt.h:26,
                     from /var/tmp/portage/dev-libs/spdlog-1.8.5/work/spdlog-1.8.5/include/spdlog/common.h:36,
                     from /var/tmp/portage/dev-libs/spdlog-1.8.5/work/spdlog-1.8.5/include/spdlog/spdlog.h:12,
                     from /var/tmp/portage/dev-libs/spdlog-1.8.5/work/spdlog-1.8.5/include/spdlog/spdlog-inl.h:7,
                     from /var/tmp/portage/dev-libs/spdlog-1.8.5/work/spdlog-1.8.5/src/spdlog.cpp:8:
    /usr/include/fmt/format.h:2790:21: note: declared here
     2790 | FMT_DEPRECATED auto format_to(basic_memory_buffer<char, SIZE, Allocator>& buf,
          |                     ^~~~~~~~~
    ninja: build stopped: subcommand failed.
    

    build.log

  • error C2039: 'registry': is not a member of ':spedlog::details'

    error C2039: 'registry': is not a member of ':spedlog::details'

    I recently moved to a new Windows 10 PC and had to reconfigure my environment. Unfortunately I don't have the version of spdlog I was using previously, so I went with the latest available (1.3.1) in vcpkg. I had no issues previously trying to compile.

    The application uses a few other dependencies that are all installed via vcpkg and have no issues compiling, so I don't think it is a referencing problem.

    I am using Visual Studio 2017 with UCRT version 10.0.17134.0.

    These are the errors I am getting:

    1>e:\github\vcpkg\installed\x64-windows\include\spdlog\spdlog.h(55): error C2039: 'registry': is not a member of 'spdlog::details'
    1>e:\github\vcpkg\installed\x64-windows\include\spdlog\details\periodic_worker.h(21): note: see declaration of 'spdlog::details'
    1>e:\github\vcpkg\installed\x64-windows\include\spdlog\spdlog.h(55): error C3083: 'registry': the symbol to the left of a '::' must be a type
    1>e:\github\vcpkg\installed\x64-windows\include\spdlog\spdlog.h(55): error C2039: 'instance': is not a member of 'spdlog::details'
    1>e:\github\vcpkg\installed\x64-windows\include\spdlog\details\periodic_worker.h(21): note: see declaration of 'spdlog::details'
    1>e:\github\vcpkg\installed\x64-windows\include\spdlog\spdlog.h(55): error C3861: 'instance': identifier not found
    1>e:\github\vcpkg\installed\x64-windows\include\spdlog\spdlog.h(61): error C2039: 'registry': is not a member of 'spdlog::details'
    1>e:\github\vcpkg\installed\x64-windows\include\spdlog\details\periodic_worker.h(21): note: see declaration of 'spdlog::details'
    1>e:\github\vcpkg\installed\x64-windows\include\spdlog\spdlog.h(61): error C3083: 'registry': the symbol to the left of a '::' must be a type
    1>e:\github\vcpkg\installed\x64-windows\include\spdlog\spdlog.h(61): error C2039: 'instance': is not a member of 'spdlog::details'
    1>e:\github\vcpkg\installed\x64-windows\include\spdlog\details\periodic_worker.h(21): note: see declaration of 'spdlog::details'
    1>e:\github\vcpkg\installed\x64-windows\include\spdlog\spdlog.h(61): error C3861: 'instance': identifier not found
    
  • Issue with creating a Asynchronous log.

    Issue with creating a Asynchronous log.

    std::shared_ptrspdlog::logger my_logger; my_logger = spdlog::basic_logger_mtspdlog::async_factory("async_file_logger", "logs/async_log.txt");

    Having an issue with the following code. It is just never returning from the basic_logger_mt call. Looks to me like it is somewhere around the thread pool creation. The logger is being created in a dll plugin that is being loaded from the main exe. I thought it might be the windows issue with application deadlock, but this is not happening on exit.

    Any Ideas ?

  • Compile error with VS2017 community

    Compile error with VS2017 community

    When I imported spdlog to my project, it always compiled error with following details you can see below. Could you help me? The head file I included just called #include "spdlog/spdlog.h".

    1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.16.27023\include\algorithm(5386): error C2676: 二进制“<”:“const _Ty”不定义该运算符或到预定义运算符可接收的类型的转换 1> with 1> [ 1> _Ty=std::chrono::durationstd::chrono::system_clock::rep,std::chrono::system_clock::period 1> ] 1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.16.27023\include\algorithm(5385): note: 参见对正在编译的函数 模板 实例化“const _Ty &std::max<std::chrono::durationstd::chrono::system_clock::rep,std::chrono::system_clock::period>(const _Ty &,const _Ty &) noexcept()”的引用 1> with 1> [ 1> _Ty=std::chrono::durationstd::chrono::system_clock::rep,std::chrono::system_clock::period 1> ] 1>xxx\libraries\spdlog-1.x\include\spdlog\details\pattern_formatter-inl.h(872): note: 编译 类 模板 成员函数 "void spdlog::details::elapsed_formatter<Padder,std::chrono::seconds>::format(const spdlog::details::log_msg &,const tm &,spdlog::memory_buf_t &)" 时 1> with 1> [ 1> Padder=spdlog::details::null_scoped_padder 1> ] 1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.16.27023\include\type_traits(616): note: 参见对正在编译的 类 模板 实例化 "spdlog::details::elapsed_formatter<Padder,std::chrono::seconds>" 的引用 1> with 1> [ 1> Padder=spdlog::details::null_scoped_padder 1> ] 1>xxx\libraries\spdlog-1.x\include\spdlog\details\pattern_formatter-inl.h(1203): note: 参见对正在编译的 类 模板 实例化 "std::is_convertible<spdlog::details::elapsed_formatter<Padder,std::chrono::seconds> *,_Ty *>" 的引用 1> with 1> [ 1> Padder=spdlog::details::null_scoped_padder, 1> _Ty=spdlog::details::flag_formatter 1> ]

  • spdlog/fmt/fmt.h triggers assert in libfmt

    spdlog/fmt/fmt.h triggers assert in libfmt

    After either spdlog or libfmt update the OpenRoad FreeBSD port now fails to build:

    In file included from /wrkdirs/usr/ports/cad/openroad/work/OpenROAD-2.0/src/TritonRoute/src/gr/FlexGRCMap.cpp:29:
    In file included from /wrkdirs/usr/ports/cad/openroad/work/OpenROAD-2.0/src/TritonRoute/src/gr/FlexGRCMap.h:37:
    In file included from /wrkdirs/usr/ports/cad/openroad/work/OpenROAD-2.0/src/TritonRoute/src/frBaseTypes.h:41:
    In file included from /wrkdirs/usr/ports/cad/openroad/work/OpenROAD-2.0/src/utl/include/utl/Logger.h:46:
    In file included from /usr/local/include/spdlog/spdlog.h:12:
    In file included from /usr/local/include/spdlog/common.h:36:
    In file included from /usr/local/include/spdlog/fmt/fmt.h:25:
    /usr/local/include/fmt/core.h:1727:3: error: static_assert failed due to requirement 'formattable' "Cannot format an argument. To make type T formattable provide a formatter<T> specialization: https://fmt.dev/latest/api.html#udt"
      static_assert(
      ^
    /usr/local/include/fmt/core.h:1853:23: note: in instantiation of function template specialization 'fmt::v8::detail::make_arg<true, fmt::v8::basic_format_context<fmt::v8::appender, char>, fmt::v8::detail::type::custom_type, const fr::frMinstepTypeEnum &, 0>' requested here
            data_{detail::make_arg<
                          ^
    

    Full log (IPv6 URL).

    It appears that the cause is a version of libfmt bundled with spdlog.

    Such bundling can not work, please remove it.

    Please advise how to fix the port.

    FreeBSD 13

    Thanks.

  • HELP! Do not know how to use a custom sink for logging.

    HELP! Do not know how to use a custom sink for logging.

    Hi, I am trying to create a custom sink that would target Oracle DB. I tried to follow the example of sqlite_lite and it is something I would like to use as format and replace the code to target Oracle DB. (link to sqlite_sink: https://github.com/PedroRod/sqlite_sink/blob/master/sqlite_sink.h)

    Now the issues I am facing are (disclaimer: I am a total newbie at C++)

    1. I do not know how to use the custom sink using a logger. Therefore, how do I create a logger that will use my sink to process the log message and send it to oracle? And where in the code do I create logger that uses my custom sink, in the main code or in the custom sink's header file? I tried the following codes (found it in the wiki) in the main code of the project where I created basic_logger_mt for testing spdlog: auto sink = std::make_sharedspdlog::sinks::oracle_sink(); auto my_logger = std::make_sharedspdlog::logger("mylogger", sink); I cannot test if this creates a logger using my custom sink because of the 2nd issue.

    2. In one of my attempts I received the error in MS VS "spdlog::sinks::oracle_sink': cannot instantiate abstract class". I do not understand why that is happening and I cannot test my sink because of it.

    image

    1. On line 11 of the sqlite_sink example "class sqlite_sink : public sink" is being used whereas the spdlog wiki tells to use "class sqlite_sink : public basic_sink". Which on should I use for my custom function, 'sink' or 'basic_sink'.

    2. I am aiming to use my custom sink to log details from various parts of a large project that contains multiple .cpp files. Therefore, I would also like to know if I have to make any additions to the sqlite_sink sink to make it capable of achieving this.

    Thanks!

    The custom sink I created by customizing the sqlite_sink if anyone wants to take a look at my failure till now

    `using namespace oracle::occi; namespace spdlog { namespace sinks { using namespace oracle::occi; class oracle_sink : public sink { private: Environment *env; Connection *conn; Statement *stmt;

    	public:
    		explicit oracle_sink(const std::string& databaseName)
    		{
    			env = Environment::createEnvironment();
    
    			//createConnection(username, password, connectionstring)
    			conn = env->createConnection(password, login_name, targetdatabase);
    			stmt = conn->createStatement("INSERT INTO EVENT_LOG VALUES (:1, :2, :3, :4, :5, :6, :7, :8)");
    
    
    		}
    
    		~oracle_sink()
    		{
    			conn->terminateStatement(stmt);
    			env->terminateConnection(conn);
    			Environment::terminateEnvironment(env);
    		}
    
    
    		//void bind_to_statement(const details::log_msg& msg) const
    		//{
    		//	//getting time 
    		//	stmt->setTimestamp(1, )
    
    		//		//PID varchar(10 BYTE)
    		//		stmt->setString(2, );
    
    		//	//username varchar(256 BYTE)
    		//	stmt->setString(3, );
    
    		//	//Severity varchar(10 BYTE)
    		//	stmt->setString(4, );
    
    		//	//THREAD_NAME varchar(100 BYTE)
    		//	stmt->setString(5, );
    
    		//	//LOGGER varchar(10BYTE)
    		//	stmt->setString(6, );
    
    		//	//MESSAGE varchar(10BYTE)
    		//	stmt->setString(7, );
    
    		//	//PID CLOB
    		//	stmt->setString(8, );
    
    
    		/*}*/
    
    		void log(const details::log_msg& msg) override
    		{
    			auto time = std::chrono::system_clock::to_time_t(msg.time);
    			char time_str[26];
    			ctime_s(time_str, sizeof(time_str), &time);
    
    			//THREAD_NAME varchar(100 BYTE)
    			stmt->setString(5, time_str);
    
    			stmt->executeUpdate();
    
    			/*sqlite3_reset(_query_stmt);
    			sqlite3_clear_bindings(_query_stmt);*/
    		}
    
    	};
    }
    

    }`

  • A short guide to setting up JSON logging with spdlog

    A short guide to setting up JSON logging with spdlog

    I haven't seen any json examples anywhere with spdlog so I thought I'd share how we did it. It's not hard to have human-readable and json-based machine-readable logs. I've edited this as per @gabime's response below, you don't need to use custom formatters, you can just call set_pattern(...) directly as below.

    
       //Set up the opening brace and an array named "log"
       //we're setting a global format here but as per the docs you can set this on an individual log as well
       spdlog::set_pattern(set_pattern("{\n \"log\": [");
       auto mylogger = spdlog::basic_logger_mt("json_logger", "mylog.json");
       mylogger->info("");//this initializes the log file with the opening brace and the "log" array as above
       //We have some extra formatting on the log level %l below to keep color coding when dumping json to the console and we use a full ISO 8601 time/date format
       std::string jsonpattern = {"{\"time\": \"%Y-%m-%dT%H:%M:%S.%f%z\", \"name\": \"%n\", \"level\": \"%^%l%$\", \"process\": %P, \"thread\": %t, \"message\": \"%v\"},"};
       spdlog::set_pattern(jsonpattern);
    

    Then, log whatever you like as normal, for example:

    
       mylogger->info(“We have started.”);
    

    This will give you a log entry structured like this, although it will all be on one line:

    {
         "time": "2021-01-10T13:44:14.567117-07:00",
         "name": "json_logger",
         "level": "info",
         "process": 6828,
         "thread": 23392,
         "message": "We have started."
    }
    

    You have to make sure yourself whatever you put in your log messages is valid json, you can make those as complex as you need with a complete json object if necessary. Most C++ json libraries have the ability to dump out a std::string that can be parsed as json and can then be passed as an argument to spdlog, or you can just do plain text messages like this example.

    When you're finished logging, you have to close out the "log" array. We also drop the log to clean it up ourselves:

    auto mylogger = spdlog::get("json_logger");
    //All we're doing below is setting the same log format, without the "," at the end
    std::string jsonlastlogpattern = { "{\"time\": \"%Y-%m-%dT%H:%M:%S.%f%z\", \"name\": \"%n\", \"level\": \"%^%l%$\", \"process\": %P, \"thread\": %t, \"message\": \"%v\"}" };
    spdlog::set_pattern(jsonlastlogpattern);
    //below is our last log entry
    mylogger->info("Finished.");
    //set the last pattern to close out the "log" json array and the closing brace
    spdlog::set_pattern("]\n}");
    //this writes out the closed array to the file
    mylogger->info("");
    spdlog::drop("json_logger");
    

    You end up with a log file that looks something like this (our setup and drop is done on a different thread from actual work, hence the different thread ids) :

    {
       "log": [
          {
             "time": "2021-01-10T13:44:14.567117-07:00",
             "name": "json_logger",
             "level": "info",
             "process": 6828,
             "thread": 23392,
             "message": "We have started."
          },
          {
             "time": "2021-01-10T13:44:23.932518-07:00",
             "name": "json_logger",
             "level": "info",
             "process": 6828,
             "thread": 8048,
             "message": "We are doing something."
          },
          {
             "time": "2021-01-10T13:44:26.927726-07:00",
             "name": "json_logger",
             "level": "info",
             "process": 6828,
             "thread": 8048,
             "message": "Look a number 123.456"
          },
          {
             "time": "2021-01-10T13:44:29.631340-07:00",
             "name": "json_logger",
             "level": "info",
             "process": 6828,
             "thread": 23392,
             "message": "Finished."
          }
       ]
    }
    

    You have to watch what minimum log level you have enabled in your compile, if you've disabled "info" then you'll need to use a higher severity to set up the initial json and close it out at the end. We're also going to develop a custom sink based on the new Boost::JSON so we can have a fast, in-memory JSON log as well for real-time processing.

  • Is there a way to cleanly use spdlog after main() (i.e. in static / global objects' destructors)?

    Is there a way to cleanly use spdlog after main() (i.e. in static / global objects' destructors)?

    Hello (and thanks for your work on spdlog),

    Is there an endorsed way of logging from global / static objects' destructors (that is, after main() is done)? Specifically, I want to use a rotating, async logger, and have a static Singleton that's supposed to manage spdlog. The static object's destructor will do a drop_all() and no other objects are supposed to be using spdlog after that.

    I know that the recommended way is to call drop_all() (or shutdown()? I've seen both being recommended, and not together - should I just use one of them? both? if both, I assume drop_all() before shutdown()?).

    Anyway, I'm seeing what appears to me to be the right order of construction and destruction, that is ~thread_pool() and ~registry run after my Singletons' destructors, but I am losing a bunch of messages (pretty much all that's logged after main() doesn't show up - I've tried sleep()s before drop_all() with no success). That doesn't occur when I am using the default stdout spdlog logger.

    Long story short, is there a recommended way to be able to go about achieving this, or is logging after main() just not done under any circumstances? And for debugging, what other spdlog globals should I be watching out for (are there any others, other than registry and thread_pool)?

  • Modify travis-ci, fix compilation issues

    Modify travis-ci, fix compilation issues

    Hey, I got some time and cleaned up travis-ci, as you can see thread sanitizer detected some issues, address sanitizer also reported a leak.

    Current issues:

    • Always building with -O3 (is that really an issue though?)
    • Always building with c++11
    • Valgrind is run on examples only
    • ASAN and TSAN are not run at all

    Possible improvements:

    • Move tsan/asan handling to CMake

    Added:

    • Release/Debug job for gcc 7 and clang 3.5
    • Debug asan gcc 7 job
    • Debug tsan gcc 7 job
    • Disabled extensions
    • Added a spdlog::spdlog alias for tests

    Removed:

    • Valgrind workaround, the current version is 3.10.1
    • install_libcxx
    • Makefiles

    Fixed:

    • examples build ( fixes #783 )
    • multisink build

    Workarounds:

    • gcc7 with tsan and asan needs gold linker, otherwise linking fails becase of unrecognized option '--push-state'
  • C2338: Cannot format an argument. To make type T formattable provide a formatter<T> specialization.

    C2338: Cannot format an argument. To make type T formattable provide a formatter specialization.

    Before I start, I know that this issue already exists. But, I am quite stupid and don't know what to do. I am currently following The Cherno's game engine series and am on the Event System episode.

    This class gives me the error:

    class EventDispatcher
    {
    	template<typename T>
    	using EventFn = std::function<bool(T&)>;
    public:
    	EventDispatcher(Event& event)
    		: m_Event(event)
    	{
    	}
    	
    	template<typename T>
    	bool Dispatch(EventFn<T> func)
    	{
    		if (m_Event.GetEventType() == T::GetStaticType())
    		{
    			m_Event.m_Handled = func(*(T*)&m_Event);
    			return true;
    		}
    		return false;
    	}
    private:
    	Event& m_Event;
    };
    

    Tell me if I need to give more information please.

  • sometimes,export json has bug

    sometimes,export json has bug

    string s = "{\"nlu\":{\"input\":\"suzhou\",\"res\":\"aicar.0.8.16\",\"semantics\":{\"request\":{\"slotcount\":3,\"slots\":[{\"name\":\"intent\",\"value\":\"daohang\"},{\"name\":\"start\",\"pos\":[1,2],\"rawpinyin\":\"su zhou\",\"rawvalue\":\"number\",\"value\":\"suzhou\"},{\"name\":\"destination\",\"pos\":[3,5],\"rawpinyin\":\"bei jing\",\"rawvalue\":\"beijing\",\"value\":\"beijing\"}],\"task\":\"daohang\"}},\"skill\":\"SK_1\",\"skillId\":\"10000000289\",\"systime\":17.782958984375,\"version\":\"2017.2.13.16:38:28\"}}";
    cout << s << endl;
    
    mylog.Logger->info(s);
    

    the cout can print right but logger : [*** LOG ERROR #0001 ***] [2023-01-03 19:21:49] [cdmserver] {unmatched '}' in format string}

  • Daily rotation does not remove oldest files if one day is missing

    Daily rotation does not remove oldest files if one day is missing

    If for any reason one of the old files is missing (e.g., because one day the application has not logged), the oldest file is no more removed. For example, having these files:

    myapp_2022-11-25.log
    myapp_2022-11-24.log
    myapp_2022-11-23.log
    myapp_2022-11-21.log
    myapp_2022-11-20.log
    

    myapp_2022-11-21.log and myapp_2022-11-20.log won't be never deleted.

    This function causes the issue:

    https://github.com/gabime/spdlog/blob/v1.x/include/spdlog/sinks/daily_file_sink.h#L183

    void init_filenames_q_()
    {
        using details::os::path_exists;
    
        filenames_q_ = details::circular_q<filename_t>(static_cast<size_t>(max_files_));
        std::vector<filename_t> filenames;
        auto now = log_clock::now();
        while (filenames.size() < max_files_)
        {
            auto filename = FileNameCalc::calc_filename(base_filename_, now_tm(now));
            if (!path_exists(filename))  // <---------------- stop at the first file missing
            {
                break;
            }
            filenames.emplace_back(filename);
            now -= std::chrono::hours(24);    // <-------- goes backward 24h
        }
        for (auto iter = filenames.rbegin(); iter != filenames.rend(); ++iter)
        {
            filenames_q_.push_back(std::move(*iter));
        }
    }
    

    I guess one fix could be to change the function so that it enumerates the files with the right pattern and remove the oldest one based on the file timestamp.

  • Undefined symbols for architecture x86_64:

    Undefined symbols for architecture x86_64: "___builtin_addcll" on Mac using intel compiler

    I'm trying to compile spdlog with intel oneapi and gnu compiler on different platforms. Here are the results.

    |System|Intel onapi Compiler|Status| |-------|---------|-------| |Linux |icc/icx |Good | |Win10 |icl/icx |Good | |Mac |icc |Fail |

    |System|GNU Compiler|Status| |-------|---------|-------| |Linux |gnu |Good | |Win10 |gnu(mingw64 with msys2) |Good | |Mac |gnu12(homebrew) |Good |

    So only the intel classic compiler on Mac fails. It fails when linking the example

    [1/1] Linking CXX executable example/example
    FAILED: example/example 
    : && /opt/intel/oneapi/compiler/2022.0.0/mac/bin/intel64/icpc -O3 -DNDEBUG -Wl,-search_paths_first -Wl,-headerpad_max_install_names  example/CMakeFiles/example.dir/example.cpp.o -o example/example  libspdlog.a && :
    Undefined symbols for architecture x86_64:
      "___builtin_addcll", referenced from:
          __ZN3fmt2v96detail9dragonbox10to_decimalIdEENS2_10decimal_fpIT_EES5_ in libspdlog.a(bundled_fmtlib_format.cpp.o)
    ld: symbol(s) not found for architecture x86_64
    ninja: build stopped: subcommand failed.
    

    There are also some warnings that I don't see on other platforms, such as this one:

    [8/10] Building CXX object CMakeFiles/spdlog.dir/src/spdlog.cpp.o
    /Users/xcheng/Documents/spdlog/include/spdlog/fmt/bundled/core.h(3055): warning #3924: attribute namespace "clang" is unrecognized
            FMT_FALLTHROUGH;
            ^
              detected during:
                instantiation of "auto fmt::v9::detail::parse_format_specs<T,ParseContext>(ParseContext &)->decltype((<expression>)) [with T=fmt::v9::remove_cvref_t<int &>={int}, ParseContext=fmt::v9::detail::compile_parse_context<fmt::v9::remove_cvref_t<const char &>={char}, fmt::v9::detail::error_handler>]" at line 2954
                instantiation of "fmt::v9::detail::format_string_checker<Char, ErrorHandler, Args...>::format_string_checker(fmt::v9::basic_string_view<Char>, ErrorHandler) [with Char=fmt::v9::remove_cvref_t<const char &>={char}, ErrorHandler=fmt::v9::detail::error_handler, Args=<fmt::v9::remove_cvref_t<int &>={int}>]" at line 3008
                instantiation of "void fmt::v9::detail::check_format_string<Args...,S,<unnamed>>(S) [with Args=<int &>, S=FMT_COMPILE_STRING, <unnamed>=0]" at line 3162
                instantiation of "fmt::v9::basic_format_string<Char, Args...>::basic_format_string(const S &) [with Char=char, Args=<int &>, S=FMT_COMPILE_STRING, <unnamed>=0]" at line 110 of "/Users/xcheng/Documents/spdlog/include/spdlog/details/fmt_helper.h"
    

    Maybe this is intel compiler's problem? I just want to report this and see if anybody can reproduce this problem.

  • Fail to create logger using daily_logger_format_mt()

    Fail to create logger using daily_logger_format_mt()

    I try to create a logger with daily_logger_format_mt(), referencing to daily_filename_format_calculator's annotation in sinks/daily_file_sink.h. But I failed, and error happens when daily_file_sink::file_helper_.open() invoked, which errno = 22.

    My question is: Is it the annotation wrong or my creating method wrong, when using daily_logger_format_mt()?

    My environment:

    • OS Win10x64
    • IDE VS2022 Community

    daily_filename_format_calculator's annotation(from daily_file_sink L44 ):

    /*
     * Generator of daily log file names with strftime format.
     * Usages:
     *    auto sink =  std::make_shared<spdlog::sinks::daily_file_format_sink_mt>("myapp-%Y-%m-%d:%H:%M:%S.log", hour, minute);"
     *    auto logger = spdlog::daily_logger_format_mt("loggername, "myapp-%Y-%m-%d:%X.log", hour,  minute)"
     *
     */
    struct daily_filename_format_calculator
    {...}
    

    My creating case: add this line to daily_example() of example.cpp

    auto logger = spdlog::daily_logger_format_mt("loggername", "logs/myapp-%Y-%m-%d:%X.log", 2, 30);
    

    Console output result (error message):

    ...
    Log initialization failed: Failed opening file myapp-2022-11-04:16:25:57.log for writing: invalid argument
    

    I guess pattern flag "%X" means "%H:%M:%S". But colon(":") is not a valid character for a filename under Window10x64. After I using "%H_%M" instead of ":" , no error happens.

  • [question] When will CMAKE_SYSTEM_NAME be evaluated to

    [question] When will CMAKE_SYSTEM_NAME be evaluated to "CYGWIN" or "MSYS"?

    Problem Description

    I saw this if() statement in the spdlog project.

    if(CMAKE_SYSTEM_NAME MATCHES "CYGWIN" OR CMAKE_SYSTEM_NAME MATCHES "MSYS")
        set(CMAKE_CXX_EXTENSIONS ON)
    endif()
    

    Therefore, I tried to print CMAKE_SYSTEM_NAME when using Cygwin or MSYS compilers. However, it turns out that CMake will print Windows value for both.

    Demonstration

    • Example CMakeLists.txt

      cmake_minimum_required(VERSION 3.20)
      project(cmake-windows LANGUAGES C CXX)
      message("CMAKE_SYSTEM_NAME = ${CMAKE_SYSTEM_NAME}")
      
    • Example CMakePresets.json

      Click to expand
      {
        "version": 5,
        "configurePresets": [
          {
            "name": "msys2-gcc-x64-ninja-debug",
            "displayName": "MSYS2 GCC x64 (Ninja) Debug",
            "description": "Using GCC x64 compiler with \"Ninja\" geneartor on MSYS2 - Debug",
            "generator": "Ninja",
            "binaryDir": "${sourceDir}/build/${presetName}",
            "installDir": "${sourceDir}/install/${presetName}",
            "environment": {
              "PATH": "C:\\msys64\\usr\\bin;$penv{PATH}"
            },
            "cacheVariables": {
              "CMAKE_C_COMPILER": "gcc.exe",
              "CMAKE_CXX_COMPILER": "g++.exe",
              "CMAKE_BUILD_TYPE": "Debug"
            }
          },
          {
            "name": "cygwin-gcc-x64-ninja-debug",
            "displayName": "Cygwin GCC x64 (Ninja) Debug",
            "description": "Using GCC x64 compiler with \"Ninja\" geneartor on Cygwin - Debug",
            "generator": "Ninja",
            "environment": {
              "PATH": "C:\\cygwin64\\bin;$penv{PATH}"
            },
            "binaryDir": "${sourceDir}/build/${presetName}",
            "installDir": "${sourceDir}/install/${presetName}",
            "cacheVariables": {
              "CMAKE_C_COMPILER": "gcc.exe",
              "CMAKE_CXX_COMPILER": "g++.exe",
              "CMAKE_BUILD_TYPE": "Debug"
            }
          }
        ]
      }
      
    • Demo of GCC/MSYS2 compilers

      Click to expand
      F:\GitRepo\cmake-msys-cygwin>cmake --preset msys2-gcc-x64-ninja-debug
      Preset CMake variables:
      
        CMAKE_BUILD_TYPE="Debug"
        CMAKE_CXX_COMPILER="g++.exe"
        CMAKE_C_COMPILER="gcc.exe"
        CMAKE_INSTALL_PREFIX:PATH="F:/GitRepo/cmake-msys-cygwin/install/msys2-gcc-x64-ninja-debug"
      
      Preset environment variables:
      
        PATH="C:\msys64\usr\bin;C:\Python\Python310\Scripts\;C:\Python\Python310\;C:\Program Files\Eclipse Foundation\jdk-8.0.302.8-hotspot\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Program Files\Microsoft VS Code\bin;C:\Program Files\dotnet\;C:\Program Files\CMake\bin;C:\Program Files\Intel\WiFi\bin\;C:\Program Files\Common Files\Intel\WirelessCommon\;C:\Program Files (x86)\gsudo\;C:\Program Files\NASM;C:\Program Files\Git\cmd;C:\Program Files\Typora;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\WINDOWS\System32\OpenSSH\;C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build;C:\Program Files (x86)\Pulse Secure\VC142.CRT\X64\;C:\Program Files (x86)\Pulse Secure\VC142.CRT\X86\;C:\Program Files (x86)\Common Files\Pulse Secure\TNC Client Plugin\;C:\Program Files\MySQL\MySQL Server 8.0\bin;C:\Program Files\MySQL\MySQL Shell 8.0\bin\;C:\Users\hwhsu1231\AppData\Local\Microsoft\WindowsApps;C:\Users\hwhsu1231\.dotnet\tools;"
      
      -- The C compiler identification is GNU 11.3.0
      -- The CXX compiler identification is GNU 11.3.0
      -- Detecting C compiler ABI info
      -- Detecting C compiler ABI info - done
      -- Check for working C compiler: C:/msys64/usr/bin/gcc.exe - skipped
      -- Detecting C compile features
      -- Detecting C compile features - done
      -- Detecting CXX compiler ABI info
      -- Detecting CXX compiler ABI info - done
      -- Check for working CXX compiler: C:/msys64/usr/bin/g++.exe - skipped
      -- Detecting CXX compile features
      -- Detecting CXX compile features - done
      CMAKE_SYSTEM_NAME = Windows
      -- Configuring done
      -- Generating done
      -- Build files have been written to: F:/GitRepo/cmake-msys-cygwin/build/msys2-gcc-x64-ninja-debug
      
    • Demo of GCC/Cygwin compilers

      Click to expand
      F:\GitRepo\cmake-msys-cygwin>cmake --preset cygwin-gcc-x64-ninja-debug 
      Preset CMake variables:
      
        CMAKE_BUILD_TYPE="Debug"
        CMAKE_CXX_COMPILER="g++.exe"
        CMAKE_C_COMPILER="gcc.exe"
        CMAKE_INSTALL_PREFIX:PATH="F:/GitRepo/cmake-msys-cygwin/install/cygwin-gcc-x64-ninja-debug"
      
      Preset environment variables:
      
        PATH="C:\cygwin64\bin;C:\Python\Python310\Scripts\;C:\Python\Python310\;C:\Program Files\Eclipse Foundation\jdk-8.0.302.8-hotspot\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Program Files\Microsoft VS Code\bin;C:\Program Files\dotnet\;C:\Program Files\CMake\bin;C:\Program Files\Intel\WiFi\bin\;C:\Program Files\Common Files\Intel\WirelessCommon\;C:\Program Files (x86)\gsudo\;C:\Program Files\NASM;C:\Program Files\Git\cmd;C:\Program Files\Typora;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\WINDOWS\System32\OpenSSH\;C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build;C:\Program Files (x86)\Pulse Secure\VC142.CRT\X64\;C:\Program Files (x86)\Pulse Secure\VC142.CRT\X86\;C:\Program Files (x86)\Common Files\Pulse Secure\TNC Client Plugin\;C:\Program Files\MySQL\MySQL Server 8.0\bin;C:\Program Files\MySQL\MySQL Shell 8.0\bin\;C:\Users\hwhsu1231\AppData\Local\Microsoft\WindowsApps;C:\Users\hwhsu1231\.dotnet\tools;"
      
      -- The C compiler identification is GNU 11.3.0
      -- The CXX compiler identification is GNU 11.3.0
      -- Detecting C compiler ABI info
      -- Detecting C compiler ABI info - done
      -- Check for working C compiler: C:/cygwin64/bin/gcc.exe - skipped
      -- Detecting C compile features
      -- Detecting C compile features - done
      -- Detecting CXX compiler ABI info
      -- Detecting CXX compiler ABI info - done
      -- Check for working CXX compiler: C:/cygwin64/bin/g++.exe - skipped
      -- Detecting CXX compile features
      -- Detecting CXX compile features - done
      CMAKE_SYSTEM_NAME = Windows
      -- Configuring done
      -- Generating done
      -- Build files have been written to: F:/GitRepo/cmake-msys-cygwin/build/cygwin-gcc-x64-ninja-debug
      
Reckless logging. Low-latency, high-throughput, asynchronous logging library for C++.
Reckless logging. Low-latency, high-throughput, asynchronous logging library for C++.

Introduction Reckless is an extremely low-latency, high-throughput logging library. It was created because I needed to perform extensive diagnostic lo

Dec 20, 2022
Colorful Logging is a simple and efficient library allowing for logging and benchmarking.
Colorful Logging is a simple and efficient library allowing for  logging and benchmarking.

Colorful-Logging "Colorful Logging" is a library allowing for simple and efficient logging as well for benchmarking. What can you use it for? -Obvious

Feb 17, 2022
Fast C++ logging library.

spdlog Very fast, header-only/compiled, C++ logging library. Install Header only version Copy the source folder to your build tree and use a C++11 com

Jan 1, 2023
A Fast and Convenient C++ Logging Library for Low-latency or Real-time Environments

xtr What is it? XTR is a C++ logging library aimed at applications with low-latency or real-time requirements. The cost of log statements is minimised

Jul 17, 2022
Yet another logging library.

Blackhole - eating your logs with pleasure Blackhole is an attribute-based logger with strong focus on gaining maximum performance as possible for suc

Dec 20, 2022
A lightweight C++ logging library
A lightweight C++ logging library

Loguru: a lightweight and flexible C++ logging library. At a glance Documentation Documentation can be found at https://emilk.github.io/loguru/index.h

Jan 7, 2023
Portable, simple and extensible C++ logging library
Portable, simple and extensible C++ logging library

Plog - portable, simple and extensible C++ logging library Pretty powerful logging library in about 1000 lines of code Introduction Hello log! Feature

Dec 29, 2022
Asynchronous Low Latency C++ Logging Library

Quill Asynchronous Low Latency C++ Logging Library Introduction Features Performance Supported Platforms And Compilers Basic Usage CMake Integration D

Dec 20, 2022
Cute Log is a C++ Library that competes to be a unique logging tool.

Cute Log Cute Log is a C++ Library that competes to be a unique logging tool. Version: 2 Installation Click "Code" on the main repo page (This one.).

Oct 13, 2022
fmtlog is a performant fmtlib-style logging library with latency in nanoseconds.

fmtlog fmtlog is a performant asynchronous logging library using fmt library format. Features Faster - lower runtime latency than NanoLog and higher t

Jan 6, 2023
Minimalistic logging library with threads and manual callstacks

Minimalistic logging library with threads and manual callstacks

Dec 5, 2022
logog is a portable C++ library to facilitate logging of real-time events in performance-oriented applications

logog is a portable C++ library to facilitate logging of real-time events in performance-oriented applications, such as games. It is especially appropriate for projects that have constrained memory and constrained CPU requirements.

Oct 21, 2020
Boost Logging library

Boost.Log, part of collection of the Boost C++ Libraries, provides tools for adding logging to libraries and applications. Directories build - Boost.L

Dec 22, 2022
C++ implementation of the Google logging module

Google Logging Library The Google Logging Library (glog) implements application-level logging. The library provides logging APIs based on C++-style st

Jan 9, 2023
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.

% log4cplus README Short Description log4cplus is a simple to use C++17 logging API providing thread--safe, flexible, and arbitrarily granular control

Jan 4, 2023
Uberlog - Cross platform multi-process C++ logging system

uberlog uberlog is a cross platform C++ logging system that is: Small Fast Robust Runs on Linux, Windows, OSX MIT License Small Two headers, and three

Sep 29, 2022
Fast binary logger for C++
Fast binary logger for C++

Highlights Logs messages in a compact binary format Fast Hundreds of millions of logs per second Average latency of 2-7 ns for basic data types See be

Dec 23, 2022
Reckless logging. Low-latency, high-throughput, asynchronous logging library for C++.
Reckless logging. Low-latency, high-throughput, asynchronous logging library for C++.

Introduction Reckless is an extremely low-latency, high-throughput logging library. It was created because I needed to perform extensive diagnostic lo

Dec 20, 2022