Files
thrillwiki_django_no_react/docs/architecture/adr-007-logging-standardization.md
pacnpal ca770d76ff Enhance documentation and management commands for ThrillWiki
- Updated backend README.md to include detailed management commands for configuration, database operations, cache management, data management, user authentication, content/media handling, trending/discovery, testing/development, and security/auditing.
- Added a new MANAGEMENT_COMMANDS.md file for comprehensive command reference.
- Included logging standardization details in architecture documentation (ADR-007).
- Improved production checklist with configuration validation and cache verification steps.
- Expanded API documentation to include error logging details.
- Created a documentation review checklist to ensure completeness and accuracy.
2025-12-23 21:28:14 -05:00

217 lines
6.5 KiB
Markdown

# ADR-007: Logging Standardization Pattern
## Status
Accepted
## Context
As the ThrillWiki application grew, logging patterns became inconsistent across different modules. Some files had no logging, others used print statements, and logging levels were applied inconsistently. This made debugging production issues difficult and prevented effective monitoring.
The team needed:
- Consistent logging patterns across all modules
- Structured logging with contextual information
- Security event tracking for compliance
- Performance monitoring capabilities
- Integration with centralized logging systems (Sentry, CloudWatch)
## Decision
We implemented a **standardized logging pattern** with centralized utilities for structured logging.
### Core Pattern
Every module initializes a logger using Python's standard logging:
```python
import logging
logger = logging.getLogger(__name__)
```
### Centralized Logging Utilities
Created `apps.core.logging` module with specialized logging functions:
1. **`log_exception(logger, exception, context, request)`**
- Logs exceptions with full stack trace
- Includes request context (user, IP, path)
- Automatically sends to Sentry in production
2. **`log_business_event(logger, event_type, message, context, request)`**
- Logs significant business operations
- Used for FSM transitions, user actions, data changes
- Structured format for analytics
3. **`log_security_event(logger, event_type, message, severity, context, request)`**
- Logs authentication and authorization events
- Tracks security-relevant actions
- Supports compliance auditing
### Log Levels
Standardized log level usage:
| Level | Usage |
|-------|-------|
| `DEBUG` | Detailed diagnostic information (disabled in production) |
| `INFO` | General operational events (user actions, searches) |
| `WARNING` | Unexpected conditions that don't prevent operation |
| `ERROR` | Error conditions requiring attention |
| `CRITICAL` | System failures requiring immediate action |
### Logging Configuration
Modular logging configuration in `config/settings/logging.py`:
```python
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'json': {
'()': 'pythonjsonlogger.jsonlogger.JsonFormatter',
'format': '%(asctime)s %(name)s %(levelname)s %(message)s',
},
'verbose': {
'format': '{levelname} {asctime} {name} {message}',
'style': '{',
},
},
'handlers': {
'console': {
'class': 'logging.StreamHandler',
'formatter': 'verbose',
},
'file': {
'class': 'logging.handlers.RotatingFileHandler',
'filename': 'logs/django.log',
'maxBytes': 10485760, # 10MB
'backupCount': 5,
'formatter': 'json',
},
'sentry': {
'class': 'sentry_sdk.integrations.logging.EventHandler',
'level': 'ERROR',
},
},
'loggers': {
'django': {
'handlers': ['console', 'file'],
'level': 'INFO',
},
'apps': {
'handlers': ['console', 'file', 'sentry'],
'level': 'INFO',
'propagate': False,
},
},
}
```
## Consequences
### Benefits
1. **Consistent Debugging**: All modules log in the same format
2. **Structured Logs**: JSON format enables log aggregation and analysis
3. **Security Auditing**: Dedicated security event logging for compliance
4. **Performance Monitoring**: Cache and query performance tracking
5. **Production Monitoring**: Integration with Sentry for error tracking
6. **Contextual Information**: All logs include user, request, and operation context
### Trade-offs
1. **Verbosity**: More logging code in each module
2. **Performance**: Logging has minimal overhead (~1-2ms per log)
3. **Storage**: JSON logs consume more disk space than plain text
4. **Learning Curve**: Developers must learn when to use each logging function
### Implementation Guidelines
1. **Logger Initialization**: Every view, service, and middleware file must initialize a logger
2. **Exception Handling**: Always use `log_exception()` in exception handlers
3. **Business Events**: Use `log_business_event()` for FSM transitions and significant actions
4. **Security Events**: Use `log_security_event()` for authentication and authorization
5. **Sensitive Data**: Never log passwords, tokens, session IDs, or PII
### Example Usage
```python
import logging
from apps.core.logging import log_exception, log_business_event, log_security_event
logger = logging.getLogger(__name__)
class ParkDetailView(DetailView):
def get_object(self):
try:
park = super().get_object()
logger.info(f"Park viewed: {park.name}", extra={
'park_id': park.id,
'user_id': self.request.user.id if self.request.user.is_authenticated else None,
})
return park
except Park.DoesNotExist as e:
log_exception(
logger,
e,
context={'slug': self.kwargs.get('slug')},
request=self.request,
)
raise
def post(self, request, *args, **kwargs):
park = self.get_object()
old_status = park.status
park.approve()
park.save()
log_business_event(
logger,
event_type='fsm_transition',
message=f'Park approved: {park.name}',
context={
'model': 'Park',
'object_id': park.id,
'old_state': old_status,
'new_state': park.status,
},
request=request,
)
return redirect('park_detail', slug=park.slug)
```
## Alternatives Considered
### Django Debug Toolbar Only
**Rejected because:**
- Only works in development
- No production monitoring
- No structured logging
- No security event tracking
### Third-Party Logging Service (Datadog, New Relic)
**Rejected because:**
- High cost for small team
- Vendor lock-in
- Sentry + CloudWatch sufficient for current needs
### Print Statements
**Rejected because:**
- Not configurable
- No log levels
- No structured format
- Not production-ready
## References
- [Python Logging Documentation](https://docs.python.org/3/library/logging.html)
- [Django Logging Documentation](https://docs.djangoproject.com/en/5.0/topics/logging/)
- [Sentry Integration](https://docs.sentry.io/platforms/python/guides/django/)
- [Code Standards - Logging](../../backend/docs/code_standards.md#logging-standards)