fix(system): 优化服务状态检查的异常处理逻辑

在 `system.py` 中更新了服务状态检查的异常处理逻辑,当 supervisor 未安装或未运行时,记录为 WARNING 并返回友好的错误信息。增强了日志记录的可读性,确保在出现问题时提供清晰的反馈。同时,在 `position_manager.py` 中改进了止损止盈检查的错误日志,确保记录详细的错误信息以便于调试。
This commit is contained in:
薇薇安 2026-02-17 07:53:54 +08:00
parent c750478af9
commit 3a2536ae96
3 changed files with 42 additions and 16 deletions

View File

@ -917,14 +917,28 @@ async def list_trading_services(_admin: Dict[str, Any] = Depends(require_system_
"raw": status_all
}
except Exception as e:
# 如果 supervisorctl status 失败,可能返回非 0 exit code
# 但 _run_supervisorctl 已经处理了 status 命令的 exit 3 (stopped)
# 如果是其他错误,记录日志并返回空列表
# supervisor 未安装/未运行时(如 unix socket 不存在)避免刷 ERROR改为 WARNING 并返回友好说明
err_msg = str(e).strip()
if not err_msg:
err_msg = repr(e)
is_supervisor_unavailable = (
"no such file" in err_msg.lower()
or "connection refused" in err_msg.lower()
or "sock" in err_msg.lower()
or "unix://" in err_msg.lower()
)
if is_supervisor_unavailable:
logger.warning(f"列出服务失败supervisor 未运行或不可用): {err_msg}")
return {
"summary": {"total": 0, "running": 0, "stopped": 0, "unknown": 0},
"services": [],
"error": "supervisor 未安装或未运行,请检查 supervisord 或配置 SUPERVISOR_CONF"
}
logger.error(f"列出服务失败: {e}")
return {
"summary": {"total": 0, "running": 0, "stopped": 0, "unknown": 0},
"services": [],
"error": str(e)
"error": err_msg
}

View File

@ -2032,30 +2032,41 @@ class BinanceClient:
# 优先尝试 WebSocket 下单(减少 REST 超时)
if self._ws_trade_client and self._ws_trade_client.is_connected():
try:
# 准备 WS 参数(需包含 apiKey, timestamp, signature
# 准备 WS 参数(与币安 WS 文档一致apiKey, timestamp, recvWindow, 其余同 REST
ws_params = dict(params)
ws_params["apiKey"] = self.api_key
ts_ms = int(time.time() * 1000)
if "timestamp" not in ws_params:
ws_params["timestamp"] = int(time.time() * 1000)
# 计算签名:币安要求参与签名的值格式与 REST 一致(布尔小写、空值不参与或为空串)
ws_params["timestamp"] = ts_ms
else:
ws_params["timestamp"] = int(ws_params["timestamp"])
# 扩大接收窗口,避免服务器与本地时钟偏差导致签名被拒
ws_params["recvWindow"] = 60000
# 币安 WS 文档中 closePosition 为 STRING发送与签名均用 "true"/"false"
if ws_params.get("closePosition") is True:
ws_params["closePosition"] = "true"
elif ws_params.get("closePosition") is False:
ws_params["closePosition"] = "false"
# 计算签名:参与签名的字符串必须与 REST 一致(键按字母序、值统一为字符串,布尔为 true/false
if "signature" not in ws_params:
import hmac
import hashlib
from urllib.parse import urlencode
def _param_val_for_signature(v):
def _val_for_sig(v):
if v is True:
return "true"
if v is False:
return "false"
if v is None:
return ""
s = str(v).strip()
return s if s else ""
sign_params = [(k, _param_val_for_signature(v)) for k, v in ws_params.items() if k != "signature"]
query_string = urlencode(sorted(sign_params))
if isinstance(v, (int, float)):
return str(int(v)) if isinstance(v, float) and v == int(v) else str(v)
return str(v).strip()
to_sign = [(k, _val_for_sig(v)) for k, v in ws_params.items() if k != "signature"]
query_string = urlencode(sorted(to_sign))
signature = hmac.new(
self.api_secret.encode('utf-8'),
query_string.encode('utf-8'),
self.api_secret.encode("utf-8"),
query_string.encode("utf-8"),
hashlib.sha256
).hexdigest()
ws_params["signature"] = signature
@ -2357,7 +2368,7 @@ class BinanceClient:
# 如果还是失败,记录详细参数用于调试
logger.error(f"{symbol} ❌ 所有重试都失败,保护单挂单失败")
logger.error(f" 参数: {params}")
logger.error(f" 对冲模式: {dual}")
logger.error(f" 对冲模式: {dual}None 表示无法读取持仓模式,请检查网络或 API 权限)")
return None
except BinanceAPIException as e:

View File

@ -2383,7 +2383,8 @@ class PositionManager:
continue
except Exception as e:
logger.error(f"检查止损止盈失败: {e}")
err_msg = str(e).strip() or repr(e) or type(e).__name__
logger.error(f"检查止损止盈失败: {err_msg}")
return closed_positions