You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
167 lines
3.5 KiB
167 lines
3.5 KiB
# Logging Constraints
|
|
|
|
## Core Rule
|
|
|
|
**Use `logging.getLogger(__name__)` - never use `print()`**
|
|
|
|
## Logger Initialization
|
|
|
|
Get logger at module level:
|
|
|
|
```python
|
|
# GOOD: Use logging.getLogger(__name__)
|
|
import logging
|
|
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
def some_function():
|
|
_logger.info("Processing started")
|
|
_logger.debug("Detail: %s", detail)
|
|
```
|
|
|
|
## Logger Naming
|
|
|
|
Use `__name__` for automatic module path:
|
|
|
|
```python
|
|
# In database.py - logger will be "database"
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
# In pipeline/svd_pipeline.py - logger will be "pipeline.svd_pipeline"
|
|
_logger = logging.getLogger(__name__)
|
|
```
|
|
|
|
## Log Levels
|
|
|
|
| Level | When to Use |
|
|
|-------|-------------|
|
|
| DEBUG | Detailed diagnostic info (dev only) |
|
|
| INFO | Normal operation milestones |
|
|
| WARNING | Unexpected but handled (fallbacks) |
|
|
| ERROR | Operation failed, may need attention |
|
|
| CRITICAL | Fatal error, program may crash |
|
|
|
|
## Examples
|
|
|
|
### Good Logging Practice
|
|
```python
|
|
_logger.info("Pipeline run: %s → %s (%s windows)", start, end, count)
|
|
_logger.debug("Batch embedding attempt %d failed: %s", attempt, exc)
|
|
_logger.warning("Fallback used for motion %d: %s", motion_id, reason)
|
|
_logger.error("Query failed: %s", exc)
|
|
```
|
|
|
|
### Bad: Using print()
|
|
```python
|
|
# BAD - don't use print
|
|
print(f"Fetched {len(voting_records)} voting records from API")
|
|
print(f"Error fetching motions from API: {e}")
|
|
```
|
|
|
|
### Good: Using logger
|
|
```python
|
|
# GOOD - use logger
|
|
_logger.info("Fetched %d voting records from API", len(voting_records))
|
|
_logger.error("Error fetching motions from API: %s", e)
|
|
```
|
|
|
|
## Exception Logging
|
|
|
|
Use `_logger.exception()` for caught exceptions (includes traceback):
|
|
|
|
```python
|
|
try:
|
|
result = risky_operation()
|
|
except Exception as exc:
|
|
_logger.exception("Operation failed: %s", exc)
|
|
return fallback_value
|
|
```
|
|
|
|
Use `_logger.error()` with explicit exception for controlled errors:
|
|
|
|
```python
|
|
try:
|
|
result = risky_operation()
|
|
except Exception as exc:
|
|
_logger.error("Operation failed: %s", exc)
|
|
return fallback_value
|
|
```
|
|
|
|
## Configuration
|
|
|
|
Ensure logging is configured in entry points:
|
|
|
|
```python
|
|
# pipeline/run_pipeline.py
|
|
def run(args):
|
|
logging.basicConfig(
|
|
level=logging.INFO,
|
|
format="%(asctime)s %(levelname)s %(name)s: %(message)s",
|
|
)
|
|
# ... rest of pipeline
|
|
```
|
|
|
|
## Anti-Patterns
|
|
|
|
### Debug Prints in Production Code
|
|
```python
|
|
# BAD
|
|
print(f"[TRAJ DEBUG] processing window {wid}")
|
|
|
|
# GOOD
|
|
_logger.debug("Processing window %s", wid)
|
|
```
|
|
|
|
### Inconsistent Logger Names
|
|
```python
|
|
# BAD - mixing _logger and logger
|
|
_logger = logging.getLogger(__name__)
|
|
logger = logging.getLogger("other") # Inconsistent
|
|
|
|
# GOOD - use single consistent pattern
|
|
_logger = logging.getLogger(__name__)
|
|
```
|
|
|
|
### Missing Logger Initialization
|
|
```python
|
|
# BAD - no logger defined
|
|
def some_function():
|
|
logging.getLogger(__name__).info("...") # Redundant calls
|
|
|
|
# GOOD - define once at module level
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
def some_function():
|
|
_logger.info("...")
|
|
```
|
|
|
|
## Sensitive Data
|
|
|
|
Never log sensitive information:
|
|
- API keys
|
|
- User votes
|
|
- Session IDs (if tied to user data)
|
|
- Personal information
|
|
|
|
```python
|
|
# BAD
|
|
_logger.info("User %s voted %s", user_id, vote)
|
|
|
|
# GOOD - log aggregates, not individual votes
|
|
_logger.info("Vote recorded for session %s", session_id[:8])
|
|
```
|
|
|
|
## Structured Logging
|
|
|
|
For complex data, use structured logging:
|
|
|
|
```python
|
|
_logger.info(
|
|
"Motion processed",
|
|
extra={
|
|
"motion_id": motion_id,
|
|
"policy_area": policy_area,
|
|
"processing_time_ms": elapsed_ms,
|
|
}
|
|
)
|
|
```
|
|
|