from __future__ import annotations import json import logging import sys from datetime import datetime, timezone class JsonLineFormatter(logging.Formatter): def format(self, record: logging.LogRecord) -> str: payload = { 'ts': datetime.now(timezone.utc).isoformat(), 'level': record.levelname, 'logger': record.name, 'message': record.getMessage(), } if record.exc_info: payload['exception'] = self.formatException(record.exc_info) return json.dumps(payload, ensure_ascii=False) def setup_logging(name: str = 'app_kit', level: int = logging.INFO, stream=None) -> logging.Logger: logger = logging.getLogger(name) logger.setLevel(level) if not any(getattr(h, '_all4_json', False) for h in logger.handlers): handler = logging.StreamHandler(stream or sys.stdout) handler._all4_json = True # type: ignore[attr-defined] handler.setFormatter(JsonLineFormatter()) logger.addHandler(handler) logger.propagate = False return logger