3.5 KiB
3.5 KiB
name, description, argument-hint
| name | description | argument-hint |
|---|---|---|
| python-logging-dictconfig | Set up idiomatic Python logging with logging.config.dictConfig. Use when creating or refactoring logging setup, standardizing handlers/formatters, and enforcing centralized config. | Target context (single script, package, FastAPI app, or CLI) and desired log destinations |
Idiomatic Python Logging with dictConfig
Use this skill to produce a minimal, centralized logging setup using logging.config.dictConfig.
Load references only when needed:
- Python logging overview and hierarchy: ./references/python-logging-docs.md
When to Use
- A project configures logging ad hoc with
basicConfigacross multiple modules. - You need one canonical logging configuration for app startup.
- You need consistent formatting and levels across console/file handlers.
- You want library modules to use named loggers without configuring logging themselves.
Inputs To Collect
- Runtime type: script, library, web app, worker, CLI.
- Destinations: stdout only, file only, or both.
- Desired default level:
INFO,DEBUG, etc. - Whether third-party loggers should be tuned (for example
uvicorn,sqlalchemy).
If missing, assume:
- stdout handler
- human-readable formatter
- root level
INFO disable_existing_loggers: False
Procedure
- Define a single
LOGGINGdictionary in one startup-oriented module (for examplelogging_config.py). - Include
version: 1and setdisable_existing_loggers: Falseunless there is a specific reason to silence existing loggers. - Define formatters first, then handlers, then logger routing (
rootand optional namedloggers). - Use
logging.config.dictConfig(LOGGING)exactly once during application startup. - In all modules, get loggers via
logger = logging.getLogger(__name__)and never callbasicConfig. - Keep libraries configuration-free: libraries should emit logs, applications decide routing.
- Verify behavior with a quick smoke check at multiple levels (
DEBUG,INFO,WARNING,ERROR).
Minimal Baseline Template
# logging_config.py
from logging.config import dictConfig
LOGGING = {
"version": 1,
"disable_existing_loggers": False,
"formatters": {
"standard": {
"format": "%(asctime)s %(levelname)s %(name)s: %(message)s"
}
},
"handlers": {
"console": {
"class": "logging.StreamHandler",
"level": "INFO",
"formatter": "standard",
"stream": "ext://sys.stdout",
}
},
"root": {
"level": "INFO",
"handlers": ["console"],
},
}
def configure_logging() -> None:
dictConfig(LOGGING)
# app startup
from .logging_config import configure_logging
configure_logging()
# any module
import logging
logger = logging.getLogger(__name__)
logger.info("module initialized")
Completion Checks
dictConfigis called once at startup, not per module.- No
basicConfigcalls remain. - Modules use
getLogger(__name__). - Logs appear at expected level and destination.
- Third-party logger noise is intentionally configured or left at defaults.
Branching Guidance
- If structured logs are required: switch formatter output to JSON while keeping
dictConfigtopology unchanged. - If both console and file output are needed: add a file handler and attach it to
root. - If a specific framework logger is too noisy: add a named logger override under
loggers.