- db_layer 新增 reclaim_stale_processing: PROCESSING 超过 push_timeout+120s 重置 PENDING - dispatcher 轮询前先回收僵尸任务(进程重启/Edge重启导致 in-flight 请求丢失的场景) - logger 增加 fam-core/logs/fam-core.log 文件输出(daemon 模式 stdout 不可见)
45 lines
1.5 KiB
Python
45 lines
1.5 KiB
Python
"""
|
||
日志工具 - 统一格式,带 task_id 作为 trace_id
|
||
"""
|
||
import logging
|
||
import os
|
||
import sys
|
||
from datetime import datetime
|
||
|
||
# 日志目录:fam-core/logs/(相对 src 的上一级),失败则退化为仅 stdout
|
||
_LOG_DIR = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), 'logs')
|
||
|
||
|
||
def setup_logger(name='fam-core', level=logging.INFO):
|
||
"""配置并返回 logger(stdout + 文件双写)"""
|
||
logger = logging.getLogger(name)
|
||
if logger.handlers:
|
||
return logger
|
||
logger.setLevel(level)
|
||
formatter = logging.Formatter(
|
||
'%(asctime)s [%(name)s] %(levelname)s %(message)s',
|
||
datefmt='%Y-%m-%d %H:%M:%S'
|
||
)
|
||
handler = logging.StreamHandler(sys.stdout)
|
||
handler.setFormatter(formatter)
|
||
logger.addHandler(handler)
|
||
# 文件输出(daemon 模式下 stdout 不可见,文件是唯一可追溯日志)
|
||
try:
|
||
os.makedirs(_LOG_DIR, exist_ok=True)
|
||
file_handler = logging.FileHandler(
|
||
os.path.join(_LOG_DIR, 'fam-core.log'), encoding='utf-8')
|
||
file_handler.setFormatter(formatter)
|
||
logger.addHandler(file_handler)
|
||
except OSError:
|
||
pass # 目录不可写时退化为仅 stdout
|
||
return logger
|
||
|
||
|
||
def log_task(logger, task_id, stage, message, level=logging.INFO, duration_ms=None):
|
||
"""带 task_id 的结构化日志"""
|
||
parts = [f"[task_id={task_id}]", stage]
|
||
if duration_ms is not None:
|
||
parts.append(f"done in {duration_ms}ms")
|
||
parts.append(message)
|
||
logger.log(level, ' '.join(parts))
|