Integrating spdlog with syslog: A Complete Guide to the Syslog Sink
spdlog ships with a dedicated syslog sink that forwards log records to the native POSIX syslog(3) service, implemented in include/spdlog/sinks/syslog_sink.h.
Integrating spdlog with the system syslog daemon allows applications to leverage centralized logging infrastructure on Linux and Unix systems. The gabime/spdlog repository provides a template-based syslog_sink class that handles all POSIX syslog API calls, including openlog, syslog, and closelog, while translating spdlog severity levels to standard syslog priorities.
Understanding the syslog_sink Architecture
The core of spdlog syslog integration resides in the syslog_sink template class defined in include/spdlog/sinks/syslog_sink.h. This sink extends base_sink<Mutex> and manages the lifecycle of the native syslog connection.
Template Structure and Thread Safety
The sink uses a mutex template parameter to control concurrency:
syslog_sink_mt→syslog_sink<std::mutex>for multithreaded applicationssyslog_sink_st→syslog_sink<details::null_mutex>for single-threaded contexts with zero overhead
The constructor accepts three critical parameters: an ident string (the program name appearing in syslog entries), option flags (such as LOG_PID to include the process ID), and a facility code (like LOG_USER or LOG_LOCAL0).
POSIX syslog Integration
When instantiated, the sink immediately calls ::openlog to establish the connection to the syslog daemon. Each log message passes through the following flow:
- The base sink formats the message using the configured pattern
- The sink maps
spdlog::levelvalues (info, warn, error) to correspondingLOG_*priorities - The formatted string is forwarded to
::syslog - Upon destruction,
::closelogreleases system resources
Configuring syslog_logger Factory Helpers
Rather than manually constructing sinks, use the convenience factory functions exposed in the public API. These helpers instantiate a logger that owns a syslog_sink and automatically register it in spdlog's global registry.
Multithreaded factory:
auto logger = spdlog::syslog_logger_mt("syslog", "my-app", LOG_PID, LOG_USER);
Single-threaded factory:
auto logger = spdlog::syslog_logger_st("syslog_st", "my-app", LOG_PID);
After registration, retrieve the logger anywhere in your application using spdlog::get("syslog").
Practical Implementation Examples
Basic Single-Sink Setup
Create a dedicated syslog logger with the default thread-safe configuration:
#include "spdlog/spdlog.h"
#include "spdlog/sinks/syslog_sink.h"
int main()
{
// ident = program name, LOG_PID adds the PID, LOG_USER is the facility
auto syslog_logger = spdlog::syslog_logger_mt("syslog", "my-app", LOG_PID, LOG_USER);
syslog_logger->info("Application started");
syslog_logger->warn("Low-level warning");
syslog_logger->error("An error occurred: {}", std::strerror(errno));
}
Multi-Sink Configuration (Console + Syslog)
Combine stdout output with system logging by constructing multiple sinks and passing them to a single logger:
#include "spdlog/spdlog.h"
#include "spdlog/sinks/stdout_color_sinks.h"
#include "spdlog/sinks/syslog_sink.h"
int main()
{
auto console = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
console->set_level(spdlog::level::info);
console->set_pattern("[%l] %v");
auto syslog = std::make_shared<spdlog::sinks::syslog_sink_mt>("my-app", LOG_PID);
syslog->set_level(spdlog::level::warn); // only warnings+ go to syslog
spdlog::logger logger("dual", {console, syslog});
logger.set_level(spdlog::level::debug);
logger.debug("Debug message – stays on console only");
logger.warn("Warning – appears on console and syslog");
}
Single-Threaded Optimization
For performance-critical single-threaded applications, eliminate mutex overhead by using the _st variant:
auto syslog_logger = spdlog::syslog_logger_st("syslog_st", "my-app", LOG_PID);
syslog_logger->info("Running in a single-threaded context");
Advanced Configuration Options
Formatting Control with enable_formatting
By default, syslog_sink forwards formatted text to the syslog daemon. Set enable_formatting to false to send raw message templates (including % placeholders), allowing the external syslog service to handle interpolation:
auto syslog = std::make_shared<spdlog::sinks::syslog_sink_mt>("my-app", LOG_PID);
syslog->enable_formatting = false; // Sends raw format string to syslog
This is useful when the syslog daemon performs structured parsing or custom formatting of log entries.
Summary
- Primary Header: All syslog functionality resides in
include/spdlog/sinks/syslog_sink.hwithin thegabime/spdlogrepository. - Thread Safety: Choose between
syslog_sink_mt(thread-safe) andsyslog_sink_st(lock-free) based on your concurrency requirements. - Factory Methods: Use
spdlog::syslog_logger_mt()orspdlog::syslog_logger_st()to create and register loggers automatically. - POSIX Mapping: The sink handles translation between
spdlog::levelenums and standardLOG_*priorities, managingopenlog,syslog, andcloselogcalls internally. - Flexible Output: Combine the syslog sink with other sinks (stdout, file) to create multi-target logging strategies with independent level filtering.
Frequently Asked Questions
What is the difference between syslog_sink_mt and syslog_sink_st?
syslog_sink_mt uses std::mutex to protect shared resources, making it safe for concurrent access from multiple threads. syslog_sink_st uses details::null_mutex, which compiles to no-ops and provides higher performance in single-threaded applications where synchronization is unnecessary.
How do I prevent duplicate logs when using multiple sinks?
Configure severity level filtering on individual sinks rather than the logger. Set the syslog sink to a higher threshold (e.g., spdlog::level::warn) while keeping the console sink at debug or info. This ensures only warnings and errors reach the system log while verbose output remains local.
Can I use custom syslog facilities like LOG_LOCAL0?
Yes. The third parameter to the syslog_sink constructor or factory function accepts any valid POSIX facility constant, including LOG_LOCAL0 through LOG_LOCAL7, LOG_DAEMON, LOG_AUTH, or LOG_SYSLOG. These facilities route messages to specific system log files based on your syslog daemon configuration.
Does spdlog's syslog sink work on Windows?
No. The syslog_sink implementation relies exclusively on POSIX syslog(3) APIs (openlog, syslog, closelog), which are not available on Windows. For Windows Event Log integration, use the msvc_sink or implement a custom sink using the Windows Event Logging API.
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 →