| """Structured logging helpers for the GCMD classifier MVP.""" |
|
|
| from __future__ import annotations |
|
|
| import logging |
| from typing import Any |
|
|
| _SECRET_MARKERS = ("api_key", "apikey", "authorization", "token", "secret", "password", "header") |
|
|
|
|
| def get_logger(name: str = "gcmd_classifier") -> logging.Logger: |
| """Return a package logger without forcing global logging configuration.""" |
| return logging.getLogger(name) |
|
|
|
|
| def sanitize_log_details(details: dict[str, Any]) -> dict[str, Any]: |
| """Remove values whose keys look like secrets or sensitive headers.""" |
| sanitized: dict[str, Any] = {} |
| for key, value in details.items(): |
| lowered = key.lower() |
| if any(marker in lowered for marker in _SECRET_MARKERS): |
| sanitized[key] = "[REDACTED]" |
| elif isinstance(value, dict): |
| sanitized[key] = sanitize_log_details(value) |
| else: |
| sanitized[key] = value |
| return sanitized |
|
|
|
|
| def log_event(logger: logging.Logger, event: str, **details: Any) -> None: |
| """Emit a structured event through standard logging without secrets.""" |
| safe_details = sanitize_log_details(details) |
| logger.info("gcmd_classifier_event", extra={"event": event, "details": safe_details}) |
|
|