# ============================================================ # Project: EDGAR Research Database # Description: SEC EDGAR Research Infrastructure # # Authors: # - Manel Kammoun — manel.kammoun@uqo.ca # - Djerrycharli Tandjambianda — djerrycharli.tandjambianda@uqo.ca # - Simon-Pierre Boucher — simon-pierre.boucher@uqo.ca # # Institution: # Université du Québec en Outaouais (UQO) # # License: # Research / Academic Use # ============================================================ from __future__ import annotations import json import logging import os import sys from datetime import datetime, timezone from pathlib import Path class JsonFormatter(logging.Formatter): def format(self, record: logging.LogRecord) -> str: log_entry = { "timestamp": datetime.now(timezone.utc).isoformat(), "level": record.levelname, "logger": record.name, "message": record.getMessage(), } if record.exc_info and record.exc_info[1]: log_entry["exception"] = self.formatException(record.exc_info) for key in ("filing", "cik", "accession", "form_type", "step"): val = getattr(record, key, None) if val is not None: log_entry[key] = val return json.dumps(log_entry) def setup_logging( name: str = "edgar", level: str | None = None, log_dir: Path | None = None, log_format: str | None = None, ) -> logging.Logger: level = level or os.environ.get("LOG_LEVEL", "INFO") log_format = log_format or os.environ.get("LOG_FORMAT", "text") logger = logging.getLogger(name) logger.setLevel(getattr(logging, level.upper(), logging.INFO)) if logger.handlers: return logger console = logging.StreamHandler(sys.stdout) if log_format == "json": console.setFormatter(JsonFormatter()) else: console.setFormatter( logging.Formatter("%(asctime)s [%(levelname)-8s] %(name)s — %(message)s") ) logger.addHandler(console) if log_dir: log_dir.mkdir(parents=True, exist_ok=True) today = datetime.now().strftime("%Y-%m-%d") file_handler = logging.FileHandler(log_dir / f"{name}_{today}.log") file_handler.setFormatter(JsonFormatter()) logger.addHandler(file_handler) return logger def get_logger(name: str) -> logging.Logger: return logging.getLogger(f"edgar.{name}")