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.
3.0 KiB
3.0 KiB
| title | category | severity |
|---|---|---|
| Logging Constraints | constraints | critical |
Logging Constraints
Core Rule
Use logging.getLogger(__name__) - never use print()
CRITICAL ANTI-PATTERN: api_client.py uses print() instead of logging (11 instances).
CRITICAL Anti-Pattern: print() Instead of Logging
File: api_client.py
Evidence: Lines with print(f"...") instead of _logger.info(...)
Broken code:
def get_motions(self, ...):
try:
# ...
print(f"Fetched {len(voting_records)} voting records from API") # BAD
print(f"Processed into {len(motions)} unique motions") # BAD
except Exception as e:
print(f"Error fetching motions from API: {e}") # BAD - no traceback
Fix:
import logging
_logger = logging.getLogger(__name__)
def get_motions(self, ...):
try:
_logger.info("Fetched %d voting records from API", len(voting_records))
_logger.info("Processed into %d unique motions", len(motions))
except Exception as e:
_logger.exception("Error fetching motions from API: %s", e)
return []
Logger Initialization
Get logger at module level:
# 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:
# 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__)
INCONSISTENCY WARNING: 16 files use logger, 17 files use _logger. Choose one convention.
Recommendation: Use _logger (with underscore) for module-level loggers to distinguish from class-level loggers.
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 |
Exception Logging
Use _logger.exception() for caught exceptions (includes traceback):
try:
result = risky_operation()
except Exception as exc:
_logger.exception("Operation failed: %s", exc)
return fallback_value
Anti-Patterns
Debug Prints in Production Code
# BAD
print(f"[TRAJ DEBUG] processing window {wid}")
# GOOD
_logger.debug("Processing window %s", wid)
Inconsistent Logger Names
# BAD - mixing _logger and logger
_logger = logging.getLogger(__name__)
logger = logging.getLogger("other") # Inconsistent
Sensitive Data
Never log sensitive information:
- API keys
- User votes
- Session IDs (if tied to user data)
- Personal information
# 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])