Files
drive/logging_config.py
2026-10-18 23:48:22 +05:30

49 lines
1.8 KiB
Python

"""Logging setup: stdout (always) plus a rotating file locally, with secret redaction."""
from __future__ import annotations
import logging
import logging.handlers
from pathlib import Path
FORMAT = "%(asctime)s %(levelname)-7s %(name)s: %(message)s"
class RedactSecrets(logging.Filter):
"""Replace known secret values in every log record."""
def __init__(self, secrets: list[str]):
super().__init__()
self._secrets = sorted({s for s in secrets if s}, key=len, reverse=True)
def filter(self, record: logging.LogRecord) -> bool:
if not self._secrets:
return True
message = record.getMessage()
redacted = message
for secret in self._secrets:
redacted = redacted.replace(secret, "***")
if redacted != message:
record.msg, record.args = redacted, None
return True
def setup_logging(level: str = "INFO", *, log_dir: Path | None = None, secrets: list[str] | None = None) -> None:
"""``log_dir=None`` logs to stdout only (Heroku collects stdout via `heroku logs`)."""
root = logging.getLogger()
root.setLevel(level)
for handler in list(root.handlers):
root.removeHandler(handler)
redact = RedactSecrets(secrets or [])
handlers: list[logging.Handler] = [logging.StreamHandler()]
if log_dir is not None:
log_dir.mkdir(parents=True, exist_ok=True)
handlers.append(
logging.handlers.RotatingFileHandler(log_dir / "bot.log", maxBytes=10 * 1024 * 1024, backupCount=5, encoding="utf-8")
)
for handler in handlers:
handler.setFormatter(logging.Formatter(FORMAT))
handler.addFilter(redact)
root.addHandler(handler)
for noisy in ("telethon", "googleapiclient.discovery_cache", "urllib3", "google_auth_httplib2"):
logging.getLogger(noisy).setLevel(logging.WARNING)