chore: auto release commit (2026-09-15 00:32:44)
All checks were successful
技能自动化发布 / release (push) Successful in 7s
All checks were successful
技能自动化发布 / release (push) Successful in 7s
This commit is contained in:
@@ -1,20 +1,35 @@
|
||||
"""logging 配置:降级到 stderr,避免污染 stdout(stdout 留给结构化输出如 JSON)。
|
||||
|
||||
优先用 jiangchang_skill_core 提供的 logging;本地无该包时降级到 stderr。
|
||||
|
||||
v1.1.18:本地降级路径追加 RotatingFileHandler(按 LOG_FILE env 决定是否落文件)。
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import logging.handlers
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
from util.constants import LOG_LOGGER_NAME, SKILL_SLUG, SKILL_VERSION
|
||||
from util.constants import (
|
||||
LOG_LOGGER_NAME,
|
||||
SKILL_SLUG,
|
||||
SKILL_VERSION,
|
||||
)
|
||||
|
||||
_configured = False
|
||||
|
||||
|
||||
def setup_skill_logging() -> logging.Logger:
|
||||
"""初始化 skill logger(幂等)。"""
|
||||
"""初始化 skill logger(幂等)。
|
||||
|
||||
本地降级行为(无 jiangchang_skill_core 时):
|
||||
- 若 LOG_FILE 已设:追加 RotatingFileHandler(LOG_MAX_BYTES × LOG_BACKUP_COUNT)
|
||||
- 始终追加 StreamHandler(sys.stderr)
|
||||
- logger level 取自 LOG_LEVEL(默认 INFO)
|
||||
"""
|
||||
global _configured
|
||||
logger = logging.getLogger(LOG_LOGGER_NAME)
|
||||
if _configured:
|
||||
@@ -30,15 +45,38 @@ def setup_skill_logging() -> logging.Logger:
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
# 本地降级:基础 stderr handler,UTF-8 safe
|
||||
handler = logging.StreamHandler(sys.stderr)
|
||||
handler.setFormatter(
|
||||
logging.Formatter(
|
||||
fmt=f"%(asctime)s [{SKILL_SLUG}] %(levelname)s %(message)s",
|
||||
datefmt="%Y-%m-%d %H:%M:%S",
|
||||
)
|
||||
# logger 级别
|
||||
level_name = os.environ.get("LOG_LEVEL", "INFO").upper()
|
||||
logger.setLevel(getattr(logging, level_name, logging.INFO))
|
||||
|
||||
formatter = logging.Formatter(
|
||||
fmt=f"%(asctime)s [{SKILL_SLUG}] %(levelname)s %(message)s",
|
||||
datefmt="%Y-%m-%d %H:%M:%S",
|
||||
)
|
||||
logger.setLevel(logging.INFO)
|
||||
|
||||
# 本地降级:可选 RotatingFileHandler
|
||||
log_file_str = os.environ.get("LOG_FILE")
|
||||
if log_file_str:
|
||||
log_path = Path(log_file_str)
|
||||
if not log_path.is_absolute():
|
||||
from util.runtime_paths import get_logs_dir
|
||||
|
||||
log_path = get_logs_dir() / log_file_str
|
||||
log_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
max_bytes = int(os.environ.get("LOG_MAX_BYTES", str(5 * 1024 * 1024)))
|
||||
backup_count = int(os.environ.get("LOG_BACKUP_COUNT", "5"))
|
||||
file_handler = logging.handlers.RotatingFileHandler(
|
||||
log_path,
|
||||
maxBytes=max_bytes,
|
||||
backupCount=backup_count,
|
||||
encoding="utf-8",
|
||||
)
|
||||
file_handler.setFormatter(formatter)
|
||||
logger.addHandler(file_handler)
|
||||
|
||||
# 始终保留 stderr handler
|
||||
handler = logging.StreamHandler(sys.stderr)
|
||||
handler.setFormatter(formatter)
|
||||
logger.addHandler(handler)
|
||||
logger.propagate = False
|
||||
_configured = True
|
||||
@@ -51,3 +89,19 @@ def get_skill_logger() -> logging.Logger:
|
||||
if not _configured:
|
||||
return setup_skill_logging()
|
||||
return logging.getLogger(LOG_LOGGER_NAME)
|
||||
|
||||
|
||||
def reset_for_tests() -> None:
|
||||
"""测试用:重置 _configured flag,让 setup_skill_logging 重新初始化。
|
||||
|
||||
必须在每个修改日志配置的测试 fixture 里调用,否则 env 改动不会生效。
|
||||
"""
|
||||
global _configured
|
||||
logger = logging.getLogger(LOG_LOGGER_NAME)
|
||||
for h in list(logger.handlers):
|
||||
try:
|
||||
h.close()
|
||||
except Exception:
|
||||
pass
|
||||
logger.removeHandler(h)
|
||||
_configured = False
|
||||
|
||||
Reference in New Issue
Block a user