主题
XHIM SDK 运行诊断
xhim_v1_client_get_diagnostics() 提供同步、只读、无网络和无磁盘 I/O 的运行 快照,适合客户应用的健康页、客服工单和故障矩阵自动化。该接口不会触发回调, 也不会改变 Client 生命周期。
c
xhim_v1_diagnostics_snapshot_t snapshot = {0};
snapshot.struct_size = sizeof(snapshot);
int32_t status = xhim_v1_client_get_diagnostics(client, &snapshot);
if (status == XHIM_V1_STATUS_OK &&
snapshot.schema_version ==
XHIM_V1_DIAGNOSTICS_SNAPSHOT_SCHEMA_VERSION) {
/* 将所需计数复制到客户自己的指标系统。 */
}隐私边界
快照只包含状态、Epoch/Generation、队列容量与深度、活跃请求/订阅数量以及 拒绝、丢弃、合并计数。它不包含账号或任何可直接识别业务主体的信息,具体为:
- App、账号、用户、会话、消息或媒体任务 ID;
- 数据库路径、域名、URL、Cursor 或本地文件路径;
- Token、签名、密钥、消息 Payload、错误文本或调用栈。
因此可以把结构化数值发送到客户自己的观测平台,但不应把它与业务日志拼接成 可能重新识别用户的明细事件。SDK 本身不上传诊断数据。
关键指标解释
client_state/account_epoch/connection_generation:当前生命周期和 Fence;active_requests/event_subscribers:C ABI 尚未完成的请求及事件订阅;ffi_*:平台回调线程的事件队列、Completion 预留和拒绝/丢弃数量;engine_callback_*:Core 私有串行回调执行器的普通、控制和状态泵通道;state_relay_*:C ABI 状态中继;慢回调导致 latest-wins 时state_relay_coalesced增长;engine_state_mailbox_*:Engine 状态邮箱及其合并数量;closing:Client 已进入不可逆关闭路径,宿主不应再发起新请求。
队列“当前深度”为瞬时值,采样后可能立刻变化;拒绝、丢弃和合并计数才适合 告警。建议按 30–60 秒采样,并对“计数增量”告警,不要高频轮询。
建议告警
| 现象 | 建议动作 |
|---|---|
任一 *_rejections 持续增长 | 检查宿主是否在回调中做阻塞 I/O,并降低并发突发 |
ffi_pending_events 长时间接近容量 | 缩短事件回调,只复制数据后切换到业务线程 |
active_requests 持续增长且网络异常 | 使用通用请求取消并核查 Product Adapter 超时 |
*_coalesced 增长 | 将状态事件当失效通知,收到后重新读取权威状态 |
client_state=FATAL 或 closing=1 | 停止新请求,保存快照并按生命周期重新创建 Client |
诊断结构通过 struct_size + schema_version 独立演进。这里的 struct_size 在调用前是调用方实际分配的字节容量,SDK 只写入当前版本已知且 能放入该容量的前缀,并保留这个容量值;容量小于当前必需前缀时返回 XHIM_V1_STATUS_INVALID_ARGUMENT。应用应忽略未知尾字段,不应按固定字节自行 序列化内存;转换为自己的命名字段后再上报。
客户支持包
XHIM 提供完全离线、仅使用 Python 标准库的支持包工具。它不会读取数据库、 应用沙盒、系统日志或网络配置,也不会上传文件。收集器只接受以下三类显式输入:
- 一份严格的 SDK diagnostics Schema v1 JSON;
- 一份只含稳定机器码的结构化 JSONL 日志;
- 可选、严格白名单的非敏感环境元数据。
工具采取 fail-closed 策略。发现 Token、Authorization、Cookie、Key、Secret、 Payload、Message、Path、URL、账号/用户/会话/会话消息 ID 等字段时会拒绝整个 输入,不会先替换成 *** 再继续打包。任意未知字段、重复 JSON Key、非法 UTF-8、NaN/Infinity、符号链接、超限文件或不完整 JSONL 行也会失败。
从五端取得快照
- iOS/macOS:
try client.diagnostics(); - Android:
client.diagnostics(); - Windows:
client.GetDiagnostics(); - HarmonyOS:
client.diagnostics(); - C ABI:
xhim_v1_client_get_diagnostics()。
把返回模型显式映射到 scripts/support/examples/diagnostics.schema-v1.example.json 的 snake_case 字段,不要直接对平台对象做反射式全量序列化。支持包边界有意排除了 accountEpoch/account_epoch:它在 SDK 内只是匿名生命周期 Fence,但为了满足 客户导出时“任何账号类字段均拒绝”的更严格规则,不进入支持包。struct_size、 保留字段以及平台对象中的派生 clientState 也不序列化;使用 nativeClientState 作为 client_state。
Diagnostics JSON 必须包含示例中的全部字段。captured_at 使用带 Z 的 RFC3339 UTC 时间,布尔值必须是真正的 JSON Boolean,所有计数必须是 0...UInt64.max,client_state 必须是稳定值 0...9。
结构化日志 Schema
每行必须是一个完整 JSON Object,且只允许以下字段:
json
{
"schema_version": 1,
"timestamp": "2026-07-26T08:00:00Z",
"severity": "warning",
"component": "network",
"stable_code": "network_offline",
"retryable": true,
"counters": {
"attempt": 1,
"retry_after_ms": 500
}
}severity 只允许 debug/info/warning/error/critical;component 只允许 SDK 约定的 sdk/runtime/lifecycle/auth/network/transport/sync/storage/media/push/ ffi/ui。stable_code 是最长 64 字符的小写机器码。counters 仅允许工具中 固定的次数、耗时、队列、HTTP/Native/Server 数值码、Generation 和 Revision 字段。时间必须按 UTC 非递减排列。
不要写入 XHIMError.message、异常文本、调用栈、请求或响应 Body、Trace/Operation ID,也不要把任意字典塞进 counters。完整例子见 scripts/support/examples/logs.schema-v1.example.jsonl。
可选元数据
metadata.json 只允许:平台、CPU 架构、SDK SemVer、应用版本、OS 主版本、 Debug/Release、部署环境和分发渠道。它不接受备注、工单内容、客户名称、设备 标识或任意扩展属性。示例位于 scripts/support/examples/metadata.schema-v1.example.json。
生成与验证
sdk-source-commit 必须来自所接入 XHIM 二进制随附的发布清单,不能使用应用 仓库 Commit,也不能手工缩写:
bash
python3 scripts/support/collect_support_bundle.py \
--diagnostics /absolute/path/diagnostics.json \
--logs /absolute/path/xhim-stable-code.jsonl \
--metadata /absolute/path/metadata.json \
--sdk-source-commit 0123456789abcdef0123456789abcdef01234567 \
--output /absolute/path/xhim-support.zip
python3 scripts/support/verify_support_bundle.py \
/absolute/path/xhim-support.zip \
--expected-sdk-source-commit \
0123456789abcdef0123456789abcdef01234567输出路径必须不存在;工具不会覆盖旧包。ZIP 固定为 Store 模式、固定时间、 固定顺序和固定权限,相同输入会生成逐字节相同的文件。内部 manifest.json 记录工具版本、SDK Source Commit、每个 Entry 的大小、记录数和 SHA-256。验证器独立重算 Schema、边界和 Hash,并拒绝压缩 Entry、Zip Bomb、 路径穿越、重复名、额外文件、前后隐藏数据或任何篡改。
默认限制如下:
| 输入 | 限制 |
|---|---|
| Diagnostics JSON | 128 KiB,恰好 1 个快照 |
| JSONL | 2 MiB、5,000 行、每行 2,048 Bytes |
| 可选 Metadata | 16 KiB,恰好 1 个对象 |
| 最终 ZIP | 3 MiB、3–4 个固定 Entry |
支持包即使不含业务标识,也可能反映故障发生时间和运行负载。应用仍应取得客户 同意,通过受控工单系统传输,并按客户合同和隐私政策设置最短保留期。