콘텐츠로 이동

이벤트 스키마

Framedash는 원시 텔레메트리를 ClickHouse의 events 테이블에 저장합니다. 세 가지 경로에서 SQL로 읽을 수 있습니다.

이 페이지는 컬럼과 검증기 규칙을 정리합니다. Claude Code 플러그인 없이도 쿼리를 작성할 수 있도록 하기 위함입니다.

원시 SQL에는 data:admin scope를 가진 API 키(Full 프리셋)가 필요합니다. Read-only 키는 내장 분석 엔드포인트와 MCP 도구를 사용할 수 있지만 원시 query 경로는 사용할 수 없습니다. Ingest(events:write) 키는 설계상 쿼리도, 자신의 프로젝트 열거도 할 수 없습니다.

쿼리는 검증되고, 프로젝트 격리를 강제하도록 재작성되며, 읽기 전용 연결에서 실행됩니다. 검증기는 다음을 강제합니다.

  • SELECT만 허용. INSERT, UPDATE, DELETE, DROP, ALTER, CREATE, TRUNCATE, SYSTEM, OPTIMIZE, KILL, 그리고 UNION / EXCEPT / INTERSECT는 불가.
  • FROM / JOIN에는 두 테이블만 등장할 수 있습니다. events(원시 이벤트)와 daily_sessions_project_mv(사전 집계된 일별 세션)입니다. FROM events로 그대로 작성하면 격리 필터가 자동 주입됩니다.
  • SQL에서 tenant_idproject_id를 참조하지 마세요. 자동으로 스코프되며, 직접 참조하면 거부됩니다.
  • 문자열 리터럴은 작은따옴표만 사용합니다. 큰따옴표와 백틱은 거부됩니다.
  • SETTINGS, FORMAT, GLOBAL 절은 불가. IN (SELECT ...)IN ('a','b')는 가능하며, IN some_table은 불가합니다.
  • 최상위 LIMIT을 생략하면 자동으로 하나가 추가됩니다.

결과는 { "rows": [ { "col": "value" } ], "rowCount": 123 } 형태입니다. CLI와 MCP 도구는 이 형태 그대로 반환합니다. REST 엔드포인트를 직접 호출하면 표준 API 엔벨로프로 감싸집니다: { "success": true, "data": { "rows": [...], "rowCount": 123 } }. MCP query 도구는 최대 1000행, REST 엔드포인트와 CLI는 최대 10000행입니다. 더 큰 추출에는 LIMIT ... OFFSET ...으로 페이징하거나 timestamp 범위를 좁히세요.

컬럼타입비고
event_nameString이벤트 이름, 예: player_death, level_start, perf_heartbeat
timestampDateTime64(6)이벤트 시각(UTC)
session_idString플레이 세션 id
player_idString안정적인 플레이어/기기 id
position_x, position_y, position_zFloat32월드 좌표
map_idString맵/레벨 식별자
fpsFloat32프레임레이트(perf 이벤트)
frame_time_msFloat32프레임 타임 ms(perf 이벤트)
memory_used_bytesInt64메모리 바이트(perf 이벤트)
gpu_time_msFloat32GPU 시간 ms(perf 이벤트)
game_thread_msFloat32게임 스레드 시간 ms
render_thread_msFloat32렌더 스레드 시간 ms
camera_yaw, camera_pitchNullable(Float32)카메라 방향
sourceStringSDK 자체 내부 이벤트(session_start, perf_heartbeat)는 automated. Track(...) 호출은 player. CI 여부를 나타내지 않음(아래 규약 참고)
build_idString빌드 식별자(perf-diff 후보)
platformString예: windows, android
engine_versionString엔진/빌드 버전 문자열
attributesMap(String, String)커스텀 문자열 속성
metricsMap(String, Float64)커스텀 수치 메트릭

Map 타입 컬럼은 대괄호로 접근합니다. attributes['ci.branch'], metrics['score'] 형태입니다.

server_timestamp 컬럼은 없습니다. 이벤트 시각에는 timestamp를 사용하세요. 존재하지 않는 컬럼을 선택하면 쿼리 오류가 반환되므로, 먼저 위의 이름을 확인하세요. 거부된 쿼리는 HTTP 400과 ClickHouse 진단 메시지(존재하지 않는 컬럼, 테이블, 함수, 구문 오류, 타입 불일치, 금지된 연산)를 반환하며, 인프라 장애만 500을 반환합니다.

  • 자동 성능 이벤트는 perf_heartbeat입니다. perf 쿼리는 WHERE event_name = 'perf_heartbeat'로 필터링하세요. 모든 이벤트가 fps / frame_time_ms를 갖는 것은 아닙니다.
  • source = 'automated'는 SDK 자체 내부 이벤트(session_start, perf_heartbeat)를 나타내며 여러분의 Track(...) 호출과 구분하기 위한 것입니다. CI 여부와 관계없이 모든 세션에서 설정되므로 이것만으로는 CI 실행을 식별할 수 없습니다.
  • CI 프로파일링 데이터를 걸러내려면 source가 아니라 build_id 또는 attributes['ci.*'] 태그(BeginAutomatedSession / BeginAutomatedSessionFromEnvironment가 설정)를 사용하세요.
  • CI 메타데이터는 attributes에 실립니다. attributes['ci.branch'], attributes['ci.commit'], attributes['ci.scenario']와 일급 build_id 컬럼입니다.
  • 이벤트 이름은 Track(...)에서 직접 고르는 자유 문자열입니다. 공식 SDK 샘플은 snake_case(player_death, level_start)를 사용합니다. 프로젝트 전체에서 하나의 규약으로 통일하세요.
  • timestamp는 항상 범위를 지정하세요. 테이블은 일 단위로 파티션되므로 범위를 좁히면 파티션이 정리되어 빨라집니다.

오늘의 활성 플레이어 수:

SELECT uniqExact(player_id) AS dau
FROM events
WHERE timestamp >= today()

최근 7일간 이벤트 이름별 건수:

SELECT event_name, count() AS events, uniqExact(session_id) AS sessions
FROM events
WHERE timestamp >= today() - 7
GROUP BY event_name
ORDER BY events DESC

빌드별 성능 백분위수:

SELECT build_id,
count() AS samples,
round(quantile(0.50)(fps), 1) AS fps_p50,
round(quantile(0.95)(frame_time_ms), 2) AS frametime_p95_ms
FROM events
WHERE event_name = 'perf_heartbeat'
AND timestamp >= today() - 14
GROUP BY build_id
ORDER BY samples DESC