feat: record call observability columns and terminal failure rows
Grow the telemetry contract from 26 to 36 fields and give every logical call a failure terminal row, so SQL can finally answer "how many calls failed" and "why did the whole pool die". Schema and port move together with the emitter writes in one commit: splitting them would ship columns that nothing populates. - schema: append 10 nullable columns (scope, operation, logical_call_id, event_kind, http_status_code, error_type, cause_type, error_body, attempts, total_latency_ms) to all five definition sites in one order - ports: 10 keyword-only parameters without defaults; the protocol signature is now the single source the assembly gate derives from - emitter: take domain exception objects instead of pre-flattened text and pin down the diagnostics in one helper; a relabelled 503 stays 503 and success rows leave all five columns NULL - emitter: reject recorders whose record_llm_call cannot accept the current field shape at assembly time, since _record would otherwise swallow the TypeError and drop every row while calls keep succeeding - clients: write at most one terminal row per logical call through a single shared exit, deduplicated by the call context; TelemetryMW stops writing terminals so the two sites cannot double count - clients: cancellation stays best effort and propagates, non-domain exceptions get no terminal row and keep their classification - transports: give _status_to_error an explicit operation and fix the historically mislabelled embedding HTTP failures - structured: promote the bounded error formatter so the reask feedback and the terminal explanation share one set of limits Terminal rows carry no cost and no tokens, so cost aggregation is unchanged; failure counts must now filter on event_kind.
This commit is contained in:
@@ -271,7 +271,7 @@ class TelemetryStatusProvider(Protocol):
|
||||
|
||||
@runtime_checkable
|
||||
class TelemetryRecorder(Protocol):
|
||||
"""遥测后端;26 字段冻结(M1 设计 §4.4 + issue #3/#4/#11/#16/#20),唯一调用点是 TelemetryEmitter。
|
||||
"""遥测后端;36 字段冻结(M1 设计 §4.4 + issue #3/#4/#11/#16/#20 + 1.3.5),唯一调用点是 TelemetryEmitter。
|
||||
|
||||
新增参数不设默认值: 库外无第三方实现者(三项目迁移时删除了各自的同名
|
||||
Protocol),完整签名的成本为零,而少写一列会被 emitter 的降级吞成 warning。
|
||||
@@ -286,6 +286,15 @@ class TelemetryRecorder(Protocol):
|
||||
|
||||
recorder 只负责落库,不做任何语义判断,与 `sampling` 列由
|
||||
`canonical_sampling_json()` 在 emitter 侧定型是同一先例。
|
||||
|
||||
1.3.5 新增十列同理已在 emitter 侧定型: `operation` 是**公开方法**四值之一
|
||||
(与 `PolyGatewayError.operation` 这个 HTTP 子操作是两个语义);`event_kind` 区分
|
||||
attempt / cache_hit / terminal_failure 三类行;`attempts` 与 `total_latency_ms`
|
||||
只在终态行非空;`error_body` 沿用 transport 侧 `summarize_body` 的上限,
|
||||
**不进 `PGW_TELEMETRY_TEXT_CAP` 的覆盖面**。
|
||||
|
||||
**本签名是装配闸的唯一事实源**: `TelemetryEmitter.__init__` 按它派生参数名做
|
||||
一次 `signature.bind` 形状校验(设计 §7),改本签名即改闸的判据。
|
||||
"""
|
||||
|
||||
async def record_llm_call(
|
||||
@@ -317,4 +326,14 @@ class TelemetryRecorder(Protocol):
|
||||
meta: str,
|
||||
thinking_observation: str,
|
||||
reasoning_effort: str | None,
|
||||
scope: str,
|
||||
operation: str,
|
||||
logical_call_id: str | None,
|
||||
event_kind: str,
|
||||
http_status_code: int | None,
|
||||
error_type: str | None,
|
||||
cause_type: str | None,
|
||||
error_body: str | None,
|
||||
attempts: int | None,
|
||||
total_latency_ms: int | None,
|
||||
) -> None: ...
|
||||
|
||||
Reference in New Issue
Block a user