How to Configure spdlog Sinks: A Complete Guide to Console, File, and Async Logging
spdlog sinks are configured by creating std::shared_ptr instances of specific sink types (such as stdout_color_sink_mt or basic_file_sink_mt), setting their individual patterns and log levels, and passing them to an spdlog::logger constructor or using factory helpers like spdlog::stdout_color_mt().
In the gabime/spdlog repository, sinks are the fundamental output drivers that handle where log messages are written. Understanding how to configure spdlog sinks allows you to route logs to multiple destinations simultaneously, each with independent formatting and verbosity settings. This guide covers the exact implementation details found in the spdlog source code, including the specific headers and factory functions you need to build flexible logging pipelines.
Understanding spdlog Sinks and Loggers
A sink in spdlog is any class derived from spdlog::sinks::sink (defined in include/spdlog/sinks/sink.h) that implements the actual write logic. The spdlog::logger class (in include/spdlog/logger.h) holds a collection of sink pointers via std::vector<spdlog::sink_ptr> and forwards formatted log records to each attached sink.
Key architectural points:
- Sinks are shared resources managed via
std::shared_ptr<spdlog::sinks::sink> - Multiple loggers can share the same sink instance
- Each sink maintains its own pattern formatter and log level filter
- Factory functions in
include/spdlog/spdlog.hprovide convenient one-liner setup for common configurations
Step-by-Step Sink Configuration
Choose a Sink Type
Available sink implementations are located under include/spdlog/sinks/:
stdout_color_sink– Colored console output (Windows and POSIX). Header:include/spdlog/sinks/stdout_color_sinks.hbasic_file_sink– Simple file appending. Header:include/spdlog/sinks/basic_file_sink.hrotating_file_sink– Size-based rotation (creates numbered backups). Header:include/spdlog/sinks/rotating_file_sink.hdaily_file_sink– Time-based rotation (new file each day). Header:include/spdlog/sinks/daily_file_sink.hsyslog_sink/systemd_sink– Unix syslog or systemd journal integration
Create and Configure Sink Instances
Instantiate sinks using std::make_shared with the thread-safe _mt (multi-threaded) variants:
auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>("logs/app.log", true);
Configure individual sink behavior using set_pattern() and set_level():
console_sink->set_pattern("%^[%T] %n: %v%$"); // Colored output
console_sink->set_level(spdlog::level::info);
file_sink->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%l] %v");
file_sink->set_level(spdlog::level::debug);
Assemble the Logger
Create a logger with multiple sinks by passing a vector of spdlog::sink_ptr:
std::vector<spdlog::sink_ptr> sinks {console_sink, file_sink};
auto logger = std::make_shared<spdlog::logger>("multi_sink",
sinks.begin(),
sinks.end());
spdlog::register_logger(logger);
Alternatively, use convenience factories for single-sink loggers:
auto logger = spdlog::stdout_color_mt("console_logger");
auto file_logger = spdlog::basic_logger_mt("file_logger", "logs/output.log");
Practical Implementation Examples
Console and File Sinks with Different Log Levels
This example from include/spdlog/sinks/stdout_color_sinks.h and include/spdlog/sinks/basic_file_sink.h demonstrates routing debug messages to file while restricting console output to info and above:
#include <spdlog/spdlog.h>
#include <spdlog/sinks/stdout_color_sinks.h>
#include <spdlog/sinks/basic_file_sink.h>
int main() {
// Create sinks
auto console = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
auto file = std::make_shared<spdlog::sinks::basic_file_sink_mt>("logs/app.log", true);
// Configure individually
console->set_pattern("%^[%T] %n: %v%$");
console->set_level(spdlog::level::info);
file->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%l] %v");
file->set_level(spdlog::level::debug);
// Assemble multi-sink logger
std::vector<spdlog::sink_ptr> sinks{console, file};
auto logger = std::make_shared<spdlog::logger>("app", sinks.begin(), sinks.end());
spdlog::register_logger(logger);
// Usage: debug only appears in file
logger->info("Application started");
logger->debug("Debug details hidden from console");
}
Rotating File Sink Configuration
The rotating_file_sink (in include/spdlog/sinks/rotating_file_sink.h) rotates files when they reach a specified size:
#include <spdlog/spdlog.h>
#include <spdlog/sinks/rotating_file_sink.h>
int main() {
// Rotate at 5 MB, keep 3 archived files
auto rotating = spdlog::rotating_logger_mt("rotating_logger",
"logs/rotating.log",
5 * 1024 * 1024, // 5 MB
3);
rotating->info("This creates rotating.log, rotating.1.log, etc.");
}
Async Logger with Multiple Sinks
For high-performance logging, combine sinks with the async thread pool (defined in include/spdlog/async.h):
#include <spdlog/async.h>
#include <spdlog/sinks/stdout_color_sinks.h>
#include <spdlog/sinks/daily_file_sink.h>
int main() {
// Initialize thread pool: queue size 8192, 1 worker thread
spdlog::init_thread_pool(8192, 1);
// Create sinks
auto console = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
auto daily = std::make_shared<spdlog::sinks::daily_file_sink_mt>("logs/daily.log", 0, 0);
// Build async logger with overflow policy
std::vector<spdlog::sink_ptr> sinks{console, daily};
auto async_logger = std::make_shared<spdlog::async_logger>("async",
sinks.begin(), sinks.end(),
spdlog::thread_pool(),
spdlog::async_overflow_policy::block);
spdlog::register_logger(async_logger);
async_logger->info("Non-blocking async logging initialized");
}
Summary
- Sink Creation: Instantiate concrete sink classes from
include/spdlog/sinks/usingstd::make_sharedwith the_mtsuffix for thread safety. - Individual Configuration: Each sink supports independent
set_pattern()andset_level()calls to control formatting and filtering. - Logger Assembly: Pass sink pointers to
spdlog::loggerconstructors or use factory helpers ininclude/spdlog/spdlog.hfor single-sink setups. - Async Support: Use
spdlog::init_thread_pool()andspdlog::async_logger(frominclude/spdlog/async.h) when combining multiple sinks with asynchronous logging. - Thread Safety: All
_mtsink variants are thread-safe, allowing shared use across multiple loggers and threads.
Frequently Asked Questions
How do I register a custom logger with multiple sinks?
After creating your std::shared_ptr<spdlog::logger> with the desired sinks, call spdlog::register_logger(logger) to make it accessible via spdlog::get("logger_name") throughout your application. This is implemented in include/spdlog/spdlog.h and manages the global logger registry.
Can I share the same sink between multiple loggers?
Yes. Since sinks are held by std::shared_ptr<spdlog::sinks::sink>, you can pass the same sink instance to multiple spdlog::logger constructors. This is useful when you want multiple log categories (e.g., "network" and "database") writing to the same file or console output with identical formatting.
What is the difference between basic_file_sink and rotating_file_sink?
basic_file_sink_mt (in include/spdlog/sinks/basic_file_sink.h) provides simple file appending without size limits. rotating_file_sink_mt (in include/spdlog/sinks/rotating_file_sink.h) automatically archives the current log file when it exceeds a specified size, maintaining a fixed number of backups (e.g., app.log, app.1.log, app.2.log).
How do I configure spdlog sinks to use different log levels for different outputs?
Create separate sink instances and call set_level() on each before attaching them to the logger. For example, set console_sink->set_level(spdlog::level::warn) and file_sink->set_level(spdlog::level::debug). The logger will forward messages to both sinks, but each sink filters independently according to its configured level threshold.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →