# How to Register and Retrieve Loggers by Name in spdlog

> Learn to register and retrieve loggers by name in spdlog. Discover how spdlog's global registry simplifies centralized logger management for your C++ applications.

- Repository: [Gabi Melman/spdlog](https://github.com/gabime/spdlog)
- Tags: how-to-guide
- Published: 2026-07-22

---

**spdlog maintains a thread‑safe global registry that maps logger names to `std::shared_ptr<spdlog::logger>` instances, providing `spdlog::register_logger()`, `spdlog::register_or_replace()`, and `spdlog::get()` for centralized logger management.**

The gabime/spdlog library implements a singleton registry pattern that enables you to register and retrieve loggers by name throughout your application. This architecture, defined in [`include/spdlog/details/registry.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/details/registry.h), stores loggers in an internal `std::unordered_map` protected by a mutex, ensuring safe concurrent access while allowing you to share logging instances across modules using string identifiers.

## Understanding the Logger Registry Architecture

At the core of spdlog's naming system is the `spdlog::details::registry` class, implemented across [`include/spdlog/details/registry.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/details/registry.h) and [`registry-inl.h`](https://github.com/gabime/spdlog/blob/main/registry-inl.h). The registry maintains a private `std::unordered_map<std::string, std::shared_ptr<logger>> loggers_` that serves as the authoritative lookup table for all named loggers.

You interact with this singleton through public API functions declared in [`include/spdlog/spdlog.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/spdlog.h). The registry instance is acquired via `spdlog::details::registry::instance()`, though you typically call the wrapper functions directly rather than accessing the singleton yourself.

## How to Register Loggers by Name

### Automatic Registration via Factory Functions

When you create a logger using `spdlog::create<>` (or convenience functions like `spdlog::basic_logger_mt`), spdlog automatically registers the new instance if the `automatic_registration_` flag is enabled (default: **true**). This behavior is controlled by `spdlog::set_automatic_registration(bool)`.

```cpp
// Automatically registered under the name "file_log"
auto file_logger = spdlog::create<spdlog::sinks::basic_file_sink_mt>("file_log", "application.log");

```

### Manual Registration with register_logger

For loggers constructed manually or received from external sources, use **`spdlog::register_logger()`**. This function forwards to `registry::register_logger`, which inserts the shared pointer into the internal map.

```cpp
auto custom_logger = std::make_shared<spdlog::logger>("network_logger",
    std::make_shared<spdlog::sinks::stdout_color_sink_mt>());
spdlog::register_logger(custom_logger);  // Throws spdlog_ex if name exists

```

**Critical behavior**: If a logger with the same name already exists, `register_logger` throws a `spdlog_ex` exception. Always use this method when you want to ensure no accidental overwrites occur.

### Replacing Existing Loggers with register_or_replace

To overwrite an existing logger without handling exceptions, call **`spdlog::register_or_replace()`**. This invokes `registry::register_or_replace`, which updates the map entry regardless of whether the name already exists.

```cpp
auto new_logger = std::make_shared<spdlog::logger>("network_logger",
    std::make_shared<spdlog::sinks::stderr_sink_mt>());
spdlog::register_or_replace(new_logger);  // Silently replaces previous "network_logger"

```

## How to Retrieve Loggers by Name

To obtain a registered logger, use **`spdlog::get("logger_name")`**, which returns the result of `registry::instance().get(name)`. The function looks up the name in the internal map and returns a `std::shared_ptr<spdlog::logger>` or `nullptr` if the name is not found.

```cpp
// Retrieve and use
if (auto logger = spdlog::get("network_logger")) {
    logger->info("Connection established");
}

// Safe retrieval with null check
auto maybe_logger = spdlog::get("unknown_logger");
if (!maybe_logger) {
    spdlog::error("Logger not found in registry");
}

```

## Thread Safety and Concurrent Access

The spdlog registry guarantees thread safety for all public operations through a private **`std::mutex logger_map_mutex_`**. Whether you are registering, replacing, or retrieving loggers by name, the internal mutex ensures safe concurrent access from multiple threads.

This means you can safely call `spdlog::get()` from worker threads while the main thread registers new loggers, without implementing additional synchronization in your application code.

## Practical Code Examples

```cpp
#include <spdlog/spdlog.h>
#include <spdlog/sinks/basic_file_sink.h>
#include <spdlog/sinks/stdout_color_sinks.h>

void setup_logging() {
    // 1. Create and auto-register a file logger
    auto file_logger = spdlog::create<spdlog::sinks::basic_file_sink_mt>(
        "file_log", "logs.txt");
    
    // 2. Manual registration of a custom configured logger
    auto custom_logger = std::make_shared<spdlog::logger>("my_logger",
        std::make_shared<spdlog::sinks::stdout_color_sink_mt>());
    spdlog::register_logger(custom_logger);
    
    // 3. Replace an existing logger (no exception thrown)
    auto new_logger = std::make_shared<spdlog::logger>("my_logger",
        std::make_shared<spdlog::sinks::stderr_sink_mt>());
    spdlog::register_or_replace(new_logger);
    
    // 4. Retrieve by name and log
    if (auto logger = spdlog::get("my_logger")) {
        logger->info("Hello from {}", logger->name());
    }
    
    // 5. Handle missing loggers safely
    auto unknown = spdlog::get("nonexistent");
    if (!unknown) {
        spdlog::error("Logger not registered");
    }
}

```

## Summary

- **spdlog uses a singleton registry** (`spdlog::details::registry`) to manage a global map of named loggers, implemented in [`include/spdlog/details/registry.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/details/registry.h).
- **Register loggers** using `spdlog::register_logger()` (throws on duplicates) or `spdlog::register_or_replace()` (overwrites existing).
- **Retrieve loggers** using `spdlog::get("name")`, which returns a `shared_ptr` or `nullptr` if the name is not found.
- **Automatic registration** occurs by default when using `spdlog::create<>`, but can be disabled via `spdlog::set_automatic_registration(false)`.
- **All registry operations are thread-safe**, protected by an internal mutex allowing concurrent registration and retrieval across threads.

## Frequently Asked Questions

### What happens if I try to register a logger with a name that already exists?

Calling `spdlog::register_logger()` throws a `spdlog_ex` exception if the name is already present in the registry. To avoid this, use `spdlog::register_or_replace()`, which silently overwrites the existing entry with the new logger instance.

### How do I disable automatic registration when creating loggers?

Call `spdlog::set_automatic_registration(false)` before using factory functions like `spdlog::create<>`. When disabled, newly created loggers will not be added to the global registry, allowing you to manage logger lifecycles manually or keep them as private instances.

### Is the spdlog registry thread-safe for concurrent get and register operations?

Yes. According to the source code in [`registry-inl.h`](https://github.com/gabime/spdlog/blob/main/registry-inl.h), all public registry methods lock a private `std::mutex logger_map_mutex_` before accessing the internal map. This ensures that multiple threads can safely call `spdlog::get()`, `spdlog::register_logger()`, and `spdlog::register_or_replace()` concurrently without data races.

### What is the performance cost of retrieving loggers by name?

Retrieval performs a lookup in an `std::unordered_map<std::string, std::shared_ptr<logger>>` while holding a mutex lock. For high‑performance scenarios requiring frequent access, store the returned `shared_ptr` locally rather than repeatedly calling `spdlog::get()`, though the mutex overhead is minimal for typical logging patterns.