Spaces:
Sleeping
Sleeping
File size: 1,997 Bytes
083d098 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | from __future__ import annotations
import json
import logging
import logging.handlers
import os
from datetime import datetime, timezone
# Mirrors Hugging Face's LOG_LEVEL convention; use BEACON_ prefix to avoid collisions.
_LOG_LEVEL = os.getenv("BEACON_LOG_LEVEL", "WARNING").upper()
_LOG_DIR = os.getenv("BEACON_LOG_DIR", "logs")
_configured = False
class _JSONFormatter(logging.Formatter):
"""Structured JSON lines for the rotating file handler."""
def format(self, record: logging.LogRecord) -> str:
entry: dict = {
"timestamp": datetime.now(timezone.utc).isoformat(),
"level": record.levelname,
"logger": record.name,
"message": record.getMessage(),
}
if hasattr(record, "data"):
entry["data"] = record.data
return json.dumps(entry, default=str)
def _setup() -> None:
global _configured
if _configured:
return
_configured = True
level = getattr(logging, _LOG_LEVEL, logging.WARNING)
root = logging.getLogger("beacon")
root.setLevel(logging.DEBUG) # individual handlers apply their own level
root.propagate = False
# Console — same format string as HuggingFace transformers/datasets
console = logging.StreamHandler()
console.setLevel(level)
console.setFormatter(logging.Formatter("%(levelname)s:%(name)s:%(message)s"))
root.addHandler(console)
# Rotating JSON file — always DEBUG so nothing is silently dropped
os.makedirs(_LOG_DIR, exist_ok=True)
fh = logging.handlers.RotatingFileHandler(
os.path.join(_LOG_DIR, "beacon.log"),
maxBytes=10 * 1024 * 1024,
backupCount=5,
encoding="utf-8",
)
fh.setLevel(logging.DEBUG)
fh.setFormatter(_JSONFormatter())
root.addHandler(fh)
def get_logger(name: str) -> logging.Logger:
"""Return a ``beacon.<name>`` logger, configuring handlers on first call."""
_setup()
return logging.getLogger(f"beacon.{name}")
|