renamed python-logging
This commit is contained in:
@@ -253,7 +253,7 @@ Allowed exception:
|
|||||||
Existing markdown reference sets are valid examples of authored source material for this architecture:
|
Existing markdown reference sets are valid examples of authored source material for this architecture:
|
||||||
|
|
||||||
1. docs/skills/pytesting/references/pytest-docs.md
|
1. docs/skills/pytesting/references/pytest-docs.md
|
||||||
2. docs/skills/python-logging-dictconfig/references/python-logging-docs.md
|
2. docs/skills/python-logging/references/python-logging-docs.md
|
||||||
3. docs/skills/fastapi-uv-docker/references/fastapi-best-practices.md
|
3. docs/skills/fastapi-uv-docker/references/fastapi-best-practices.md
|
||||||
|
|
||||||
These inputs are treated as content sources, while resource URIs and catalog payloads remain the machine-facing contracts.
|
These inputs are treated as content sources, while resource URIs and catalog payloads remain the machine-facing contracts.
|
||||||
|
|||||||
+1
-1
@@ -194,7 +194,7 @@ This keeps docs publication explicit and predictable.
|
|||||||
Existing reference docs remain valid content inputs in this pattern:
|
Existing reference docs remain valid content inputs in this pattern:
|
||||||
|
|
||||||
1. docs/skills/pytesting/references/pytest-docs.md
|
1. docs/skills/pytesting/references/pytest-docs.md
|
||||||
2. docs/skills/python-logging-dictconfig/references/python-logging-docs.md
|
2. docs/skills/python-logging/references/python-logging-docs.md
|
||||||
3. docs/skills/fastapi-uv-docker/references/fastapi-best-practices.md
|
3. docs/skills/fastapi-uv-docker/references/fastapi-best-practices.md
|
||||||
|
|
||||||
These are source documents, not deployment artifacts.
|
These are source documents, not deployment artifacts.
|
||||||
|
|||||||
@@ -1,115 +0,0 @@
|
|||||||
---
|
|
||||||
name: python-logging-dictconfig
|
|
||||||
description: 'Set up idiomatic Python logging with logging.config.dictConfig. Use when creating or refactoring logging setup, standardizing handlers/formatters, and enforcing centralized config.'
|
|
||||||
x-personal-mcp:
|
|
||||||
id: python-logging-dictconfig
|
|
||||||
version: 1.0.0
|
|
||||||
tags:
|
|
||||||
- logging
|
|
||||||
- python
|
|
||||||
- observability
|
|
||||||
capabilities:
|
|
||||||
- resource://skills/python-logging-dictconfig/document
|
|
||||||
---
|
|
||||||
|
|
||||||
# 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: [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.
|
|
||||||
4. 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
|
|
||||||
|
|
||||||
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`).
|
|
||||||
4. Use `logging.config.dictConfig(LOGGING)` exactly once during application startup.
|
|
||||||
5. In all modules, get loggers via `logger = logging.getLogger(__name__)` and never call `basicConfig`.
|
|
||||||
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 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": {
|
|
||||||
"basic": {
|
|
||||||
"format": "%(asctime)s.%(msecs)03d [%(levelname)s] %(message)s",
|
|
||||||
"datefmt": "%Y-%m-%d %H:%M:%S",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"handlers": {
|
|
||||||
"console": {
|
|
||||||
"class": "logging.StreamHandler",
|
|
||||||
"formatter": "basic",
|
|
||||||
"stream": "ext://sys.stdout",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"root": {
|
|
||||||
"level": "INFO",
|
|
||||||
"handlers": ["console"],
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
def configure_logging() -> None:
|
|
||||||
logging.config.dictConfig(LOGGING)
|
|
||||||
```
|
|
||||||
|
|
||||||
```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
|
|
||||||
import logging
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
```
|
|
||||||
|
|
||||||
## Completion Checks
|
|
||||||
1. `dictConfig` is called once at startup, not per module.
|
|
||||||
2. No `basicConfig` calls remain.
|
|
||||||
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.
|
|
||||||
- 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`.
|
|
||||||
@@ -0,0 +1,140 @@
|
|||||||
|
---
|
||||||
|
name: python-logging
|
||||||
|
description: 'Design, review, or refactor Python logging. Use when choosing logger names, levels, handlers, library/application boundaries, basicConfig, dictConfig, structured logs, or operational logging defaults.'
|
||||||
|
x-personal-mcp:
|
||||||
|
id: python-logging
|
||||||
|
version: 1.0.0
|
||||||
|
tags:
|
||||||
|
- logging
|
||||||
|
- python
|
||||||
|
- observability
|
||||||
|
capabilities:
|
||||||
|
- resource://skills/python-logging/document
|
||||||
|
---
|
||||||
|
|
||||||
|
# Python Logging
|
||||||
|
|
||||||
|
Use this skill to produce idiomatic Python logging guidance or a small logging setup for an application, library, CLI, worker, or web service.
|
||||||
|
|
||||||
|
Load references only when needed:
|
||||||
|
- Python logging overview, library guidance, handlers, and dictConfig schema: [Python logging references](./references/python-logging-docs.md)
|
||||||
|
|
||||||
|
## When to Use
|
||||||
|
|
||||||
|
- A project mixes `print`, root logger calls, scattered `basicConfig`, or ad hoc handlers.
|
||||||
|
- You need to choose logging levels, destinations, formatter fields, or logger names.
|
||||||
|
- You need a clear boundary between library logging and application logging configuration.
|
||||||
|
- You need a centralized logging setup, including a `logging.config.dictConfig` section.
|
||||||
|
- You are tuning framework or third-party loggers such as `uvicorn`, `sqlalchemy`, or HTTP clients.
|
||||||
|
|
||||||
|
## Inputs To Collect
|
||||||
|
|
||||||
|
1. Runtime type: script, library, CLI, web app, worker, service, or notebook.
|
||||||
|
2. Audience: humans in a terminal, operators in files, machines in JSON, or test assertions.
|
||||||
|
3. Destinations: stdout/stderr, file, rotating file, queue, syslog, external collector, or none for libraries.
|
||||||
|
4. Default level and verbosity controls: `INFO`, `DEBUG`, CLI flag, environment variable, or config file.
|
||||||
|
5. Operational constraints: async event loop, multiprocessing, container logs, sensitive data, or high-volume paths.
|
||||||
|
|
||||||
|
If missing, assume:
|
||||||
|
- application code, not a reusable library
|
||||||
|
- stdout console logging
|
||||||
|
- human-readable formatter
|
||||||
|
- root level `INFO`
|
||||||
|
- no file logging unless requested
|
||||||
|
|
||||||
|
## Procedure
|
||||||
|
|
||||||
|
1. Classify the project boundary first: application code configures logging; library code emits logs and avoids configuring handlers.
|
||||||
|
2. In modules, create loggers with `logger = logging.getLogger(__name__)` so logger names follow the package hierarchy.
|
||||||
|
3. Use level semantics consistently: `DEBUG` for diagnosis, `INFO` for normal milestones, `WARNING` for notable recoverable conditions, `ERROR` for failed operations, and `CRITICAL` for process-threatening failures.
|
||||||
|
4. Prefer parameterized logging calls such as `logger.info("Processed %s items", count)` so message formatting is deferred until the record is emitted.
|
||||||
|
5. Configure handlers and formatters once during application startup. For small scripts, `basicConfig` can be enough; for applications, prefer a centralized configuration function.
|
||||||
|
6. Keep third-party logger overrides explicit and narrow. Tune noisy loggers by name instead of muting broad logger hierarchies.
|
||||||
|
7. Smoke-check output at expected levels and destinations, including one suppressed `DEBUG` message and one exception path if errors are logged.
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
- Do not name a module `logging.py`; it shadows the standard library package.
|
||||||
|
- Do not call `basicConfig` or attach handlers in every module.
|
||||||
|
- Do not log to the root logger from libraries. Use named loggers and, only if needed, attach `logging.NullHandler()` to the library's top-level logger.
|
||||||
|
- Do not create loggers per request, user, file, or connection. Use contextual fields, adapters, or filters instead.
|
||||||
|
- Use `logger.exception(...)` only inside an exception handler when the traceback is useful.
|
||||||
|
- For async or high-throughput code, avoid slow network or file handlers on the hot path; consider `QueueHandler` and a listener.
|
||||||
|
- Avoid custom levels unless there is a strong interoperability reason.
|
||||||
|
|
||||||
|
## Using dictConfig
|
||||||
|
|
||||||
|
Use `logging.config.dictConfig` when configuration should be centralized, data-driven, or richer than `basicConfig`.
|
||||||
|
|
||||||
|
1. Define one `LOGGING` dictionary in a startup-oriented module such as `logging_config.py`.
|
||||||
|
2. Include `version: 1` and usually set `disable_existing_loggers: False` so existing named loggers are not silently disabled.
|
||||||
|
3. Define formatters, then handlers, then logger routing with `root` and optional named `loggers`.
|
||||||
|
4. Call `logging.config.dictConfig(LOGGING)` once during application startup.
|
||||||
|
5. Keep application logging calls unchanged when adding new destinations or formats.
|
||||||
|
|
||||||
|
### Minimal dictConfig Baseline
|
||||||
|
|
||||||
|
```python title="logging_config.py"
|
||||||
|
import logging.config
|
||||||
|
|
||||||
|
LOGGING = {
|
||||||
|
"version": 1,
|
||||||
|
"disable_existing_loggers": False,
|
||||||
|
"formatters": {
|
||||||
|
"console": {
|
||||||
|
"format": "%(asctime)s.%(msecs)03d %(levelname)s %(name)s %(message)s",
|
||||||
|
"datefmt": "%Y-%m-%d %H:%M:%S",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"handlers": {
|
||||||
|
"console": {
|
||||||
|
"class": "logging.StreamHandler",
|
||||||
|
"formatter": "console",
|
||||||
|
"stream": "ext://sys.stdout",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"level": "INFO",
|
||||||
|
"handlers": ["console"],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def configure_logging() -> None:
|
||||||
|
logging.config.dictConfig(LOGGING)
|
||||||
|
```
|
||||||
|
|
||||||
|
```python title="app.py"
|
||||||
|
from .logging_config import configure_logging
|
||||||
|
|
||||||
|
configure_logging()
|
||||||
|
```
|
||||||
|
|
||||||
|
```python title="feature.py"
|
||||||
|
import logging
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def run(count: int) -> None:
|
||||||
|
logger.info("Processing %s items", count)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Branching Guidance
|
||||||
|
|
||||||
|
- If the code is a tiny script: use `basicConfig` once near the entry point and module loggers elsewhere.
|
||||||
|
- If the code is a library: remove handlers and configuration calls; document logger names and optionally add `NullHandler` at the package root.
|
||||||
|
- If structured logs are required: keep the same logger and handler topology, but switch formatter output to JSON or a structured formatter.
|
||||||
|
- If console and file output are needed: add one file or rotating-file handler and attach it centrally.
|
||||||
|
- If multiple processes write to one file: use a queue/listener or process-safe collection path rather than opening the same file independently in each process.
|
||||||
|
- If a framework logger is noisy: add a named logger override with a level and leave unrelated logger propagation alone.
|
||||||
|
|
||||||
|
## Completion Checks
|
||||||
|
|
||||||
|
1. Modules use `logging.getLogger(__name__)`.
|
||||||
|
2. Application startup configures logging once.
|
||||||
|
3. Libraries do not configure application handlers.
|
||||||
|
4. Levels match the severity semantics in this skill.
|
||||||
|
5. Logs include enough context to identify source, severity, and event without leaking secrets.
|
||||||
|
6. Expected destinations receive messages and suppressed levels stay quiet.
|
||||||
|
7. No source file or package is named `logging.py`.
|
||||||
+8
-6
@@ -1,6 +1,6 @@
|
|||||||
# Python Logging References
|
# Python Logging Source References
|
||||||
|
|
||||||
Use these official Python docs when applying this skill.
|
Use these official Python docs when applying the Python logging skill.
|
||||||
|
|
||||||
## Core Documentation
|
## Core Documentation
|
||||||
|
|
||||||
@@ -10,13 +10,15 @@ Use these official Python docs when applying this skill.
|
|||||||
- [logging API reference](https://docs.python.org/3/library/logging.html)
|
- [logging API reference](https://docs.python.org/3/library/logging.html)
|
||||||
- [logging.config reference](https://docs.python.org/3/library/logging.config.html)
|
- [logging.config reference](https://docs.python.org/3/library/logging.config.html)
|
||||||
|
|
||||||
## dictConfig-Specific
|
## Configuration And dictConfig
|
||||||
|
|
||||||
!!! info "dictConfig references"
|
!!! info "dictConfig references"
|
||||||
- [Dictionary schema details](https://docs.python.org/3/library/logging.config.html#logging-config-dictschema) for `version`, formatters, handlers, loggers, and root.
|
- [Dictionary schema details](https://docs.python.org/3/library/logging.config.html#logging-config-dictschema) for `version`, formatters, handlers, loggers, and root.
|
||||||
- [`logging.config.dictConfig`](https://docs.python.org/3/library/logging.config.html#logging.config.dictConfig) function reference.
|
- [`logging.config.dictConfig`](https://docs.python.org/3/library/logging.config.html#logging.config.dictConfig) function reference.
|
||||||
|
|
||||||
## Practical Notes
|
## Practical Notes
|
||||||
- Prefer app-level centralized config with one startup call to `dictConfig`.
|
- Prefer module loggers created with `logging.getLogger(__name__)`.
|
||||||
- In modules, use `logging.getLogger(__name__)`.
|
- Let applications configure handlers and formatters; libraries should emit logs without taking over routing.
|
||||||
- Avoid calling `basicConfig` in libraries or scattered modules.
|
- Use `basicConfig` for simple scripts and `dictConfig` for centralized application configuration.
|
||||||
|
- Explicitly set `disable_existing_loggers: False` in `dictConfig` unless disabling existing non-root loggers is intentional.
|
||||||
|
- Use queue-based handlers when slow handlers would block async, threaded, or high-volume code paths.
|
||||||
+8
-2
@@ -94,6 +94,7 @@ nav = [
|
|||||||
{ "Engine" = "skills/fastapi-async-sqlalchemy-modernization/references/engine.md" },
|
{ "Engine" = "skills/fastapi-async-sqlalchemy-modernization/references/engine.md" },
|
||||||
{ "Session" = "skills/fastapi-async-sqlalchemy-modernization/references/session.md" },
|
{ "Session" = "skills/fastapi-async-sqlalchemy-modernization/references/session.md" },
|
||||||
{ "Tx" = "skills/fastapi-async-sqlalchemy-modernization/references/transactions.md" },
|
{ "Tx" = "skills/fastapi-async-sqlalchemy-modernization/references/transactions.md" },
|
||||||
|
{ "SQLModel" = "skills/fastapi-async-sqlalchemy-modernization/references/sqlmodel.md" },
|
||||||
{ "IO" = "skills/fastapi-async-sqlalchemy-modernization/references/implicit_io.md" },
|
{ "IO" = "skills/fastapi-async-sqlalchemy-modernization/references/implicit_io.md" },
|
||||||
{ "Obs" = "skills/fastapi-async-sqlalchemy-modernization/references/observability.md" },
|
{ "Obs" = "skills/fastapi-async-sqlalchemy-modernization/references/observability.md" },
|
||||||
{ "Template" = "skills/fastapi-async-sqlalchemy-modernization/references/template.md" },
|
{ "Template" = "skills/fastapi-async-sqlalchemy-modernization/references/template.md" },
|
||||||
@@ -121,8 +122,13 @@ nav = [
|
|||||||
{ "Ecosystem" = "skills/mcp-details/references/ecosystem-and-tooling.md" },
|
{ "Ecosystem" = "skills/mcp-details/references/ecosystem-and-tooling.md" },
|
||||||
] },
|
] },
|
||||||
{ "Logging" = [
|
{ "Logging" = [
|
||||||
{ "Overview" = "skills/python-logging-dictconfig/SKILL.md" },
|
{ "Overview" = "skills/python-logging/SKILL.md" },
|
||||||
{ "Docs" = "skills/python-logging-dictconfig/references/python-logging-docs.md" },
|
{ "Docs" = "skills/python-logging/references/python-logging-docs.md" },
|
||||||
|
] },
|
||||||
|
{ "Pydantic Settings" = [
|
||||||
|
{ "Overview" = "skills/pydantic-settings/SKILL.md" },
|
||||||
|
{ "Source Docs" = "skills/pydantic-settings/references/source-documentation.md" },
|
||||||
|
{ "Workflow" = "skills/pydantic-settings/references/implementation-workflow.md" },
|
||||||
] },
|
] },
|
||||||
{ "Ruff" = [
|
{ "Ruff" = [
|
||||||
{ "Overview" = "skills/ruff-linting-formating/SKILL.md" },
|
{ "Overview" = "skills/ruff-linting-formating/SKILL.md" },
|
||||||
|
|||||||
Reference in New Issue
Block a user