fix: check the meta key budget before scanning every key
The key-count cap exists to catch a whole request body dumped into meta. That is exactly the shape where the per-key regex runs tens of thousands of times before the real reason surfaces, so the cheap check goes first. Also correct two stale docstrings: postgres.py still claimed 22 columns (it is 24), and _canonical_meta_json promised to raise on non-finite floats. It is evaluated inside _record's degradation try, so the real outcome is a warning plus a dropped row -- never an error the caller sees. What the gate actually buys us is the SQLite side, whose meta is a TEXT column that would happily store a literal NaN.
This commit is contained in:
@@ -115,6 +115,10 @@ def _validate_tenant_id(tenant_id: str | None, origin: str) -> None:
|
||||
|
||||
def _validate_meta_keys(meta: Mapping[str, Any], origin: str) -> None:
|
||||
"""键形态与数量;键集合被假定为低基数且稳定,故收紧到 OTel semconv 字符集。"""
|
||||
# 数量闸先于逐键校验: 这道闸要防的正是"整个请求体被塞进 meta"的形态,
|
||||
# 那时逐键正则会先跑上万次才报出真正的原因,拖慢的恰是出错路径
|
||||
if len(meta) > _META_MAX_KEYS:
|
||||
raise ValueError(f"{origin} 的 meta 键数超限(上限 {_META_MAX_KEYS}): {len(meta)}")
|
||||
for key in meta:
|
||||
if not isinstance(key, str):
|
||||
raise ValueError(f"{origin} 的 meta 键必须是 str: {key!r}")
|
||||
@@ -127,8 +131,6 @@ def _validate_meta_keys(meta: Mapping[str, Any], origin: str) -> None:
|
||||
raise ValueError(
|
||||
f"{origin} 的 meta 键 {key!r} 不合法: 只允许小写字母/数字/下划线/点,长度 1-64"
|
||||
)
|
||||
if len(meta) > _META_MAX_KEYS:
|
||||
raise ValueError(f"{origin} 的 meta 键数超限(上限 {_META_MAX_KEYS}): {len(meta)}")
|
||||
|
||||
|
||||
def _validate_meta_values(meta: Mapping[str, Any], origin: str) -> None:
|
||||
|
||||
Reference in New Issue
Block a user