Skip to main content

The registry

The registry is a global nameโ†’logger map. It's what makes spdlog::get("db") work from any file in your program without threading a reference through every function call, and it's also what makes shutdown order matter โ€” everything registered has to be torn down, and torn down in a sane order, before the process exits.

What lives in itโ€‹

Any logger created through a factory helper (stdout_color_mt, basic_logger_mt, etc.), plus anything you explicitly pass to spdlog::register_logger(...). The default logger โ€” the one behind spdlog::info(...) โ€” lives here too, under the name "".

Looking upโ€‹

auto logger = spdlog::get("db");
if (logger) {
logger->info("query took {}ms", elapsed_ms);
}
spdlog::get returns nullptr, it does not throw โ€” check it

A typo'd or not-yet-created logger name silently returns nullptr from spdlog::get. Dereferencing that is a crash, and it's a crash that only shows up once, at the log call site that happens to run first โ€” always check before use.

The default loggerโ€‹

spdlog::default_logger() returns the logger behind the free functions (spdlog::info, spdlog::warn, ...). spdlog::set_default_logger(...) replaces it โ€” useful for redirecting every unqualified log call to a file or a multi-sink logger without touching call sites.

auto file_logger = spdlog::basic_logger_mt("main_file", "logs/app.log");
spdlog::set_default_logger(file_logger);

spdlog::info("this now goes to logs/app.log"); // no call-site changes needed

The old default logger is simply replaced โ€” if nothing else holds a shared_ptr to it, it's destroyed once the swap happens.

Global operationsโ€‹

spdlog::set_level(...), spdlog::set_pattern(...), spdlog::flush_on(...), and spdlog::apply_all(fn) all iterate the registry and apply to every logger in it.

An unregistered logger is invisible to every global setter

A logger built with explicit construction and never passed to register_logger won't be touched by spdlog::set_level, spdlog::apply_all, or any other registry-wide call โ€” you have to configure it directly.

Automatic registrationโ€‹

If you're writing library code, spdlog::set_automatic_registration(false) stops the factory helpers from adding new loggers to the registry.

Libraries should not register loggers into the host application's registry

A registered logger from your library can collide by name with one the application creates, and it shows up in the application's apply_all calls whether the application wants it to or not. Disable automatic registration, or better, let the application pass you a logger instead of creating your own.

Droppingโ€‹

spdlog::drop(name) removes one logger from the registry; spdlog::drop_all() removes every one. Neither destroys the logger immediately if something else still holds a shared_ptr to it โ€” dropping only removes the registry's reference. See Logger lifecycle for what that means for shutdown ordering.

See alsoโ€‹