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:
|
||||
|
||||
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
|
||||
|
||||
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:
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
@@ -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.config reference](https://docs.python.org/3/library/logging.config.html)
|
||||
|
||||
## dictConfig-Specific
|
||||
## Configuration And dictConfig
|
||||
|
||||
!!! 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.
|
||||
- [`logging.config.dictConfig`](https://docs.python.org/3/library/logging.config.html#logging.config.dictConfig) function reference.
|
||||
|
||||
## Practical Notes
|
||||
- Prefer app-level centralized config with one startup call to `dictConfig`.
|
||||
- In modules, use `logging.getLogger(__name__)`.
|
||||
- Avoid calling `basicConfig` in libraries or scattered modules.
|
||||
- Prefer module loggers created with `logging.getLogger(__name__)`.
|
||||
- Let applications configure handlers and formatters; libraries should emit logs without taking over routing.
|
||||
- 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" },
|
||||
{ "Session" = "skills/fastapi-async-sqlalchemy-modernization/references/session.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" },
|
||||
{ "Obs" = "skills/fastapi-async-sqlalchemy-modernization/references/observability.md" },
|
||||
{ "Template" = "skills/fastapi-async-sqlalchemy-modernization/references/template.md" },
|
||||
@@ -121,8 +122,13 @@ nav = [
|
||||
{ "Ecosystem" = "skills/mcp-details/references/ecosystem-and-tooling.md" },
|
||||
] },
|
||||
{ "Logging" = [
|
||||
{ "Overview" = "skills/python-logging-dictconfig/SKILL.md" },
|
||||
{ "Docs" = "skills/python-logging-dictconfig/references/python-logging-docs.md" },
|
||||
{ "Overview" = "skills/python-logging/SKILL.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" = [
|
||||
{ "Overview" = "skills/ruff-linting-formating/SKILL.md" },
|
||||
|
||||
Reference in New Issue
Block a user