50 lines
1.8 KiB
Python

import json
import logging
import time
from pathlib import Path
from typing import Any, Dict
class AuditLogger:
def __init__(self, log_path: str):
self.log_path = Path(log_path)
self.log_path.parent.mkdir(parents=True, exist_ok=True)
self.json_log_path = self.log_path.with_suffix(".jsonl")
self.text_logger = logging.getLogger("audit_text")
self.text_logger.setLevel(logging.INFO)
if not self.text_logger.handlers:
handler = logging.FileHandler(self.log_path, encoding="utf-8")
formatter = logging.Formatter("%(asctime)s %(levelname)s %(message)s")
handler.setFormatter(formatter)
self.text_logger.addHandler(handler)
@staticmethod
def sanitize(payload: Dict[str, Any]) -> Dict[str, Any]:
hidden_keys = {"token", "authorization", "password", "password_hash", "command"}
sanitized: Dict[str, Any] = {}
for key, value in payload.items():
if key.lower() in hidden_keys:
sanitized[key] = "***"
else:
sanitized[key] = value
return sanitized
def log(self, **kwargs: Any) -> None:
start = time.perf_counter()
record = self.sanitize(kwargs)
record["ts"] = time.time()
record["duration_ms"] = int((time.perf_counter() - start) * 1000)
self.text_logger.info(
"operation=%s target=%s result=%s code=%s request_id=%s",
record.get("operation"),
record.get("target"),
record.get("result"),
record.get("error_code"),
record.get("request_id"),
)
with self.json_log_path.open("a", encoding="utf-8") as file:
file.write(json.dumps(record, ensure_ascii=False) + "\n")