span 能带多少属性和事件?超了会丢哪些?状态 OK、ERROR、UNSET 的设置规则是什么?异常是怎么记进 span 的?一个属性占多少字节?属性里的密码和 token 怎么统一去掉?这篇用 OpenTelemetry Python SDK 和 Collector 逐项量出来。
属性:保留 128 个,键编号 72~199,dropped_attributes=72;事件:保留 128 个,编号 72~199,dropped_events=72
这一步里 SDK 打出的 warning 日志(去重后的内容 × 次数):“Attributes dict is full. Dropping the oldest key-value pair from attributes to make space …”× 72;“String attribute value exceeds max length of 20, truncating.…”× 2
max_attribute_length=20 时:字符串 100 字符 → 保留 20 字符;字符串数组里 50 字符的元素 → 20 字符,5 字符的元素 → 5 字符;超大整数属性 → 12345678901234567890
属性值的类型限制(保留下来的属性值):v.list=(1, 2, 3);v.map={'a': 1};v.mixed_list=(1, 'a');v.none=None;v.object=None;v.str='v';SDK 的 warning 日志:“Invalid type `<class 'object'>` for attribute value. Expected one of bool, str, None, byte…”× 1。没有抛异常属性和事件默认各 128 个,超限时丢掉最先加的;可以用 SpanLimits 设置值的最大长度。
调用顺序 | 最终状态 | 描述
------------------------+-------+-----
什么都不设置 | UNSET | None
ERROR("a") | ERROR | 'a'
ERROR("a") → ERROR("b") | ERROR | 'b'
ERROR → OK | OK | None
OK → ERROR | OK | None
OK → UNSET | OK | None
ERROR → UNSET | ERROR | 'a'
OK 带描述 | OK | None
SDK 的 warning 日志(去重 × 次数):“description should only be set when status_code is set to StatusCode.ERROR…”× 1
做法 | 最终状态 | 状态描述 | exception 事件数 | exception 事件的属性键
------------------------------+-------+--------------------+---------------+------------------------------------------------------------------------
默认(异常离开 with 块) | ERROR | 'ValueError: boom' | 1 | exception.escaped,exception.message,exception.stacktrace,exception.type
record_exception=False | ERROR | 'ValueError: boom' | 0 |
set_status_on_exception=False | UNSET | None | 1 | exception.escaped,exception.message,exception.stacktrace,exception.type
两个都 False | UNSET | None | 0 |
手动 record_exception(不设状态) | UNSET | None | 1 | exception.escaped,exception.message,exception.stacktrace,exception.typeOK 是终态;异常默认同时记录事件并把状态置为 ERROR;手动 record_exception 只加事件。
内容 | 序列化后的 span 字节数 | 平均每个属性/事件增加的字节数 --------------------+----------------+---------------- (a)0 个属性 | 289 | 0 (a)10 个属性,值 20 字符 | 701 | 41.2 (a)50 个属性,值 20 字符 | 2341 | 41.0 (a)128 个属性,值 20 字符 | 5539 | 41.0 (b)10 个属性,值 20 字符 | 701 | 41.2 (b)10 个属性,值 200 字符 | 2531 | 224.2 (b)10 个属性,值 2000 字符 | 20534 | 2024.5 (c)10 个事件(各 2 个属性) | 881 | 59.2 OTLP 里每个属性的键和值各占字节,键名(这里是 attr.name.NNN)也要付出空间,值越长越大;个数上限由 max_attributes 控制,值的长度上限由 max_attribute_length 控制
每个属性的键和值各占字节,值越长越大,事件也有固定开销。
配置 | user.email | password | http.url
------------------------------------+------------------------------------------------------------------+----------+-------------------------------------------------------------
(a)没有处理器 | alice@example.com | hunter2 | https://api.example.com/login?user=alice&token=SECRET123&x=1
(b)attributes/scrub + transform/url | ff8d9819fc0e12bf0d24892e45987e249a28dce836a85cad60e28eaaa8c6d976 | (已删除) | https://api.example.com/login?user=alice&token=***&x=1
SDK 把属性原样放进 span,不会替你脱敏;在 Collector 里可以统一删除、哈希或者按正则替换,这样所有服务不用各自改代码
ERRORS {}SDK 不脱敏,可以在 Collector 里统一删除、哈希或按正则替换。