raghava4u's picture
Upload folder using huggingface_hub
d53dc44 verified
Raw History Blame Contribute Delete
3.21 kB
"""
monitoring/logger.py — Structured JSON logging with file and console handlers.
All log entries are structured JSON for machine parsing.
"""
from __future__ import annotations
import json
import logging
import os
import sys
from datetime import datetime, timezone
from pathlib import Path
import config
LOG_DIR = Path(config.BASE_DIR) / "logs"
LOG_DIR.mkdir(parents=True, exist_ok=True)
class JSONFormatter(logging.Formatter):
"""Structured JSON log 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(),
"module": record.module,
"function": record.funcName,
"line": record.lineno,
}
if record.exc_info and record.exc_info[1]:
log_entry["exception"] = str(record.exc_info[1])
if config.DRY_RUN:
log_entry["mode"] = "DRY_RUN"
elif config.TRADING_MODE == "paper":
log_entry["mode"] = "PAPER"
else:
log_entry["mode"] = config.TRADING_MODE.upper()
return json.dumps(log_entry)
class ConsoleFormatter(logging.Formatter):
"""Colored console formatter."""
COLORS = {
"DEBUG": "\033[36m",
"INFO": "\033[32m",
"WARNING": "\033[33m",
"ERROR": "\033[31m",
"CRITICAL": "\033[1;31m",
}
RESET = "\033[0m"
def format(self, record: logging.LogRecord) -> str:
color = self.COLORS.get(record.levelname, "")
prefix = "[DRY_RUN] " if config.DRY_RUN else ""
return (
f"{color}{record.levelname:8s}{self.RESET} "
f"{prefix}{record.name}: {record.getMessage()}"
)
def setup_logging(level: str = "INFO"):
"""Configure logging for the entire trading system."""
root = logging.getLogger()
root.setLevel(getattr(logging, level.upper(), logging.INFO))
# Remove existing handlers
root.handlers.clear()
# Console handler
console = logging.StreamHandler(sys.stdout)
console.setFormatter(ConsoleFormatter())
console.setLevel(logging.INFO)
root.addHandler(console)
# JSON file handler
today = datetime.now().strftime("%Y-%m-%d")
log_file = LOG_DIR / f"trading_{today}.jsonl"
file_handler = logging.FileHandler(str(log_file), encoding="utf-8")
file_handler.setFormatter(JSONFormatter())
file_handler.setLevel(logging.DEBUG)
root.addHandler(file_handler)
# Error file handler
error_file = LOG_DIR / f"errors_{today}.jsonl"
error_handler = logging.FileHandler(str(error_file), encoding="utf-8")
error_handler.setFormatter(JSONFormatter())
error_handler.setLevel(logging.ERROR)
root.addHandler(error_handler)
logging.getLogger("urllib3").setLevel(logging.WARNING)
logging.getLogger("websocket").setLevel(logging.WARNING)
logger = logging.getLogger("trading_system")
logger.info("Logging initialized: console + %s", log_file)
return logger