# Python Logging Infrastructure

`pytools.logging` is a phased, state-driven logging subsystem.

It is built for:
- single-process scripts and CLIs
- API servers (including Uvicorn workers)
- deterministic cross-process logging behavior

## High-Level Model

The package separates configuration from runtime mutation:

1. `bootstrap(...)` defines baseline `LoggingState`
2. `resolve_logging_env_path(...)` discovers optional `.env.pytools_logging` path
3. mutate helpers update state (`merge_logger_levels`, `set_root_level`, etc.)
4. `apply_state(...)` activates runtime logging via `dictConfig`
5. `export_config(...)` serializes config for external runtimes

Only `apply_config(...)` / `apply_state(...)` perform side effects.

## Core Types and Modules

- `state.py`: `LoggingState` source of truth
- `bootstrap.py`: pure baseline state definition
- `resolve.py`: path discovery (`explicit > env var > project_root/.env.pytools_logging`)
- `mutate.py`: controlled, copy-safe state overlays
- `export.py`: pure `LoggingState -> dictConfig`
- `apply.py`: explicit runtime activation boundary
- `factories.py`: stable callable factories referenced by `dictConfig`

## Quickstart

```python
import logging

from pytools.logging import bootstrap, merge_logger_levels, set_root_level
from pytools.logging.apply import apply_state

state = bootstrap(root_level=logging.WARNING)
state = merge_logger_levels(state, {"my.module": logging.DEBUG})
state = set_root_level(state, logging.INFO)
apply_state(state)
```

## Path Resolution Behavior

`resolve_logging_env_path(...)` uses:
1. explicit path argument
2. `PYTOOLS_LOGGING_CONFIG_FILE`
3. `{project_root}/.env.pytools_logging`

If none exists, it returns `None` and the app continues safely without file-based overrides.

## Debugging the Logging System
In a consuming applicaiton, if you want to debug the actual logging system's initialization (resolve, mutate, export, etc.) you must pass in the pytools.logging.* logger specs into the bootstrap (or one_shot) as `.env.pytools_logging` or other env vars do not get set up in one_shot (or through system lifecycle) by bootstrap itself.

Alternatively, you can set using Pythons default logging setLevel before your run any bootstrap or logging system commands:

```python
# ./src/your/package/__init__.py

import logging

logging.getLogger("pytools.logging").setLevel(logging.DEBUG)
```

## See Also

- [Usage examples](./USAGE.md)