数据模型
本文介绍 Framedash SDK 收集和发送的遥测数据结构。
每个事件都是一个 GameTelemetryEvent,以 Protobuf 序列化后通过 TelemetryBatch 发送到 POST /v1/events。每个事件对应 ClickHouse events 表中的一行。Schema 是固定的(在 telemetry.proto 中定义);游戏专属数据可以存放在灵活的 attributes / metrics 映射中,但值必须保持在下方的摄取限制内。
标识与上下文
Section titled “标识与上下文”| 字段 | 类型 | 说明 |
|---|---|---|
event_name | string | 事件标识符,例如 player_death,或自动事件 session_start / perf_heartbeat。 |
timestamp_us | int64 | 事件发生时间(Unix epoch 微秒,以 DateTime64(6) 存储)。 |
session_id | string | 游戏会话标识符。 |
player_id | string | 显式玩家标识符。SDK 收集的唯一 PII。COPPA 模式下会被清除。 |
map_id | string | 用于空间分析的地图 / 关卡标识符。 |
build_id | string | 构建版本。 |
platform | string | 引擎报告的平台名称(Unity 为 Application.platform,UE 为 IniPlatformName,Godot 为 OS.GetName())。 |
engine_version | string | 引擎版本(Unity 为 Application.unityVersion,UE 为 FEngineVersion,Godot 为 Engine.GetVersionInfo()["string"])。 |
source | enum | 事件来源:player / automated / unspecified。 |
| 字段 | 类型 | 说明 |
|---|---|---|
position | Vector3(x、y、z 浮点数) | 世界空间位置。以 position_x / position_y / position_z 存储。 |
camera_yaw | float(可选) | 相机水平旋转(度)。0 = 正北,顺时针,范围 [0, 360)。当 SDK 不采集相机时不存在。 |
camera_pitch | float(可选) | 相机垂直旋转(度)。-90 = 正下方,+90 = 正上方。 |
camera_yaw 与 camera_pitch 要么一起发送,要么都不发送。缺少该值表示“未采集”,而非 0。
由 SDK 自动收集,尤其是在每 10 秒发送一次的 perf_heartbeat 事件中:
| 字段 | 类型 | 单位 / 备注 |
|---|---|---|
fps | float | 每秒帧数 |
frame_time_ms | float | 毫秒 |
gpu_time_ms | float | 毫秒 |
game_thread_ms | float | CPU 游戏线程时间(ms)。0 = 未收集 |
render_thread_ms | float | CPU 渲染线程时间(ms)。0 = 未收集 |
memory_used_bytes | int64 | 字节 |
加载耗时与磁盘 I/O 指标
Section titled “加载耗时与磁盘 I/O 指标”Unity SDK 0.1.3、UE5 SDK 0.1.6 和 Godot SDK 0.1.4 新增了两项自动收集的性能信号。二者都会进入 perf-diff(构建比对)回归门禁和仪表盘图表。
map_load:由BeginMapLoad/EndMapLoad或ReportMapLoad在地图或关卡加载完成时发出的专用自动事件。它携带metrics["load_time_ms"]与attributes["map_name"],并有意将map_id留空,从而不进入空间热力图和激活门禁。io.read_bytes/io.read_time_ms/io.read_ops:以相对上一次 heartbeat 的增量附加到perf_heartbeat的metrics映射的磁盘读取计数器。只有在真正采集到样本之后才会出现。自动来源在 Unity 上仅限 Editor / Development Build(AsyncReadManagerMetrics),在 UE5 上为选择性开启(bTrackDiskIo),在 Godot 上仅限手动(ReportIoSample)。
各引擎的 API 和线程规则见各 SDK 指南。
内存分类指标
Section titled “内存分类指标”受支持的 SDK 会把各内存分类的用量作为 mem.* 指标附加到 perf_heartbeat 和带位置的事件上。可用的键与收集方式因引擎而异。
- UE5 SDK 0.1.7 及更高版本:
mem.vram以及依赖 LLM 的mem.textures/mem.meshes/mem.audio。三者都需要 opt-in(bTrackMemoryDetail,默认关闭);mem.vram无需 LLM,但在无头 /-nullrhi运行中不会附加(此时是键缺失,而非0)。 - Unity SDK 0.1.4 及更高版本:
mem.vram和mem.heap。自动收集,无需 opt-in。 - Godot SDK 0.1.5 及更高版本:
mem.vram、mem.textures和mem.buffers。自动收集,无需 opt-in。
三者都放在 metrics 映射中,未追踪的分类会让该键缺失(表示“未收集”,与已收集的 0 不同)。mem.vram 同时也是 perf-diff(构建比对)的比较指标。各引擎细节见 UE5 SDK、Unity SDK 和 Godot SDK 指南。
游戏专属上下文通过两个灵活映射发送,无需更改 Schema:
| 字段 | 类型 | 说明 |
|---|---|---|
attributes | map<string, string> | 字符串键值对,例如 weapon: "rifle"。COPPA 模式下整体丢弃。 |
metrics | map<string, double> | 数值测量值,例如 damage: 42.5。 |
摄取验证限制
Section titled “摄取验证限制”摄取管道会验证每个解码后的事件。如果批次中的任何一个事件超出这些限制,该批次可能在请求时被拒绝,或在异步处理期间被整体丢弃。因此,自定义 SDK 和原始 Protobuf 发送方应在 flush 前钳制取值。官方 Unity、UE5 和 Godot SDK 会在客户端应用这些钳制。
| 字段 | 限制 |
|---|---|
timestamp_us | 必须在过去 30 天内,且不得超过未来 48 小时。 |
event_name / session_id | 必填且不能为空。event_name 最多 128 个字符,session_id 最多 64 个字符。 |
player_id, map_id, build_id | 各最多 128 个字符。 |
source, platform, engine_version | 各最多 64 个字符。 |
position_x / position_y / position_z | 必须是有限数字,绝对值不超过 1e9。 |
fps | 0 到 1000 之间的有限数字。 |
frame_time_ms / gpu_time_ms / game_thread_ms / render_thread_ms | 0 到 10000 之间的有限毫秒值。 |
memory_used_bytes | 0 到 64 GiB 之间的整数。 |
attributes | 最多 50 个条目;key 最多 64 个字符;value 最多 512 个字符。 |
metrics | 最多 50 个条目;key 最多 64 个字符;value 必须是有限数字。 |
camera_yaw / camera_pitch | 必须同时存在或同时省略。yaw 归一化为 [0, 360),pitch 归一化为 [-90, 90]。 |
SDK 发送 TelemetryBatch(即 GameTelemetryEvent 列表)。API 密钥和 SDK 版本通过 HTTP 头(X-API-Key、X-SDK-Version)传输,而非放在载荷正文中。
自定义发送方应将发送时的 HTTP 请求正文(如果使用 gzip,则为压缩后)保持在 126,000 bytes 以内。生产摄取会以 413 拒绝更大的正文;官方 SDK 会在明显低于该上限时 flush。