fix(telemetry): INSERT OR IGNORE + WAL + try/except 三层防御加固
根治遥测写入主键冲突(UNIQUE constraint)和并发写锁(database is locked) 导致的异常冒泡,遥测侧信道错误不再污染 LLM 重试链。 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
+41
-26
@@ -10,6 +10,8 @@ import asyncio
|
||||
import sqlite3
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from loguru import logger
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from pathlib import Path
|
||||
|
||||
@@ -45,7 +47,7 @@ class SQLiteTelemetryRecorder:
|
||||
"""
|
||||
|
||||
_INSERT_SQL = """
|
||||
INSERT INTO llm_calls (
|
||||
INSERT OR IGNORE INTO llm_calls (
|
||||
call_id, parent_call_id, session_id,
|
||||
model_name, provider, messages, response, thinking,
|
||||
prompt_tokens, completion_tokens, latency_ms,
|
||||
@@ -85,33 +87,46 @@ class SQLiteTelemetryRecorder:
|
||||
cache_hit: bool,
|
||||
error: str | None,
|
||||
) -> None:
|
||||
"""同步写入一条 LLM 调用记录到 SQLite。"""
|
||||
conn = sqlite3.connect(str(self._db_path))
|
||||
"""同步写入一条 LLM 调用记录到 SQLite。
|
||||
|
||||
三层防御加固:
|
||||
1. INSERT OR IGNORE — 主键冲突静默忽略
|
||||
2. WAL + busy_timeout — 并发写锁容忍
|
||||
3. try/except sqlite3.Error — DB 错误不冒泡到调用方
|
||||
"""
|
||||
try:
|
||||
self._ensure_table(conn)
|
||||
conn.execute(
|
||||
self._INSERT_SQL,
|
||||
(
|
||||
call_id,
|
||||
parent_call_id,
|
||||
session_id,
|
||||
model_name,
|
||||
provider,
|
||||
messages,
|
||||
response,
|
||||
thinking,
|
||||
prompt_tokens,
|
||||
completion_tokens,
|
||||
latency_ms,
|
||||
ttft_ms,
|
||||
max_inter_token_ms,
|
||||
int(cache_hit),
|
||||
error,
|
||||
),
|
||||
conn = sqlite3.connect(str(self._db_path), timeout=10.0)
|
||||
try:
|
||||
conn.execute("PRAGMA journal_mode=WAL")
|
||||
conn.execute("PRAGMA busy_timeout=5000")
|
||||
self._ensure_table(conn)
|
||||
conn.execute(
|
||||
self._INSERT_SQL,
|
||||
(
|
||||
call_id,
|
||||
parent_call_id,
|
||||
session_id,
|
||||
model_name,
|
||||
provider,
|
||||
messages,
|
||||
response,
|
||||
thinking,
|
||||
prompt_tokens,
|
||||
completion_tokens,
|
||||
latency_ms,
|
||||
ttft_ms,
|
||||
max_inter_token_ms,
|
||||
int(cache_hit),
|
||||
error,
|
||||
),
|
||||
)
|
||||
conn.commit()
|
||||
finally:
|
||||
conn.close()
|
||||
except sqlite3.Error as exc:
|
||||
logger.warning(
|
||||
"遥测写入失败(已降级),call_id={}: {}", call_id, exc
|
||||
)
|
||||
conn.commit()
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
async def record_llm_call(
|
||||
self,
|
||||
|
||||
Reference in New Issue
Block a user