# How to Load Log Levels from Environment Variables in spdlog

> Easily load spdlog log levels from environment variables. Call spdlog::cfg::load_env_levels() to configure logger verbosity dynamically at runtime.

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

---

**Call `spdlog::cfg::load_env_levels()` after including `<spdlog/cfg/env.h>` to read the `SPDLOG_LEVEL` environment variable and configure global and named logger verbosity at runtime.**

The spdlog library provides a lightweight configuration mechanism that lets you control logging verbosity without recompiling your application. By using the `SPDLOG_LEVEL` environment variable, you can dynamically set global and per-logger levels through a simple API call. This guide explains how to load log levels from environment variables in spdlog using the implementation found in the gabime/spdlog repository.

## Implementation Overview

The environment variable configuration system centers on two headers in the `include/spdlog/cfg/` directory. The **[`include/spdlog/cfg/env.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/cfg/env.h)** header defines the `load_env_levels()` function that initiates the loading process. This function delegates the actual parsing work to **[`include/spdlog/cfg/helpers.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/cfg/helpers.h)**, which implements the `load_levels` helper that interprets the string format and updates the logger registry.

## The SPDLOG_LEVEL Format

The environment variable follows a comma-separated syntax similar to the Rust env_logger crate. You can specify a global level for all loggers and override specific named loggers with different levels.

- `export SPDLOG_LEVEL=debug` — Sets **all** loggers to **debug**.
- `export SPDLOG_LEVEL="off,logger1=debug"` — Turns logging **off** globally but enables **debug** for **logger1**.
- `export SPDLOG_LEVEL="off,logger1=debug,logger2=info"` — Disables global logging, sets **debug** for **logger1**, and **info** for **logger2**.

If a level name is not recognized, spdlog falls back to **info** as the default severity, as noted in the comments within [`include/spdlog/cfg/env.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/cfg/env.h).

## How Environment Loading Works

When you invoke `spdlog::cfg::load_env_levels()`, the function executes a three-step process defined in the source files:

1. **Reading the variable**: The function calls `spdlog::details::os::getenv("SPDLOG_LEVEL")` from [`include/spdlog/details/os.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/details/os.h) to retrieve the environment variable value in a cross-platform manner.
2. **Parsing the configuration**: If the variable is set, the string is passed to `spdlog::cfg::helpers::load_levels` in [`include/spdlog/cfg/helpers.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/cfg/helpers.h). This parser tokenizes the comma-separated entries and maps level names to enum values.
3. **Updating the registry**: The helper updates the central logger registry in [`include/spdlog/details/registry.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/details/registry.h), applying the global default level and specific overrides to existing named loggers.

## Usage Example

To activate the feature, include the configuration header and call the loader before creating loggers, typically at the start of your `main()` function:

```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");
}

```

Call `load_env_levels()` before any logging operations to ensure all loggers inherit the environment-specified levels.

## Key Source Files

The environment variable configuration relies on these specific files in the gabime/spdlog repository:

- **[`include/spdlog/cfg/env.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/cfg/env.h)** — Defines `load_env_levels` that reads the environment variable and delegates to the level-parsing helper.
- **[`include/spdlog/cfg/helpers.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/cfg/helpers.h)** — Implements `load_levels` which parses the comma-separated specification and updates the registry.
- **[`include/spdlog/details/os.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/details/os.h)** — Provides the cross-platform `os::getenv` wrapper used to read environment variables.
- **[`include/spdlog/details/registry.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/details/registry.h)** — Holds the central logger registry that `helpers::load_levels` manipulates.

## Summary

- **Call `spdlog::cfg::load_env_levels()`** early in your application to read the `SPDLOG_LEVEL` environment variable.
- The format supports **global levels** and **per-logger overrides** using comma-separated syntax like `off,logger1=debug`.
- The implementation uses **[`include/spdlog/cfg/env.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/cfg/env.h)** and **[`include/spdlog/cfg/helpers.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/cfg/helpers.h)** to parse and apply configuration.
- Invalid level names automatically fall back to **info** level, as implemented in the source.
- This approach enables dynamic verbosity control without recompiling, ideal for containerized deployments.

## Frequently Asked Questions

### What is the exact format for the SPDLOG_LEVEL environment variable?

The format uses comma-separated key-value pairs where the first optional value sets the global level, and subsequent entries specify per-logger overrides. For example, `export SPDLOG_LEVEL="warn,myapp=debug"` sets the global default to **warn** but allows **myapp** to log at **debug** level. This syntax mirrors the Rust env_logger crate convention.

### Where should I call `load_env_levels()` in my application?

Invoke `spdlog::cfg::load_env_levels()` at the beginning of your `main()` function before creating any logger instances. According to the source code in [`include/spdlog/cfg/env.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/cfg/env.h), this ensures the registry is configured before loggers are instantiated, allowing them to respect the environment variable settings immediately.

### What happens if I specify an invalid log level name in the environment variable?

If the parser encounters an unrecognized level string in [`include/spdlog/cfg/helpers.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/cfg/helpers.h), it defaults to **info** level as a fallback mechanism. This safety feature ensures that typographical errors in the environment variable do not disable logging entirely or cause runtime failures.

### Can I use environment variable configuration with custom loggers created after calling `load_env_levels()`?

Yes. The `spdlog::cfg::helpers::load_levels` function updates the central registry in [`include/spdlog/details/registry.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/details/registry.h), which manages all loggers. When you create new loggers after calling `load_env_levels()`, they will automatically adopt the global level setting from `SPDLOG_LEVEL`, while specific named overrides apply if they match the logger name.