# How to Configure spdlog to Load Log Levels from Environment Variables at Runtime

> Easily configure spdlog runtime log levels using environment variables. Call spdlog cfg load env levels to set global and named logger levels dynamically without recompiling your C++ application.

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

---

**Call `spdlog::cfg::load_env_levels()` at the start of your application to read the `SPDLOG_LEVEL` environment variable and configure global and named logger levels without recompiling.**

The spdlog library provides a lightweight mechanism to configure logging verbosity at runtime using environment variables. By leveraging the `SPDLOG_LEVEL` variable, you can control the log levels of all registered loggers or specific named instances without modifying source code, making it ideal for containerized deployments and production debugging scenarios in the `gabime/spdlog` repository.

## How Environment Variable Configuration Works in spdlog

The core functionality resides in **[`include/spdlog/cfg/env.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/cfg/env.h)**, which defines the **spdlog::cfg::load_env_levels()** function. When invoked, this function reads the `SPDLOG_LEVEL` environment variable using the cross-platform wrapper **spdlog::details::os::getenv()** (defined in [`include/spdlog/details/os.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/details/os.h)) and delegates the parsing logic to the configuration helpers.

### The Configuration Loading Process

When you call `spdlog::cfg::load_env_levels()`, the library executes the following steps:

1. Retrieves the value of `SPDLOG_LEVEL` via the `os::getenv` wrapper.
2. If the variable is set, forwards the string to **spdlog::cfg::helpers::load_levels** in [`include/spdlog/cfg/helpers.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/cfg/helpers.h).
3. Parses the comma-separated specification and updates the central logger registry maintained in [`include/spdlog/details/registry.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/details/registry.h).

## SPDLOG_LEVEL Format and Syntax

The format mirrors the Rust **env_logger** crate specification, supporting both global defaults and per-logger overrides:

- **Global level only**: `export SPDLOG_LEVEL=debug` sets all loggers to debug.
- **Per-logger overrides**: `export SPDLOG_LEVEL="off,logger1=debug"` disables logging globally but enables debug for "logger1".
- **Multiple overrides**: `export SPDLOG_LEVEL="off,logger1=debug,logger2=info"` combines global off with specific levels for multiple loggers.

If an unrecognized level name is encountered, spdlog falls back to **info** (as noted in the implementation comments in [`env.h`](https://github.com/gabime/spdlog/blob/main/env.h) lines 12–13).

## Implementation Details and Source Code

The configuration system relies on two primary components:

- **[`include/spdlog/cfg/helpers.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/cfg/helpers.h)**: Implements the `load_levels` function that tokenizes the environment string and updates individual logger levels in the registry.
- **[`include/spdlog/details/registry.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/details/registry.h)**: Maintains the central logger registry that stores all named loggers and their configured levels.

The parsing logic handles comma-separated key-value pairs where the first element (lacking an equals sign) specifies the global level, and subsequent `name=level` pairs target specific loggers.

## Practical Implementation Example

To activate runtime level configuration, include the header and invoke the loader before creating any loggers, typically at the beginning of `main()`:

```cpp
#include <spdlog/spdlog.h>
#include <spdlog/cfg/env.h>

int main() {
    // Load log-level configuration from SPDLOG_LEVEL
    spdlog::cfg::load_env_levels();   // reads the env variable

    // Now create loggers; they will respect the configured levels
    auto logger = spdlog::stdout_color_mt("logger1");
    logger->info("This message follows the level from SPDLOG_LEVEL");
}

```

This approach ensures that all subsequently created loggers inherit the levels specified in the environment variable.

## Summary

- **spdlog::cfg::load_env_levels()** reads the `SPDLOG_LEVEL` environment variable at runtime to configure logger verbosity.
- The implementation spans [`include/spdlog/cfg/env.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/cfg/env.h), [`include/spdlog/cfg/helpers.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/cfg/helpers.h), and [`include/spdlog/details/os.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/details/os.h).
- The format supports global levels and per-logger overrides using comma-separated syntax (e.g., `off,logger1=debug`).
- Unrecognized level names default to **info** according to the source code in [`env.h`](https://github.com/gabime/spdlog/blob/main/env.h).
- Call the loader function before instantiating loggers to ensure all registered instances receive the configured levels.

## Frequently Asked Questions

### What happens if SPDLOG_LEVEL is not set?

If the environment variable is undefined or empty, `spdlog::cfg::load_env_levels()` returns without modifying any logger levels. Loggers retain their default construction levels, typically **info** or whatever level was explicitly set programmatically.

### Can I change log levels after calling load_env_levels()?

While `load_env_levels()` is typically called once at startup, you can invoke it multiple times to re-read the environment variable. Newly created loggers will respect the current environment state, and existing loggers will have their levels updated based on the latest variable value.

### How does spdlog handle invalid level names in the environment variable?

According to the implementation in [`include/spdlog/cfg/env.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/cfg/env.h), if a level name cannot be recognized during parsing, spdlog falls back to **info** level for that specific entry. This ensures that typos in the environment variable do not crash the application but instead result in a reasonable default verbosity.

### Does this feature work on Windows as well as Linux?

Yes, the functionality is cross-platform. The library uses `spdlog::details::os::getenv()` defined in [`include/spdlog/details/os.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/details/os.h), which abstracts platform-specific environment variable access, ensuring consistent behavior across Windows, Linux, and macOS.