python-logging
/python-logging
Python logging with the standard library logging module and structlog. Covers log levels, handlers, formatters, structured logging, and production best practices for FastAPI/Django applications. USE WHEN: user mentions "python logging", "fastapi logging", "django logging", asks about "how to log in python", "python logging module", "logging configuration python" DO NOT USE FOR: Node.js logging - use `nodejs-logging` instead, Java logging - use `slf4j` or `logback`, structlog-specific - use `structlog` skill for deep dive
- Author
- claude-dev-suite ↗
- Repository
- claude-dev-suite ↗
- Licence
- MIT
- Last repository change
- 21.10.2026
Assessment and security
- Files in this package
- 2
- Scripts
- 0
- HTML comments
- 0
- URLs in SKILL.md
- 2
No signals detected. Repository changed on 21.10.2026, without references to retired models or APIs.
MIT, open: use and modify while retaining author attribution.
What it does and when to use it
Python logging with the standard library logging module and structlog. Covers log levels, handlers, formatters, structured logging, and production best practices for FastAPI/Django applications. USE WHEN: user mentions "python logging", "fastapi logging", "django logging", asks about "how to log in python", "python logging module", "logging configuration python" DO NOT USE FOR: Node.js logging - use `nodejs-logging` instead, Java logging - use `slf4j` or `logback`, structlog-specific - use `structlog` skill for deep dive
Triggers from the description
Original author description
Python logging with the standard library logging module and structlog. Covers log levels, handlers, formatters, structured logging, and production best practices for FastAPI/Django applications. USE WHEN: user mentions "python logging", "fastapi logging", "django logging", asks about "how to log in python", "python logging module", "logging configuration python" DO NOT USE FOR: Node.js logging - use `nodejs-logging` instead, Java logging - use `slf4j` or `logback`, structlog-specific - use `structlog` skill for deep dive
How it works
- Standard Library (logging)
- Structlog (Structured Logging)
- FastAPI Integration
- Django Integration
- Best Practices
- When NOT to Use This Skill
- Anti-Patterns
- Quick Troubleshooting
- Reference
SKILL.md preview
---
name: python-logging
description: |
Python logging with the standard library logging module and structlog.
Covers log levels, handlers, formatters, structured logging, and
production best practices for FastAPI/Django applications.
USE WHEN: user mentions "python logging", "fastapi logging", "django logging",
asks about "how to log in python", "python logging module", "logging configuration python"
DO NOT USE FOR: Node.js logging - use `nodejs-logging` instead, Java logging - use `slf4j` or `logback`,
structlog-specific - use `structlog` skill for deep dive
allowed-tools: Read, Grep, Glob, Write, Edit
---
# Python Logging
> **Deep Knowledge**: Use `mcp__documentation__fetch_docs` with technology: `python` for comprehensive documentation.
## Standard Library (logging)
### Basic Setup
```python
import logging
# Configure root logger
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
# Get logger for module
logger = logging.getLogger(__name__)
# Usage
logger.debug('Debug message')
logger.info('Info message')
logger.warning('Warning message')
logger.error('Error message')
logger.critical('Critical message')
```
### Advanced Configuration
```python
import logging
import logging.handlers
import sys
def setup_logging(level: str = 'INFO') -> None:
"""Configure application logging."""
# Create formatter
formatter = logging.Formatter(
fmt='%(asctime)s | %(levelname)-8s | %(name)s:%(lineno)d | %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
# Console handler
console_handler = logging.StreamHandler(sys.stdout)
console_handler.setFormatter(formatter)
console_handler.setLevel(logging.DEBUG)
# File handler with rotation
file_handler = logging.handlers.RotatingFileHandler(
filename='logs/app.log',
maxBytes=100 * 1024 * 1024, # 100MB
backupCount=5,
encoding='utf-8'
)
file_handler.setFormatter(formatter)
file_handler.setLevel(logging.INFO)
# Configure root logger
root_logger = logging.getLogger()
root_logger.setLevel(getattr(logging, level.upper()))
root_logger.addHandler(console_handler)
root_logger.addHandler(file_handler)
# Reduce noise from third-party libraries
logging.getLogger('urllib3').setLevel(logging.WARNING)
logging.getLogger('httpx').setLevel(logging.WARNING)
```
### Log Levels
| Level | Numeric | Usage |
|-------|---------|-------|
| `CRITICAL` | 50 | System unusable |
| `ERROR` | 40 | Error conditions |
| `WARNING` | 30 | Warning conditions |
| `INFO` | 20 | Normal operations |
| `DEBUG` | 10 | Debug information |
| `NOTSET` | 0 | Inherit from parent |
### Exception Logging
```python
try:
result = process_data(data)
except ValueError as e:
logger.error('Invalid data format: %s', e)
except Exception:
logger.exception('Unexpected error processing data') # Includes traceback
raise
```
### Extra Context
```python
# Using extra parameter
logger.info('User logged in', extra={'user_id': user.id, 'ip': request.ip})
# Custom LoggerAdapter for consistent context
class ContextLogger(logging.LoggerAdapter):
def process(self, msg, kwargs):
extra = kwargs.get('extra', {})
extra.update(self.extra)
kwargs['extra'] = extra
return msg, kwargs
logger = ContextLogger(logging.getLogger(__name__), {'request_id': request_id})
logger.info('Processing request')
```
## Structlog (Structured Logging)
### Installation
```bash
pip install structlog
```
### Basic Setup
```python
import structlog
structlog.configure(
processors=[
structlog.stdlib.filter_by_level,
structlog.stdlib.add_logger_name,
structlog.stdlib.add_log_level,
structlog.stdlib.PositionalArgumentsFormatter(),
structlog.processors.TimeStamper(fmt='iso'),
structlog.processors.StackInfoRenderer(),
structlog.processors.format_exc_info,
structlog.processors.UnicodeDecoder(),
structlog.processors.JSONRenderer() # or ConsoleRenderer() for dev
],
wrapper_class=structlog.stdlib.BoundLogger,
context_class=dict,
logger_factory=structlog.stdlib.LoggerFactory(),
cache_logger_on_first_use=True,
)
logger = structlog.get_logger()
```
### Usage
```python
# Basic logging
logger.info('Server started', port=8000, host='0.0.0.0')
# Bind context
log = logger.bind(user_id=user.id, request_id=request_id)
log.info('Processing request')
log.info('Request completed', status=200, duration_ms=45)
# Exception logging
try:
process()
except Exception:
logger.exception('Processing failed', order_id=order.id)
```
### Output (JSON)
```json
{
"event": "Processing request",
"user_id": 123,
"request_id": "abc-123",
"timestamp": "2025-01-15T10:30:00.000000Z",
"level": "info",
"logger": "myapp.services"
}
```
### Development vs Production
```python
import structlog
import sys
def configure_logging(env: str = 'development'):
shared_processors = [
structlog.stdlib.add_log_level,
structlog.stdlib.add_logger_name,
structlog.processors.TimeStamper(fmt='iso'),
structlog.processors.StackInfoRenderer(),
structlog.processors.format_exc_info,
]
if env == 'production':
# JSON output for log aggregation
processors = shared_processors + [
structlog.processors.JSONRenderer()
]
else:
# Pretty console output for development
processors = shared_processors + [
structlog.dev.ConsoleRenderer(colors=True)
]
structlog.configure(
processors=processors,
wrapper_class=structlog.stdlib.BoundLogger,
context_class=dict,
logger_factory=structlog.stdlib.LoggerFactory(),
cache_logger_on_first_use=True,
)
```
## FastAPI Integration
### Middleware for Request Logging
```python
import time
import uuid
from fastapi import FastAPI, Request
import structlog
app = FastAPI()
logger = structlog.get_logger()
@app.middleware('http')
async def logging_middleware(request: Request, call_next):
request_id = str(uuid.uuid4())
start_time = time.perf_counter()
# Bind context for this request
structlog.contextvars.clear_contextvars()
structlog.contextvars.bind_contextvars(
request_id=request_id,
method=request.method,
path=request.url.path,
)
logger.info('Request started')
response = await call_next(request)
duration_ms = (time.perf_counter() - start_time) * 1000
logger.info(
'Request completed',
status_code=response.status_code,
duration_ms=round(duration_ms, 2)
)
response.headers['X-Request-ID'] = request_id
return response
```
### Dependency Injection
```python
from fastapi import Depends
import structlog
def get_logger() -> structlog.stdlib.BoundLogger:
return structlog.get_logger()
@app.get('/users/{user_id}')
async def get_user(
user_id: int,
logger: structlog.stdlib.BoundLogger = Depends(get_logger)
):
logger = logger.bind(user_id=user_id)
logger.info('Fetching user')
# ...
```
## Django Integration
### settings.py
```python
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'verbose': {
'format': '{asctime} {levelname} {name} {message}',
'style': '{',
},
'json': {
'()': 'pythonjsonlogger.jsonlogger.JsonFormatter',
'format': '%(asctime)s %(levelname)s %(name)s %(message)s',
},
},
'handlers': {
'console': {
'class': 'logging.StreamHandler',
'formatter': 'verbose',
},
'file': {
'class': 'logging.handlers.RotatingFileHandler',
'filename': 'logs/django.log',
'maxBytes': 100 * 1024 * 1024,
'backupCount': 5,
'formatter': 'json',
},
},
'root': {
'handlers': ['console', 'file'],
'level': 'INFO',
},
'loggers': {
'django': {
'handlers': ['console'],
'level': 'INFO',
'propagate': False,
},
'django.db.backends': {
'level': 'WARNING', # Reduce SQL noise
},
},
}
```
## Best Practices
### DO
```python
# Use module-level loggers
logger = logging.getLogger(__name__)
# Use lazy formatting
logger.info('User %s performed %s', user_id, action)
# Include context
logger.info('Order processed', extra={'order_id': order.id, 'total': total})
# Log exceptions with traceback
logger.exception('Failed to process order')
```
### DON'T
```python
# Don't use f-strings (evaluated even when level is disabled)
logger.debug(f'Processing {expensive_computation()}') # BAD
# Don't log sensitive data
logger.info('Login: user=%s, password=%s', user, password) # BAD!
# Don't use print() for logging
print(f'Error: {error}') # BAD - use logger.error()
```
### Sensitive Data Handling
```python
import re
class SensitiveDataFilter(logging.Filter):
PATTERNS = [
(re.compile(r'password["\']?\s*[:=]\s*["\']?[^"\'}\s]+'), 'password=***'),
(re.compile(r'token["\']?\s*[:=]\s*["\']?[^"\'}\s]+'), 'token=***'),
]
def filter(self, record):
message = record.getMessage()
for pattern, replacement in self.PATTERNS:
message = pattern.sub(replacement, message)
record.msg = message
record.args = ()
return True
# Add filter to handler
handler.addFilter(SensitiveDataFilter())
```
## When NOT to Use This Skill
- **structlog-specific questions**: Use `structlog` skill for detailed configuration
- **Node.js/Java projects**: Use language-appropriate logging skills
- **Simple print debugging**: print() is fine for quick scripts
- **Third-party library internals**: Consult library-specific docs
- **Log analysis**: Use `log-analyzer` MCP server instead
## Anti-Patterns
| Anti-Pattern | Why It's Bad | Solution |
|--------------|--------------|----------|
| Using print() for logging | No control, no filtering, no formatting | Use logging module |
| f-strings in log messages | Always evaluated, performance hit | Use lazy formatting: `logger.info('User %s', user_id)` |
| Not using module-level loggers | Loses context about log source | Use `logger = logging.getLogger(__name__)` |
| Root logger configuration in libraries | Affects all applications | Only configure in main application |
| Logging exceptions without traceback | Loses debugging context | Use `logger.exception()` in except blocks |
| Not rotating log files | Disk fills up | Use RotatingFileHandler or TimedRotatingFileHandler |
## Quick Troubleshooting
| Issue | Cause | Solution |
|-------|-------|----------|
| Logs not appearing | Log level too high | Check logger.setLevel() and handler levels |
| Duplicate log messages | Multiple handlers on same logger | Check handler configuration, set propagate=False |
| No traceback in logs | Using logger.error() instead of exception() | Use `logger.exception()` in except blocks |
| Third-party library spam | Noisy library logs | Set specific logger levels: `logging.getLogger('urllib3').setLevel(WARNING)` |
| Performance issues | Too many handlers or formatters | Simplify configuration, use appropriate log levels |
| Missing context | Not using extra parameter | Use `logger.info('msg', extra={'key': value})` or LoggerAdapter |
## Reference
- [Quick Reference: Cheatsheet](quick-ref/cheatsheet.md)
- [Python logging HOWTO](https://docs.python.org/3/howto/logging.html)
- [Structlog Documentation](https://www.structlog.org/)
Files in this package (2)
- SKILL.md 11 KB
- quick-ref/cheatsheet.md 1 KB
Versions
The database has no other skills named python-logging.
Database snapshot: 13.11.2026 · package version d073cbc69d7d (SHA-256 digest of the entire package)
Downloads in the last 30 days: 0 · ranking
Report a problem with this skill: harmful content, incorrect descriptions or an author’s removal request.
Similar skills
- 100structlog
structlog - structured logging library for Python with native JSON support, context binding, and processor pipeline. Integrates with FastAPI, Django, and standard logging module. USE WHEN: user mentions "structlog", "python structured logging", "context binding", asks about… - 95java-logging
Java logging with SLF4J facade, Logback, and Log4j2 implementations. Covers configuration, log levels, structured logging, async logging, and production best practices for Spring Boot applications. USE WHEN: user mentions "java logging", "spring boot logging", "slf4j setup",… - 100structlog-python
Add structured logging to Python with structlog: key-value events rendered as JSON in production or colored console lines in development, request-scoped context through contextvars, and standard-library integration so third-party library logs share the same format. Use when a… - 100logging
Structured logging conventions for DraftForge backend (Django/Celery/Daphne) and frontend (React). This skill should be used when adding log statements, creating new modules, debugging with logs, or reviewing logging patterns. Covers structlog usage, system/subsystem taxonomy,… - 100observability-and-logging
Structured logging (structlog), PII/secret redaction, OpenTelemetry tracing, Sentry, Prometheus RED metrics, and health probes for FastAPI backends. Use when adding observability or redacting PII from logs. - 100logging-standards
Structured logging standards: log levels, structured fields, correlation IDs, PII masking, and event naming. TRIGGER when: adding log statements, configuring loggers, or reviewing log output. SKIP: metrics and alerting (use monitoring-observability); error control flow (use…