How to Send Logs to Syslog Using spdlog: A Complete Implementation Guide

spdlog provides a dedicated syslog sink in spdlog/sinks/syslog_sink.h that forwards formatted log messages to the Unix syslog service through the syslog_logger_mt and syslog_logger_st factory functions.

The gabime/spdlog library ships with native Unix syslog integration, allowing you to route application logs directly to the system logger. If you need to send logs to syslog using spdlog, you can leverage the syslog_sink class and its accompanying factory functions to handle openlog initialization and priority mapping automatically.

Understanding the spdlog Syslog Sink Architecture

The syslog implementation follows spdlog’s standard sink architecture defined in include/spdlog/sinks/base_sink.h. According to the gabime/spdlog source code, the syslog_sink class inherits from base_sink<Mutex> and overrides the sink_it_ and flush_ methods to interface with the system ::syslog call.

Key components in include/spdlog/sinks/syslog_sink.h include:

  • syslog_sink: The core sink class that maps spdlog severity levels to syslog priorities using the internal syslog_levels_ array.
  • syslog_logger_mt: A convenience factory that creates a thread-safe logger instance backed by a mutex-protected sink.
  • syslog_logger_st: A factory for single-threaded contexts that uses a null-mutex to eliminate synchronization overhead.

Creating a Syslog Logger in spdlog

To begin sending logs to syslog, include the syslog sink header and instantiate a logger using one of the provided factory functions.

Multi-Threaded Syslog Logger

For applications logging from multiple threads, use the syslog_logger_mt factory. This creates a logger with a mutex-backed sink to prevent race conditions during message emission.

#include <spdlog/spdlog.h>
#include <spdlog/sinks/syslog_sink.h>

int main() {
    // ident: program name, option: LOG_PID, facility: LOG_USER, formatting: disabled
    auto logger = spdlog::syslog_logger_mt("syslog_demo",
                                           "my_app",
                                           LOG_PID,
                                           LOG_USER,
                                           false);

    spdlog::register_logger(logger);
    
    logger->info("Application started");
    logger->error("Failed to open configuration file");
}

Syslog Logger with Custom Formatting

When enable_formatting is set to true, the sink applies your configured pattern formatter before transmitting to syslog. This allows timestamps, thread IDs, and custom layout patterns to appear in system logs.

#include <spdlog/spdlog.h>
#include <spdlog/sinks/syslog_sink.h>
#include <spdlog/pattern_formatter.h>

int main() {
    // Create a formatter with timestamp and thread ID
    auto formatter = std::make_unique<spdlog::pattern_formatter>(
        "%Y-%m-%d %H:%M:%S [%t] %v");

    // Construct sink with formatting enabled
    auto sink = std::make_shared<spdlog::sinks::syslog_sink_mt>(
        "my_app", LOG_PID, LOG_LOCAL0, true);
    sink->set_formatter(std::move(formatter));

    auto logger = std::make_shared<spdlog::logger>("formatted_syslog", sink);
    spdlog::register_logger(logger);

    logger->warn("Custom formatted message");
}

Single-Threaded Variant for Performance

If your application guarantees single-threaded logging, use syslog_logger_st to avoid mutex contention entirely. The _st variant uses a null-mutex template parameter, reducing overhead as implemented in the source.

auto logger = spdlog::syslog_logger_st("single_thread_logger",
                                       "my_app",
                                       LOG_PID,
                                       LOG_LOCAL1,
                                       false);

Configuring Syslog Sink Parameters

The syslog_sink constructor and factory functions accept four critical parameters that control syslog behavior:

  • ident: A string identifier passed to openlog(). If empty, the system defaults to the program name.
  • option: Bitwise flags such as LOG_PID (include PID in messages) or LOG_CONS (write to console on syslog failure).
  • facility: The syslog facility code determining the message category, such as LOG_USER, LOG_DAEMON, or LOG_LOCAL0 through LOG_LOCAL7.
  • enable_formatting: When false, the sink transmits raw log payloads. When true, it processes messages through the attached spdlog formatter before calling ::syslog.

Summary

  • Include spdlog/sinks/syslog_sink.h to access the syslog implementation in gabime/spdlog.
  • Choose syslog_logger_mt for multi-threaded applications or syslog_logger_st for single-threaded performance.
  • Configure the ident, option, and facility parameters to match your system logging requirements.
  • Enable formatting to apply spdlog patterns, or disable it to transmit raw messages to syslog.

Frequently Asked Questions

What header file is required for spdlog syslog support?

You must include <spdlog/sinks/syslog_sink.h> in addition to the main spdlog header. This file defines the syslog_sink class and the syslog_logger_mt and syslog_logger_st factory functions.

How does spdlog map its log levels to syslog priorities?

The syslog_sink class maintains an internal syslog_levels_ array that translates spdlog severity levels (trace, debug, info, warning, error, critical) to their corresponding syslog priority constants (LOG_DEBUG, LOG_INFO, LOG_WARNING, etc.) before calling the system syslog() function.

Can I use custom formatting with the spdlog syslog sink?

Yes. Construct the sink with enable_formatting set to true, then attach a custom pattern_formatter using the set_formatter() method. The sink will apply your pattern before transmitting the message to the syslog service.

Which factory should I use, syslog_logger_mt or syslog_logger_st?

Use syslog_logger_mt when your application logs from multiple threads concurrently, as it uses a std::mutex to protect shared state. Use syslog_logger_st only when logging from a single thread, as it avoids mutex overhead by using a null-mutex implementation, improving performance in single-threaded contexts.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →