Custom formatters
When no built-in pattern flag carries the field you need — a request id, a thread name, a tenant — the supported move is adding your own pattern flag, not stuffing that field into every individual log message by hand.
custom_flag_formatter
class thread_name_flag : public spdlog::custom_flag_formatter {
public:
void format(const spdlog::details::log_msg&, const std::tm&,
spdlog::memory_buf_t& dest) override {
std::string name = current_thread_name(); // your own lookup
dest.append(name.data(), name.data() + name.size());
}
std::unique_ptr<custom_flag_formatter> clone() const override {
return spdlog::details::make_unique<thread_name_flag>(*this);
}
};
Wiring it up
auto f = std::make_unique<spdlog::pattern_formatter>();
f->add_flag<thread_name_flag>('*').set_pattern("[%*] %v");
spdlog::set_formatter(std::move(f));
'*' is the flag character you're choosing to bind — pick one that isn't already a built-in flag (see
Pattern flags for the reserved set).
clone() is not optional
spdlog clones the formatter once per sink so each sink can format independently. If clone() doesn't
copy every piece of state your flag depends on, sinks beyond the first silently format with
default-initialized (often empty or wrong) state — no crash, no warning, just quietly incorrect
output in the second and later sinks.
Replacing the whole formatter
For a wire format that isn't line-oriented at all — say, a fixed binary layout for a metrics
collector — implement spdlog::formatter directly instead of composing pattern flags. That's more
work than custom_flag_formatter, but it's the right tool when the pattern-flag model (a sequence of
fields in a text line) doesn't match what you're producing.
Where formatters live
A formatter can be set per logger or per sink, following the same override rules as patterns — see Multi-sink loggers. Whichever level you set it at, remember it gets cloned once per sink; see Sink overview for how a sink actually consumes its formatter.
See also
- Pattern flags — the built-in flags this extends.
- Custom sinks — the sibling extension point for destinations rather than formatting.
- Source location and structured logging — a concrete use case for a custom flag.
- spdlog overview.