mirror of
https://github.com/gabime/spdlog.git
synced 2026-06-28 18:57:25 +00:00
Page:
QuickStart
Pages
3. Custom formatting)
Asynchronous logging
CMake
Creating loggers
Custom formatting
Default logger
Error handling
FAQ
Flush policy
Home
How to use spdlog in DLLs
Integrating into Eclipse IDE
Language bindings
Logger registry
Makefile Only
Note for adding sinks on the fly
Preventing child processes from inheriting open log files
Preventing undefined thread ids in child processes
QuickStart
Reference documentation using Doxygen
Setting up JSON logging with spdlog
Sinks
Thread Safety
Tweaking
Windows unicode filenames
Clone
7
QuickStart
estarmel edited this page 2025-04-22 15:38:50 +08:00
Table of Contents
- Basic example
- Create an asynchronous logger using factory method
- Create an asynchronous logger and change thread pool settings
- Create multiple loggers that share the same file (sink) aka categories
- Create a logger with multiple sinks, each sink with its own formatting and log level
- Logging macros
- Log user-defined objects
#include "spdlog/spdlog.h"
int main()
{
//Use the default logger (stdout, multi-threaded, colored)
spdlog::info("Hello, {}!", "World");
}
spdlog provides a python like formatting API using the bundled fmt lib (see the reference):
logger->info("Hello {} {} !!", "param1", 123.4);
spdlog takes the "include what you need" approach - your code should include the features that are actually needed.
For example, if you only need rotating logger, you need to include "spdlog/sinks/rotating_file_sink.h".
Another example would be to include "spdlog/async.h" to get asynchronous logging features.
Basic example
#include <iostream>
#include "spdlog/spdlog.h"
#include "spdlog/sinks/basic_file_sink.h" // support for basic file logging
#include "spdlog/sinks/rotating_file_sink.h" // support for rotating file logging
int main(int, char* [])
{
try
{
// Create basic file logger (not rotated)
auto my_logger = spdlog::basic_logger_mt("basic_logger", "logs/basic.txt");
// create a file rotating logger with 5mb size max and 3 rotated files
auto file_logger = spdlog::rotating_logger_mt("file_logger", "myfilename", 1024 * 1024 * 5, 3);
}
catch (const spdlog::spdlog_ex& ex)
{
std::cout << "Log initialization failed: " << ex.what() << std::endl;
}
}
Create an asynchronous logger using factory method
#include <iostream>
#include "spdlog/spdlog.h"
#include "spdlog/async.h" //support for async logging.
#include "spdlog/sinks/basic_file_sink.h"
int main(int, char* [])
{
try
{
auto async_file = spdlog::basic_logger_mt<spdlog::async_factory>("async_file_logger", "logs/async_log.txt");
for (int i = 1; i < 101; ++i)
{
async_file->info("Async message #{}", i);
}
// Under VisualStudio, this must be called before main finishes to workaround a known VS issue
spdlog::drop_all();
}
catch (const spdlog::spdlog_ex& ex)
{
std::cout << "Log initialization failed: " << ex.what() << std::endl;
}
}
Create an asynchronous logger and change thread pool settings
#include <iostream>
#include "spdlog/spdlog.h"
#include "spdlog/async.h" //support for async logging
#include "spdlog/sinks/basic_file_sink.h"
#include "spdlog/sinks/daily_file_sink.h"
int main(int, char* [])
{
try
{
auto daily_sink = std::make_shared<spdlog::sinks::daily_file_sink_mt>("logfile", 23, 59);
// default thread pool settings can be modified *before* creating the async logger:
spdlog::init_thread_pool(10000, 1); // queue with 10K items and 1 backing thread.
auto async_file = spdlog::basic_logger_mt<spdlog::async_factory>("async_file_logger", "logs/async_log.txt");
spdlog::drop_all();
}
catch (const spdlog::spdlog_ex& ex)
{
std::cout << "Log initialization failed: " << ex.what() << std::endl;
}
}
Create multiple loggers that share the same file (sink) aka categories
#include <iostream>
#include "spdlog/spdlog.h"
#include "spdlog/sinks/daily_file_sink.h"
int main(int, char* [])
{
try
{
auto daily_sink = std::make_shared<spdlog::sinks::daily_file_sink_mt>("logfile", 23, 59);
// create synchronous loggers
auto net_logger = std::make_shared<spdlog::logger>("net", daily_sink);
auto hw_logger = std::make_shared<spdlog::logger>("hw", daily_sink);
auto db_logger = std::make_shared<spdlog::logger>("db", daily_sink);
net_logger->set_level(spdlog::level::critical); // independent levels
hw_logger->set_level(spdlog::level::debug);
// globally register the loggers so they can be accessed using spdlog::get(logger_name)
spdlog::register_logger(net_logger);
}
catch (const spdlog::spdlog_ex& ex)
{
std::cout << "Log initialization failed: " << ex.what() << std::endl;
}
}
Create a logger with multiple sinks, each sink with its own formatting and log level
//
// Logger with console and file output.
// the console will show only warnings or worse, while the file will log all messages.
//
#include <iostream>
#include "spdlog/spdlog.h"
#include "spdlog/sinks/stdout_color_sinks.h" // or "../stdout_sinks.h" if no colors needed
#include "spdlog/sinks/basic_file_sink.h"
int main(int, char* [])
{
try
{
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::sinks_init_list sink_list = { file_sink, console_sink };
spdlog::logger logger("multi_sink", sink_list.begin(), sink_list.end());
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");
// or you can even set multi_sink logger as default logger
spdlog::set_default_logger(std::make_shared<spdlog::logger>("multi_sink", spdlog::sinks_init_list({console_sink, file_sink})));
}
catch (const spdlog::spdlog_ex& ex)
{
std::cout << "Log initialization failed: " << ex.what() << std::endl;
}
}
Logging macros
You can define SPDLOG_ACTIVE_LEVEL to the desired log level before including "spdlog.h".
This will turn on/off logging statements at compile time
#define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_DEBUG
spdlog::set_level(spdlog::level::debug); // or spdlog::set_level(spdlog::level::trace);
SPDLOG_LOGGER_TRACE(file_logger , "Some trace message that will not be evaluated.{} ,{}", 1, 3.23);
SPDLOG_LOGGER_DEBUG(file_logger , "Some Debug message that will be evaluated.. {} ,{}", 1, 3.23);
SPDLOG_DEBUG("Some debug message to default logger that will be evaluated");
Notice that spdlog::set_level is also necessary to print out debug or trace messages.
Log user-defined objects
#include "spdlog/spdlog.h"
#include "spdlog/fmt/ostr.h" // must be included
#include "spdlog/sinks/stdout_sinks.h"
class some_class {};
std::ostream& operator<<(std::ostream& os, const some_class& c)
{
return os << "some_class";
}
// fmt v10 and above requires `fmt::formatter<T>` extends `fmt::ostream_formatter`.
// See: https://github.com/fmtlib/fmt/issues/3318
template <> struct fmt::formatter<some_class> : fmt::ostream_formatter {};
void custom_class_example()
{
some_class c;
auto console = spdlog::stdout_logger_mt("console");
console->info("custom class with operator<<: {}..", c);
}
or use the bundled fmt lib when advanced formatting is needed:
#include <iterator>
#include "spdlog/spdlog.h"
#include "spdlog/fmt/ostr.h" // must be included
#include "spdlog/sinks/stdout_sinks.h"
class some_class {
int code;
};
template<typename OStream>
friend OStream &operator<<(OStream &os, const some_class& to_log)
{
fmt::format_to(std::ostream_iterator<char>(os), "{:04X}", to_log.code);
return os;
}
void custom_class_example()
{
some_class c; c.code = 17;
auto console = spdlog::stdout_logger_mt("console");
console->info("custom class with operator<< using fmt: {}..", c);
}
©gabime 2023-2024 spdlog. All Rights Reserved.