From 85eb75d1888e3b4951eef46bd3cc708fbbec5b39 Mon Sep 17 00:00:00 2001 From: John Lancaster <32917998+jsl12@users.noreply.github.com> Date: Fri, 19 Jun 2026 17:40:04 -0500 Subject: [PATCH] logging --- .../skills/python-logging-dictconfig/SKILL.md | 34 ++++++++++++------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/docs/skills/python-logging-dictconfig/SKILL.md b/docs/skills/python-logging-dictconfig/SKILL.md index 5a31b1c..66b640c 100644 --- a/docs/skills/python-logging-dictconfig/SKILL.md +++ b/docs/skills/python-logging-dictconfig/SKILL.md @@ -12,12 +12,14 @@ Load references only when needed: - Python logging overview and hierarchy: [Python logging references](./references/python-logging-docs.md) ## When to Use + - A project configures logging ad hoc with `basicConfig` across 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 + 1. Runtime type: script, library, web app, worker, CLI. 2. Destinations: stdout only, file only, or both. 3. Desired default level: `INFO`, `DEBUG`, etc. @@ -30,6 +32,7 @@ If missing, assume: - `disable_existing_loggers: False` ## Procedure + 1. Define a single `LOGGING` dictionary in one startup-oriented module (for example `logging_config.py`). 2. Include `version: 1` and set `disable_existing_loggers: False` unless there is a specific reason to silence existing loggers. 3. Define formatters first, then handlers, then logger routing (`root` and optional named `loggers`). @@ -38,24 +41,28 @@ If missing, assume: 6. Keep libraries configuration-free: libraries should emit logs, applications decide routing. 7. Verify behavior with a quick smoke check at multiple levels (`DEBUG`, `INFO`, `WARNING`, `ERROR`). -## Minimal Baseline Template -```python -# logging_config.py -from logging.config import dictConfig +## Minimal Baseline Templates + +### Configuration + +!!! warning "Don't use the name `logging.py` because it will conflict + +```python title="logging_config.py" +import logging.config LOGGING = { "version": 1, "disable_existing_loggers": False, "formatters": { - "standard": { - "format": "%(asctime)s %(levelname)s %(name)s: %(message)s" + "basic": { + "format": "%(asctime)s.%(msecs)03d [%(levelname)s] %(message)s", + "datefmt": "%Y-%m-%d %H:%M:%S", } }, "handlers": { "console": { "class": "logging.StreamHandler", - "level": "INFO", - "formatter": "standard", + "formatter": "basic", "stream": "ext://sys.stdout", } }, @@ -66,22 +73,24 @@ LOGGING = { } def configure_logging() -> None: - dictConfig(LOGGING) + logging.config.dictConfig(LOGGING) ``` -```python +```python title="app.py" # app startup from .logging_config import configure_logging configure_logging() ``` +### Usage + +The preferred way of instantiating loggers is at the top of modules like this: + ```python -# any module import logging logger = logging.getLogger(__name__) -logger.info("module initialized") ``` ## Completion Checks @@ -90,6 +99,7 @@ logger.info("module initialized") 3. Modules use `getLogger(__name__)`. 4. Logs appear at expected level and destination. 5. Third-party logger noise is intentionally configured or left at defaults. +6. No module named `logging.py` in the project. ## Branching Guidance - If structured logs are required: switch formatter output to JSON while keeping `dictConfig` topology unchanged.