Skip to content

Data Model

This page describes the telemetry data collected and sent by the Framedash SDKs.

Every event is a single GameTelemetryEvent, serialized with Protobuf and sent in a TelemetryBatch to POST /v1/events. Each event maps to one row in the ClickHouse events table. The schema is fixed (defined in telemetry.proto); game-specific data goes into flexible attributes and metrics maps, so adding new data never requires a schema change as long as values stay within the ingest limits below.

FieldTypeDescription
event_namestringEvent identifier, e.g. player_death, or the automatic session_start / perf_heartbeat.
timestamp_usint64Event time as a Unix epoch in microseconds (stored as DateTime64(6)).
session_idstringGame session identifier.
player_idstringExplicit player identifier; the only PII the SDK collects, cleared under COPPA mode.
map_idstringMap / level identifier for spatial analytics.
build_idstringBuild version.
platformstringEngine-reported platform name (Unity Application.platform, UE IniPlatformName, Godot OS.GetName()).
engine_versionstringEngine version (Unity Application.unityVersion, UE FEngineVersion, Godot Engine.GetVersionInfo()["string"]).
sourceenumOrigin of the event: player, automated, or unspecified.
FieldTypeDescription
positionVector3 (x, y, z floats)World-space position. Stored as position_x / position_y / position_z.
camera_yawfloat (optional)Horizontal camera rotation in degrees: 0 = North, clockwise, range [0, 360). Absent when the SDK does not capture camera.
camera_pitchfloat (optional)Vertical camera rotation in degrees: -90 = straight down, +90 = straight up.

camera_yaw and camera_pitch are sent together or not at all, so a missing value means “not captured” rather than zero.

Collected automatically by the SDK, most importantly on the perf_heartbeat event, emitted every 10 seconds:

FieldTypeUnit / Notes
fpsfloatframes per second
frame_time_msfloatmilliseconds
gpu_time_msfloatmilliseconds
game_thread_msfloatCPU game-thread time in ms (0 = not collected)
render_thread_msfloatCPU render-thread time in ms (0 = not collected)
memory_used_bytesint64bytes

Two more automatic performance signals ship in Unity SDK 0.1.3, UE5 SDK 0.1.6, and Godot SDK 0.1.4. Both feed the perf-diff / build-comparison regression gate and the dashboard charts.

  • map_load: a dedicated auto event that BeginMapLoad / EndMapLoad or ReportMapLoad emits when a map or level finishes loading. It carries metrics["load_time_ms"] and attributes["map_name"], and it deliberately leaves map_id empty so it stays out of spatial heatmaps and the activation gate.
  • io.read_bytes / io.read_time_ms / io.read_ops: disk-read counters attached to the perf_heartbeat metrics map as deltas since the previous heartbeat. They appear only after a real sample has landed. The automatic source is Editor / Development-build only on Unity (AsyncReadManagerMetrics), opt-in on UE5 (bTrackDiskIo), and manual-only on Godot (ReportIoSample).

See each SDK guide for the per-engine API and threading rules.

Supported SDKs attach memory-category usage as mem.* metrics on perf_heartbeat and position-qualified events. The available keys and how they are collected differ per engine.

  • UE5 SDK 0.1.7 and later: mem.vram plus the LLM-dependent mem.textures / mem.meshes / mem.audio. All are opt-in (bTrackMemoryDetail, off by default); mem.vram needs no LLM but is absent on headless / -nullrhi runs (which emit an absent key, not 0).
  • Unity SDK 0.1.4 and later: mem.vram and mem.heap. Collected automatically, no opt-in.
  • Godot SDK 0.1.5 and later: mem.vram, mem.textures, and mem.buffers. Collected automatically, no opt-in.

All ride in the metrics map, and an untracked category leaves its key absent (which means “not collected”, distinct from a collected 0). mem.vram is also a perf-diff (build-comparison) metric. See the UE5 SDK, Unity SDK, and Godot SDK guides for per-engine details.

Game-specific context travels in two flexible maps, with no schema change required:

FieldTypeDescription
attributesmap<string, string>String key-value pairs, e.g. weapon: "rifle". Dropped entirely under COPPA mode.
metricsmap<string, double>Numeric measurements, e.g. damage: 42.5.

The ingest pipeline validates every decoded event. If any event in a batch is outside these limits, the batch can be rejected at request time or dropped during async processing, so custom SDKs and raw Protobuf senders should clamp values before flushing. The official Unity, UE5, and Godot SDKs apply these clamps client-side.

FieldLimit
timestamp_usMust be within the last 30 days and no more than 48 hours in the future.
event_name / session_idRequired and non-empty. event_name is max 128 chars; session_id is max 64 chars.
player_id, map_id, build_idMax 128 chars each.
source, platform, engine_versionMax 64 chars each.
position_x / position_y / position_zFinite numbers with absolute value at or below 1e9.
fpsFinite number from 0 to 1000.
frame_time_ms / gpu_time_ms / game_thread_ms / render_thread_msFinite milliseconds from 0 to 10000.
memory_used_bytesInteger from 0 to 64 GiB.
attributesMax 50 entries; keys max 64 chars; values max 512 chars.
metricsMax 50 entries; keys max 64 chars; values must be finite numbers.
camera_yaw / camera_pitchBoth present or both absent. Yaw is normalized to [0, 360) and pitch to [-90, 90].

SDKs send a TelemetryBatch, which is simply a list of GameTelemetryEvent values. The API key and SDK version travel in HTTP headers (X-API-Key, X-SDK-Version), not in the payload body.

Custom senders should keep the HTTP request body as sent (after gzip compression, if used) at or below 126,000 bytes. Larger production ingest bodies are rejected with 413; the official SDKs flush well below that cap.