Skip to main content

Multi-sink loggers

One logger, several destinations — this is the standard shape for a real application: everything to a file for later inspection, warnings and above to the console for whoever's watching right now.

Constructing one

multi_sink.cpp
std::vector<spdlog::sink_ptr> sinks;

auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
console_sink->set_level(spdlog::level::warn);
sinks.push_back(console_sink);

auto file_sink = std::make_shared<spdlog::sinks::rotating_file_sink_mt>(
"logs/app.log", 1024 * 1024 * 5, 3);
file_sink->set_level(spdlog::level::debug);
sinks.push_back(file_sink);

auto logger = std::make_shared<spdlog::logger>("app", sinks.begin(), sinks.end());
logger->set_level(spdlog::level::debug);
spdlog::register_logger(logger);

Per-sink levels

Each sink filters independently of the others and independently of the logger's own level.

Logger levelSink level
FiltersEvery message, before any sink sees itOnly that sink's output
Order appliedFirstSecond, per sink
Typical useThe loosest level you'll ever want anywhereTighten per destination

In the example above, the logger passes debug and up; the console sink then narrows that further to warn+, while the file sink keeps everything down to debug. The console stays quiet, the file gets everything.

Per-sink patterns

Each sink can have its own set_pattern, independent of the others — a short colored pattern for the console, a full timestamped one for the file:

console_sink->set_pattern("[%^%l%$] %v");
file_sink->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%n] [%l] %v");

See Pattern flags for the full flag reference.

The fan-out

One log call, filtered once by the logger, then filtered and formatted independently by each sink that's still interested.

Cost

Every enabled sink formats the message on its own — there's no shared formatting pass. A logger with five sinks does five separate format operations per log call.

Sinks each run their own formatter — five sinks means five format passes

If profiling shows formatting cost dominating, that cost scales with sink count, not just message volume. Fewer, more targeted sinks (or moving expensive sinks to async) is the usual fix.

See also