- alphaear-deepear-lite: DeepEar Lite API integration - alphaear-logic-visualizer: Draw.io XML finance diagrams - alphaear-news: Real-time finance news (10+ sources) - alphaear-predictor: Kronos time-series forecasting - alphaear-reporter: Professional financial reports - alphaear-search: Web search + local RAG - alphaear-sentiment: FinBERT/LLM sentiment analysis - alphaear-signal-tracker: Signal evolution tracking - alphaear-stock: A-Share/HK/US stock data Updates: - All scripts updated to use universal .env path - Added JINA_API_KEY, LLM_*, DEEPSEEK_API_KEY to .env.example - Updated load_dotenv() to use ~/.config/opencode/.env
46 lines
1.0 KiB
Python
46 lines
1.0 KiB
Python
import os
|
|
import sys
|
|
from datetime import datetime
|
|
from typing import Optional
|
|
|
|
from loguru import logger
|
|
|
|
|
|
def setup_file_logging(
|
|
run_id: str,
|
|
log_dir: str = "logs",
|
|
level: str = "INFO",
|
|
retention: str = "10 days",
|
|
rotation: str = "20 MB",
|
|
) -> str:
|
|
"""Configure Loguru to log to stderr + a per-run file.
|
|
|
|
Returns the log file path.
|
|
"""
|
|
os.makedirs(log_dir, exist_ok=True)
|
|
|
|
# Remove default handler to avoid duplicate logs.
|
|
logger.remove()
|
|
|
|
# Console
|
|
logger.add(sys.stderr, level=level, backtrace=False, diagnose=False)
|
|
|
|
# File (safe for multi-thread via enqueue)
|
|
log_path = os.path.join(log_dir, f"signalflux_{run_id}.log")
|
|
logger.add(
|
|
log_path,
|
|
level=level,
|
|
rotation=rotation,
|
|
retention=retention,
|
|
enqueue=True,
|
|
backtrace=True,
|
|
diagnose=False,
|
|
encoding="utf-8",
|
|
)
|
|
return log_path
|
|
|
|
|
|
def make_run_id(prefix: Optional[str] = None) -> str:
|
|
ts = datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
return f"{prefix}_{ts}" if prefix else ts
|