Skip to main content

Sink overview

The split of responsibility is deliberate: a logger decides whether to log at all, a sink decides where and how an accepted message ends up. Everything about spdlog's sink family — the built-in ones and the ones you write — follows from that one interface.

The sink interface

class sink {
public:
virtual ~sink() = default;
virtual void log(const spdlog::details::log_msg& msg) = 0;
virtual void flush() = 0;
virtual void set_pattern(const std::string& pattern) = 0;
virtual void set_formatter(std::unique_ptr<spdlog::formatter> sink_formatter) = 0;
};

log receives an already level-checked message; flush forces buffered output out; the two set_pattern/set_formatter calls control how that message is rendered before it's written.

Decision diagram

The _mt / _st suffix

Every built-in sink ships in a mutex-guarded (_mt) and unguarded (_st) flavor — same class, different locking.

_st_mt
Locking costNoneOne mutex lock/unlock per log() call
Safe from multiple threadsNoYes
When to useA logger you've confirmed is single-threadedThe default choice

Sinks are shareable

A sink_ptr (a std::shared_ptr<sink>) can back more than one logger. That's how two independent components write to the same file without interleaving corrupted lines — the mutex lives on the sink, so every writer through it serializes correctly regardless of which logger they came through. See Multi-sink loggers for the construction pattern.

Built-in sink families

FamilyHeaderPage
Consolespdlog/sinks/stdout_color_sinks.hConsole sinks
Filespdlog/sinks/basic_file_sink.hFile sinks
Rotating / dailyspdlog/sinks/rotating_file_sink.h, daily_file_sink.hRotating and daily sinks
Syslog / platformspdlog/sinks/syslog_sink.h and othersSyslog and platform sinks

See also