feat: record stream end mode in telemetry
llm_calls gains a nullable stream_end TEXT column (auto backfill, manual-mode trimming as in 1.3.8). TelemetryRecorder.record_llm_call takes a new required keyword stream_end; the emitter reads it from the response on attempt rows and writes NULL for failed, cache-hit and terminal rows. Red: 18 tests in tests/unit/test_telemetry.py and test_ports.py failed against the pre-change source (missing column, 38-field signature, stream_end absent from emitted rows).
This commit is contained in:
@@ -72,6 +72,8 @@ _EXPECTED_COLUMNS = [
|
||||
# —— 1.3.8 沉默归因两列(issue #27)——
|
||||
"stall_ms",
|
||||
"stall_count",
|
||||
# —— 1.3.10 结束方式(#31)——
|
||||
"stream_end",
|
||||
]
|
||||
|
||||
# 1.3.5 之前那张表的 27 个物理列(26 个 INSERT 字段 + created_at)。写成固定切片
|
||||
@@ -173,6 +175,8 @@ def _minimal_fields(call_id: str | None = None, **overrides) -> dict[str, object
|
||||
# —— 1.3.8 两列: 沉默归因只属流式 chat 成功 attempt 行(issue #27),普通行 NULL ——
|
||||
"stall_ms": None,
|
||||
"stall_count": None,
|
||||
# —— 1.3.10: 结束方式只属流式成功 attempt 行,普通行 NULL ——
|
||||
"stream_end": None,
|
||||
}
|
||||
fields.update(overrides)
|
||||
return fields
|
||||
@@ -775,7 +779,7 @@ class TestCallerDimensionsAcceptance:
|
||||
"WHERE table_schema = $1 AND table_name = 'llm_calls' ORDER BY ordinal_position",
|
||||
schema,
|
||||
)
|
||||
# 22 → 38 个 recorder 字段(加 created_at 共 39 个物理列),且新列追加在末尾
|
||||
# 22 → 39 个 recorder 字段(加 created_at 共 40 个物理列),且新列追加在末尾
|
||||
assert [r["column_name"] for r in cols] == _EXPECTED_COLUMNS
|
||||
rows = await _fetch(
|
||||
schema_dsn,
|
||||
@@ -1106,7 +1110,7 @@ class TestCallObservabilityColumnsAcceptance:
|
||||
"""
|
||||
|
||||
async def test_pre_135_table_gains_the_ten_columns_and_old_rows_stay_null(self, pre_135_schema):
|
||||
"""27 列旧表 auto 补齐到 39 列(1.3.5 十列 + 1.3.8 两列),新行两类取值读得回,**历史行新增列一律 NULL**。
|
||||
"""27 列旧表 auto 补齐到 40 列(1.3.5 十列 + 1.3.8 两列 + 1.3.10 一列),新行两类取值读得回,**历史行新增列一律 NULL**。
|
||||
|
||||
旧行不回填是本版的明示决策(设计 §5): NULL 表达的是"补列之前根本没记过
|
||||
这件事",与任何哨兵值都不是一回事。若哪天有人给这十列加了 DEFAULT,历史行
|
||||
@@ -1148,7 +1152,7 @@ class TestCallObservabilityColumnsAcceptance:
|
||||
"WHERE table_schema = $1 AND table_name = 'llm_calls' ORDER BY ordinal_position",
|
||||
schema,
|
||||
)
|
||||
# 26 → 38 个 recorder 字段(加 created_at 共 39 个物理列),新列追加在末尾:
|
||||
# 26 → 39 个 recorder 字段(加 created_at 共 40 个物理列),新列追加在末尾:
|
||||
# 列序与新建库一致才不会让两条升级路径分叉
|
||||
assert [r["column_name"] for r in cols] == _EXPECTED_COLUMNS
|
||||
|
||||
@@ -1176,6 +1180,8 @@ class TestCallObservabilityColumnsAcceptance:
|
||||
# 1.3.8 两列: 普通成功 attempt 行无沉默观测 → NULL
|
||||
"stall_ms": None,
|
||||
"stall_count": None,
|
||||
# 1.3.10: 该行未传结束方式 → NULL
|
||||
"stream_end": None,
|
||||
}
|
||||
assert dict(by_id["term"]) == {
|
||||
"call_id": "term",
|
||||
@@ -1192,6 +1198,8 @@ class TestCallObservabilityColumnsAcceptance:
|
||||
# 1.3.8 两列: 终态行无 transport 观测 → NULL
|
||||
"stall_ms": None,
|
||||
"stall_count": None,
|
||||
# 1.3.10: 终态行无流可言 → NULL
|
||||
"stream_end": None,
|
||||
}
|
||||
# 历史行: 十列逐列 NULL(整体比对,漏掉任一列都红)
|
||||
assert dict(by_id["pre135"]) == {
|
||||
@@ -1349,7 +1357,7 @@ class TestPublishedSchemaScript:
|
||||
|
||||
await _execute_script(fresh_dsn, script)
|
||||
actual = [r["column_name"] for r in await _fetch(fresh_dsn, _PHYSICAL_COLUMNS_SQL, schema)]
|
||||
# 物理列 = 38 个 INSERT 字段 + 库从不显式写的 created_at;对着库常量比,不另抄一份
|
||||
# 物理列 = 39 个 INSERT 字段 + 库从不显式写的 created_at;对着库常量比,不另抄一份
|
||||
assert set(actual) == set(COLUMNS) | {"created_at"}
|
||||
# 列序也不许漂: 新列必须排在 created_at 之后,否则新建库与 ALTER 升级的列序分叉
|
||||
assert actual == _EXPECTED_COLUMNS
|
||||
|
||||
Reference in New Issue
Block a user