This is the full developer documentation for Framedash
# Framedash ドキュメント
> ゲームテレメトリ SaaS「Framedash」のドキュメントサイト。SDK 統合、API リファレンス、ヒートマップ・CI プロファイリングの概念ガイド。
ゲームテレメトリ SaaS
# ゲームのパフォーマンスを、マップ上で可視化する。
FPS・メモリ・GPU のテレメトリをヒートマップで把握し、CI パイプラインの build\_id でビルドごとの変化を Regression ページや静的しきい値アラートから確認できます。Unity / UE5 / Godot に組み込めます。
[クイックスタート ](/getting-started/quickstart/)[API リファレンス](/api/overview/)
app.framedash.dev/projects/rpg

60 fps
P99 フレームタイム
はじめる
## SDK から本番のテレメトリまで
SDK の統合から API でのアクセスまで、必要なものはここに揃っています。
### [Framedash とは](/getting-started/introduction/)
ゲームに特化したテレメトリ基盤。FPS・メモリ・GPU をマップ上に可視化し、ビルドごとの変化を確認できます。
[詳しく見る](/getting-started/introduction/)
### [SDK を統合](/sdk/unity/)
Unity / UE5 / Godot プロジェクトに SDK を追加し、テレメトリ送信を開始できます。
[Unity SDK ](/sdk/unity/)[UE5 SDK ](/sdk/unreal/)[Godot SDK](/sdk/godot/)
### [API でアクセス](/api/overview/)
REST API でイベントデータを取得・分析。CLI / MCP Server / TypeScript クライアントとも連携できます。
[API 概要](/api/overview/)
### [コンセプトを理解](/concepts/heatmaps/)
ヒートマップ、CI 統合プロファイリング、コンテンツレジストリの仕組みを学びます。
[コンセプト](/concepts/heatmaps/)
### [AI コーディングエージェント](/mcp/claude-code-plugin/)
AI coding agent を使っていますか。Claude Code や Codex、MCP クライアントからテレメトリを照会できます。
[Claude Code ](/mcp/claude-code-plugin/)[Codex ](/mcp/codex/)[MCP Server](/mcp/overview/)
## 数分で計測を開始
SDK を追加し、API キーで初期化するだけ。テレメトリは自動で送信されます。
1 **SDK を追加** — エンジン別ガイドからインストール
2 **初期化** — API キーで TelemetrySDK.Initialize()
3 **送信** — Track() でイベントを記録
[Unity の手順を見る](/sdk/unity/)
GameBootstrap.cs
```csharp
using Framedash;
// 起動時に一度だけ初期化し、イベントを送信
TelemetrySDK.Initialize(apiKey: apiKey, buildId: Application.version);
TelemetrySDK.Instance.Track(
eventName: "player_death",
mapId: "desert_01",
position: transform.position);
```
対応プラットフォーム
## スタジオのスタックに、そのまま
UnityUnreal Engine 5Godot 4C# SDKC++ SDKREST APICLIMCP Server
 Framedash Docs · Crane Valley LLC
[API](/api/overview/)[アプリ](https://app.framedash.dev)
# API クライアント
> Framedash 開発者プラットフォーム向けの TypeScript / JavaScript API クライアント。
Framedash API クライアント(`@framedash/api-client`)は、Framedash 開発者プラットフォームの REST API を型付きで扱う TypeScript / JavaScript クライアントです。`@framedash/cli` と `@framedash/mcp-server` の内部で使われているものと同じクライアントを単独パッケージとして公開しており、Framedash のテレメトリを自社の内製ツール・ダッシュボード・自動化処理に直接組み込めます。
認証、プロジェクトスコープのパス生成、レスポンスのアンラップ、構造化エラーに加え、いくつかのセキュリティガード(HTTPS 限定のベース URL、認証情報を漏らさないリダイレクト拒否、リクエストタイムアウト)を内蔵しているため、データの取得に集中できます。
## 要件
[Section titled “要件”](#要件)
* Node.js 20 以降(グローバル `fetch`、`AbortSignal.timeout`、`node:net` を使用)
* 呼び出す API に必要な scope を持つ API キー、または OAuth 2.1 アクセストークン。raw SQL の例には Full プリセットの API キーが必要で、単純な読み取りリクエストには Read-only プリセットまたは `analytics:read` を許可されたアクセストークンを使用できます。
ノート
これはブラウザ向け SDK ではなく、Node.js のサーバーサイド / ツール用クライアントです。API キーは `X-API-Key` ヘッダー、OAuth アクセストークンは `Authorization` ヘッダー(Bearer トークン)で送信するため、信頼できる環境(CI、バックエンドサービス、内部 CLI など)で実行してください。Developer Platform の認証情報をゲームクライアントやブラウザに同梱しないでください。ゲーム内テレメトリには [Unity](/sdk/unity/)、[UE5](/sdk/unreal/)、または [Godot](/sdk/godot/) の SDK を使用します。
## インストール
[Section titled “インストール”](#インストール)
```bash
npm install @framedash/api-client
```
## クイックスタート
[Section titled “クイックスタート”](#クイックスタート)
```typescript
import { ApiClient, ApiError } from "@framedash/api-client";
const client = new ApiClient({
baseUrl: "https://app.framedash.dev",
apiKey: process.env.FRAMEDASH_API_KEY ?? "",
projectId: process.env.FRAMEDASH_PROJECT_ID ?? "",
onError: (err: ApiError) => {
// onError は成功以外のレスポンスで呼ばれます。必ず throw(または終了)すること。
// 戻り値の型は `never` です。throw した値は await へ伝播します。
throw err;
},
});
// プロジェクトスコープの GET -> /api/v1/projects/{projectId}/dashboard?days=30
const dashboard = await client.get(client.projectPath("dashboard?days=30"));
console.log(dashboard);
```
クライアントは API のエンベロープを自動でアンラップします。成功時の `{ "success": true, "data": ... }` は `data` の値だけに解決されます。
## 設定
[Section titled “設定”](#設定)
`ApiClient` のコンストラクタは 1 つのオプションオブジェクトを受け取ります:
| オプション | 型 | 説明 |
| ------------- | ---------------------------- | ------------------------------------------------------------------------------------------------ |
| `baseUrl` | string | アプリケーションホスト URL(例: `https://app.framedash.dev`)。HTTPS 必須(HTTP は localhost / ループバックのみ許可)。 |
| `apiKey` | string | API キー。毎リクエストの `X-API-Key` ヘッダーで送信されます。`accessToken` とのどちらか一方だけを指定します。 |
| `accessToken` | string | OAuth 2.1 アクセストークン。毎リクエストの `Authorization` ヘッダーで Bearer トークンとして送信されます。`apiKey` とのどちらか一方だけを指定します。 |
| `projectId` | string | デフォルトのプロジェクト UUID。`projectPath()` に必須。プロジェクト外パスでは `X-Project-Id` ヘッダーとしても送信されます。 |
| `onError` | `(error: ApiError) => never` | 成功以外のレスポンスで呼ばれます。throw またはプロセス終了が必須です。 |
`apiKey` と `accessToken` は必ずどちらか一方だけを指定します。両方またはどちらも指定しない場合、コンストラクタは throw します。
ノート
`baseUrl` はアプリケーションホスト URL です。クライアントが内部的に `/api/v1/...` などの API パスを付加します(`projectPath()` がプロジェクトスコープのプレフィックスを構築します)。これは REST API を直接呼び出す際に使う [API リファレンス](/api/overview/) のベース URL(`app.framedash.dev/api`)とは異なります。どちらも同じエンドポイントに到達します。
ベース URL はクライアント構築時に検証され、安全でない、または不正な URL は即座に throw されます。同じチェックは公開関数 `assertSafeBaseUrl(baseUrl)` で自分でも実行できます。
## リクエストの実行
[Section titled “リクエストの実行”](#リクエストの実行)
4 つの HTTP ヘルパーで Web API をカバーします。いずれもアンラップ済みの `data` ペイロードを返し、ジェネリックパラメータで型を指定できます:
```typescript
const data = await client.get("/api/v1/...");
await client.post("/api/v1/...", body);
await client.patch("/api/v1/...", body);
await client.delete("/api/v1/...");
```
### プロジェクトスコープのパス
[Section titled “プロジェクトスコープのパス”](#プロジェクトスコープのパス)
ほとんどのエンドポイントはプロジェクト単位です。`projectPath(suffix)` は、クライアントに設定された `projectId` を使って `/api/v1/projects/{projectId}/{suffix}` を構築します:
```typescript
// GET /api/v1/projects/{projectId}/status
const status = await client.get(client.projectPath("status"));
// GET /api/v1/projects/{projectId}/retention?days=30
const retention = await client.get(client.projectPath("retention?days=30"));
// GET /api/v1/projects/{projectId}/maps
const maps = await client.get(client.projectPath("maps"));
```
`projectId` が未設定のまま `projectPath()` を呼ぶと throw されます。
### プロジェクトコンテキストの切り替え
[Section titled “プロジェクトコンテキストの切り替え”](#プロジェクトコンテキストの切り替え)
`withProject(projectId)` は、同じベース URL・認証情報・エラーハンドラを再利用しつつ、別プロジェクトにバインドされた新しいクライアントを返します。元のクライアントは変更されません:
```typescript
const other = client.withProject("another-project-uuid");
const otherStatus = await other.get(other.projectPath("status"));
// 現在バインドされているプロジェクト ID:
console.log(client.currentProjectId);
```
## 使用例
[Section titled “使用例”](#使用例)
### キーの検証(whoami)
[Section titled “キーの検証(whoami)”](#キーの検証whoami)
```typescript
// GET /api/v1/whoami: キーが有効か確認し、非機密のメタデータを返します。
const me = await client.get("/api/v1/whoami");
```
### ヒートマップの取得
[Section titled “ヒートマップの取得”](#ヒートマップの取得)
```typescript
// GET /api/v1/projects/{projectId}/heatmap?mapId=arena&days=7
const cells = await client.get(client.projectPath("heatmap?mapId=arena&days=7"));
```
### SQL クエリの実行
[Section titled “SQL クエリの実行”](#sql-クエリの実行)
```typescript
const rows = await client.post("/api/v1/query", {
sql: "SELECT event_name, count() FROM events GROUP BY event_name",
project_id: client.currentProjectId,
limit: 100,
});
```
### アラートの管理
[Section titled “アラートの管理”](#アラートの管理)
```typescript
// アラートルールの一覧取得
const alerts = await client.get(client.projectPath("alerts"));
// アラートルールの作成
const created = await client.post(client.projectPath("alerts"), {
name: "FPS Alert",
// ...残りのルールフィールド
});
// アラートルールの無効化
await client.delete(client.projectPath(`alerts/${alertId}`));
```
### コンテンツレジストリへのインポート
[Section titled “コンテンツレジストリへのインポート”](#コンテンツレジストリへのインポート)
```typescript
// content エンドポイントはパス上ではプロジェクトスコープではありません。
// クライアントが設定済みの projectId から X-Project-Id ヘッダーを自動付加します。
// 一括 upsert のボディは配列を entries プロパティで包みます(1 リクエストあたり最大 500 件)。
await client.post("/api/v1/content", { entries });
const content = await client.get("/api/v1/content");
```
エンドポイント・クエリパラメータ・ペイロード構造の一覧は [API リファレンス](/api/overview/) を参照してください。
## エラーハンドリング
[Section titled “エラーハンドリング”](#エラーハンドリング)
サーバーから受け取った失敗レスポンス(予期しないリダイレクト、2xx 以外のステータス、JSON 以外のボディ、`success: true` を持たないボディ)は `ApiError` に変換され、`onError` コールバックに渡されます。ネットワーク障害と 30 秒のタイムアウトは `fetch` のネイティブエラーのまま reject され、`onError` は呼ばれないため、呼び出し側の `try` / `catch` で両方を処理してください。`ApiError` はレスポンスに含まれていれば解析済みの RFC 9457 Problem Details を保持します:
| メンバー | 型 | 説明 |
| --------------- | --------------------- | ---------------------------------- |
| `status` | number | HTTP ステータスコード。 |
| `headers` | Headers | レスポンスヘッダー(例: `X-RateLimit-Reset`)。 |
| `message` | string | 人間可読のエラーメッセージ。 |
| `retryable` | boolean | API がリトライ可能と示したかどうか。 |
| `retryAfter` | `number \| undefined` | 推奨リトライ間隔(秒)。 |
| `errorCategory` | `string \| undefined` | API のエラーカテゴリ。 |
| `problem` | ProblemDetails | 解析済みの生の Problem Details オブジェクト。 |
レート制限を考慮したハンドラ:
```typescript
const client = new ApiClient({
baseUrl: "https://app.framedash.dev",
apiKey: process.env.FRAMEDASH_API_KEY ?? "",
projectId: process.env.FRAMEDASH_PROJECT_ID ?? "",
onError: (err: ApiError): never => {
if (err.status === 429) {
const retryAfter = err.retryAfter ?? err.headers.get("X-RateLimit-Reset");
throw new Error(`Rate limited; retry after ${retryAfter}`);
}
throw err;
},
});
```
ノート
`onError` の戻り値の型は `never` です。コールバックは必ず throw するか処理を終了させてください。誤って return した場合でも、クライアントは不正な結果を返す代わりに防御的にエラーを throw します。
## セキュリティ動作
[Section titled “セキュリティ動作”](#セキュリティ動作)
認証情報が漏れないよう、クライアントはいくつかの安全策を強制します:
* HTTPS 限定のベース URL。プレーンな HTTP は `localhost` / ループバックの開発エンドポイントを除き拒否され、認証情報を埋め込んだ URL(`https://...@host`)も拒否されます。
* リダイレクト不可。API はプログラム的な JSON リクエストをリダイレクトしないため、3xx はすべてエラー扱いです。クライアントはリダイレクト先に `X-API-Key` または `Authorization` ヘッダーを再送しません。
* 1 リクエストあたり 30 秒のタイムアウト(`AbortSignal.timeout` 経由)。
## 次のステップ
[Section titled “次のステップ”](#次のステップ)
* [API リファレンス](/api/overview/): REST エンドポイントの詳細
* [CLI リファレンス](/cli/overview/): このクライアントを利用したコマンドラインツール
* [MCP Server](/mcp/overview/): このクライアントを利用した LLM 連携
# イベントスキーマ
> Framedash の events テーブルのカラム一覧とクエリ規則。クエリエンドポイント、CLI、MCP から SQL を書くためのリファレンス。
Framedash は生のテレメトリを ClickHouse の `events` テーブルに保存します。 このテーブルは次の 3 つの経路から SQL で読み取れます。
* REST の [`POST /v1/query`](/api/overview/#querying-telemetry) エンドポイント
* [`framedash query`](/cli/overview/#framedash-query) CLI コマンド
* MCP の `query` ツール
このページはカラムとバリデータの規則を示します。 Claude Code プラグインがなくてもクエリを書けるようにするためのものです。
取り込み形式ではなく、クエリで返るカラム
このページは `/v1/query` やエクスポートで返ってくるカラムを説明するものであり、イベントを送るためのリクエスト形式ではありません。 取り込みエンドポイント(`POST /v1/events`)は SDK の protobuf ワイヤ形式(`TelemetryBatch`)のみを受け付けます。JSON での取り込み経路はありません。 このワイヤ形式を生成する、公式にサポートされた手段が公式 SDK([Unity](/sdk/unity/)、[UE5](/sdk/unreal/)、[Godot](/sdk/godot/))です。 SDK を使わず raw HTTP でイベントを送るには、proto3 スキーマと送信手順をまとめた[直接 HTTP 取り込み](/api/http-ingestion/)を参照してください。 ただし、ほとんどの統合では引き続き公式 SDK を使ってください。
## アクセスと scope
[Section titled “アクセスと scope”](#アクセスと-scope)
raw SQL には `data:admin` scope を持つ API キー(Full プリセット)が必要です。 Read-only キーは組み込みの分析エンドポイントと MCP ツールを使えますが、raw な `query` 経路は使えません。 Ingest(`events:write`)キーは設計上クエリを実行できず、自身のプロジェクトを列挙することもできません。
## クエリ規則
[Section titled “クエリ規則”](#クエリ規則)
クエリはバリデーションされ、プロジェクト分離を強制するよう書き換えられ、読み取り専用の接続で実行されます。 バリデータは次を強制します。
* `SELECT` のみ。`INSERT` / `UPDATE` / `DELETE` / `DROP` / `ALTER` / `CREATE` / `TRUNCATE` / `SYSTEM` / `OPTIMIZE` / `KILL`、`UNION` / `EXCEPT` / `INTERSECT` は不可。
* `FROM` / `JOIN` に書けるテーブルは 2 つだけ。`events`(生イベント)と `daily_sessions_project_mv`(日次セッションの事前集計)。`FROM events` と素直に書けば、分離フィルタは自動で注入されます。
* SQL 内で `tenant_id` や `project_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` の範囲を絞ってください。
## カラム
[Section titled “カラム”](#カラム)
| カラム | 型 | 補足 |
| ---------------------------------------- | -------------------- | ------------------------------------------------------------------------------------------------------------------- |
| `event_name` | String | イベント名。例: `player_death`、`level_start`、`perf_heartbeat` |
| `timestamp` | DateTime64(6) | イベント時刻(UTC) |
| `session_id` | String | プレイセッション ID |
| `player_id` | String | 安定したプレイヤー/デバイス ID |
| `position_x`, `position_y`, `position_z` | Float32 | ワールド座標 |
| `map_id` | String | マップ/レベル識別子 |
| `fps` | Float32 | フレームレート(perf イベント) |
| `frame_time_ms` | Float32 | フレームタイム ms(perf イベント) |
| `memory_used_bytes` | Int64 | メモリ量 byte(perf イベント) |
| `gpu_time_ms` | Float32 | GPU 時間 ms(perf イベント) |
| `game_thread_ms` | Float32 | ゲームスレッド時間 ms |
| `render_thread_ms` | Float32 | レンダースレッド時間 ms |
| `camera_yaw`, `camera_pitch` | Nullable(Float32) | カメラの向き |
| `source` | String | SDK 自身の内部イベント(session\_start、perf\_heartbeat)は `automated`。あなたの `Track(...)` 呼び出しは `player`。CI の指標ではありません(下記の規約を参照) |
| `build_id` | String | ビルド識別子(perf-diff の候補) |
| `platform` | String | 例: `windows`、`android` |
| `engine_version` | String | エンジン/ビルドのバージョン文字列 |
| `attributes` | Map(String, String) | カスタムの文字列属性 |
| `metrics` | Map(String, Float64) | カスタムの数値メトリクス |
Map 型のカラムはブラケットでアクセスします。`attributes['ci.branch']`、`metrics['score']` の形です。
`server_timestamp` というカラムはありません。 イベント時刻には `timestamp` を使ってください。 存在しないカラムを指定するとクエリエラーになるため、先に上の名前を確認してください。 却下されたクエリは HTTP 400 で ClickHouse の診断メッセージ(未知のカラム、テーブル、関数、構文エラー、型の不一致、禁止された操作)を返し、インフラ側の障害のみ 500 を返します。
## 規約
[Section titled “規約”](#規約)
* 自動のパフォーマンスイベントは `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` は常に範囲を絞ってください。テーブルは日付でパーティション分割されているため、範囲を絞るとパーティションが刈り込まれて高速になります。
## 例
[Section titled “例”](#例)
今日のアクティブプレイヤー数。
```sql
SELECT uniqExact(player_id) AS dau
FROM events
WHERE timestamp >= today()
```
直近 7 日のイベント名別の件数。
```sql
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
```
ビルドごとのパフォーマンスパーセンタイル。
```sql
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
```
## 次のステップ
[Section titled “次のステップ”](#次のステップ)
* [API 概要](/api/overview/): 認証とクエリエンドポイント
* [CLI リファレンス](/cli/overview/): `framedash query`
* [トラブルシューティング](/sdk/troubleshooting/): クエリの前にイベント到達を確認する
# 直接 HTTP 取り込み(protobuf)
> 公式 SDK を使わずに、protobuf エンコードしたテレメトリを取り込みエンドポイントへ直接 POST する手順と proto3 スキーマ。
公式 SDK を使わずにテレメトリを送るには、取り込みエンドポイントへ protobuf エンコードした `TelemetryBatch` を直接 POST します。 ほとんどの統合では [Unity](/sdk/unity/)、[UE5](/sdk/unreal/)、[Godot](/sdk/godot/) の公式 SDK を使ってください。 このページは、SDK が提供されていないエンジンや、独自の送信基盤を持つチーム向けの下位レベルの手順です。
## エンドポイント
[Section titled “エンドポイント”](#エンドポイント)
| 項目 | 値 |
| --------------- | --------------------------------------------- |
| メソッドと URL | `POST https://ingest.framedash.dev/v1/events` |
| `Content-Type` | `application/x-protobuf` |
| `X-API-Key` | `events:write` scope を持つ Ingest キー |
| `X-SDK-Version` | SDK バージョン識別子(例: `custom-1.0.0`) |
`Content-Length` は実際のボディサイズと一致させます。 gzip 圧縮を使う場合は `Content-Encoding: gzip` を付けます。
リクエストボディは、gzip 圧縮後のサイズで 126,000 バイト以下に収めてください。 これを超えると `413` を返します。 `application/x-protobuf` 以外の `Content-Type`、および `gzip` 以外の `Content-Encoding` は `415` を返します。 `Content-Length` がないと `411` を返します。 バッチを非同期処理用に受理すると `202` と `{ "status": "accepted" }` を返します。 これは、各イベントが後段の検証を通過したことや永続ストレージへ保存されたことの確認ではありません。デコード可能なバッチでも、無効なイベントは後から破棄されることがあります。
取り込まれたイベントが `builds` やクエリ、ダッシュボードに反映されるまでには 20〜30 秒ほどかかります。 すぐに表示されなくても取り込みが失敗したわけではありません。 独自送信のエンドツーエンド確認では、1 件のイベントに `ingest_probe_` のような一意のマーカーを付け、`` を実行ごとに UUID などへ置き換えます。待機後に `data:admin` scope を持つ **Full** キーでそのマーカーを正確にクエリします。Read-only キーの `analytics:read` scope では集計 API を参照できますが、ここで使う raw SQL の `framedash query` は実行できません。
```bash
framedash query --api-key-file full.key --project-id \
"SELECT count(), max(timestamp) FROM events WHERE event_name = 'ingest_probe_'"
```
件数が 1 以上で、最大時刻が今回の実行時刻と一致する場合にだけ永続保存を確認できます。過去のテストイベントを誤検出しないよう、テストごとに新しいマーカーを使ってください。
## proto3 スキーマ
[Section titled “proto3 スキーマ”](#proto3-スキーマ)
ボディは `framedash.v1.TelemetryBatch` メッセージ(proto3)をエンコードしたバイト列です。 `api_key` と `sdk_version` はペイロードではなく HTTP ヘッダー(`X-API-Key`、`X-SDK-Version`)で送ります。 次が完全なスキーマ定義です。
```proto
syntax = "proto3";
package framedash.v1;
// 3D position vector for spatial analytics (heatmaps, player tracking).
message Vector3 {
float x = 1;
float y = 2;
float z = 3;
}
// Source of the telemetry event.
enum TelemetrySource {
TELEMETRY_SOURCE_UNSPECIFIED = 0;
TELEMETRY_SOURCE_PLAYER = 1;
TELEMETRY_SOURCE_AUTOMATED = 2;
}
// Core telemetry event emitted by game SDKs.
// Each event maps to a single row in the ClickHouse `framedash.events` table.
message GameTelemetryEvent {
string event_name = 1;
// Unix epoch in microseconds. Stored as DateTime64(6) in ClickHouse.
int64 timestamp_us = 2;
string session_id = 3;
// Explicit player identifier — the only PII the SDK may collect.
string player_id = 4;
Vector3 position = 5;
string map_id = 6;
reserved 7;
reserved "zone_id";
float fps = 8;
float frame_time_ms = 9;
int64 memory_used_bytes = 10;
float gpu_time_ms = 11;
// Free-form string key-value pairs for game-specific context.
map attributes = 12;
// Free-form numeric metrics for game-specific measurements.
map metrics = 13;
// Source of the telemetry event.
TelemetrySource source = 14;
string build_id = 15;
string platform = 16;
string engine_version = 17;
// Camera orientation in degrees.
// camera_yaw: horizontal rotation (0 = North, clockwise, [0, 360)).
// camera_pitch: vertical rotation (-90 = straight down, +90 = straight up).
// 'optional' enables has-field presence tracking — distinguishes
// "not sent by SDK" (absent) from "facing North at level" (0, 0).
optional float camera_yaw = 18;
optional float camera_pitch = 19;
// CPU game thread time in milliseconds (logic, AI, physics).
// 0 = not collected (old SDK or unavailable).
float game_thread_ms = 20;
// CPU render thread time in milliseconds (draw commands, culling).
// 0 = not collected (old SDK or unavailable).
float render_thread_ms = 21;
}
// Batch wrapper sent by SDKs via POST /v1/events.
// api_key and sdk_version are transmitted in HTTP headers (X-API-Key, X-SDK-Version),
// not in the Protobuf payload.
message TelemetryBatch {
repeated GameTelemetryEvent events = 1;
}
```
## 送信例
[Section titled “送信例”](#送信例)
`.proto` を `protoc`(または `buf`)でコンパイルし、生成コードで `TelemetryBatch` を組み立ててバイト列にシリアライズします。 シリアライズしたバイト列をファイルに書き出し、`curl` の `--data-binary` で POST します。
```bash
# 1. proto をコンパイル(例: Python)
protoc --python_out=. telemetry.proto
# 2. アプリのコードで TelemetryBatch を組み立て、batch.bin へ書き出す
# 3. POST する
curl -X POST https://ingest.framedash.dev/v1/events \
-H "X-API-Key: fd_your_ingest_key_here" \
-H "X-SDK-Version: custom-1.0.0" \
-H "Content-Type: application/x-protobuf" \
--data-binary @batch.bin
```
各イベントは、[データモデル](/sdk/data-model/#%E5%8F%96%E3%82%8A%E8%BE%BC%E3%81%BF%E6%A4%9C%E8%A8%BC%E4%B8%8A%E9%99%90)の取り込み検証上限を満たす必要があります。 `timestamp_us` は直近 30 日以内かつ 48 時間以上未来でないこと、`event_name` と `session_id` は空でないこと、文字列やマップの各フィールドは上限内であること、数値メトリクスは有限であることが求められます。 公式 SDK はこれらの値を送信前にクランプします。
## 次のステップ
[Section titled “次のステップ”](#次のステップ)
* [イベントスキーマ](/api/events-schema/): クエリで返るカラム
* [API 概要](/api/overview/): 認証とレスポンス形式
* [トラブルシューティング](/sdk/troubleshooting/): イベント到達の確認
# API 概要
> Framedash REST API の概要と認証方法。
Framedash REST API を使用して、テレメトリデータの取得・分析を行えます。
ノート
API リファレンスの詳細ページは英語のみで提供されています。サイドバーの「Framedash API」セクションをご覧ください。
## ベース URL
[Section titled “ベース URL”](#ベース-url)
| サービス | URL |
| ----------------------------------------------------------------- | ------------------------------- |
| Web API (Projects, Maps, Content, Query, Analytics, Alerts, Data) | `https://app.framedash.dev/api` |
| Ingest API (Event Ingestion) | `https://ingest.framedash.dev` |
パスに `/api` を含める
Web API のベース URL は `https://app.framedash.dev/api` で、エンドポイントの完全なベースは `https://app.framedash.dev/api/v1` です。 `/api` を省いて `https://app.framedash.dev/v1/...` を呼ぶと、JSON エラーではなく `307` リダイレクトで HTML のサインインページに転送されます。 JSON の代わりに HTML が返ってきたら、パスに `/api` が含まれているか確認してください。
## 認証
[Section titled “認証”](#認証)
`/api/v1` 配下の REST API は、API キーまたは OAuth 2.1 Bearer トークンのいずれかを受け付けます。 両方を送った場合は `X-API-Key` ヘッダーが優先されます。 ほとんどの統合では API キーを使い、`X-API-Key` ヘッダーで指定します:
```plaintext
X-API-Key: fd_your_api_key_here
```
API キーはダッシュボードの各プロジェクトの「API キー」ページで作成できます。新しいキーは `fd_` プレフィックスを使用し、認可はプレフィックスではなく保存された scope によって決まります。
Free プランでは、1 つのプロジェクトにつき有効な API キーは最大 2 個までで、キーの値は作成時に一度だけ表示されます。上限に達した場合は、不要なキーを無効化してから新しいキーを作成してください。
URL パスがプロジェクトにスコープされていないエンドポイント (`/v1/content` 配下のコンテンツレジストリなど) では、対象プロジェクトを示す `X-Project-Id` ヘッダーも必要です:
```plaintext
X-Project-Id: your-project-uuid
```
### API キープリセット
[Section titled “API キープリセット”](#api-キープリセット)
| プリセット | Scope | 用途 |
| ------------ | ------------------------------------------------- | --------------------------------------------------- |
| Ingest | `events:write` | SDK からのイベント取り込みのみ |
| Read-only | `analytics:read` | ダッシュボード、ステータス、分析の読み取り、CLI の読み取り、raw SQL 以外の MCP ツール |
| Read & Write | `analytics:read`, `resources:write` | 読み取りに加え、マップ、コンテンツ、アラートの変更 |
| Full | `analytics:read`, `resources:write`, `data:admin` | raw SQL クエリ、データエクスポート、プレイヤー削除 |
scope はエンドポイントごとに固定
各エンドポイントが要求する scope は決まっています。 読み取り系エンドポイントは `analytics:read`、`query` とデータエクスポートは `data:admin`、マップやコンテンツの変更は `resources:write`、イベント取り込みは `events:write` だけを受け付けます。 `events:write` だけを持つ Ingest キーは、どの読み取りエンドポイントでも認可されません。 イベントを送らずにこのキーの動作を確認するには、scope を問わずキーを検証する `GET /v1/whoami` を呼びます(後述)。
### キーの検証
[Section titled “キーの検証”](#キーの検証)
`GET /v1/whoami` は、有効な API キーであれば scope を問わず検証し、そのキーに関する非機密のメタデータを返します。 `events:write` だけを持つ Ingest キーのように、どの読み取りエンドポイントにも到達できないキーでも、これで動作を確認できます。 受け付けるのは `X-API-Key` ヘッダーのみで、OAuth Bearer トークンは受け付けません。
```bash
curl https://app.framedash.dev/api/v1/whoami \
-H "X-API-Key: fd_your_api_key_here"
```
レスポンスは scope に応じて段階的です。 読み取り系または管理系の scope(`analytics:read`、`resources:write`、`data:admin`)を持つキーは、完全なメタデータ `{ projectId, projectName, tenantId, planId, scopes }` を返します。 データプレーンのみのキーは `{ projectId, scopes }` だけを返します。 キーの生の値は返しません。 キーが無い場合や無効な場合は `401` を返します。
このエンドポイントには、プランのクォータとは別に、テナントごとに 1 時間あたり 60 リクエストの専用レート制限があります。 上限を超えると `Retry-After` ヘッダー付きの `429` を返します。
### OAuth 2.1
[Section titled “OAuth 2.1”](#oauth-21)
REST API は API キーの代わりに OAuth 2.1 Bearer トークンも受け付けます:
```plaintext
Authorization: Bearer
```
Framedash は OAuth 2.1 認可サーバーです。 クライアントは `{origin}/.well-known/oauth-authorization-server` からエンドポイントを検出できます(`{origin}` は `https://app.framedash.dev`):
| エンドポイント | URL |
| --------------------- | ----------------------------- |
| 認可 | `{origin}/oauth/authorize` |
| トークン | `{origin}/api/oauth/token` |
| 動的クライアント登録 (RFC 7591) | `{origin}/api/oauth/register` |
| 失効 | `{origin}/api/oauth/revoke` |
対応するのは PKCE(`S256`)付きの認可コードフローのみで、パブリッククライアント(`token_endpoint_auth_method` が `none`)向けです。 グラントタイプは `authorization_code` と `refresh_token` です。
OAuth トークンが持てる scope は `analytics:read` と `resources:write` のみです。 クライアントが scope を指定しない場合は `analytics:read` が付与されます。 `data:admin`、`events:write`、`events:synthetic` の各 scope は OAuth では付与されないため、これらを必要とする操作は API キー専用のままです。 たとえば `POST /v1/query` は `data:admin` を必要とするため、OAuth トークンでは呼び出せません。
### 連携済みアプリ
[Section titled “連携済みアプリ”](#連携済みアプリ)
認可済みの OAuth アプリは、ダッシュボードの「設定」→「連携済みアプリ」に一覧表示されます。 各エントリにはクライアント名、付与された scope、許可したプロジェクト、作成日時と最終利用日時が表示され、個別に失効させられます。
## テレメトリのクエリ
[Section titled “テレメトリのクエリ”](#テレメトリのクエリ)
取り込まれたイベントは SQL でクエリできます。 `project_id` はヘッダーではなく JSON ボディで送り、`X-API-Key` で認証します。 raw SQL には `data:admin` scope(Full プリセット)が必要です。
```bash
curl -X POST https://app.framedash.dev/api/v1/query \
-H "X-API-Key: fd_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"project_id": "your-project-uuid",
"sql": "SELECT event_name, count() AS events FROM events WHERE timestamp >= today() GROUP BY event_name ORDER BY events DESC",
"limit": 100
}'
```
レスポンスは `{ "success": true, "data": { "rows": [...], "rowCount": N } }` です。 却下されたクエリは HTTP 400 で ClickHouse の診断メッセージ(未知のカラム、テーブル、関数、構文エラー、型の不一致、禁止された操作)を返します。 インフラ側の障害のみ 500 を返します。 カラムとバリデータの規則は[イベントスキーマ](/api/events-schema/)を、イベント到達の確認は[トラブルシューティング](/sdk/troubleshooting/)を参照してください。
## イベントの取り込み
[Section titled “イベントの取り込み”](#イベントの取り込み)
取り込みエンドポイント(`POST /v1/events`)は `application/x-protobuf` のみを受け付けます(JSON ボディは `415` を返します)。 イベントは公式の [Unity](/sdk/unity/)、[UE5](/sdk/unreal/)、[Godot](/sdk/godot/) SDK が生成します。 これらの SDK は protobuf の `TelemetryBatch` をエンコードし、必要なヘッダーを自動で設定します。 手動でイベントを送るには、その protobuf スキーマを自分でエンコードし、`X-API-Key`(`events:write` scope)、`Content-Type: application/x-protobuf`、`Content-Length`、`X-SDK-Version` を送る必要があります。 ほとんどの統合では、直接送信せず SDK を使ってください。
## レート制限
[Section titled “レート制限”](#レート制限)
API のレート制限はアカウント(テナント)単位で、1 時間あたりのリクエスト数で数えます。 同じアカウントに属するすべてのプロジェクトと API キーが、1 つの上限を共有します。 Free プランは 1 時間あたり 100 リクエスト、有料プランはこれより多くなります。
どのレスポンスにも以下の 3 つのヘッダーが付きます:
```plaintext
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 99
X-RateLimit-Reset: 1782968400000
```
`X-RateLimit-Reset` は秒ではなくミリ秒単位の Unix タイムスタンプです。
上限に達すると `429` を返します。 このとき `X-RateLimit-Remaining` は `0` になり、待機秒数を示す `Retry-After` ヘッダーが追加されます:
```plaintext
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1782968400000
Retry-After: 3400
```
制限はスライディングウィンドウで計算されます。 そのため `X-RateLimit-Reset` が示す時刻を過ぎた直後でも、まだ制限がかかることがあり、`Retry-After` が 1 時間近くまで跳ね上がることがあります。 リセット時刻を狙って再送するのではなく、`429` レスポンスの `Retry-After` に従って待機してください。 通常のレスポンスでは `X-RateLimit-Remaining` を見て、上限に達する前にリクエストの間隔を空けてください。
リモート MCP エンドポイント
ホスト型のリモート MCP エンドポイント(`POST /api/mcp`)には、上記のアカウント単位のレート制限に加えて、認証前の入口に IP アドレス単位の別のレート制限があります。
## レスポンス形式
[Section titled “レスポンス形式”](#レスポンス形式)
Web API(`app.framedash.dev/api`)と Ingest API(`ingest.framedash.dev`)はエラーの形が異なります。 1 つのパーサーで両方を扱えると仮定せず、エンドポイントごとに形を分けて処理してください。
### Web API
[Section titled “Web API”](#web-api)
成功時:
```json
{
"success": true,
"data": { ... }
}
```
エラー時、API は RFC 9457 Problem Details を `application/problem+json` 形式で返します:
```json
{
"type": "about:blank",
"title": "Forbidden",
"status": 403,
"detail": "Plan limit reached.",
"error_category": "authorization",
"retryable": false
}
```
| メンバー | 説明 |
| ---------------- | -------------------------------------------------------------------------------------------------------------------- |
| `type` | 問題タイプの URI。特定のタイプがない場合は `about:blank`。 |
| `title` | HTTP ステータスの短い人間可読な要約。 |
| `status` | HTTP ステータスコード。 |
| `detail` | この個別エラーの人間可読な説明。 |
| `error_category` | `authentication`, `authorization`, `validation`, `rate_limit`, `not_found`, `conflict`, `payload`, `internal` のいずれか。 |
| `retryable` | リトライで成功し得るか(429 と 503 では `true`)。 |
| `retry_after` | 任意。推奨リトライ待機秒数。 |
### Ingest API
[Section titled “Ingest API”](#ingest-api)
成功時:
```json
{
"status": "accepted"
}
```
エラー時:
```json
{
"error": "Error message"
}
```
## OpenAPI スペック
[Section titled “OpenAPI スペック”](#openapi-スペック)
API スペックは [OpenAPI 3.1 形式でダウンロード](/openapi.yaml)できます。
## エンドポイント一覧
[Section titled “エンドポイント一覧”](#エンドポイント一覧)
詳細はサイドバーの自動生成 API リファレンスをご覧ください。
### Projects
[Section titled “Projects”](#projects)
| エンドポイント | メソッド | 説明 |
| -------------------------- | ---- | ---------------- |
| `/v1/projects` | GET | API キーに紐づくプロジェクト |
| `/v1/projects/{id}/status` | GET | プロジェクトステータス |
### キー検証
[Section titled “キー検証”](#キー検証)
| エンドポイント | メソッド | 説明 |
| ------------ | ---- | ------------------------- |
| `/v1/whoami` | GET | API キーを検証し、非機密のキーメタデータを返す |
### Analytics
[Section titled “Analytics”](#analytics)
| エンドポイント | メソッド | 説明 |
| ---------------------------------- | ---- | ------------------------------ |
| `/v1/projects/{id}/dashboard` | GET | ダッシュボード指標(DAU、MAU、セッション、イベント数) |
| `/v1/projects/{id}/builds` | GET | パフォーマンスデータがあるビルド ID 一覧 |
| `/v1/projects/{id}/builds/compare` | GET | 2 つのビルドのパフォーマンス比較 |
| `/v1/projects/{id}/heatmap` | GET | マップのヒートマップデータ |
| `/v1/projects/{id}/retention` | GET | プレイヤーリテンションコホート |
| `/v1/projects/{id}/funnels` | GET | ファネルコンバージョン分析 |
| `/v1/projects/{id}/insights` | GET | ディメンション別の集計分析 |
builds のパラメータ
`/v1/projects/{id}/builds` は `days`(7、14、30、90 のいずれか。デフォルト 30)、最新 50 件の枠外のビルドを取得する `buildId`、約 60 秒の集計キャッシュをバイパスする `fresh=1` を受け付けます。 `/v1/projects/{id}/builds/compare` は `baseline` と `candidate`(同一の場合は 400 で却下)を必須とし、さらに `days`、`mapId`、`platform`、`fresh=1` を受け付けます。 パフォーマンスを持つイベントがないビルドは 404 を返します。
### Alerts
[Section titled “Alerts”](#alerts)
| エンドポイント | メソッド | 説明 |
| -------------------------------------- | ------ | ------------ |
| `/v1/projects/{id}/alerts` | GET | アラートルール一覧 |
| `/v1/projects/{id}/alerts` | POST | アラートルール作成 |
| `/v1/projects/{id}/alerts/{alertId}` | GET | アラートルール取得 |
| `/v1/projects/{id}/alerts/{alertId}` | PATCH | アラートルール更新 |
| `/v1/projects/{id}/alerts/{alertId}` | DELETE | アラートルール無効化 |
| `/v1/projects/{id}/alerts/history` | GET | アラート評価履歴 |
| `/v1/projects/{id}/threshold-profiles` | GET | しきい値プロファイル一覧 |
### Maps
[Section titled “Maps”](#maps)
| エンドポイント | メソッド | 説明 |
| -------------------------------- | ------ | --------- |
| `/v1/projects/{id}/maps` | GET | マップ一覧 |
| `/v1/projects/{id}/maps/{mapId}` | DELETE | マップ削除 |
| `/v1/maps/upload` | POST | マップアップロード |
### Content Registry
[Section titled “Content Registry”](#content-registry)
| エンドポイント | メソッド | 説明 |
| ------------- | ------ | -------------- |
| `/v1/content` | GET | コンテンツエントリ一覧 |
| `/v1/content` | POST | コンテンツエントリ作成・更新 |
| `/v1/content` | DELETE | コンテンツエントリ削除 |
### Query
[Section titled “Query”](#query)
| エンドポイント | メソッド | 説明 |
| ----------- | ---- | ------- |
| `/v1/query` | POST | 分析クエリ実行 |
### Data
[Section titled “Data”](#data)
| エンドポイント | メソッド | 説明 |
| ----------------- | ---- | ----------------------- |
| `/v1/data/export` | GET | アクセス可能なプロジェクトデータのエクスポート |
| `/v1/data/erase` | POST | 指定プレイヤーのテレメトリ削除 |
### Event Ingestion
[Section titled “Event Ingestion”](#event-ingestion)
| エンドポイント | メソッド | 説明 |
| ------------ | ---- | ------------- |
| `/v1/events` | POST | テレメトリイベント取り込み |
# CLI リファレンス
> Framedash CLI のインストールとコマンド一覧。
Framedash CLI は、ターミナルからテレメトリデータ・アナリティクス・プロジェクト管理にアクセスできるツールです。CI/CD パイプラインでのマップアップロードやコンテンツ同期にも対応しています。
## インストール
[Section titled “インストール”](#インストール)
Node.js と npm が必要です。 グローバルにインストールするか、`npx` でインストールせずに都度実行できます。
```bash
# グローバルにインストール
npm install -g @framedash/cli
# またはインストールせずに実行
npx @framedash/cli --help
```
## 認証
[Section titled “認証”](#認証)
API キーは環境変数で渡すか、ファイルから読み取ります。
```bash
# 環境変数
export FRAMEDASH_API_KEY=fd_your_api_key_here
# またはファイルから(- で標準入力)
framedash status --api-key-file ./read.key
```
キーの有効性と紐付けプロジェクトを確認:
```bash
framedash auth
```
注意
raw な `--api-key` フラグより、`FRAMEDASH_API_KEY` か `--api-key-file` を優先してください。 コマンドラインに渡したキーはプロセス一覧とシェル履歴に残ります。 CLI 自身も `--api-key` の使用時に警告します。
CLI は `framedash login` で対話的にサインインもできます。 OAuth セッションを保存するため、以降の読み取りコマンドではキーを渡す必要がありません。
## 共通オプション
[Section titled “共通オプション”](#共通オプション)
ほとんどのコマンドで以下のオプションが使用できます:
| オプション | 説明 |
| ----------------------- | ----------------------------------------------- |
| `--api-key ` | API キー(または `FRAMEDASH_API_KEY` 環境変数) |
| `--api-key-file ` | ファイルから API キーを読み取る(`-` で標準入力) |
| `--project-id ` | プロジェクト ID(または `FRAMEDASH_PROJECT_ID` 環境変数) |
| `--base-url ` | API ホスト URL(デフォルト: `https://app.framedash.dev`) |
| `--format ` | 出力形式: `json`, `table`, `csv`(デフォルト: `json`) |
| `-h, --help` | ヘルプを表示 |
ノート
`framedash auth` は `--project-id` 不要です(API キーの検証のみ)。 `framedash map-capture` は独自のオプションパーサーを使用します (下記参照)。
ノート
`--base-url` はアプリケーションホスト URL です。CLI は内部的に API パス(例: `/api/v1/...`)を付加します。これは [API リファレンス](/api/overview/) のベース URL(`app.framedash.dev/api`)とは異なります。後者は REST API を直接呼び出す場合に使用します。
プロジェクト ID を調べる
`--project-id` に渡す UUID は `framedash projects list` で確認できます。 `framedash auth` もアクセスできるプロジェクトを表示します。
## コマンド
[Section titled “コマンド”](#コマンド)
このページはよく使うコマンドを扱います。 バージョンごとの正確な一覧は `framedash --help`(または `framedash --help`)で確認してください。
### `framedash auth`
[Section titled “framedash auth”](#framedash-auth)
API キーの検証と紐付けプロジェクトの表示。
```bash
framedash auth
```
オプション: `--api-key`, `--base-url`, `--format`
ノート
`framedash auth` は `analytics:read` スコープを必要とする読み取り呼び出しでキーを検証します。 `events:write` のみの Ingest キーはこの方法では検証できません。 Ingest キーを試すには、SDK でイベントを送信します。
`--format json` では標準出力に JSON 文書だけを出力するため、`jq` などへ安全にパイプできます。検証結果や認証情報の参照元を示すステータス行は標準エラーに表示されます。
### `framedash login` / `framedash logout`
[Section titled “framedash login / framedash logout”](#framedash-login--framedash-logout)
`framedash login` は OAuth 2.1 の認可コードフローと PKCE(`S256`)で対話的にサインインします。 システムブラウザで `{base-url}/oauth/authorize` を開き、ループバックリダイレクトを使って最大 5 分間、承認を待ちます。
```bash
framedash login
```
| オプション | 説明 |
| ------------------ | ------------------------------------------ |
| `--scopes ` | 要求する scope(スペース区切り。デフォルト `analytics:read`) |
| `--no-browser` | ブラウザを開かず認可 URL を出力する |
| `--base-url ` | 認可サーバー(デフォルト `https://app.framedash.dev`) |
トークンは `~/.config/framedash/credentials.json` に保存され(`XDG_CONFIG_HOME` を尊重します。Windows でも同じパス規約です)、サーバーオリジンごとにキー付けされて自動でリフレッシュされます。 トークンの値が出力されることはありません。
`framedash logout` はトークンをサーバー側で失効させ(ベストエフォート)、解決されたベース URL のローカル認証情報を削除します。 `--all` を付けると全オリジンをクリアします。 API キーには影響しません。
```bash
framedash logout
framedash logout --all
```
明示的な `--api-key`、`--api-key-file`、`FRAMEDASH_API_KEY` は、保存済みのログインより常に優先されます。 そのため CI では `framedash login` ではなく `FRAMEDASH_API_KEY` で認証してください。 `login` で付与したグラントは、ダッシュボードの「設定」→「連携済みアプリ」で確認および失効ができます。
### `framedash projects list`
[Section titled “framedash projects list”](#framedash-projects-list)
アクセスできるプロジェクト(`id`、`name`、`createdAt`)を一覧表示します。 `analytics:read` スコープを持つ API キーまたは OAuth ログインで動作し、`--project-id` は不要です。 `events:write` のみの Ingest キーではプロジェクトを一覧表示できません。 `@framedash/cli` 0.1.4 以降で利用できます。
```bash
framedash projects list --format table
```
出力形式は `--format json|table|csv` を指定できます。
### `framedash status`
[Section titled “framedash status”](#framedash-status)
プロジェクトのヘルスステータスを表示。
```bash
framedash status
```
`kpis.fetchedAt` は KPI スナップショットを問い合わせた時刻(Unix ミリ秒)です。通常はサーバーキャッシュを使います。CI やトラブルシューティングで新しい問い合わせ結果が必要な場合は `--fresh` でキャッシュを迂回します。このオプションは `@framedash/cli` 0.1.7 には含まれません。より新しいリリースをインストールし、`framedash status --help` に表示されることを確認してから使用してください。
### `framedash dashboard`
[Section titled “framedash dashboard”](#framedash-dashboard)
ダッシュボード KPI(DAU、MAU、セッション、イベント数)を表示。
```bash
framedash dashboard --days 30
```
| オプション | 値 | デフォルト |
| -------- | ------------- | ----- |
| `--days` | 7, 14, 30, 90 | 30 |
### `framedash retention`
[Section titled “framedash retention”](#framedash-retention)
プレイヤーリテンションコホート(D1、D7、D30)を表示。
```bash
framedash retention --days 14
```
| オプション | 値 | デフォルト |
| -------- | ------------- | ----- |
| `--days` | 7, 14, 30, 90 | 30 |
### `framedash funnel`
[Section titled “framedash funnel”](#framedash-funnel)
イベントファネルを分析し、ステップ間のプレイヤーコンバージョンを測定。
```bash
framedash funnel --steps "player_spawn,player_death,player_respawn"
```
| オプション | 説明 | デフォルト |
| ---------- | --------------------------------------- | ----- |
| `--steps` | カンマ区切りのイベント名(必須、2-8 ステップ) | — |
| `--window` | タイムウィンドウ(秒): 3600, 21600, 86400, 604800 | 86400 |
| `--days` | 期間: 7, 14, 30, 90 | 30 |
### `framedash builds`
[Section titled “framedash builds”](#framedash-builds)
プロジェクトで検出されたビルド ID を新しい順に表示。`framedash perf-diff` の比較対象を選ぶために使います。
```bash
framedash builds --days 30
```
| オプション | 値 | デフォルト |
| -------- | ------------- | ----- |
| `--days` | 7, 14, 30, 90 | 30 |
分析系の `--days` と ヒートマップの `days`
分析系コマンド(`dashboard`、`retention`、`funnel`、`builds`、`perf-diff`)の `--days` は 7、14、30、90 です。 ヒートマップ API の `days`(1、7、14、30)とは意図的に異なる集合です。
### `framedash perf-diff`
[Section titled “framedash perf-diff”](#framedash-perf-diff)
2 つのビルドの P50/P95 パフォーマンス(フレームタイム、メモリ、GPU 時間)を比較します。`--fail-on-regression` を付けると、候補ビルドがしきい値を超えて悪化した場合に終了コード 1 で失敗します。
```bash
framedash perf-diff --baseline "$BASE_SHA" --candidate "$GITHUB_SHA" \
--threshold 5 --fail-on-regression
```
| オプション | 説明 |
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--baseline ` | 比較基準の `build_id`(必須) |
| `--candidate ` | テスト対象の `build_id`(必須) |
| `--metric ` | 1 つのメトリクスに限定: `frame_time`, `memory`, `gpu_time`, `io.read_bytes`, `io.read_time_ms`, `io.read_ops`, `load_time_ms`, `mem.vram`(デフォルトは全メトリクス)。`load_time_ms` は SDK のマップロード計測が、`mem.vram` は SDK の VRAM サンプリングが必要 |
| `--threshold ` | 許容する悪化率(%)。デフォルトは 0 |
| `--fail-on-regression` | 回帰検出時に非ゼロで終了 |
| `--days ` | 期間: 7, 14, 30, 90(デフォルト 30) |
| `--map ` | 特定マップに限定 |
| `--platform ` | 特定プラットフォームに限定 |
`--baseline` と `--candidate` には異なるビルド ID を指定します。 CLI は同一の ID を拒否するため、設定を誤った CI ジョブは、ビルドを自分自身と比較する前に早期に失敗します。
`isRegression` と `--threshold` の関係
出力に含まれるメトリクスごとの `isRegression` フラグは方向性だけを表します。 しきい値は適用されず、少しでも悪化していれば `true` になります。 `--threshold` の値が左右するのは、`--fail-on-regression` を付けたときの終了コードだけです。
### `framedash run-profile-test`
[Section titled “framedash run-profile-test”](#framedash-run-profile-test)
CI でプロファイリングビルドをエンドツーエンドで実行します: `FRAMEDASH_*` 自動セッション変数をエクスポートし、ゲーム/プロファイリングコマンドを起動し、テレメトリーの取り込みを待ってから、基準ビルドに対して `perf-diff` ゲートを実行します。`builds` と `perf-diff` を組み合わせたターンキーコマンドです。
```bash
framedash run-profile-test \
--command "./Build/Game.exe -nullrhi -ExecCmds='Automation RunTest Perf'" \
--scenario nightly --api-key-file ci-read.key \
--baseline "$BASE_SHA" --threshold 5 --fail-on-regression
```
| オプション | 説明 |
| ---------------------- | ------------------------------------------------- |
| `--command ` | シェル経由で起動するゲーム/プロファイリングコマンド(必須) |
| `--build-id ` | 候補の `build_id`(デフォルト: `--commit`、なければ `git HEAD`) |
| `--branch ` | デフォルト: `git rev-parse --abbrev-ref HEAD` |
| `--commit ` | デフォルト: `git rev-parse HEAD` |
| `--scenario ` | テストシナリオのラベル |
| `--ingest-timeout ` | 新しいテレメトリーを待つ最大秒数(デフォルト 180) |
| `--poll-interval ` | 取り込みのポーリング間隔(秒、デフォルト 5) |
| `--skip-wait` | 取り込み待ちをスキップ |
| `--baseline ` | 候補を比較する基準の `build_id` |
`--baseline`, `--metric`, `--threshold`, `--fail-on-regression`, `--days`, `--map`, `--platform` の各フラグは [`framedash perf-diff`](#framedash-perf-diff) と同じ挙動です。
起動されたコマンドは `FRAMEDASH_BUILD_ID` / `FRAMEDASH_GIT_BRANCH` / `FRAMEDASH_GIT_COMMIT` / `FRAMEDASH_TEST_SCENARIO` を継承します。SDK が `BeginAutomatedSessionFromEnvironment()` を一度呼べば、以降は全イベントへ自動でタグが付き、イベントごとのタグ付けコードは不要です。詳しい手順は [CI プロファイリング](/concepts/ci-profiling/) を参照してください。
ノート
ゲートは `analytics:read` キーでテレメトリーを読み取り、起動されるゲームは別の `events:write` 取り込みキーでテレメトリーを送信します。名前の衝突を避けるため、ゲートキーは `FRAMEDASH_API_KEY` 環境変数ではなく `--api-key-file` で渡し、`FRAMEDASH_API_KEY` はゲームの取り込みキー用に残してください。
### `framedash query`
[Section titled “framedash query”](#framedash-query)
テレメトリデータに対する SQL クエリを実行。
```bash
# インライン SQL
framedash query "SELECT event_name, count() FROM events GROUP BY event_name"
# ファイルから読み込み
framedash query --file ./queries/daily-active.sql
```
| オプション | 説明 |
| --------------- | ---------------------------- |
| `--file ` | インライン引数の代わりにファイルから SQL を読み込み |
| `--limit ` | 返却する最大行数 |
ノート
`framedash query` には `data:admin` scope を持つ API キー(Full キー)が必要です。 `framedash login` の OAuth ログインは `data:admin` を持てないため、ログインだけではこのコマンドを実行できません。 Full キーを `FRAMEDASH_API_KEY` または `--api-key` / `--api-key-file` で渡してください。
### `framedash alerts`
[Section titled “framedash alerts”](#framedash-alerts)
パフォーマンスアラートルールの管理。
```bash
# アラートルール一覧
framedash alerts list
# 新規アラートルール作成
framedash alerts create --name "FPS Alert" --map-id \
--threshold-profile-id --metric fps --threshold-level warn \
--fail-percentage 20 --evaluation-days 7 --cell-size 25 \
--cooldown-minutes 60
# アラートルール更新
framedash alerts update --name "Updated Alert"
# アラートルール無効化
framedash alerts delete
```
ノート
`framedash alerts create` と `framedash alerts update` は、1 つのルールに最大 10 個のしきい値プロファイルを紐付ける `--threshold-profile-ids ` を受け付けます(`@framedash/cli` 0.1.6 以降)。 紐付けた各プロファイルは、それぞれ独立して発火し、解消します。 単数形の `--threshold-profile-id` は、プロファイルが 1 つの場合のために残っています。 `alerts create` は 2 つのフラグのうち少なくとも一方を必須とし、両方を渡したときは `--threshold-profile-ids` が優先されます。
ノート
`alerts delete` はルールを削除せず、無効化します(`isActive=false`)。 ルールは保持され、`framedash alerts update --is-active true` で再度有効化できます。 無効化したルールはプランのアラートルール上限には数えられないため、再有効化はその上限の対象になります。
### `framedash threshold-profiles`
[Section titled “framedash threshold-profiles”](#framedash-threshold-profiles)
アラートルールが参照するパフォーマンスしきい値プロファイル(メトリクスごとの warn/good の帯)を管理します。
新しく作成したプロジェクトには、`Default` という名前の自動作成プロファイルが 1 つ用意されています(デバイスフィルターはすべてワイルドカード、しきい値は組み込みの既定値)。 そのためアラートルールはすぐにプロファイルを参照でき、後から編集や追加ができます。
```bash
# しきい値プロファイル一覧
framedash threshold-profiles list
# しきい値プロファイルを作成
framedash threshold-profiles create --name "Console 60fps" \
--fps-good 60 --fps-warn 30 --platform windows
# しきい値プロファイルを削除
framedash threshold-profiles delete
```
`framedash threshold-profiles create`(`@framedash/cli` 0.1.7 以降)はプロファイルを作成します。 `--name` は必須です(最大 100 文字)。 しきい値のペアは任意で、省略すると組み込みの既定値が使われます:`--fps-good` / `--fps-warn`(FPS)、`--frame-time-good` / `--frame-time-warn`(ミリ秒)、`--memory-good` / `--memory-warn`(MB)、`--gpu-time-good` / `--gpu-time-warn`(ミリ秒)。 FPS は高いほどよい指標(good が warn より大きい)で、それ以外は低いほどよい指標(good が warn より小さい)です。 デバイスフィルター(`--platform`、`--resolution`(例: `1920x1080`)、`--build-config`、`--gpu`、`--storage`)は任意で、省略したフィルターはワイルドカードとして扱われます。 作成には `resources:write` スコープを持つ API キー、または `--scopes` に `resources:write` を含めて実行した `framedash login` の OAuth セッションが必要です(既定のログインは `analytics:read` のみを要求します)。 名前の重複や、まったく同一のデバイスフィルターの組み合わせ(5 つのフィルターがすべて一致)はサーバーが `409` で拒否しますが、一部だけ重なる組み合わせは作成でき、コマンドは重なったプロファイル名を報告します。 成功すると CLI は `Threshold profile created` と作成したプロファイルを出力します。
`framedash threshold-profiles delete `(`@framedash/cli` 0.1.8 以降)はプロファイルを削除します。 このコマンドには `resources:write` スコープを持つ API キー、または `--scopes` に `resources:write` を含めて実行した `framedash login` の OAuth セッションが必要です(既定のログインは `analytics:read` のみを要求します)。 アラートルールから参照されているプロファイル(主となるしきい値プロファイル、またはバンドルの一員)はサーバーが `409` で拒否します。 アラートルールを無効化しても削除できるようにはならないため、先に該当するアラートルールを `framedash alerts update --threshold-profile-ids <...>` で別のプロファイルに付け替えてください。
### `framedash maps`
[Section titled “framedash maps”](#framedash-maps)
ゲームマップの管理。
```bash
# マップ一覧
framedash maps list
# マップ ID でマップを削除
framedash maps delete
```
ここで指定する識別子は、マップのキャプチャ時に付けた `mapId` スラッグです。 内部の UUID 主キーではありません。
### `framedash map-capture`
[Section titled “framedash map-capture”](#framedash-map-capture)
キャプチャしたマップ画像をアップロード。このコマンドは独自のオプションパーサーを持ち、共通グローバルオプションは使用しません。
```bash
# アップロード内容のプレビュー(ドライラン)
framedash map-capture --input-dir ./captures --upload --dry-run
# マップキャプチャをアップロード
framedash map-capture --input-dir ./captures --upload \
--api-key fd_xxx --project-id
```
| オプション | 説明 |
| --------------------------- | ------------------------------------------- |
| `--input-dir ` | キャプチャ画像のディレクトリ(必須) |
| `--upload` | 実際にアップロードを実行(必須) |
| `--api-key ` | アップロード用 API キー |
| `--project-id ` | 対象プロジェクト |
| `--base-url ` | API ベース URL |
| `--dry-run` | 送信せずにプレビュー |
| `--metadata-pattern ` | 一致する JSON サイドカーだけを読み込み(例: `*.capture.json`) |
#### 入力の契約
[Section titled “入力の契約”](#入力の契約)
`--input-dir` は再帰せずに走査されます。 既定では、その直下にあるすべての `*.json` ファイルがキャプチャメタデータのサイドカーとして扱われます。 無関係な JSON も同じディレクトリにある場合は `--metadata-pattern '*.capture.json'` を指定し、サイドカー名を合わせてください。`--metadata-pattern` は `@framedash/cli` 0.1.7 には含まれません。より新しいリリースをインストールし、`framedash map-capture --help` に表示されることを確認してから使用してください。 コマンドは選択された各 JSON を読み込んで検証し、そこで参照している画像をアップロードします。 サイドカーは `image_path` で画像を指定し、このパスは入力ディレクトリからの相対で解決されます。 絶対パスやディレクトリの外へ抜けるパスは拒否されますが、入力ディレクトリ内のサブディレクトリは許可されます。 対応する画像形式は `.png`、`.jpg`、`.jpeg`、`.webp` です。
必須フィールド:
| フィールド | 型 | 備考 |
| ------------------ | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `version` | 文字列 | リテラル `"1.0"` |
| `map_id` | 文字列 | 1〜128 文字 |
| `image_path` | 文字列 | `--input-dir` からの相対パス |
| `image_dimensions` | オブジェクト | `{ "width", "height" }`、正の整数 |
| `world_bounds` | オブジェクト | `{ "min": {x,y,z}, "max": {x,y,z} }`、有限の数値。`max.x` は `min.x` より、`max.y` は `min.y` より大きい必要があります。`z` は制約なし。値はエンジンのワールド単位(Unreal Engine ではセンチメートルなど) |
任意フィールド:
| フィールド | 型 | 備考 |
| ------------------- | --- | ------------ |
| `projection` | 文字列 | 自由記述 |
| `capture_axis` | 文字列 | 自由記述 |
| `coordinate_system` | 文字列 | 自由記述 |
| `engine` | 文字列 | 自由記述 |
| `build_id` | 文字列 | 最大 255 文字 |
| `captured_at` | 文字列 | ISO 8601 の日時 |
具体例を示します。 画像 `arena.png`(1024x1024 の俯瞰キャプチャ)と、その隣にサイドカー `arena.json` を `./captures` に置きます。
```json
{
"version": "1.0",
"map_id": "arena_dust",
"image_path": "arena.png",
"image_dimensions": { "width": 1024, "height": 1024 },
"world_bounds": {
"min": { "x": -8192, "y": -8192, "z": 0 },
"max": { "x": 8192, "y": 8192, "z": 2048 }
},
"engine": "UE5",
"captured_at": "2026-07-16T09:30:00Z"
}
```
まず `--dry-run` で検証します。 認証情報は不要で、アップロードは行いません。
```bash
framedash map-capture --input-dir ./captures --dry-run
```
ドライランはファイルごとに 1 行(`map_id=..., image=..., bounds=[minX,minY]→[maxX,maxY], size=WxH`)を出力し、続けて `Done: N succeeded, M failed` の要約を表示します。 検証に失敗したファイルが 1 つでもあれば終了コード 1 で終わります。 失敗が 0 件と報告されたら、実際にアップロードします。 アップロードは `/api/v1/maps/upload` へのマルチパート `POST` で、`resources:write` スコープを持つ API キーが必要です。
```bash
framedash map-capture --input-dir ./captures --upload \
--api-key fd_xxx --project-id
```
### `framedash content`
[Section titled “framedash content”](#framedash-content)
コンテンツレジストリ(アイテム、武器、イベント種別など)の管理。
```bash
# コンテンツエントリ一覧
framedash content list
# JSON ファイルからコンテンツをインポート
framedash content import ./game-content.json
# UUID で削除
framedash content delete
# タイプとコンテンツ ID で削除
framedash content delete --type weapon --content-id ak47
```
インポート JSON は配列または `{ "entries": [...] }` を受け付けます。各エントリには空でない文字列の `contentType`, `contentId`, `displayName` が必要です。任意の `description` と `category` は文字列または `null`、`metadata` はオブジェクトまたは `null` です。リクエスト送信前の検証エラーには 1 始まりのエントリ番号が表示されます。
## レート制限
[Section titled “レート制限”](#レート制限)
1 時間あたりの API レート制限はアカウント(テナント)単位で適用され、そのアカウントが持つすべてのプロジェクトと API キーで共有されます。 Free プランは 1 時間あたり 100 リクエスト、上位プランはそれ以上です。 枠が共有されるため、並列で走る CLI の呼び出しや別々のキーは、いずれも同じプールを消費します。
429 が返ったときは、`X-RateLimit-Reset` のタイムスタンプを基準にスケジュールするのではなく、毎回 `Retry-After` ヘッダーに従います。 どちらの値もスライディングウィンドウから算出されるため、表示されたリセット直後の実際の待ち時間を短く見積もることがあり、リセット時刻ちょうどに再試行すると再び 429 になることがあります。
## CI/CD での使用
[Section titled “CI/CD での使用”](#cicd-での使用)
GitHub Actions の例:
```yaml
- name: Upload maps and import content
env:
FRAMEDASH_API_KEY: ${{ secrets.FRAMEDASH_API_KEY }}
FRAMEDASH_PROJECT_ID: ${{ vars.PROJECT_ID }}
run: |
framedash map-capture --input-dir ./map-captures --upload
framedash content import ./game-content.json
```
Jenkins および TeamCity の例については [CI/CD 統合ガイド](/integrations/ci-cd/) を参照してください。
## 次のステップ
[Section titled “次のステップ”](#次のステップ)
* [イベントスキーマ](/api/events-schema/): `framedash query` のカラムと規則
* [トラブルシューティング](/sdk/troubleshooting/): イベント到達の確認
* [API リファレンス](/api/overview/): REST API の詳細
* [CI/CD 統合](/integrations/ci-cd/): Jenkins および TeamCity パイプライン例
* [CI プロファイリング](/concepts/ci-profiling/): 自動パフォーマンスプロファイリング設定
# CI 統合プロファイリング
> CI ビルドのテレメトリーにタグを付け、ダッシュボードで回帰を確認します。
CI 統合プロファイリングでは、自動ビルドから送信するテレメトリーに `build_id` を付け、Framedash 上でビルドごとのパフォーマンスを確認します。現時点で利用できるのは、ビルドフィルター、Regression ページ、`framedash builds`、CI 側で実行する `framedash perf-diff` ゲート、`framedash run-profile-test` ランナー、しきい値プロファイル、静的しきい値アラートです。Framedash がホストするプロファイリングジョブや前回ビルドとの差分通知はまだ未実装です。
## 仕組み
[Section titled “仕組み”](#仕組み)
1. **CI ビルド**: ゲームのビルドを作成
2. **自動テスト**: 事前定義されたシナリオを自動実行
3. **テレメトリー収集**: SDK が CI の `build_id` 付きでパフォーマンスデータを送信
4. **ダッシュボード確認**: Regression ページやビルドフィルターでビルドを比較
5. **CI ゲート**: `framedash run-profile-test`(または `framedash builds` + `framedash perf-diff`)でビルド間の回帰時にビルドを失敗させる
6. **任意のアラート**: しきい値プロファイルとアラートルールで FPS、フレームタイム、メモリの静的上限/下限を監視
## セットアップ
[Section titled “セットアップ”](#セットアップ)
### 1. CI 環境での SDK 設定
[Section titled “1. CI 環境での SDK 設定”](#1-ci-環境での-sdk-設定)
SDK の初期化時に `build_id` を CI 環境変数から設定します。
#### Unity / Godot
[Section titled “Unity / Godot”](#unity--godot)
```csharp
TelemetrySDK.Initialize(
apiKey: System.Environment.GetEnvironmentVariable("FRAMEDASH_API_KEY"),
buildId: System.Environment.GetEnvironmentVariable("FRAMEDASH_BUILD_ID"));
```
#### UE5
[Section titled “UE5”](#ue5)
```cpp
if (auto* Subsystem = GetGameInstance()->GetSubsystem())
{
FString ApiKey = FPlatformMisc::GetEnvironmentVariable(TEXT("FRAMEDASH_API_KEY"));
FString BuildId = FPlatformMisc::GetEnvironmentVariable(TEXT("FRAMEDASH_BUILD_ID"));
// EndpointUrl に空文字列を渡してデフォルト値を使用
Subsystem->InitializeTelemetry(ApiKey, TEXT(""), BuildId);
}
```
### 2. 自動セッションのタグ付け
[Section titled “2. 自動セッションのタグ付け”](#2-自動セッションのタグ付け)
自動テストのエントリーポイントで自動セッション API を一度呼び出すと、すべてのイベントに CI のビルドと branch/commit/scenario が付与されます。`BeginAutomatedSessionFromEnvironment()` は、`framedash run-profile-test` がエクスポートする `FRAMEDASH_BUILD_ID` / `FRAMEDASH_GIT_BRANCH` / `FRAMEDASH_GIT_COMMIT` / `FRAMEDASH_TEST_SCENARIO` を読み取ります:
#### Unity / Godot
[Section titled “Unity / Godot”](#unity--godot-1)
```csharp
TelemetrySDK.Instance.BeginAutomatedSessionFromEnvironment();
// ... プロファイリングシナリオを実行 ...
TelemetrySDK.Instance.EndAutomatedSession();
```
#### UE5
[Section titled “UE5”](#ue5-1)
```cpp
if (auto* Subsystem = GetGameInstance()->GetSubsystem())
{
Subsystem->BeginAutomatedSessionFromEnvironment();
// ... プロファイリングシナリオを実行 ...
Subsystem->EndAutomatedSession();
}
```
`build_id` は最上位フィールドとして、branch/commit/scenario は `ci.branch` / `ci.commit` / `ci.scenario` 属性として付与されます。
### 3. テストシナリオの定義
[Section titled “3. テストシナリオの定義”](#3-テストシナリオの定義)
各マップ/エリアを巡回するテストシナリオを作成し、一貫したデータを収集します。
### 4. プロファイリングゲートの実行
[Section titled “4. プロファイリングゲートの実行”](#4-プロファイリングゲートの実行)
最も簡単な方法は `framedash run-profile-test` です: `FRAMEDASH_*` セッション変数をエクスポートし、プロファイリングビルドを起動し、テレメトリーの取り込みを待ってから、ビルド間の回帰時にジョブを失敗させます。
```bash
framedash run-profile-test \
--command "./Build/Game.exe -nullrhi -ExecCmds='Automation RunTest Perf'" \
--scenario nightly --api-key-file ci-read.key \
--baseline "$BASE_SHA" --threshold 5 --fail-on-regression
```
手動でステップを実行することもできます。比較可能なビルド ID を確認し、候補ビルドがしきい値を超えて悪化した場合にパイプラインを失敗させます:
```bash
framedash builds --days 30
framedash perf-diff --baseline "$BASE_SHA" --candidate "$GITHUB_SHA" \
--threshold 5 --fail-on-regression
```
`perf-diff` はフレームタイム、メモリ、GPU 時間、マップロード時間(`load_time_ms`)、ディスク I/O(`io.read_bytes` / `io.read_time_ms` / `io.read_ops`)、GPU VRAM(`mem.vram`)を lower-is-better 指標として比較します。マップロードと `io.*` のサンプルには Unity 0.1.3 / UE5 0.1.6 / Godot 0.1.4 以降の SDK が必要で、`mem.vram` には UE5 SDK 0.1.7 以降(オプトイン、非ヘッドレス)、Unity SDK 0.1.4 以降、または Godot SDK 0.1.5 以降が必要です。ベースラインにデータが無いビルドの `mem.vram` は比較不能(not comparable)として扱われます。ホスト型の前回ビルド差分アラートではなく、CI がコマンドを実行して合否を管理します。
ノート
ゲートは `analytics:read` キーでテレメトリーを読み取り、起動されるゲームは別の `events:write` 取り込みキーでテレメトリーを送信します。名前の衝突を避けるため、ゲートキーは `FRAMEDASH_API_KEY` 環境変数ではなく `--api-key-file` で渡し、`FRAMEDASH_API_KEY` はゲームの取り込みキー用に残してください。
ダッシュボードでは静的なしきい値も設定できます:
* FPS が許容下限を下回る
* フレームタイムが 33ms を超過
* メモリ使用量が予算を超過
## 活用例
[Section titled “活用例”](#活用例)
* **プルリクエストのパフォーマンスチェック**: PR ビルドにテレメトリーを紐付け、マージ前に確認
* **ナイトリービルドの監視**: build ID ごとの日次パフォーマンススナップショットを残す
* **リリース前の品質ゲート**: `framedash perf-diff` または CI 側の静的しきい値で判定
## 次のステップ
[Section titled “次のステップ”](#次のステップ)
* [CLI リファレンス](/cli/overview/): CI パイプラインでの CLI 活用
* [ヒートマップ](/concepts/heatmaps/): パフォーマンスの可視化
# コンテンツレジストリ
> ゲームコンテンツの静的メタデータとテレメトリのリンク機能。
コンテンツレジストリは、ゲーム内のマップ・アイテム・スキルなどの静的メタデータを管理し、テレメトリデータと紐づける機能です。
## なぜ必要か
[Section titled “なぜ必要か”](#なぜ必要か)
汎用のテレメトリツールでは、イベントデータに含まれる ID が何を指しているかわかりません。コンテンツレジストリを使うことで:
* `item_id: "sword_01"` → 「炎の剣 (レア / 武器カテゴリ)」
* `map_id: "map_desert"` → 「砂漠アリーナ (PvP マップ)」
テレメトリにゲーム文脈を付与し、意味のある分析を可能にします。
## コンテンツの種類
[Section titled “コンテンツの種類”](#コンテンツの種類)
| 種類 | 説明 | 例 |
| ----------- | --------- | -------------- |
| `map` | ゲームマップ | ステージ、アリーナ、ワールド |
| `item` | ゲーム内アイテム | 武器、消耗品、装備 |
| `skill` | スキル/アビリティ | 攻撃、バフ、パッシブ |
| `character` | キャラクター | プレイアブル、NPC |
| `custom` | カスタム定義 | 任意のゲーム要素 |
## データ同期
[Section titled “データ同期”](#データ同期)
コンテンツレジストリのデータは、ゲームのマスタデータと同期します。
### 手動登録
[Section titled “手動登録”](#手動登録)
ダッシュボードから個別に登録するか、REST API で登録します。`POST /v1/content` エンドポイントは `X-Project-Id` ヘッダーを必須とし、エントリを `entries` エンベロープでラップします:
```bash
curl -X POST https://app.framedash.dev/api/v1/content \
-H "X-API-Key: fd_your_api_key_here" \
-H "X-Project-Id: your-project-uuid" \
-H "Content-Type: application/json" \
-d '{
"entries": [
{
"contentType": "item",
"contentId": "item_hp_01",
"displayName": "Health Potion",
"metadata": { "rarity": "common", "category": "consumable" }
}
]
}'
```
### 一括インポート (推奨)
[Section titled “一括インポート (推奨)”](#一括インポート-推奨)
CI パイプラインから CLI でマスタデータを JSON 一括インポートします。CLI はエントリのプレーンな JSON 配列を受け付けます (`entries` エンベロープは不要):
```bash
framedash content import ./game-content.json
```
`game-content.json` の形式:
```json
[
{
"contentType": "item",
"contentId": "item_hp_01",
"displayName": "Health Potion",
"metadata": { "rarity": "common", "category": "consumable" }
}
]
```
各エントリには `contentType`、`contentId`、`displayName` が必須で、`metadata` は任意です。
## テレメトリとの連携
[Section titled “テレメトリとの連携”](#テレメトリとの連携)
SDK でイベントを送信する際に、対応するコンテンツ ID (`contentId` に対応する `map_id`、`item_id` など) を含めると、ダッシュボードでコンテンツ名やメタデータが自動表示されます。
## 次のステップ
[Section titled “次のステップ”](#次のステップ)
* [API リファレンス](/api/overview/): コンテンツレジストリ API
* [CLI リファレンス](/cli/overview/): データ同期コマンド
# パフォーマンスヒートマップ
> Framedash のヒートマップ機能の概念と活用方法。
パフォーマンスヒートマップは、ゲームマップ上にパフォーマンスデータをオーバーレイ表示する Framedash の中核機能です。
## 概要
[Section titled “概要”](#概要)
SDK が収集するパフォーマンスサンプルには位置情報 (ワールド座標) が含まれます。これをマップ画像上にプロットし、カラーグラデーションで可視化したものがヒートマップです。
## 可視化できるメトリクス
[Section titled “可視化できるメトリクス”](#可視化できるメトリクス)
* **FPS**: フレームレートの分布。赤いエリアはパフォーマンスが低い
* **フレームタイム**: フレームあたりの処理時間
* **GPU 時間**: レンダリングのボトルネック特定
* **メモリ使用量**: メモリリークの発見
## フィルタリング
[Section titled “フィルタリング”](#フィルタリング)
マップ詳細ページのコントロールで、表示を以下の条件で絞り込めます:
* **メトリクス**: FPS、フレームタイム、GPU 時間、メモリなど(パフォーマンスモード)。イベントモードではイベント名で絞り込みます
* **セルサイズ**: 集計する格子の大きさ(5m / 10m / 25m / 50m)
* **期間**: 直近 1 / 7 / 14 / 30 日
* **ビルド**: 表示するビルドを 1 つ選びます(複数ビルドの同時表示はできません)
* **プラットフォーム**: windows、android など
* **カラーモード**: 相対表示としきい値表示の切り替え
* **Z 軸(高さ)**: 高さのレンジを絞るスライサー
パフォーマンスデータに解像度、GPU、ストレージ、ビルド構成の属性が含まれる場合は、それらの次元でも絞り込めます。 しきい値プロファイルを使うと、これらの属性ごとに合否のしきい値を切り替えられます。
## ビルド間の比較
[Section titled “ビルド間の比較”](#ビルド間の比較)
ヒートマップ自体は 1 つのビルドを表示します。 2 つのビルドを比べるときは、リグレッションページを使います。 リグレッションページは基準ビルドと候補ビルドを選び、FPS やフレームタイムなどの指標を数値の表で比較します。 ヒートマップを左右に並べて見せる表示ではありません。
## エディター内クラウドヒートマップ
[Section titled “エディター内クラウドヒートマップ”](#エディター内クラウドヒートマップ)
UE5 SDK 0.1.7 以降では、`FramedashEditor` モジュールが追加する **Framedash Heatmap** タブから、クラウドで集計済みのヒートマップをエディター内で直接取得できます。0.1.13 以降では、Play-in-Editor(PIE)以外の状態で各レベルビューポートの **Show > Framedash Heatmap** を有効にします。ヒートマップはPIE中に自動で一時停止し、終了後に復元されます。 パッケージビルドやダッシュボードを開かずに、セルごとのパフォーマンスを確認できます。 詳細は [UE5 SDK ガイド](/sdk/unreal/) を参照してください。
Unity SDK 0.1.4 以降では、エディター専用の `Framedash.Editor` アセンブリが、クラウドで集計済みのヒートマップセルを SceneView に半透明のクアッドとしてオーバーレイ表示します。 詳細は [Unity SDK ガイド](/sdk/unity/) を参照してください。
## PNG エクスポート
[Section titled “PNG エクスポート”](#png-エクスポート)
マップ詳細ページ(「プロジェクト」→「\[プロジェクト]」→「マップ」→「\[マップ]」)では、現在のヒートマップ表示を PNG 画像としてエクスポートできます。 画像はクライアント側でレンダリングされ、ファイル名はマップ名とモードから決まります。
Free プランでは、エクスポートした画像の右下に小さな「Powered by Framedash」のウォーターマークが入ります。 有料プラン(Starter 以上)では、ブランド表示なしでエクスポートされます。
## マップ画像
[Section titled “マップ画像”](#マップ画像)
ヒートマップの背景となるマップ画像は以下の方法で登録できます:
1. **手動アップロード**: ダッシュボードまたは API から画像をアップロード
2. **CI 自動キャプチャ**: ビルドパイプラインからワールド座標メタデータ付きの画像を自動生成
## 次のステップ
[Section titled “次のステップ”](#次のステップ)
* [CI プロファイリング](/concepts/ci-profiling/): 自動パフォーマンステスト
* [API リファレンス](/api/overview/): マップデータの管理
# Framedash とは
> Framedash の概要と主要機能の紹介。
Framedash は、ゲーム開発に特化したテレメトリ SaaS です。汎用 APM では得られない、ゲーム文脈でのパフォーマンス分析を提供します。
## 主要機能
[Section titled “主要機能”](#主要機能)
### パフォーマンスヒートマップ
[Section titled “パフォーマンスヒートマップ”](#パフォーマンスヒートマップ)
FPS、フレームタイム、GPU 時間、メモリ使用量をゲームマップ上にオーバーレイ表示。デバイスやビルドプロファイルでフィルタリングし、問題エリアを直感的に特定できます。
### CI 統合プロファイリング
[Section titled “CI 統合プロファイリング”](#ci-統合プロファイリング)
ビルドパイプラインからテレメトリを収集し、`build_id` でタグ付けして、Regression ページ、`framedash perf-diff`、静的しきい値アラートで性能変化を確認します。ビルド間の合否判定は CI 側で管理します。
### マップ自動キャプチャ
[Section titled “マップ自動キャプチャ”](#マップ自動キャプチャ)
CI からワールド座標メタデータ付きのマップ画像を自動生成。手動スクリーンショットは不要です。
### ゲームコンテンツレジストリ
[Section titled “ゲームコンテンツレジストリ”](#ゲームコンテンツレジストリ)
マップ、アイテム、スキルなどの静的メタデータをテレメトリにリンク。ゲーム文脈での分析を実現します。
### 開発者プラットフォーム
[Section titled “開発者プラットフォーム”](#開発者プラットフォーム)
REST API、TypeScript クライアント、CLI、MCP Server。SQL でクエリし、CI/CD に組み込み、LLM ツールと連携。データ主権を確保しながら柔軟なワークフローを構築できます。
## 対応エンジン
[Section titled “対応エンジン”](#対応エンジン)
* **Unity** 2022.3+
* **Unreal Engine** 5.3+
* **Godot** 4.3+(.NET / C# ビルド)
## 次のステップ
[Section titled “次のステップ”](#次のステップ)
* [クイックスタート](/getting-started/quickstart/): 5 分で最初のヒートマップを表示
* [SDK ガイド](/sdk/unity/): エンジン別の統合手順
# クイックスタート
> Framedash を 5 分でセットアップし、最初のヒートマップを表示する手順。
このガイドでは、Framedash の無料アカウントを作成し、SDK を統合して最初のパフォーマンスデータを送信するまでの手順を説明します。
AI コーディングエージェントを使う場合
Claude Code や Codex、その他の MCP クライアントを使っているなら、エージェントに Framedash の設定を任せられます。 [Claude Code Plugin](/mcp/claude-code-plugin/)、[Codex CLI](/mcp/codex/)、または [AGENTS.md スニペット](/mcp/agents-md-snippet/) を参照して、ドキュメント、CLI、MCP サーバーをエージェントに渡してください。
## 1. アカウント作成
[Section titled “1. アカウント作成”](#1-アカウント作成)
1. [Framedash サインアップページ](https://app.framedash.dev/ja/sign-up) にアクセス
2. メールアドレスで登録、または Google / GitHub / Microsoft で続行
3. 利用規約に同意してアカウント作成を完了
## 2. プロジェクトと API キーを作成
[Section titled “2. プロジェクトと API キーを作成”](#2-プロジェクトと-api-キーを作成)
ダッシュボードにログイン後:
1. 「新規プロジェクト」をクリック
2. プロジェクト名を入力して作成
3. 作成したプロジェクトを開き、「API キー」に移動
4. Ingest プリセットの `fd_` API キーを作成し、ダイアログを閉じる前にコピー
ノート
Free プランでは 1 プロジェクトあたり有効な API キーを最大 2 個まで保持でき、キーの値は作成時に一度だけ表示されます。上限に達した場合は、古いキーを無効化してから新しいキーを作成してください。
Ingest キーはイベントの送信のみが可能です。 後で CLI や REST の生の SQL クエリで取り込みを確認するには、別途 Full のキーが必要です(生の SQL には `data:admin` スコープが必要です。手順 5 で扱います)。
## 3. SDK 統合
[Section titled “3. SDK 統合”](#3-sdk-統合)
使用するエンジンに応じて SDK を統合します:
* [Unity SDK セットアップ →](/sdk/unity/)
* [UE5 SDK セットアップ →](/sdk/unreal/)
* [Godot SDK セットアップ →](/sdk/godot/)
## 4. データ送信
[Section titled “4. データ送信”](#4-データ送信)
SDK をセットアップしたら、ゲームを実行するとパフォーマンスデータが自動的に Framedash に送信されます。
CI やヘッドレス環境で実行する場合は、使用するエンジンの「ヘッドレス / CI」セクションを参照してください: [Unity](/sdk/unity/#%E3%83%98%E3%83%83%E3%83%89%E3%83%AC%E3%82%B9--ci)、[UE5](/sdk/unreal/#%E3%83%98%E3%83%83%E3%83%89%E3%83%AC%E3%82%B9--ci)、[Godot](/sdk/godot/#%E3%83%98%E3%83%83%E3%83%89%E3%83%AC%E3%82%B9--ci)。
ヒント
最初の統合では、SDK の詳細ログを有効にすると送信の確認ができます。 バッチの送信に成功すると `HTTP 202` が記録されます。 取り込まれたイベントがビルドやダッシュボードに反映されるまでには 20〜30 秒ほどかかるため、すぐに表示されなくても取り込みが失敗したわけではありません。 何も届かない場合は[トラブルシューティング](/sdk/troubleshooting/)を参照してください。
## 5. ヒートマップを確認
[Section titled “5. ヒートマップを確認”](#5-ヒートマップを確認)
プロジェクトの「マップ」ページを開き、マップをアップロードするかデモデータを生成します。マップを開いて「ヒートマップ」モードに切り替えると、パフォーマンスデータがマップ上にオーバーレイ表示されます。
ダッシュボードを使わずに取り込みを確認するには、[CLI](/cli/overview/#framedash-query) や [REST クエリエンドポイント](/api/overview/#%E3%83%86%E3%83%AC%E3%83%A1%E3%83%88%E3%83%AA%E3%81%AE%E3%82%AF%E3%82%A8%E3%83%AA) からデータをクエリしてください。生のSQLクエリには `data:admin` スコープが必要なので、Full の API キーを使ってください。Read-only キーでは 403 になります。
## 次のステップ
[Section titled “次のステップ”](#次のステップ)
* [データモデル](/sdk/data-model/): 送信されるデータの構造を理解
* [イベントスキーマ](/api/events-schema/): クエリできるカラム
* [トラブルシューティング](/sdk/troubleshooting/): イベントが表示されないとき
* [CI プロファイリング](/concepts/ci-profiling/): 自動テストの設定
# Claude Code、Codex、任意の MCP クライアントを 5 分でセットアップする
> Framedash の MCP サーバー、Claude Code プラグイン、AGENTS.md スニペット、CI ゲート用の CLI を使って、AI コーディングエージェントをゲームテレメトリーに接続します。
AI コーディングエージェントに Framedash のテレメトリーを読ませ、CI をゲートさせる最短の方法です。 エージェントに合わせて経路を選んでください。 Claude Code プラグイン、任意の MCP クライアント向けの素の MCP 登録、リポジトリを認識するエージェント向けの `AGENTS.md` スニペットの 3 つです。 いずれも同じ `@framedash/mcp-server` パッケージと `FRAMEDASH_API_KEY` を使います。
## はじめる前に
[Section titled “はじめる前に”](#はじめる前に)
ダッシュボードで API キーを作成し、シェルでエクスポートします。 キーをチャットに貼り付けないでください。
```bash
export FRAMEDASH_API_KEY="fd_xxx"
export FRAMEDASH_PROJECT_ID="your-project-uuid" # 任意
```
分析ツールには Read-only キーを、raw SQL の `query` ツールも使うなら Full キーを使ってください。
## 経路 A:Claude Code プラグイン
[Section titled “経路 A:Claude Code プラグイン”](#経路-aclaude-code-プラグイン)
このプラグインには、MCP サーバー、CLI と SQL クエリパターンのスキル、Unity、UE5、Godot の統合ガイド、`/framedash:setup` コマンドが含まれます。 マーケットプレイスを追加してインストールします。
```bash
claude plugin marketplace add crane-valley/framedash-claude-plugin
claude plugin install framedash@framedash
```
その後、Claude Code 内で `/framedash:setup` を実行するとガイド付きで設定できます。 全内容は [Claude Code プラグインガイド](/mcp/claude-code-plugin/)を参照してください。
## 経路 B:素の MCP サーバー(任意のクライアント)
[Section titled “経路 B:素の MCP サーバー(任意のクライアント)”](#経路-b素の-mcp-サーバー任意のクライアント)
MCP ツールだけが必要なら、stdio サーバーを直接登録します。 Claude Code の場合:
```bash
claude mcp add framedash \
-e FRAMEDASH_API_KEY=fd_xxx \
-e FRAMEDASH_PROJECT_ID=your-project-uuid \
-- npx -y @framedash/mcp-server
```
他の MCP クライアントも、それぞれの設定で同じ `npx -y @framedash/mcp-server` コマンドを受け付けます。 Codex CLI は `codex mcp add` または `config.toml` で登録します。 詳細は [Codex CLI](/mcp/codex/) を参照してください。 サーバーは 12 個の読み取り専用ツール(ダッシュボード、リテンション、ファネル、インサイト、ヒートマップ、プロジェクトとアラートの一覧、Full キーでの raw SQL)と 4 個のリソースを提供します。 全一覧は [MCP サーバーリファレンス](/mcp/overview/)にあります。
リモート MCP サーバーと OAuth に対応したクライアントは、ローカルインストールを省き、ホスト型エンドポイント `https://app.framedash.dev/api/mcp` を使えます。
## 経路 C:AGENTS.md スニペット
[Section titled “経路 C:AGENTS.md スニペット”](#経路-cagentsmd-スニペット)
リポジトリを認識するエージェントには、Framedash のブロックを `AGENTS.md`(Codex など)または `CLAUDE.md`(Claude Code)に貼り付けます。 ドキュメント、CLI、MCP サーバー、環境変数を一箇所でエージェントに示せます。 [AGENTS.md スニペット](/mcp/agents-md-snippet/)からコピーしてください。
## エージェントから CI をゲートする
[Section titled “エージェントから CI をゲートする”](#エージェントから-ci-をゲートする)
同じキーで CLI も動くため、エージェントはパフォーマンスゲートを組めます。 `@framedash/cli` をインストールし、候補がしきい値を超えて悪化したときにビルドを失敗させます。
```bash
npm install -g @framedash/cli
framedash perf-diff --baseline "$BASE_SHA" --candidate "$GITHUB_SHA" \
--threshold 5 --fail-on-regression
```
エンドツーエンドのプロファイリングゲートは、[CI 統合プロファイリング](/concepts/ci-profiling/)を参照してください。
## 次のステップ
[Section titled “次のステップ”](#次のステップ)
* [MCP サーバーリファレンス](/mcp/overview/):全ツール、リソース、ホスト型エンドポイント
* [Claude Code プラグイン](/mcp/claude-code-plugin/):スキル、スコープ、セットアップ
* [CLI リファレンス](/cli/overview/):CI とローカルクエリ用のコマンド
# Framedash と汎用ゲーム分析ツールの違い
> Framedash が得意とすること(空間的なパフォーマンステレメトリー、CI 回帰ゲート、エージェント/MCP アクセス、ClickHouse SQL)と、汎用ゲーム分析や LiveOps 製品が注力することを整理します。
Framedash と汎用のゲーム分析製品は重なる部分もありますが、得意とする仕事が異なります。 このページでは、Framedash が何をうまくこなすように作られているかを説明します。 より広い分析基盤と並べて、あるいはその代わりに、どこで使うかを判断できるようにするためです。 特定の製品名は挙げず、優劣も主張しません。 目的は、ニーズに合う道具を選ぶ助けになることです。
## Framedash が得意とすること
[Section titled “Framedash が得意とすること”](#framedash-が得意とすること)
Framedash は、場所、ビルド、自動化に結びついたパフォーマンステレメトリーに集中しています。
* **空間的なパフォーマンステレメトリー**:サンプルはワールド座標の `position` と `map_id` を持ちます。そのため FPS、フレームタイム、GPU 時間、メモリを、レベル上のヒートマップとして描画できます。これは、ビルドが遅いかどうかだけでなく、どこで遅いかに答えます。[パフォーマンスヒートマップ](/concepts/heatmaps/)を参照してください。
* **CI 回帰ゲート**:`framedash perf-diff` と `run-profile-test` は候補ビルドをベースラインと比較し、しきい値を超えて悪化すると非ゼロで終了します。これにより、パフォーマンス回帰があればプルリクエストのビルドを失敗させられます。[CI 統合プロファイリング](/concepts/ci-profiling/)を参照してください。
* **エージェントと MCP によるアクセス**:MCP サーバー、CLI、公開された OpenAPI スキーマにより、AI コーディングエージェントやスクリプトがテレメトリーを直接照会できます。[MCP サーバー](/mcp/overview/)を参照してください。
* **ClickHouse への直接 SQL**:Full キーがあれば、`query` ツールと `POST /v1/query` が raw events テーブルに対して読み取り専用 SQL を実行できます。あらかじめ用意されたレポートに限りません。
Framedash はダッシュボード KPI、リテンションコホート、ファネル分析も提供するため、パフォーマンス専用ではありません。 ただしこれらは、上記のパフォーマンス分析や空間分析を補完するものであり、完全な行動分析スイートを置き換えるためのものではありません。
## 汎用分析ツールと LiveOps 製品が注力すること
[Section titled “汎用分析ツールと LiveOps 製品が注力すること”](#汎用分析ツールと-liveops-製品が注力すること)
広範なゲーム分析と LiveOps のプラットフォームは、通常、プレイヤー行動とゲーム内経済を中心に作られています。 たとえば、詳細な収益化とアプリ内課金のレポート、A/B テスト、リモート設定とフィーチャーフラグ、ライブイベントのスケジューリング、プレイヤーセグメンテーション、プッシュやアプリ内メッセージなどです。 これらは Framedash が対象としない大きな領域です。
## どちらを選ぶか
[Section titled “どちらを選ぶか”](#どちらを選ぶか)
いま必要なのが、マップ上でフレームレートが落ちる場所を見ること、CI で回帰したビルドを止めること、AI エージェントに MCP と SQL でテレメトリーを照会させることなら、Framedash はその用途に特化して設計されています。 主目的が収益化分析、実験、ライブ運営ツール(LiveOps)であれば、汎用製品のほうが適していることが多く、Framedash の代わりではなく併用できます。
## 次のステップ
[Section titled “次のステップ”](#次のステップ)
* [はじめに](/getting-started/introduction/):Framedash が収集し表示するもの
* [CI 統合プロファイリング](/concepts/ci-profiling/):回帰ゲート
* [MCP サーバー](/mcp/overview/):エージェントと SQL のアクセス
# マップ上のどこで FPS が落ちるかを見つける
> Framedash のパフォーマンスヒートマップで、マップ上のどの位置でフレームレート、GPU 時間、メモリが悪化しているかを、マップに紐付いたテレメトリーから可視化します。
フレームレートの平均値は、ビルドが遅いことは教えてくれますが、どこで遅いかは教えてくれません。 Framedash のパフォーマンスヒートマップは、各サンプルをワールド座標でプロットします。 そのため、マップ上の赤い領域が FPS の落ちる場所になります。 このガイドでは、マップに紐付いたテレメトリーを送信し、特定エリアの FPS ヒートマップを読み取る方法を示します。
ヒートマップの概念と表示できる指標は、[パフォーマンスヒートマップ](/concepts/heatmaps/)を参照してください。
## 1. マップに紐付いたテレメトリーを送信する
[Section titled “1. マップに紐付いたテレメトリーを送信する”](#1-マップに紐付いたテレメトリーを送信する)
ヒートマップは、各サンプルを `map_id` とワールド座標の `position` でプロットします。 そのため、サンプルがマップ上に載るのは、その両方を持つときだけです。 これらは `Track` にマップ識別子とプレイヤー位置を渡して付与します。 自動の `perf_heartbeat` は意図的に非空間で、空の `map_id` と位置なしで送信されます。 そのため `perf_heartbeat` は、マップのヒートマップではなく、CI 回帰ゲートとダッシュボードのグラフに使われます。 マップ上にパフォーマンスデータを載せるには、注目したい場所から位置付きの `Track` イベントを送信してください。
```csharp
TelemetrySDK.Instance.Track(
eventName: "player_death",
mapId: "map_01",
position: transform.position);
```
UE5 SDK は、サブシステム経由で同じ 3 つの引数を受け取ります。
```cpp
if (auto* Framedash = GetGameInstance()->GetSubsystem())
{
const FVector PlayerLocation(1000.0f, 2000.0f, 50.0f);
Framedash->Track(TEXT("player_death"), TEXT("Map01"), PlayerLocation);
}
```
位置は `position_x` / `position_y` / `position_z` として保存され、`map_id` は最上位フィールドです。 これにより、すべてのサンプルが正しいマップ上に配置されます。 イベントスキーマの全体は[データモデル](/sdk/data-model/)を参照してください。
## 2. マップ画像を登録する
[Section titled “2. マップ画像を登録する”](#2-マップ画像を登録する)
ヒートマップは、レベルの背景画像の上に描画されます。 次の 2 つの方法のいずれかで登録します。
* ダッシュボードから、または API で画像をアップロードする。
* ビルドパイプラインからワールド座標メタデータ付きの画像を自動生成し、`framedash map-capture --input-dir ./captures --upload` でアップロードする。
## 3. FPS ヒートマップを読み取る
[Section titled “3. FPS ヒートマップを読み取る”](#3-fps-ヒートマップを読み取る)
マップ詳細ページ(「プロジェクト」→「\[プロジェクト]」→「マップ」→「\[マップ]」)を開き、Heatmap モードに切り替えると、FPS、フレームタイム、GPU 時間、メモリがレベル上にオーバーレイ表示されます。 赤い領域が最もパフォーマンスの低い場所を示します。 表示はビルドバージョン、デバイスプロファイル、日時範囲、セッションで絞り込めます。 2 つのビルドを並べて、最適化がホットスポットを実際に動かしたかを確認することもできます。
同じデータをプログラムから取得するには、MCP の `get_heatmap` ツールか REST エンドポイントを使います。 `get_heatmap` は `map_id`(必須)に加えて `cell_size`、`days`、任意の `event_name` を受け取ります。 REST の対応は `GET /v1/projects/{id}/heatmap` です。 MCP で接続した AI エージェントは、このツールで「マップの FPS ヒートマップを表示して」に直接答えられます。 詳細は [MCP サーバーリファレンス](/mcp/overview/)を参照してください。
## 次のステップ
[Section titled “次のステップ”](#次のステップ)
* [パフォーマンスヒートマップ](/concepts/heatmaps/):指標、フィルタリング、ビルド比較
* [データモデル](/sdk/data-model/):位置、`map_id`、パフォーマンスフィールド
* [MCP サーバー](/mcp/overview/):自然言語でヒートマップを照会する
# Godot のパフォーマンス回帰を CI で検出する
> Framedash の Godot SDK と framedash perf-diff ゲートを使い、Godot のフレームタイム、メモリ、GPU 時間が悪化したときに CI ビルドを失敗させます。
Godot のパフォーマンス回帰をマージ前に止めるには、各ビルドのテレメトリーに `build_id` を付け、CI 上でプロファイリングシナリオを実行し、`framedash perf-diff` でパイプラインをゲートします。 候補ビルドが既知の良好なベースラインに対してしきい値を超えて悪化すると、コマンドは非ゼロで終了し、ジョブを失敗させます。 このガイドでは、Framedash の Godot SDK(.NET ビルドの Godot 4.3 以降向けの C# アドオン)でこの仕組みを構築します。
ビルドのタグ付けと回帰ゲートの考え方は、[CI 統合プロファイリング](/concepts/ci-profiling/)を参照してください。
## 1. CI のビルド ID でタグ付けする
[Section titled “1. CI のビルド ID でタグ付けする”](#1-ci-のビルド-id-でタグ付けする)
CI のコミットやビルド識別子を `build_id` として SDK に渡すと、その実行のすべてのイベントが一つのビルドに紐付きます。 `framedash run-profile-test`(手順 4)がエクスポートする変数 `FRAMEDASH_BUILD_ID` を読み取り、テレメトリーの `build_id` をゲートが待つ値に一致させます。
```csharp
TelemetrySDK.Initialize(
apiKey: System.Environment.GetEnvironmentVariable("FRAMEDASH_API_KEY"),
buildId: System.Environment.GetEnvironmentVariable("FRAMEDASH_BUILD_ID"));
```
別の変数(たとえば `CI_COMMIT_SHA`)でビルドをタグ付けする場合は、その同じ値を `run-profile-test` の `--build-id` にも渡して両者を一致させてください。 一致しないと、ゲートは取り込まれない `build_id` を待ち続けてタイムアウトします。 Godot SDK は Unity SDK と同じ C# テレメトリー API を共有します。 インストールと .NET のセットアップは [Godot SDK ガイド](/sdk/godot/)を参照してください。
## 2. 自動セッションにタグを付ける
[Section titled “2. 自動セッションにタグを付ける”](#2-自動セッションにタグを付ける)
テストのエントリーポイントで自動セッション API を一度呼び出します。 `BeginAutomatedSessionFromEnvironment()` は、`framedash run-profile-test` がエクスポートする `FRAMEDASH_BUILD_ID` / `FRAMEDASH_GIT_BRANCH` / `FRAMEDASH_GIT_COMMIT` / `FRAMEDASH_TEST_SCENARIO` を読み取ります。 これにより、イベントごとのタグ付けコードなしで、すべてのイベントにビルドと branch/commit/scenario が付与されます。
```csharp
TelemetrySDK.Instance.BeginAutomatedSessionFromEnvironment();
// ... プロファイリングシナリオを実行 ...
TelemetrySDK.Instance.EndAutomatedSession();
```
## 3. CI 向けに C# ソリューションをビルドする
[Section titled “3. CI 向けに C# ソリューションをビルドする”](#3-ci-向けに-c-ソリューションをビルドする)
Godot エディターの Build は、C# プロジェクトの `.csproj` と `.sln` を生成します。 `godot --headless --build-solutions --quit` は*既存の*ソリューションをコンパイルするだけで、エディターで一度も開いたことのないプロジェクトでは終了コード 0 でもプロジェクトファイルを書き出さないことがあり、CI 専用プロジェクトにはビルド対象が存在しません。 CI で安全な手順は、`.csproj` を自分で手書きしてから .NET SDK でビルドすることです。
```xml
net8.0
true
```
```bash
dotnet build
```
ヘッドレスの `--build-solutions` だけでは不十分な理由と、手書きの `.csproj` の全文は、Godot SDK ページの[一度も開いていないプロジェクトの注意点](/sdk/godot/#%E3%83%98%E3%83%83%E3%83%89%E3%83%AC%E3%82%B9--ci)を参照してください。 プロジェクトをエディターで一度開ける場合は、そこで Build をクリックし、生成された `.csproj` / `.sln` をコミットしてもかまいません。
Godot にはオフラインキューがないため、短命なヘッドレス実行は配信の完了前に終了することがあります。 プロファイリングシーンで `Flush()` を呼び、verbose ログに `HTTP 202` の行が出るまでプロセスを生かしておいてください。 ソリューション生成の注意点と、フラッシュして待機する例は [Godot SDK ガイド](/sdk/godot/#%E3%83%98%E3%83%83%E3%83%89%E3%83%AC%E3%82%B9--ci)にあります。
## 4. ゲートを実行する
[Section titled “4. ゲートを実行する”](#4-ゲートを実行する)
`framedash run-profile-test` は `FRAMEDASH_*` セッション変数をエクスポートし、プロファイリングコマンドを起動し、テレメトリーの取り込みを待ってから、ベースラインに対して `perf-diff` ゲートを実行します。
```bash
framedash run-profile-test \
--command "godot --headless --path ." \
--scenario nightly --api-key-file ci-read.key \
--baseline "$BASE_SHA" --threshold 5 --fail-on-regression
```
ゲートは `analytics:read` キーでテレメトリーを読み取り、起動されるゲームは別の `events:write` 取り込みキーでテレメトリーを送信します。 ゲートキーは `--api-key-file` で渡し、`FRAMEDASH_API_KEY` はゲームの取り込みキー用に残してください。
手動でステップを実行することもできます。 `framedash run-profile-test` は自身が起動したコマンドの中でしか `FRAMEDASH_BUILD_ID` を設定しないため、自分で実行を回す場合は好きなビルド ID で自分で `FRAMEDASH_BUILD_ID` をエクスポートし(手順 1 の初期化コードがこれを読みます)、同じ値を `--candidate` にも使ってください。
```bash
export FRAMEDASH_BUILD_ID="$GITHUB_SHA"
# ... launch your profiling run so the SDK tags telemetry with this build id ...
framedash builds --days 30
framedash perf-diff --baseline "$BASE_SHA" --candidate "$FRAMEDASH_BUILD_ID" \
--threshold 5 --fail-on-regression
```
`perf-diff` はフレームタイム、メモリ、GPU 時間、マップロード時間(`load_time_ms`)、ディスク I/O(`io.read_bytes` / `io.read_time_ms` / `io.read_ops`)を、値が小さいほど良い(lower-is-better)指標として比較します。 マップロードと `io.*` のサンプルには Godot SDK 0.1.4 以降が必要です。 `--metric` で対象指標を一つに絞ったり、`--map` や `--platform` で対象マップやプラットフォームを絞ったりできます。
## GitHub Actions の例
[Section titled “GitHub Actions の例”](#github-actions-の例)
プルリクエストごとにゲートを実行する最小構成のワークフローです。 `perf-diff` にはベースラインのコミットが必要なため `fetch-depth: 0` を指定し、`analytics:read` キーはシークレットから `ci-read.key` に書き出します。
```yaml
name: perf-regression
on: pull_request
jobs:
perf-diff:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # perf-diff needs the baseline commit
- uses: actions/setup-dotnet@v4
with:
dotnet-version: "8.x"
- name: Install the Framedash CLI
run: npm install -g @framedash/cli
- name: Build the C# solution
run: dotnet build
- name: Run the perf-diff gate
env:
FRAMEDASH_API_KEY: ${{ secrets.FRAMEDASH_INGEST_KEY }} # events:write, used by the game
FRAMEDASH_READ_KEY: ${{ secrets.FRAMEDASH_READ_KEY }} # analytics:read, used by the gate
BASE_SHA: ${{ github.event.pull_request.base.sha }}
run: |
printf '%s' "$FRAMEDASH_READ_KEY" > ci-read.key
framedash run-profile-test \
--command "godot --headless --path ." \
--scenario nightly --api-key-file ci-read.key \
--baseline "$BASE_SHA" --threshold 5 --fail-on-regression
```
ゲームを起動するには、ランナー上に Godot の .NET エディターが必要です(先行ステップでインストールするか、同梱したコンテナイメージを使ってください)。 2 つのキーは別物です。ゲームは `FRAMEDASH_API_KEY` の `events:write` キーで送信し、ゲートは `ci-read.key` の `analytics:read` キーで読み取ります。
GitHub はフォーク PR から起動されたワークフローにシークレットを渡さないため、この `pull_request` ゲートは同一リポジトリ(信頼済み)の PR でのみ動作します。 フォーク PR を受け入れる公開リポジトリでは、ジョブをガードするか(たとえば `github.event.pull_request.head.repo.fork` が true のときスキップする)、別の信頼済みワークフローからゲートを実行し、信頼できない PR のコードにキーを渡さないでください。
## REST での代替手段
[Section titled “REST での代替手段”](#rest-での代替手段)
CLI がないパイプラインでも、同じ比較を REST で利用できます。 `GET /v1/projects/{id}/builds` がビルド ID を一覧し、`GET /v1/projects/{id}/builds/compare` が 2 つのビルドを比較します。 後者は `baseline` と `candidate` を必須とし、`days` / `mapId` / `platform` / `fresh=1` を受け付けます。 詳細は [API 概要](/api/overview/)を参照してください。
## 次のステップ
[Section titled “次のステップ”](#次のステップ)
* [CI 統合プロファイリング](/concepts/ci-profiling/):概念と全体のセットアップ
* [CLI リファレンス](/cli/overview/):`perf-diff` と `run-profile-test` の全フラグ
* [Godot SDK ガイド](/sdk/godot/):インストール、ヘッドレス実行、自動収集される指標
# Unreal Engine 5 のパフォーマンス回帰を CI で検出する
> Framedash の UE5 SDK と framedash perf-diff ゲートを使い、Unreal Engine 5 のフレームタイム、メモリ、GPU 時間が悪化したときに CI ビルドを失敗させます。
Unreal Engine 5 のパフォーマンス回帰をマージ前に止めるには、各ビルドのテレメトリーに `build_id` を付け、CI 上でプロファイリングシナリオを実行し、`framedash perf-diff` でパイプラインをゲートします。 候補ビルドが既知の良好なベースラインに対してしきい値を超えて悪化すると、コマンドは非ゼロで終了し、ジョブを失敗させます。 このガイドでは、Framedash の UE5 SDK(UE 5.3 以降向けの C++ プラグイン)でこの仕組みを構築します。
ビルドのタグ付けと回帰ゲートの考え方は、[CI 統合プロファイリング](/concepts/ci-profiling/)を参照してください。
## 1. CI のビルド ID でタグ付けする
[Section titled “1. CI のビルド ID でタグ付けする”](#1-ci-のビルド-id-でタグ付けする)
CI のコミットやビルド識別子を `build_id` として SDK に渡すと、その実行のすべてのイベントが一つのビルドに紐付きます。 C++ から初期化し、`framedash run-profile-test`(手順 3)がエクスポートする変数 `FRAMEDASH_BUILD_ID` を読み取って、テレメトリーの `build_id` をゲートが待つ値に一致させます。
```cpp
if (auto* Subsystem = GetGameInstance()->GetSubsystem())
{
FString ApiKey = FPlatformMisc::GetEnvironmentVariable(TEXT("FRAMEDASH_API_KEY"));
FString BuildId = FPlatformMisc::GetEnvironmentVariable(TEXT("FRAMEDASH_BUILD_ID"));
// EndpointUrl に空文字列を渡してデフォルト値を使用
Subsystem->InitializeTelemetry(ApiKey, TEXT(""), BuildId);
}
```
別の変数(たとえば `CI_COMMIT_SHA`)でビルドをタグ付けする場合は、その同じ値を `run-profile-test` の `--build-id` にも渡して両者を一致させてください。 一致しないと、ゲートは取り込まれない `build_id` を待ち続けてタイムアウトします。 コードではなく設定で管理したい場合は、`DefaultGame.ini` の `[/Script/Framedash.FramedashSettings]` で `BuildId` を設定することもできます。 詳しい手順は [UE5 SDK ガイド](/sdk/unreal/)を参照してください。
## 2. 自動セッションにタグを付ける
[Section titled “2. 自動セッションにタグを付ける”](#2-自動セッションにタグを付ける)
テストのエントリーポイントで自動セッション API を一度呼び出します。 `BeginAutomatedSessionFromEnvironment()` は、`framedash run-profile-test` がエクスポートする `FRAMEDASH_BUILD_ID` / `FRAMEDASH_GIT_BRANCH` / `FRAMEDASH_GIT_COMMIT` / `FRAMEDASH_TEST_SCENARIO` を読み取ります。 これにより、イベントごとのタグ付けコードなしで、すべてのイベントにビルドと branch/commit/scenario が付与されます。
```cpp
if (auto* Subsystem = GetGameInstance()->GetSubsystem())
{
Subsystem->BeginAutomatedSessionFromEnvironment();
// ... プロファイリングシナリオを実行 ...
Subsystem->EndAutomatedSession();
}
```
## 3. 1 コマンドでゲートを実行する
[Section titled “3. 1 コマンドでゲートを実行する”](#3-1-コマンドでゲートを実行する)
`framedash run-profile-test` が最も簡単な方法です。 `FRAMEDASH_*` セッション変数をエクスポートし、プロファイリングビルドを起動し、テレメトリーの取り込みを待ってから、ベースラインに対して `perf-diff` ゲートを実行します。
```bash
framedash run-profile-test \
--command "./Build/Game.exe -nullrhi -ExecCmds='Automation RunTest Perf'" \
--scenario nightly --api-key-file ci-read.key \
--baseline "$BASE_SHA" --threshold 5 --fail-on-regression
```
ゲートは `analytics:read` キーでテレメトリーを読み取り、起動されるゲームは別の `events:write` 取り込みキーでテレメトリーを送信します。 ゲートキーは `--api-key-file` で渡し、`FRAMEDASH_API_KEY` はゲームの取り込みキー用に残してください。
上のコマンドには、置き換えが必要なプレースホルダーが 3 つあります。
* **`./Build/Game.exe`**: パッケージ化またはヘッドレスのゲームバイナリ。UE5 ビルドでは通常、素の `.exe` ではなく[ヘッドレス実行のセクション](/sdk/unreal/#%E3%83%98%E3%83%83%E3%83%89%E3%83%AC%E3%82%B9--ci)にある `UnrealEditor-Cmd.exe .uproject -game -nullrhi ...` の起動コマンドです。この `-game` 実行は自分では終了しないため、同セクションのタイムアウトラッパー(Windows は PowerShell の遅延後 kill、Linux / macOS は `timeout` / `gtimeout`)で打ち切り、成功判定はログの HTTP 2xx 行で行ってください。自分のビルドの実際の起動コマンドに置き換えてください。
* **`ci-read.key`**: ゲートがテレメトリーを読み取るために使う `analytics:read` API キーを格納したファイル。CI シークレットから作成します(例: `printf '%s' "$FRAMEDASH_READ_KEY" > ci-read.key`)。
* **`$BASE_SHA`**: 比較対象となる既知の正常なベースラインのコミットまたはビルド ID(例: 分岐時点の `main` の SHA)。手順 4 の `$GITHUB_SHA` はテスト対象の候補ビルドです。
CI で UE5 ビルドをヘッドレス実行するには、まずエディターターゲットをビルドし、null RHI でゲームを起動します。 正確な `UnrealEditor-Cmd.exe` の起動方法と、配信を確認するログ行は [UE5 SDK ガイド](/sdk/unreal/#%E3%83%98%E3%83%83%E3%83%89%E3%83%AC%E3%82%B9--ci)にあります。
## 4. 手動でステップを実行する
[Section titled “4. 手動でステップを実行する”](#4-手動でステップを実行する)
各ステップを分けたい場合は、比較可能なビルド ID を確認し、候補をベースラインと比較します。 `framedash run-profile-test` は自身が起動したコマンドの中でしか `FRAMEDASH_BUILD_ID` を設定しないため、自分で実行を回す場合は好きなビルド ID で自分で `FRAMEDASH_BUILD_ID` をエクスポートし(手順 1 の初期化コードがこれを読みます)、同じ値を `--candidate` にも使ってください。
```bash
export FRAMEDASH_BUILD_ID="$GITHUB_SHA"
# ... launch your profiling run so the SDK tags telemetry with this build id ...
framedash builds --days 30
framedash perf-diff --baseline "$BASE_SHA" --candidate "$FRAMEDASH_BUILD_ID" \
--threshold 5 --fail-on-regression
```
`perf-diff` はフレームタイム、メモリ、GPU 時間、マップロード時間(`load_time_ms`)、ディスク I/O(`io.read_bytes` / `io.read_time_ms` / `io.read_ops`)を、値が小さいほど良い(lower-is-better)指標として比較します。 マップロードと `io.*` のサンプルには UE5 SDK 0.1.6 以降が必要です。 `--metric` で対象指標を一つに絞ったり、`--map` や `--platform` で対象マップやプラットフォームを絞ったりできます。
## REST での代替手段
[Section titled “REST での代替手段”](#rest-での代替手段)
CLI がない言語からゲートする場合も、同じ比較を REST で利用できます。 `GET /v1/projects/{id}/builds` がビルド ID を一覧し、`GET /v1/projects/{id}/builds/compare` が 2 つのビルドを比較します。 後者は `baseline` と `candidate` を必須とし、`days` / `mapId` / `platform` / `fresh=1` を受け付けます。 詳細は [API 概要](/api/overview/)を参照してください。
## 次のステップ
[Section titled “次のステップ”](#次のステップ)
* [CI 統合プロファイリング](/concepts/ci-profiling/):概念と全体のセットアップ
* [CLI リファレンス](/cli/overview/):`perf-diff` と `run-profile-test` の全フラグ
* [UE5 SDK ガイド](/sdk/unreal/):インストール、ヘッドレス実行、自動収集される指標
# Unity のパフォーマンス回帰を CI で検出する
> Framedash の Unity SDK と framedash perf-diff ゲートを使い、Unity のフレームタイム、メモリ、GPU 時間が悪化したときに CI ビルドを失敗させます。
Unity のパフォーマンス回帰をマージ前に止めるには、各ビルドのテレメトリーに `build_id` を付け、CI 上でプロファイリングシナリオを実行し、`framedash perf-diff` でパイプラインをゲートします。 候補ビルドが既知の良好なベースラインに対してしきい値を超えて悪化すると、コマンドは非ゼロで終了し、ジョブを失敗させます。 このガイドでは、Framedash の Unity SDK(Unity 2022.3 以降)でこの仕組みを構築します。
ビルドのタグ付けと回帰ゲートの考え方は、[CI 統合プロファイリング](/concepts/ci-profiling/)を参照してください。
## 1. CI のビルド ID でタグ付けする
[Section titled “1. CI のビルド ID でタグ付けする”](#1-ci-のビルド-id-でタグ付けする)
CI のコミットやビルド識別子を `build_id` として SDK に渡すと、その実行のすべてのイベントが一つのビルドに紐付きます。
```csharp
TelemetrySDK.Initialize(
apiKey: System.Environment.GetEnvironmentVariable("FRAMEDASH_API_KEY"),
buildId: System.Environment.GetEnvironmentVariable("FRAMEDASH_BUILD_ID"));
```
CI やデスクトップビルドでは、キー引数を空にすると `Initialize` が `FRAMEDASH_API_KEY` を環境変数から読み取ります。 解決順序の詳細は [Unity SDK ガイド](/sdk/unity/)を参照してください。
## 2. 自動セッションにタグを付ける
[Section titled “2. 自動セッションにタグを付ける”](#2-自動セッションにタグを付ける)
テストのエントリーポイントで自動セッション API を一度呼び出します。 `BeginAutomatedSessionFromEnvironment()` は、`framedash run-profile-test` がエクスポートする `FRAMEDASH_BUILD_ID` / `FRAMEDASH_GIT_BRANCH` / `FRAMEDASH_GIT_COMMIT` / `FRAMEDASH_TEST_SCENARIO` を読み取ります。 これにより、イベントごとのタグ付けコードなしで、すべてのイベントにビルドと branch/commit/scenario が付与されます。
```csharp
TelemetrySDK.Instance.BeginAutomatedSessionFromEnvironment();
// ... プロファイリングシナリオを実行 ...
TelemetrySDK.Instance.EndAutomatedSession();
```
## 3. PlayMode テストからテレメトリーを送信する
[Section titled “3. PlayMode テストからテレメトリーを送信する”](#3-playmode-テストからテレメトリーを送信する)
Unity SDK はプレイヤーループ上で送信しますが、Edit モードではループが回りません。 `-batchmode -executeMethod` の単純な実行では、イベントはバッファされるだけで送信されません。 CI からテレメトリーを送信するには、PlayMode テスト(Unity Test Framework)でプレイヤーループを回し、テストをヘッドレスで実行します。
```plaintext
Unity.exe -batchmode -nographics -projectPath -runTests -testPlatform PlayMode -testResults \results.xml -logFile -
```
Test Framework に必要なアセンブリ定義や、配信を確認する `HTTP 202` のログ行を含む完全なスモークテスト例は、[Unity SDK ガイド](/sdk/unity/#headless--ci)にあります。
## 4. ゲートを実行する
[Section titled “4. ゲートを実行する”](#4-ゲートを実行する)
`framedash run-profile-test` は `FRAMEDASH_*` セッション変数をエクスポートし、テストコマンドを起動し、テレメトリーの取り込みを待ってから、ベースラインに対して `perf-diff` ゲートを実行します。
```bash
framedash run-profile-test \
--command "Unity.exe -batchmode -nographics -projectPath . -runTests -testPlatform PlayMode -logFile -" \
--scenario nightly --api-key-file ci-read.key \
--baseline "$BASE_SHA" --threshold 5 --fail-on-regression
```
ゲートは `analytics:read` キーでテレメトリーを読み取り、起動されるゲームは別の `events:write` 取り込みキーでテレメトリーを送信します。 ゲートキーは `--api-key-file` で渡し、`FRAMEDASH_API_KEY` はゲームの取り込みキー用に残してください。
手動でステップを実行することもできます。
```bash
framedash builds --days 30
framedash perf-diff --baseline "$BASE_SHA" --candidate "$GITHUB_SHA" \
--threshold 5 --fail-on-regression
```
`perf-diff` はフレームタイム、メモリ、GPU 時間、マップロード時間(`load_time_ms`)、ディスク I/O(`io.read_bytes` / `io.read_time_ms` / `io.read_ops`)を、値が小さいほど良い(lower-is-better)指標として比較します。 マップロードと `io.*` のサンプルには Unity SDK 0.1.3 以降が必要です。 `--metric` で対象指標を一つに絞ったり、`--map` や `--platform` で対象マップやプラットフォームを絞ったりできます。
## REST での代替手段
[Section titled “REST での代替手段”](#rest-での代替手段)
CLI がないパイプラインでも、同じ比較を REST で利用できます。 `GET /v1/projects/{id}/builds` がビルド ID を一覧し、`GET /v1/projects/{id}/builds/compare` が 2 つのビルドを比較します。 後者は `baseline` と `candidate` を必須とし、`days` / `mapId` / `platform` / `fresh=1` を受け付けます。 詳細は [API 概要](/api/overview/)を参照してください。
## 次のステップ
[Section titled “次のステップ”](#次のステップ)
* [CI 統合プロファイリング](/concepts/ci-profiling/):概念と全体のセットアップ
* [CLI リファレンス](/cli/overview/):`perf-diff` と `run-profile-test` の全フラグ
* [Unity SDK ガイド](/sdk/unity/):インストール、ヘッドレス実行、自動収集される指標
# CI/CD 統合ガイド
> Jenkins や TeamCity パイプラインに Framedash を統合し、自動パフォーマンス監視を実現します。
Framedash CLI はあらゆる CI/CD システムと統合できます。このガイドでは **Jenkins** と **TeamCity** のすぐに使える例を紹介します。
## 前提条件
[Section titled “前提条件”](#前提条件)
1. CI 環境に CLI をインストール:
```bash
npm install -g @framedash/cli
```
2. パフォーマンスゲートの例では [`jq`](https://jqlang.github.io/jq/) と `bc` を使用します。CI エージェントにインストールされていることを確認してください。
3. Framedash ダッシュボードで対象プロジェクトの **API キー** ページを開き、Full プリセットの API キーを作成します。本ガイドの例には raw SQL とマップアップロードが含まれるため、`data:admin` と `resources:write` scope が必要です。パイプラインでゲーム SDK を実行してテレメトリを送信する場合は、そのステージ用に別途 Ingest プリセットのキーを作成してください([CI プロファイリング](/concepts/ci-profiling/) を参照)。
4. プロジェクトページの URL(`/projects/{projectId}`)から **プロジェクト ID** を確認します。
## 環境変数
[Section titled “環境変数”](#環境変数)
CI システムのシークレット管理で以下を設定してください:
| 変数 | 必須 | 説明 |
| ---------------------- | --- | ------------------------------------------------------------------------------------------- |
| `FRAMEDASH_API_KEY` | はい | 必要な scope を持つ API キー。本ガイドの例には Full プリセットを使用します。ゲームテレメトリ送信のみなら Ingest(`events:write`)を使用します。 |
| `FRAMEDASH_PROJECT_ID` | はい | 対象プロジェクトの UUID |
| `FRAMEDASH_BASE_URL` | いいえ | カスタム API ホスト URL(デフォルト: `https://app.framedash.dev`) |
***
## Jenkins
[Section titled “Jenkins”](#jenkins)
### 認証情報の設定
[Section titled “認証情報の設定”](#認証情報の設定)
API キーを Jenkins 認証情報(Secret text)として保存します:
1. **Jenkins の管理 > 認証情報 > System > グローバル認証情報** を開きます
2. ID `framedash-api-key` で **Secret text** 認証情報を追加します
3. ID `framedash-project-id` で **Secret text** 認証情報を追加します
### 宣言的パイプライン
[Section titled “宣言的パイプライン”](#宣言的パイプライン)
#### ビルド後テレメトリ確認
[Section titled “ビルド後テレメトリ確認”](#ビルド後テレメトリ確認)
自動テスト実行後にゲームビルドがテレメトリを送信していることを確認します:
```groovy
pipeline {
agent any
environment {
FRAMEDASH_API_KEY = credentials('framedash-api-key')
FRAMEDASH_PROJECT_ID = credentials('framedash-project-id')
}
stages {
stage('Build') {
steps {
sh 'your-game-build-command'
}
}
stage('Automated Test') {
steps {
sh 'your-automated-test-command'
}
}
stage('Verify Telemetry') {
steps {
sh '''
framedash auth
framedash status --format json > status.json
echo "Project status:"
framedash status --format table
'''
}
}
}
}
```
#### パフォーマンスリグレッションゲート
[Section titled “パフォーマンスリグレッションゲート”](#パフォーマンスリグレッションゲート)
パフォーマンスメトリクスが閾値を下回った場合にビルドを失敗させます:
```groovy
pipeline {
agent any
environment {
FRAMEDASH_API_KEY = credentials('framedash-api-key')
FRAMEDASH_PROJECT_ID = credentials('framedash-project-id')
}
stages {
stage('Build & Test') {
steps {
sh 'your-game-build-and-test-command'
}
}
stage('Performance Gate') {
steps {
sh '''
RESULT=$(framedash query \
"SELECT avg(fps) as avg_fps, \
avg(frame_time_ms) as avg_frame_time \
FROM events \
WHERE event_name = 'perf_heartbeat' \
AND timestamp > now() - INTERVAL 1 HOUR" \
--format json)
AVG_FPS=$(echo "$RESULT" | jq -r '.rows[0].avg_fps // 0')
echo "Average FPS: $AVG_FPS"
if [ "$(echo "$AVG_FPS < 30" | bc -l)" -eq 1 ]; then
echo "FAILED: FPS below 30 threshold ($AVG_FPS)"
exit 1
fi
echo "PASSED: FPS meets threshold"
'''
}
}
}
post {
failure {
echo 'Performance regression detected. Check the Framedash dashboard for details.'
}
}
}
```
#### マップキャプチャアップロード
[Section titled “マップキャプチャアップロード”](#マップキャプチャアップロード)
レベルビルド後にマップ画像を自動アップロードします:
```groovy
pipeline {
agent any
environment {
FRAMEDASH_API_KEY = credentials('framedash-api-key')
FRAMEDASH_PROJECT_ID = credentials('framedash-project-id')
}
stages {
stage('Build Level') {
steps {
sh 'your-level-build-command'
}
}
stage('Capture Maps') {
steps {
sh 'your-map-capture-command --output-dir ./map_captures'
}
}
stage('Upload Maps') {
steps {
sh '''
framedash map-capture \
--input-dir ./map_captures \
--upload
'''
}
}
}
}
```
#### コンテンツレジストリ同期
[Section titled “コンテンツレジストリ同期”](#コンテンツレジストリ同期)
ゲームデータとコンテンツレジストリを同期します:
```groovy
pipeline {
agent any
environment {
FRAMEDASH_API_KEY = credentials('framedash-api-key')
FRAMEDASH_PROJECT_ID = credentials('framedash-project-id')
}
stages {
stage('Sync Content') {
steps {
sh '''
framedash content import ./game-content.json
echo "Content registry updated"
framedash content list --format table
'''
}
}
}
}
```
### 共有ライブラリ
[Section titled “共有ライブラリ”](#共有ライブラリ)
複数のゲームプロジェクトを持つ組織向けに、Jenkins 共有ライブラリを作成できます:
vars/framedashReport.groovy
```groovy
def call(Map config = [:]) {
def queryDays = config.get('days', 7)
withCredentials([
string(credentialsId: config.apiKeyCredentialId ?: 'framedash-api-key', variable: 'FRAMEDASH_API_KEY'),
string(credentialsId: config.projectIdCredentialId ?: 'framedash-project-id', variable: 'FRAMEDASH_PROJECT_ID')
]) {
sh """
echo "Framedash dashboard (${queryDays}-day summary):"
framedash dashboard --days ${queryDays} --format table
"""
}
}
```
Jenkinsfile での使用例:
```groovy
@Library('your-shared-lib') _
pipeline {
agent any
stages {
stage('Framedash Report') {
steps {
framedashReport(days: 7)
}
}
}
}
```
***
## TeamCity
[Section titled “TeamCity”](#teamcity)
### パラメータ設定
[Section titled “パラメータ設定”](#パラメータ設定)
ビルド構成に **構成パラメータ** として追加します:
1. **ビルド構成 > パラメータ** を開きます
2. パラメータ `env.FRAMEDASH_API_KEY` を追加(タイプ: Password、spec: `password display='hidden'`)
3. パラメータ `env.FRAMEDASH_PROJECT_ID` を追加(タイプ: Text)
または **プロジェクト** レベルで定義してビルド構成間で共有することもできます。
### ビルドステップ
[Section titled “ビルドステップ”](#ビルドステップ)
#### ビルド後テレメトリ確認
[Section titled “ビルド後テレメトリ確認”](#ビルド後テレメトリ確認-1)
**コマンドライン** ビルドステップを追加します:
**ステップ名:** Verify Framedash Telemetry
```bash
#!/bin/bash
set -euo pipefail
echo "Verifying Framedash authentication..."
framedash auth
echo "Project status:"
framedash status --format table
```
#### パフォーマンスリグレッションゲート
[Section titled “パフォーマンスリグレッションゲート”](#パフォーマンスリグレッションゲート-1)
**コマンドライン** ビルドステップを追加します:
**ステップ名:** Framedash Performance Gate
```bash
#!/bin/bash
set -euo pipefail
echo "Querying performance metrics..."
RESULT=$(framedash query \
"SELECT avg(fps) as avg_fps, \
avg(frame_time_ms) as avg_frame_time \
FROM events \
WHERE event_name = 'perf_heartbeat' \
AND timestamp > now() - INTERVAL 1 HOUR" \
--format json)
AVG_FPS=$(echo "$RESULT" | jq -r '.rows[0].avg_fps // 0')
echo "Average FPS: $AVG_FPS"
if [ "$(echo "$AVG_FPS < 30" | bc -l)" -eq 1 ]; then
echo "##teamcity[buildProblem description='FPS below threshold: $AVG_FPS']"
exit 1
fi
echo "##teamcity[buildStatisticValue key='framedash.avgFps' value='$AVG_FPS']"
echo "Performance gate passed"
```
ヒント
TeamCity の[サービスメッセージ](https://www.jetbrains.com/help/teamcity/service-messages.html)を使用して、カスタム統計やビルド問題を報告できます。`buildStatisticValue` メッセージにより、FPS を TeamCity の統計チャートで追跡できます。
#### マップキャプチャアップロード
[Section titled “マップキャプチャアップロード”](#マップキャプチャアップロード-1)
**コマンドライン** ビルドステップを追加します:
**ステップ名:** Upload Map Captures
```bash
#!/bin/bash
set -euo pipefail
echo "Validating map captures..."
framedash map-capture --input-dir ./map_captures --dry-run
echo "Uploading map captures..."
framedash map-capture --input-dir ./map_captures --upload
```
#### ファネル分析レポート
[Section titled “ファネル分析レポート”](#ファネル分析レポート)
コンバージョンファネルを追跡する**コマンドライン**ビルドステップを追加します:
```bash
#!/bin/bash
set -euo pipefail
echo "Funnel analysis (7-day window):"
framedash funnel \
--steps "tutorial_start,tutorial_complete,first_purchase" \
--days 7 \
--format table
```
### ビルド構成テンプレート(Kotlin DSL)
[Section titled “ビルド構成テンプレート(Kotlin DSL)”](#ビルド構成テンプレートkotlin-dsl)
Kotlin DSL を使用する TeamCity プロジェクト向け:
```kotlin
import jetbrains.buildServer.configs.kotlin.*
import jetbrains.buildServer.configs.kotlin.buildSteps.script
object FramedashPerformanceGate : BuildType({
name = "Framedash Performance Gate"
params {
password("env.FRAMEDASH_API_KEY", "", display = ParameterDisplay.HIDDEN)
text("env.FRAMEDASH_PROJECT_ID", "")
text("framedash.minFps", "30", label = "Minimum FPS Threshold")
}
steps {
script {
name = "Install Framedash CLI"
scriptContent = "npm install -g @framedash/cli"
}
script {
name = "Performance Gate"
scriptContent = """
#!/bin/bash
set -euo pipefail
MIN_FPS=%framedash.minFps%
RESULT=${'$'}(framedash query \
"SELECT avg(fps) as avg_fps FROM events \
WHERE event_name = 'perf_heartbeat' \
AND timestamp > now() - INTERVAL 1 HOUR" \
--format json)
AVG_FPS=${'$'}(echo "${'$'}RESULT" | jq -r '.rows[0].avg_fps // 0')
echo "Average FPS: ${'$'}AVG_FPS (threshold: ${'$'}MIN_FPS)"
if [ "${'$'}(echo "${'$'}AVG_FPS < ${'$'}MIN_FPS" | bc -l)" -eq 1 ]; then
echo "##teamcity[buildProblem description='FPS below threshold']"
exit 1
fi
echo "##teamcity[buildStatisticValue key='framedash.avgFps' value='${'$'}AVG_FPS']"
""".trimIndent()
}
}
})
```
### メタランナー
[Section titled “メタランナー”](#メタランナー)
再利用可能なメタランナーを作成します。プロジェクトの `.teamcity/pluginData/metaRunners/` ディレクトリに `Framedash_Performance_Gate.xml` として保存します:
```xml
Check game performance metrics via Framedash CLI
now() - INTERVAL %framedash.queryDays% DAY" \
--format json)
AVG_FPS=$(echo "$RESULT" | jq -r '.rows[0].avg_fps // 0')
echo "Average FPS: $AVG_FPS (threshold: $MIN_FPS)"
if [ "$(echo "$AVG_FPS < $MIN_FPS" | bc -l)" -eq 1 ]; then
echo "##teamcity[buildProblem description='FPS below threshold: $AVG_FPS < $MIN_FPS']"
exit 1
fi
echo "##teamcity[buildStatisticValue key='framedash.avgFps' value='$AVG_FPS']"
echo "Performance gate passed"
]]>
```
***
## 共通パターン
[Section titled “共通パターン”](#共通パターン)
### SQL ベースの品質ゲート
[Section titled “SQL ベースの品質ゲート”](#sql-ベースの品質ゲート)
`framedash query` と SQL ファイルで再現可能なチェックを実行します:
```sql
-- checks/fps-threshold.sql
SELECT
avg(fps) as avg_fps,
min(fps) as min_fps,
quantile(0.05)(fps) as p5_fps
FROM events
WHERE event_name = 'perf_heartbeat'
AND timestamp > now() - INTERVAL 1 DAY
```
```bash
framedash query --file checks/fps-threshold.sql --format json
```
### 出力形式の使い分け
[Section titled “出力形式の使い分け”](#出力形式の使い分け)
CI でのパースには `--format json` と `jq` を使用します:
```bash
# 単一値を抽出
framedash dashboard --days 7 --format json | jq '.kpis.events'
# プロジェクトステータスを確認
framedash status --format json | jq '.project.name'
```
CLI は API レスポンスのエンベロープを展開済みで出力します。 そのため `.data.*` ではなく、トップレベルのフィールド(`.kpis`、`.project`)を直接参照します。 `dashboard` の KPI メンバー名は `totalEvents` ではなく `events` です。
ビルドログの可読性には `--format table` を使用します:
```bash
framedash dashboard --days 7 --format table
framedash retention --days 30 --format table
```
### ナイトリーパフォーマンスレポート
[Section titled “ナイトリーパフォーマンスレポート”](#ナイトリーパフォーマンスレポート)
パフォーマンスサマリーを生成するナイトリービルドをスケジュールします:
```bash
#!/bin/bash
set -euo pipefail
echo "=== Framedash Nightly Report ==="
echo ""
echo "--- Project Status ---"
framedash status --format table
echo ""
echo "--- 7-Day Dashboard ---"
framedash dashboard --days 7 --format table
echo ""
echo "--- Player Retention ---"
framedash retention --days 30 --format table
echo ""
echo "--- Alert Rules ---"
framedash alerts list --format table
```
***
## トラブルシューティング
[Section titled “トラブルシューティング”](#トラブルシューティング)
### 認証エラー
[Section titled “認証エラー”](#認証エラー)
```plaintext
Error: Unauthorized (401)
```
* `FRAMEDASH_API_KEY` が設定済みで有効であることを確認してください
* `framedash auth` でキーをテストしてください
* マップアップロードには `resources:write` scope が必要です。Read & Write または Full プリセットのキーを使用してください。
### レート制限
[Section titled “レート制限”](#レート制限)
```plaintext
Error: Too Many Requests (429)
```
* レート制限はアカウント(テナント)単位で適用され、そのアカウントが持つすべてのプロジェクトと API キーで共有されます。並列で走る CI ジョブは同じ 1 時間あたりの枠を消費します(Free プランは 100 リクエスト/時、上位プランは異なります)
* 429 が返るたびに `X-RateLimit-Reset` を基準にスケジュールするのではなく、`Retry-After` ヘッダーに従ってください。リセット時刻はスライディングウィンドウから算出されるため、表示されたリセット直後の実際の待ち時間を短く見積もることがあります
* より高い制限が必要な場合はプランのアップグレードを検討してください
### ネットワーク / プロキシ
[Section titled “ネットワーク / プロキシ”](#ネットワーク--プロキシ)
CI 環境がプロキシを使用している場合:
```bash
export HTTPS_PROXY=http://proxy.example.com:8080
framedash auth
```
### CLI が見つからない
[Section titled “CLI が見つからない”](#cli-が見つからない)
CLI が CI エージェントの PATH にインストールされていることを確認してください:
```bash
# インストールを確認
which framedash || npm install -g @framedash/cli
# グローバルインストールなしで npx を使用
npx @framedash/cli auth
```
## 次のステップ
[Section titled “次のステップ”](#次のステップ)
* [CLI リファレンス](/cli/overview/): コマンドの完全なドキュメント
* [API リファレンス](/api/overview/): REST API の詳細
* [CI プロファイリング](/concepts/ci-profiling/): 自動パフォーマンスプロファイリング設定
# AGENTS.md スニペット
> ゲームリポジトリの AGENTS.md / CLAUDE.md に貼り付ける Framedash 連携ブロック。
AI コーディングエージェントにリポジトリ内で Framedash を扱わせるには、次のブロックを `AGENTS.md`(Codex など)または `CLAUDE.md`(Claude Code)に貼り付けます。 ドキュメント、CLI、MCP サーバー、環境変数への参照が 1 か所にまとまります。
```markdown
## Framedash telemetry
Framedash is this project's game telemetry service.
- Docs: https://docs.framedash.dev
- Machine-readable index: https://docs.framedash.dev/llms.txt
- CLI: `npm i -g @framedash/cli`, then `framedash --help`
- MCP server (stdio): `npx -y @framedash/mcp-server`
Environment variables (never hardcode keys):
- FRAMEDASH_API_KEY: API key with the scopes you need
- FRAMEDASH_PROJECT_ID: default project UUID (optional)
To query telemetry, use `framedash query` or the MCP `query` tool.
Event columns: https://docs.framedash.dev/api/events-schema/
```
`FRAMEDASH_API_KEY` はコミットせず、環境変数かシークレット管理サービス(AWS Secrets Manager、HashiCorp Vault、GitHub Actions のシークレットなど)から渡してください。
## エージェント別の置き場所
[Section titled “エージェント別の置き場所”](#エージェント別の置き場所)
* Codex CLI:リポジトリルートの `AGENTS.md`。設定は [Codex CLI](/mcp/codex/) を参照してください。
* Claude Code:リポジトリルートの `CLAUDE.md`、またはプラグイン([Claude Code Plugin](/mcp/claude-code-plugin/))。
# Claude Code Plugin
> Claude Code 向け Framedash プラグインのインストール。MCP Server、スキル群(CLI、クエリクックブック、perf-diff CI、Unity/UE5/Godot 統合)、セットアップコマンドを 1 パッケージで提供。
Claude Code 向け Framedash プラグインは、Claude Code からゲームテレメトリを照会するために必要なものを 1 つにまとめています。Framedash MCP Server、スキル群(CLI 利用パターン、events スキーマに対する SQL クエリクックブック、perf-diff CI レシピ、Unity/UE5/Godot の統合ガイド)、そしてガイド付き設定用の `/framedash:setup` コマンドが含まれます。
## インストール
[Section titled “インストール”](#インストール)
マーケットプレイスを追加してからプラグインをインストールします:
```bash
claude plugin marketplace add crane-valley/framedash-claude-plugin
claude plugin install framedash@framedash
```
すでに古いバージョンをインストールしている場合、上記のコマンドはどちらも「インストール済み」と報告して終了し、更新はされません。 最新版に上げるには update を実行してください(反映には Claude Code の再起動が必要です):
```bash
claude plugin update framedash@framedash
```
インストール済みのバージョンは list で確認できます:
```bash
claude plugin list
```
## 設定
[Section titled “設定”](#設定)
API キーはダッシュボードの各プロジェクトの「API キー」ページで作成できます([API 概要](/api/overview/)を参照)。 Claude Code を起動する前に、シェルで API キーを設定してください。キーをチャットに貼り付けないでください。
```bash
export FRAMEDASH_API_KEY="fd_xxx"
export FRAMEDASH_PROJECT_ID="your-project-uuid" # 任意
```
Windows PowerShell の場合:
```powershell
$env:FRAMEDASH_API_KEY="fd_xxx"
$env:FRAMEDASH_PROJECT_ID="your-project-uuid" # 任意
```
その後、Claude Code 内でガイド付きセットアップコマンドを実行します:
```plaintext
/framedash:setup
```
設定できたか確認するには、`/framedash:setup` を実行するか、読み取り系ツールを呼び出して(例:「過去 7 日間の DAU を見せて」)データが返ることを確かめてください。
## 環境変数
[Section titled “環境変数”](#環境変数)
| 変数 | 必須 | 説明 |
| ---------------------- | --- | ------------------------------------------------ |
| `FRAMEDASH_API_KEY` | はい | 使用するツールに必要な scope を持つ API キー(下記の scope 一覧を参照)。 |
| `FRAMEDASH_PROJECT_ID` | いいえ | デフォルトプロジェクト UUID。 |
| `FRAMEDASH_BASE_URL` | いいえ | API ベース URL(デフォルト: `https://app.framedash.dev`)。 |
### API キーの scope
[Section titled “API キーの scope”](#api-キーの-scope)
| scope | 付与される権限 |
| ----------------- | --------------------------------------------- |
| `analytics:read` | 読み取りツール(ダッシュボード、リテンション、ファネル、インサイト、ヒートマップ、一覧)。 |
| `data:admin` | `analytics:read` に加えて raw SQL の `query` ツール。 |
| `resources:write` | アラートの作成・更新・削除、マップの削除、コンテンツのインポート。 |
## 含まれるもの
[Section titled “含まれるもの”](#含まれるもの)
* **MCP Server** — Framedash MCP Server の宣言(stdio、`npx -y @framedash/mcp-server`)。
* **スキル** — CLI 利用パターン、events スキーマに対する SQL クエリクックブック、perf-diff CI レシピ、Unity/UE5/Godot の統合ガイド。
* **コマンド** — ガイド付き設定用の `/framedash:setup`。
## プラグインを使わない場合(raw MCP)
[Section titled “プラグインを使わない場合(raw MCP)”](#プラグインを使わない場合raw-mcp)
MCP ツールのみが必要な場合は、サーバーを直接登録します:
```bash
claude mcp add framedash \
-e FRAMEDASH_API_KEY=fd_xxx \
-e FRAMEDASH_PROJECT_ID=your-project-uuid \
-- npx -y @framedash/mcp-server
```
Windows PowerShell では、ストレートクォートを使い、行末のバックスラッシュを付けずに 1 行で書きます:
```powershell
claude mcp add framedash -e FRAMEDASH_API_KEY=fd_xxx -e FRAMEDASH_PROJECT_ID=your-project-uuid -- npx -y @framedash/mcp-server
```
ツールとリソースの完全なリファレンスは [MCP Server](/mcp/overview/) を参照してください。
## その他のコーディングエージェント
[Section titled “その他のコーディングエージェント”](#その他のコーディングエージェント)
スキルはオープンな [Agent Skills](https://agentskills.io/) 仕様(`SKILL.md`)に準拠しているため、スキルを扱うあらゆるエージェントで動作します。また MCP Server の宣言はあらゆる MCP クライアントで利用できます。Claude Code 以外(例: Codex CLI)で同じ機能を使うには、エージェントにプラグインの `SKILL.md` ファイルまたは `@framedash/mcp-server` パッケージを指定してください。
行数の上限
MCP の `query` ツールは結果を 1000 行に制限します。より大きな結果セットが必要な場合は、10000 行まで対応する REST の `/v1/query` エンドポイントを使用してください。
## 次のステップ
[Section titled “次のステップ”](#次のステップ)
* [MCP Server](/mcp/overview/): ツールとリソースの完全なリファレンス。
* [CLI リファレンス](/cli/overview/): コマンドラインツール。
リポジトリ: [crane-valley/framedash-claude-plugin](https://github.com/crane-valley/framedash-claude-plugin)(v0.2.3、MIT)。
# Codex CLI
> Codex CLI で Framedash MCP Server を使う設定。codex mcp add と config.toml の手順、AGENTS.md 連携。
Codex CLI から Framedash のテレメトリを照会するには、Framedash MCP Server を Codex に登録します。 Claude Code プラグインが提供する MCP ツールと同じものを、プラグインなしで利用できます。
## codex mcp add で登録
[Section titled “codex mcp add で登録”](#codex-mcp-add-で登録)
次のコマンドで stdio サーバーとして登録します。
```bash
codex mcp add framedash \
--env FRAMEDASH_API_KEY=fd_xxx \
--env FRAMEDASH_PROJECT_ID=your-project-uuid \
-- npx -y @framedash/mcp-server
```
`--env` は変数ごとに 1 つ指定します。 `FRAMEDASH_PROJECT_ID` は任意です。
## config.toml で登録
[Section titled “config.toml で登録”](#configtoml-で登録)
`codex mcp add` はサーバー定義を Codex の設定に保存します。 設定ファイルを直接編集する場合は、`~/.codex/config.toml` に次のエントリを追加します。
```toml
[mcp_servers.framedash]
command = "npx"
args = ["-y", "@framedash/mcp-server"]
[mcp_servers.framedash.env]
FRAMEDASH_API_KEY = "fd_xxx"
FRAMEDASH_PROJECT_ID = "your-project-uuid"
```
API キーはチャットに貼り付けず、環境変数として渡してください。
## 環境変数
[Section titled “環境変数”](#環境変数)
| 変数 | 必須 | 説明 |
| ---------------------- | --- | ------------------------------------------------ |
| `FRAMEDASH_API_KEY` | はい | MCP ツールに必要な scope を持つ API キー。 |
| `FRAMEDASH_PROJECT_ID` | いいえ | デフォルトプロジェクト UUID。 |
| `FRAMEDASH_BASE_URL` | いいえ | API ベース URL(デフォルト: `https://app.framedash.dev`)。 |
scope の詳細は [MCP Server](/mcp/overview/) を参照してください。
## AGENTS.md でエージェントに指示する
[Section titled “AGENTS.md でエージェントに指示する”](#agentsmd-でエージェントに指示する)
Codex はリポジトリの `AGENTS.md` を読み込みます。 Framedash のドキュメント、CLI、MCP サーバーへの参照を `AGENTS.md` に置いておくと、エージェントが計測とクエリの手順を把握できます。 コピー用のブロックは [AGENTS.md スニペット](/mcp/agents-md-snippet/) を参照してください。
## Claude スキルの代わりになるページ
[Section titled “Claude スキルの代わりになるページ”](#claude-スキルの代わりになるページ)
Claude Code プラグインには、SQL クエリと CI レシピをまとめたスキルが含まれます。 Codex にこのスキルは付属しませんが、同じ内容を次のページで参照できます。
* [イベントスキーマ](/api/events-schema/):クエリできるカラムとバリデーションルール。
* [トラブルシューティング](/sdk/troubleshooting/):イベントが届かないときの確認手順。
* [MCP Server](/mcp/overview/):ツールとリソースの一覧。
行数の上限
MCP の `query` ツールは結果を 1000 行に制限します。 より大きな結果セットが必要な場合は、10000 行まで対応する REST の `/v1/query` エンドポイントを使用してください。
# MCP Server
> Framedash MCP Server のセットアップとツール・リソース一覧。
Framedash MCP Server は、LLM(大規模言語モデル)から Framedash のテレメトリデータに直接アクセスするための [Model Context Protocol](https://modelcontextprotocol.io/) サーバーです。12 個の読み取り専用ツールと 4 個のリソースを提供し、自然言語でゲーム分析データを照会できます。
AI エージェント向け
機械可読なエントリーポイント:OpenAPI スキーマは [`https://docs.framedash.dev/openapi.yaml`](https://docs.framedash.dev/openapi.yaml)、本ドキュメントの索引は [`https://docs.framedash.dev/llms.txt`](https://docs.framedash.dev/llms.txt)、全文エクスポートは [`https://docs.framedash.dev/llms-full.txt`](https://docs.framedash.dev/llms-full.txt) にあります。
## セットアップ
[Section titled “セットアップ”](#セットアップ)
### Claude Desktop
[Section titled “Claude Desktop”](#claude-desktop)
`claude_desktop_config.json` に以下を追加:
```json
{
"mcpServers": {
"framedash": {
"command": "npx",
"args": ["-y", "@framedash/mcp-server"],
"env": {
"FRAMEDASH_API_KEY": "fd_xxx",
"FRAMEDASH_PROJECT_ID": "your-project-uuid"
}
}
}
}
```
### VS Code (Claude Extension)
[Section titled “VS Code (Claude Extension)”](#vs-code-claude-extension)
VS Code の設定に以下を追加:
```json
{
"claude.mcpServers": {
"framedash": {
"command": "npx",
"args": ["-y", "@framedash/mcp-server"],
"env": {
"FRAMEDASH_API_KEY": "fd_xxx",
"FRAMEDASH_PROJECT_ID": "your-project-uuid"
}
}
}
}
```
Windows
Windows では `"command": "npx"` を `"command": "cmd"` に変更し、args 配列の先頭に `"/c"` を追加してください:
```json
"command": "cmd",
"args": ["/c", "npx", "-y", "@framedash/mcp-server"]
```
### Claude Code
[Section titled “Claude Code”](#claude-code)
`claude mcp` コマンドでサーバーを登録します:
```bash
claude mcp add framedash \
-e FRAMEDASH_API_KEY=fd_xxx \
-e FRAMEDASH_PROJECT_ID=your-project-uuid \
-- npx -y @framedash/mcp-server
```
すべてのツール(raw SQL の `query` を含む)を利用するには Full プリセットキーを、raw SQL 以外の分析ツールには Read-only キーを使用してください。
## ホスト型リモートエンドポイント
[Section titled “ホスト型リモートエンドポイント”](#ホスト型リモートエンドポイント)
Framedash はリモート MCP サーバーもホストしています。 そのため、リモートサーバーと OAuth に対応した MCP クライアントは、ローカルへのインストールが不要です。 リクエストは Streamable HTTP トランスポートで `POST {origin}/api/mcp`(デフォルト `https://app.framedash.dev/api/mcp`)に送ります。 このエンドポイントはステートレスで、セッション ID を使いません。
認証は OAuth 2.1 Bearer のみで、ここでは API キーを受け付けません。 401 レスポンスには `WWW-Authenticate` ヘッダーが付き、その `resource_metadata` は `{origin}/.well-known/oauth-protected-resource` を指します。 そのため MCP の認可仕様を実装したクライアントは、認可サーバーを自動で検出し、動的クライアント登録を含めて OAuth フローを自力で完了できます。 ツール呼び出しは、REST API と同じく、付与された scope とプロジェクトの範囲で実行されます。 `GET` と `DELETE` は 405 を返します。 raw SQL の `query` ツールはリモートエンドポイントでは使えません。 これは `data:admin` scope を必要とし、OAuth トークンはこれを持てないためです。 raw SQL は引き続き stdio サーバーと Full の API キーで実行してください。
リモートエンドポイントには、アカウント単位のプラン別レート制限に加えて、認証前の入口に IP アドレス単位の別のレート制限があります。 詳細は [API 概要のレート制限](/api/overview/)を参照してください。
リモートサーバーと OAuth に対応した MCP クライアントには、stdio サーバーの代わりにインストール不要のこのホスト型エンドポイントを使ってください。 API キーベースやローカルの構成には、引き続き stdio サーバー(`npx -y @framedash/mcp-server`)が適しています。
## 環境変数
[Section titled “環境変数”](#環境変数)
| 変数 | 必須 | 説明 |
| ---------------------- | --- | --------------------------------------------------------------------------------------------------------------- |
| `FRAMEDASH_API_KEY` | はい | MCP ツールに必要な scope を持つ API キー。Full プリセットは raw SQL の `query` を含む全ツールを許可し、Read-only プリセットは raw SQL 以外の分析ツールを許可します。 |
| `FRAMEDASH_PROJECT_ID` | いいえ | デフォルトプロジェクト UUID |
| `FRAMEDASH_BASE_URL` | いいえ | API ベース URL(デフォルト: `https://app.framedash.dev`) |
ノート
`FRAMEDASH_PROJECT_ID` を省略した場合でも、各ツール呼び出し時に `project_id` 引数を指定すればプロジェクトスコープのツールは使用可能です。
## ツール
[Section titled “ツール”](#ツール)
### クエリ
[Section titled “クエリ”](#クエリ)
| ツール | 説明 | 引数 |
| ------- | ------------------------------------------- | ---------------------------------------------------------------------------- |
| `query` | ClickHouse events テーブルに対する読み取り専用 SQL クエリを実行 | `sql` (string, 必須), `project_id` (uuid, 任意), `limit` (int 1-1000, デフォルト 100) |
### アナリティクス
[Section titled “アナリティクス”](#アナリティクス)
| ツール | 説明 | 引数 |
| --------------- | ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `get_dashboard` | プロジェクト KPI(DAU、MAU、セッション、イベント数) | `project_id` (uuid, 任意), `days` (7/14/30/90, デフォルト 30) |
| `get_retention` | コホートリテンション分析 | `project_id` (uuid, 任意), `days` (7/14/30/90, デフォルト 30) |
| `get_funnel` | イベントファネル分析 | `project_id` (uuid, 任意), `steps` (string, 必須: カンマ区切り 2-8 イベント名), `days` (7/14/30/90, デフォルト 30) |
| `get_insights` | ディメンション別集計インサイト | `project_id` (uuid, 任意), `metric` (count/unique\_players, 必須), `group_by` (string, 必須: event\_name, platform 等), `days` (7/14/30/90, デフォルト 30), `limit` (10/20/50), `event_name` (string, 任意) |
| `get_heatmap` | マップのヒートマップグリッドデータ | `project_id` (uuid, 任意), `map_id` (string, 必須), `cell_size` (5/10/25/50, デフォルト 25), `days` (1/7/14/30, デフォルト 7), `event_name` (string, 任意) |
### プロジェクト
[Section titled “プロジェクト”](#プロジェクト)
| ツール | 説明 | 引数 |
| -------------------- | ---------------------------- | -------------------------------------------- |
| `list_projects` | API キーに紐付けられたプロジェクトを表示 | なし |
| `get_project_status` | プロジェクトのヘルス概要(イベント数、最終イベント時刻) | `project_id` (uuid, 任意) |
| `list_maps` | プロジェクト内のマップ一覧 | `project_id` (uuid, 任意) |
| `list_content` | コンテンツレジストリエントリ一覧 | `project_id` (uuid, 任意), `type` (string, 任意) |
### アラート
[Section titled “アラート”](#アラート)
| ツール | 説明 | 引数 |
| ------------------- | -------------- | ------------------------------------------------------ |
| `list_alerts` | アラートルール一覧 | `project_id` (uuid, 任意) |
| `get_alert_history` | アラートのトリガー・解除履歴 | `project_id` (uuid, 任意), `limit` (int 1-100, デフォルト 50) |
## リソース
[Section titled “リソース”](#リソース)
`framedash://` URI スキームで MCP リソースとしてデータにアクセスできます:
| URI | 説明 |
| ------------------------------------------ | ------------------- |
| `framedash://projects` | API キーに紐付けられたプロジェクト |
| `framedash://projects/{projectId}/maps` | マップ一覧(座標・範囲付き) |
| `framedash://projects/{projectId}/content` | コンテンツレジストリ |
| `framedash://projects/{projectId}/status` | プロジェクトの状態と統計 |
## 使用例
[Section titled “使用例”](#使用例)
MCP Server を設定すると、LLM に自然言語で問い合わせできます:
| プロンプト例 | 使用されるツール |
| ----------------------------- | -------------------------------------------------- |
| 「過去 7 日間の DAU を見せて」 | `get_dashboard` (days=7) |
| 「spawn から death までのファネルを分析して」 | `get_funnel` (steps=“player\_spawn,player\_death”) |
| 「プラットフォーム別のイベント数を教えて」 | `get_insights` (metric=count, group\_by=platform) |
| 「マップ上の FPS ヒートマップを表示して」 | `get_heatmap` (map\_id=…) |
| 「直近のアラート履歴を確認して」 | `get_alert_history` |
## 次のステップ
[Section titled “次のステップ”](#次のステップ)
* [API リファレンス](/api/overview/): REST API の詳細
* [CLI リファレンス](/cli/overview/): コマンドラインツール
# データモデル
> Framedash のテレメトリデータ構造とイベントスキーマ。
Framedash SDK が収集・送信するテレメトリデータの構造を説明します。
各イベントは 1 つの `GameTelemetryEvent` であり、Protobuf でシリアライズされ、`TelemetryBatch` として `POST /v1/events` に送信されます。各イベントは ClickHouse の `events` テーブルの 1 行に対応します。スキーマは固定です(`telemetry.proto` で定義)。ゲーム固有のデータは柔軟な `attributes` / `metrics` マップに格納できますが、下記の取り込み上限内に収める必要があります。
## イベントフィールド
[Section titled “イベントフィールド”](#イベントフィールド)
### 識別子とコンテキスト
[Section titled “識別子とコンテキスト”](#識別子とコンテキスト)
| フィールド | 型 | 説明 |
| ---------------- | ------ | ---------------------------------------------------------------------------------------------------------------- |
| `event_name` | string | イベント識別子。例: `player_death`、または自動イベント `session_start` / `perf_heartbeat`。 |
| `timestamp_us` | int64 | イベント発生時刻(Unix エポックのマイクロ秒。`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`。 |
ノート
`timestamp_us` は、イベントのペイロードに載る Protobuf のフィールド名です(`int64`、マイクロ秒)。 SQL でテレメトリを問い合わせるとき(`POST /v1/query`、CLI、MCP の `query` ツール)は、ClickHouse 側の列名が `timestamp`(`DateTime64(6)`)になります。 クエリでは `timestamp_us` ではなく `timestamp` を選択してください。 問い合わせできる列の一覧は[イベントスキーマ](/api/events-schema/)を参照してください。
### 位置とカメラ
[Section titled “位置とカメラ”](#位置とカメラ)
| フィールド | 型 | 説明 |
| -------------- | -------------------------- | --------------------------------------------------------------- |
| `position` | `Vector3`(x, y, z の float) | ワールド空間の位置。`position_x` / `position_y` / `position_z` として保存。 |
| `camera_yaw` | float(任意) | カメラの水平回転(度)。`0` = 北、時計回り、範囲 `[0, 360)`。SDK がカメラを取得しない場合は存在しません。 |
| `camera_pitch` | float(任意) | カメラの垂直回転(度)。`-90` = 真下、`+90` = 真上。 |
`camera_yaw` と `camera_pitch` は両方同時に送信されるか、まったく送信されないかのいずれかです。値が無い場合は 0 ではなく「未取得」を意味します。
### パフォーマンスメトリクス
[Section titled “パフォーマンスメトリクス”](#パフォーマンスメトリクス)
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 メトリクス”](#ロード時間とディスク-io-メトリクス)
Unity SDK 0.1.3、UE5 SDK 0.1.6、Godot SDK 0.1.4 で、自動収集されるパフォーマンス信号が 2 つ追加されました。 どちらも 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`**:`perf_heartbeat` の `metrics` マップに、前回の heartbeat からの差分として付与されるディスク読み取りカウンター。実際にサンプルが取得できてから初めて現れます。自動ソースは、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`。いずれもオプトイン(`bTrackMemoryDetail`、既定はオフ)で、`mem.vram` は LLM 不要ですがヘッドレス / `-nullrhi` 実行では付与されません(`0` ではなくキーなし)。
* **Unity SDK 0.1.4 以降**:`mem.vram` と `mem.heap`。オプトイン不要で自動収集されます。
* **Godot SDK 0.1.5 以降**:`mem.vram`、`mem.textures`、`mem.buffers`。オプトイン不要で自動収集されます。
いずれも `metrics` マップに載り、追跡されていないカテゴリはキー自体が現れません(未収集を意味し、収集された `0` とは区別されます)。 `mem.vram` は perf-diff(ビルド比較)の比較対象メトリクスでもあります。 エンジンごとの詳細は [UE5 SDK](/sdk/unreal/)、[Unity SDK](/sdk/unity/)、[Godot SDK](/sdk/godot/) の各ガイドを参照してください。
### カスタムデータ
[Section titled “カスタムデータ”](#カスタムデータ)
ゲーム固有のコンテキストは 2 つの柔軟なマップで送信され、スキーマ変更は不要です:
| フィールド | 型 | 説明 |
| ------------ | --------------------- | ----------------------------------------------------- |
| `attributes` | `map` | 文字列のキーバリュー。例: `weapon: "rifle"`。COPPA モードでは丸ごと破棄されます。 |
| `metrics` | `map` | 数値の測定値。例: `damage: 42.5`。 |
## 取り込み検証上限
[Section titled “取り込み検証上限”](#取り込み検証上限)
取り込みパイプラインはデコード後の各イベントを検証します。バッチ内の 1 イベントでも上限外の場合、経路によってリクエスト時に拒否されるか、非同期処理中にバッチ全体が破棄されます。独自 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 entries。key は最大 64 文字、value は最大 512 文字。 |
| `metrics` | 最大 50 entries。key は最大 64 文字、value は有限数。 |
| `camera_yaw` / `camera_pitch` | 両方存在するか、両方省略。yaw は `[0, 360)`、pitch は `[-90, 90]` に正規化されます。 |
## バッチエンベロープ
[Section titled “バッチエンベロープ”](#バッチエンベロープ)
SDK は `TelemetryBatch`(`GameTelemetryEvent` のリスト)を送信します。API キーと SDK バージョンはペイロード本文ではなく HTTP ヘッダー(`X-API-Key`、`X-SDK-Version`)で送信されます。
独自送信クライアントでは、送信時の HTTP リクエスト本文(gzip 圧縮を使う場合は圧縮後)を 126,000 bytes 以下にしてください。本番取り込みでは、これを超える本文は `413` で拒否されます。公式 SDK はこの上限より十分小さいサイズで flush します。
## 次のステップ
[Section titled “次のステップ”](#次のステップ)
* [API リファレンス](/api/overview/): REST API でこのデータにアクセス
* [ヒートマップ](/concepts/heatmaps/): 位置データの可視化
# Godot SDK
> Godot 4 プロジェクトへの Framedash SDK 統合ガイド。
Framedash Godot SDK (C# アドオン) を使用して、パフォーマンステレメトリを自動収集する方法を説明します。
## 要件
[Section titled “要件”](#要件)
* Godot 4.3 以上の .NET (C#) ビルド。標準の GDScript 専用ビルドでは C# アドオンをコンパイルできません。
* .NET 8 SDK 以降(`net8.0` をターゲットにできる SDK であれば可。アドオンは `net8.0` をターゲットとするゲームアセンブリにビルドされます)
* Web (HTML5) エクスポートは、Godot 4 の .NET Web エクスポートがサポートされていないため対象外です。
## インストール
[Section titled “インストール”](#インストール)
SDK は Godot Asset Library(エディター GUI)から、または GitHub から手動(スクリプト / CI 向け)でインストールできます。 CI やスクリプトでのセットアップでは、Asset Library の手順がエディター GUI を必要とするため、下の[手動インストール](#github-%E3%81%8B%E3%82%89%E6%89%8B%E5%8B%95%E3%81%A7%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB)を使ってください。
### Godot Asset Library(エディター GUI)
[Section titled “Godot Asset Library(エディター GUI)”](#godot-asset-libraryエディター-gui)
SDK は [Godot Asset Library](https://godotengine.org/asset-library/asset/5355) で公開されています。 この方法は GUI 専用です。 Godot エディターで次の手順を実行します:
1. **AssetLib** タブを開く
2. **Framedash Telemetry SDK** を検索し、バージョン `0.1.8` を選択する
3. **Download**、続けて **Install** を選択する。`addons/framedash/` を選択したままにして、アドオンが `res://addons/framedash/` にインストールされることを確認する
### GitHub から手動でインストール
[Section titled “GitHub から手動でインストール”](#github-から手動でインストール)
リリースバージョンに固定する場合や CI で使用する場合は、[Framedash Godot SDK リポジトリ](https://github.com/crane-valley/framedash-godot-sdk)をクローンします:
```bash
git clone --branch v0.1.8 --depth 1 https://github.com/crane-valley/framedash-godot-sdk.git
```
再現性のあるビルドのため、既定ブランチを追いかけるのではなくリリースタグ(`v0.1.8`)に固定します。クローン後、プロジェクトに `addons/` ディレクトリがなければ作成してから、リポジトリの `addons/framedash/` フォルダーを `res://addons/` にコピーします。
危険
SDK リポジトリは、Godot プロジェクトのディレクトリの**外側**にクローンしてください。 あるいは、`addons/framedash/` フォルダーをコピーしたあとにクローンを削除してください。 Godot の .NET はプロジェクト直下のすべての `.cs` ファイルをコンパイルするため、プロジェクトツリー内に残ったクローンは SDK 自身のソースを二重にコンパイルし、約 280 件の重複クラスエラーでビルドが失敗します。
どちらかの方法でインストールしたあと、次の手順を実行します:
1. C# ソリューションを 1 回ビルドする。これで `.csproj` / `.sln` が生成され、アドオンがコンパイルされて autoload 型が利用可能になる
2. Godot エディターで Project > Project Settings > Plugins を開く
3. **Framedash Telemetry SDK** を有効化
ノート
C# スクリプトを一度も置いていないプロジェクトには `.csproj` / `.sln` がありません。 これを生成してアドオンをコンパイルするのは C# ソリューションのビルド(手順 1)なので、プラグインを有効化する**前に**ビルドしてください。 最初のビルドが成功する前にプラグインを有効化すると、エディターは未コンパイルの C# プラグインを読み込めず、無言で自動的に無効化します。 その場合はビルド成功後に Plugins の一覧で再度有効化してください。 ヘッドレスや CI での設定は、下の「ヘッドレス / CI」を参照してください。
## 初期設定
[Section titled “初期設定”](#初期設定)
プラグインを有効にすると、`Framedash` autoload singleton が登録されます。起動直後の `_Ready()` などで SDK を一度だけ初期化します:
```csharp
using Framedash;
using Godot;
public partial class GameBootstrap : Node
{
public override void _Ready()
{
TelemetrySDK.Initialize(
apiKey: "your-api-key",
buildId: "1.0.0");
}
}
```
`endpointUrl` と `buildId` は任意です。`endpointUrl` を省略すると `https://ingest.framedash.dev/v1/events` が使われます。
ノート
このページは名前付き引数を使っています。 `TelemetrySDK.Initialize` を位置引数で呼ぶ場合(同梱アドオンの README がそうしています)、`endpointUrl` が **2 番目**の引数、`buildId` が 3 番目です: `TelemetrySDK.Initialize("your-api-key", "https://ingest.framedash.dev/v1/events", "1.0.0")`。 ビルド ID を 2 番目に渡すと、それがエンドポイント URL に設定され、エラーを出さずに送信先が誤設定されます。 `buildId:` は名前付きで渡すか、2 番目にエンドポイント(または空文字列)を置いてください。
ノート
プラグインを有効にすると `Framedash` autoload が登録されますが、この autoload は必須ではありません。 `TelemetrySDK.Initialize(...)` は、singleton が存在しなければ自分で生成します。 Plugins の UI を開けないヘッドレスや CI のプロジェクトでは、自分の起動コードから `Initialize` を呼ぶだけで十分です。
## 自動収集されるデータ
[Section titled “自動収集されるデータ”](#自動収集されるデータ)
SDK は次のデータを自動収集します:
* **FPS / フレームタイム**: 実時間のフレームデルタから算出
* **メモリ**: Godot の static memory
* **GPU / レンダー CPU 時間**: `RenderingServer` が報告する直近フレームの値
* **ゲームスレッド時間**: `_process` に費やされた時間
`session_start` は初期化時に、`perf_heartbeat` は 10 秒ごとに送信されます。
## カスタムイベント
[Section titled “カスタムイベント”](#カスタムイベント)
```csharp
TelemetrySDK.Instance.Track(
eventName: "player_death",
mapId: "map_01",
position: playerNode.GlobalPosition);
```
カテゴリ属性や数値メトリクスを付ける場合:
```csharp
using System.Collections.Generic;
TelemetrySDK.Instance.Track(
eventName: "player_death",
mapId: "map_01",
position: playerNode.GlobalPosition,
attributes: new Dictionary { { "cause", "fall_damage" } },
metrics: new Dictionary { { "health", 0f } });
```
## イベントのフラッシュ
[Section titled “イベントのフラッシュ”](#イベントのフラッシュ)
トラックしたイベントはメモリにバッファされ、30 秒間隔、またはバッチが 100 件か 100 KB に達した時点のいずれか早いほうで自動的にフラッシュされます。 長時間動くゲームでは手動でフラッシュする必要はありません。
短命な実行やヘッドレス実行は、次の自動フラッシュより前に終了することがあります。 その場合は `Flush()` を明示的に呼び、送信が確認できるまでプロセスを生かしておいてください(詳細ログには HTTP の結果が出力されます)。 `Flush()` は非同期の送信を開始するだけで、最後の送出はプロセスの終了に合わせて行われます。 そのため、同じ行で終了せず、`Flush()` を呼んでから少し間を置いて終了してください。 Godot SDK 0.1.5 以降は、正常なシャットダウン時にバッファを同期的に排出します(上限 2.5 秒)。 オフラインキューはないため、この時間内に送信が失敗したイベントや、強制終了で残ったイベントは失われます。 詳細は[トラブルシューティング](/sdk/troubleshooting/)を参照してください。
```csharp
TelemetrySDK.Instance.Flush();
```
ノート
短時間の検証実行では、サンプリングされないマーカーを送信し、非同期のフラッシュが完了するまでプロセスを維持します:
```csharp
public override async void _Ready()
{
TelemetrySDK.Initialize(apiKey: "your-api-key", buildId: "1.0.0");
TelemetrySDK.Instance.VerboseLogging = true;
// グローバルの SamplingRate が 1.0 未満だと、マーカーはサンプリングで落ちる一方、
// 自動送信される session_start は HTTP 2xx を返すため、検証が偽陽性で成功と
// 判定されることがある。このイベントのレートを 1.0 に固定してマーカーを必ず保持する。
TelemetrySDK.Instance.SetEventSamplingRate("ci_marker", 1f);
TelemetrySDK.Instance.Track(eventName: "ci_marker", mapId: "ci", position: Vector3.Zero);
TelemetrySDK.Instance.Flush();
await ToSignal(GetTree().CreateTimer(10.0), SceneTreeTimer.SignalName.Timeout);
GetTree().Quit();
}
```
`Flush()` は非同期の送信を投げっぱなしで開始するだけなので、時間を区切ったタイマーで送信が届くまでプロセスを生かしておきます。 終了する前に、詳細ログの `HTTP 202` 行を確認してください。
## プレイヤー識別子 (任意)
[Section titled “プレイヤー識別子 (任意)”](#プレイヤー識別子-任意)
デフォルトではイベントは匿名で送信されます。ログイン後に `SetPlayerId` を呼ぶと、以降のイベントにプレイヤー識別子を関連付けられます:
```csharp
TelemetrySDK.Instance.SetPlayerId(playerId);
```
## ランタイムのサンプリングオーバーライド
[Section titled “ランタイムのサンプリングオーバーライド”](#ランタイムのサンプリングオーバーライド)
SDK はグローバルなサンプリングレート(既定は `1.0` = 全件保持)を適用します。 高頻度なイベントは、実行時にグローバルレートを上書きするイベント名ごとのレートを個別に設定できます。
```csharp
Framedash.TelemetrySDK.Instance.SetEventSamplingRate("ai_pathfind_step", 0.05f); // 約 5%
Framedash.TelemetrySDK.Instance.RemoveEventSamplingRate("ai_pathfind_step"); // グローバルに戻す
```
`SetEventSamplingRate(string eventName, float rate)` はレートを \[0, 1] にクランプして設定し、`RemoveEventSamplingRate(string eventName)` はそのオーバーライドを削除します。 自動収集されるイベント(`session_start`、`perf_heartbeat`)はサンプリングの対象外です。
## マップロード時間の計測
[Section titled “マップロード時間の計測”](#マップロード時間の計測)
Godot SDK 0.1.4 以降で利用できます。 SDK はシーンやレベルの読み込みにかかった時間を計測し、`map_load` イベントとして報告できます。 このイベントはビルド比較(perf-diff)のリグレッションゲートと、ダッシュボードのロード時間チャートに使われます。
自分で制御するロードを `BeginMapLoad` / `EndMapLoad` で囲みます。
```csharp
TelemetrySDK.Instance.BeginMapLoad("Level_01");
// ... シーンを読み込む ...
TelemetrySDK.Instance.EndMapLoad();
```
`BeginMapLoad` は、ポーズやタイムスケールの影響を受けない単調増加クロックでタイマーを開始します。 `EndMapLoad` はそれを止めてイベントを送出します。 `EndMapLoad` の前に再度 `BeginMapLoad` を呼ぶと、保留中の計測は置き換えられます。
カスタムローダーやストリーミングローダーで既に時間を計測している場合は、その値を直接報告できます。
```csharp
TelemetrySDK.Instance.ReportMapLoad("Level_01", 1234f); // ロード時間(ミリ秒)
```
`ReportMapLoad` は、`loadTimeMs` が NaN、無限大、または負の値のとき、そのサンプルを丸ごと破棄します(クランプはしません)。
どちらの経路も、`metrics["load_time_ms"]` と `attributes["map_name"]` を持つ `map_load` イベントを送出します。 このイベントは意図的に `map_id` を空にしているため、空間ヒートマップとアクティベーションゲートの対象外になります。 これらの呼び出しは任意のスレッドから安全に行え、例外を投げず、`Initialize` の前は何もしません。
## ディスク I/O メトリクス
[Section titled “ディスク I/O メトリクス”](#ディスク-io-メトリクス)
Godot SDK 0.1.4 以降で利用できます。 SDK はディスク読み取りのカウンターを、`io.read_bytes`、`io.read_time_ms`、`io.read_ops` というメトリクスキーで `perf_heartbeat` イベントに付与できます。 各値は前回の heartbeat からの差分で、実際にサンプルが取得できてから初めてキーが付きます(ゼロ埋めはしません)。 他のパフォーマンスメトリクスと同様に、`io.*` は perf-diff / builds-compare のリグレッションゲートとダッシュボードのチャートに使われます。 `io.*` のしきい値アラートはありません。
Godot には自動のディスク I/O ソースがないため、`ReportIoSample` で自分でサンプルを供給します。
```csharp
TelemetrySDK.Instance.ReportIoSample(bytes: 1048576, readTimeMs: 3.2f, ops: 12);
```
## メモリカテゴリメトリクス
[Section titled “メモリカテゴリメトリクス”](#メモリカテゴリメトリクス)
Godot SDK 0.1.5 以降で利用できます。 SDK は heartbeat の周期でメモリカテゴリ別の使用量をサンプリングし、`perf_heartbeat` イベントに `mem.*` メトリクスとして自動的に付与します。 値は Godot の Performance モニターから取得し、オプトインは不要です。
* **`mem.vram`**:使用中のビデオメモリ(バイト)。
* **`mem.textures`**:テクスチャが占めるビデオメモリ(バイト)。
* **`mem.buffers`**:バッファが占めるビデオメモリ(バイト)。
読み取り値が 0 以下のときは、そのキーを付けません。 キーがないことは未収集を意味し、`0` として送ることはありません。
これらのキーは `perf_heartbeat` に加えて、位置情報付き(`map_id` が空でない)イベントにも付与されます。 `perf_heartbeat` は `map_id` が空で空間ヒートマップのグリッドに入らないため、セルごとのメモリヒートマップを作れるよう、同じサンプルを位置情報付きイベントにも載せます。 位置情報付きイベントに載るのは heartbeat の周期で更新されるキャッシュ済みサンプルです。
呼び出し側が渡したメトリクスキーは、キーの衝突時も容量の面でも常に優先されます。 `mem.*` が埋めるのは取り込み上限(メトリクス 50 件)に残った枠だけで、まず `mem.vram` から入ります。
## 設定モデル
[Section titled “設定モデル”](#設定モデル)
プラグインが登録する autoload は `TelemetrySDK.cs` のコード既定値で生成されるため、Project Settings から `[Export]` フィールドを直接編集するモデルではありません。通常は `TelemetrySDK.Initialize(...)` で設定してください。
`TelemetrySDK` スクリプトを自分の scene node に追加して独自の autoload scene として使う場合のみ、Inspector から API キー、endpoint、sampling rate、camera rotation などの `[Export]` フィールドを設定できます。
## 詳細ログ
[Section titled “詳細ログ”](#詳細ログ)
最初の統合では、詳細ログを有効にして送信を確認してください。
```csharp
TelemetrySDK.Instance.VerboseLogging = true;
```
トランスポート失敗時はリトライの梯子を記録します。例: `[Framedash] Retry 1/3 in 1.0s (HTTP 0)`。 `HTTP 0` は API による拒否ではなく、トランスポートレベルの失敗(DNS、TLS、タイムアウト)を意味します。 イベントが届かない場合は[トラブルシューティング](/sdk/troubleshooting/)を参照してください。
## ヘッドレス / CI
[Section titled “ヘッドレス / CI”](#ヘッドレス--ci)
Godot のエディター **Build** は、C# プロジェクトの `.csproj` / `.sln` を生成します。 `godot --headless --build-solutions --quit` は既存のソリューションをビルドしますが、一度もビルドしていないプロジェクトでは初回の `.csproj` / `.sln` を生成できません。 CI 専用の新規プロジェクトでは、終了コード 0 でエラーもなく完了しながら、プロジェクトファイルを何も書き出さないことがあります(4.6.3 mono で確認)。 そのため、最初のビルドをヘッドレスで行うことはできません。
エディターで一度も開いていない CI 専用プロジェクトでは、先に自分でプロジェクトファイルを作成してください。 プロジェクト直下に `.csproj` を手で作成し、`Sdk="Godot.NET.Sdk/"` を指定して `net8.0` をターゲットにします。 `Godot.NET.Sdk` のバージョンは、ビルドに使う Godot のバージョンに合わせてください。
```xml
net8.0
true
```
エディターで少なくとも一度プロジェクトを開けるなら、そこで **Build** を 1 回クリックし、生成された `.csproj` / `.sln` をコミットする方法もあります。
プロジェクトファイルを用意したら、.NET SDK でビルドします。
```bash
dotnet build
```
コンパイルされたアセンブリは `.godot/mono/temp/bin/Debug/` に生成されます。 プラグインは `Initialize` が自分で生成できる autoload を登録するだけなので、ヘッドレス実行ではエディター UI からプラグインを有効にする必要はありません。
注意
プロジェクトファイルの生成に `dotnet new sln` を使わないでください。 これは空のソリューションを作るだけで、`Godot.NET.Sdk` を参照せず、アドオンはコンパイルされません。 新しい .NET SDK では `dotnet new sln` が `.slnx` 形式のソリューションを出力し、Godot のツールが想定しない場合があります。 上記のように `.csproj` を手で書いてください。
イベントが届かない場合は[トラブルシューティング](/sdk/troubleshooting/)を参照してください。
## CI / 自動セッション
[Section titled “CI / 自動セッション”](#ci--自動セッション)
自動テストやプロファイリング実行では、セッション全体にタグを付け、各イベントが CI のビルドとその branch / commit / scenario を持つようにします。 テストのエントリーポイントで、自動セッション API を一度だけ呼び出します。
```csharp
using Framedash;
// 引数はすべて任意です。
TelemetrySDK.Instance.BeginAutomatedSession(
buildId: "build-123",
branch: "main",
commit: "abc1234",
scenario: "nightly");
// ... 自動シナリオを実行する ...
TelemetrySDK.Instance.EndAutomatedSession();
```
完全なシグネチャは `void BeginAutomatedSession(string buildId = null, string branch = null, string commit = null, string scenario = null)` です。 CI では `BeginAutomatedSessionFromEnvironment()` を使うと便利です。 これは `framedash run-profile-test` が書き出す環境変数 `FRAMEDASH_BUILD_ID`、`FRAMEDASH_GIT_BRANCH`、`FRAMEDASH_GIT_COMMIT`、`FRAMEDASH_TEST_SCENARIO` を読み取ります。
```csharp
TelemetrySDK.Instance.BeginAutomatedSessionFromEnvironment();
// ... 自動シナリオを実行する ...
TelemetrySDK.Instance.EndAutomatedSession();
```
自動セッションは、セッション内のすべてのイベントに `build_id` の上書きと `ci.branch` / `ci.commit` / `ci.scenario` 属性を付与します。 これがビルド比較(perf-diff)の CI ゲートに使われます。 イベントの `source` は変わりません。 SDK 自身の自動イベント(`session_start`、`perf_heartbeat`)は `source=automated` のまま、`Track` イベントは `source=player` のままで、これは CI でも通常のプレイでも同じです。 パイプライン全体は [CI プロファイリング](/concepts/ci-profiling/) を参照してください。
## 次のステップ
[Section titled “次のステップ”](#次のステップ)
* [データモデル](/sdk/data-model/): テレメトリデータの構造
* [トラブルシューティング](/sdk/troubleshooting/): イベントが表示されないとき
* [ヒートマップ](/concepts/heatmaps/): 収集したデータの可視化
# トラブルシューティング
> テレメトリイベントが表示されない原因を切り分ける。詳細ログ、到達までの時間、トランスポート障害、オフラインキュー、到達の確認方法。
SDK を統合してゲームを実行したのに、データが表示されない。 そのときは以下のチェックを順に進めてください。
## どれくらいで届くか
[Section titled “どれくらいで届くか”](#どれくらいで届くか)
パイプラインが温まっていれば、取り込まれたイベントは数秒でクエリできます。 アイドル状態のあとの最初のイベントは、ストレージがコールドから再開するため時間がかかることがあります。 そのため、送信失敗と判断する前に数分待ってください。 数分たっても何も届かないなら、トランスポートのチェックに進みます。
## 詳細ログを有効にする
[Section titled “詳細ログを有効にする”](#詳細ログを有効にする)
既定では SDK は送信についてほとんどログを出しません。 まず詳細ログを有効にしてください。 バッチがプロセスから出ていったか、サーバーが何を返したかがわかります。
* Unity: `TelemetrySDK.Instance.VerboseLogging = true;` で詳細ログを有効にします(初期化の前後どちらでも反映されます)。フラッシュ成功時は `[Framedash] Flushed N events (HTTP 202)` を記録します。
* UE5: SDK は `LogFramedash` カテゴリにログを出します。`-LogCmds="LogFramedash Verbose"` を付けて起動します(またはコンソールで `Log LogFramedash Verbose` を実行)。送信時は `SendBatch: N events -> ...` に続けて HTTP の結果を記録します。
* Godot: `TelemetrySDK.Instance.VerboseLogging = true;` で詳細ログを有効にします(初期化の前後どちらでも反映されます)。トランスポート失敗時はリトライの梯子を記録します。例: `[Framedash] Retry 1/3 in 1.0s (HTTP 0)`。
## 結果コードを読む
[Section titled “結果コードを読む”](#結果コードを読む)
記録された HTTP ステータスが、問題の場所を教えてくれます。
* 202: 非同期処理用に受理されました。リクエストは取り込みキューに到達していますが、永続保存の確認ではありません。無効なイベントは後段の検証で破棄されることがあります。下記の一意なマーカーで確認してください。
* 0(Godot)または接続タイムアウト: トランスポートレベルの失敗(DNS、TLS、プロキシ、IPv6)であり、API による拒否ではありません。次の節を参照してください。
* 401 / 403: API キーがないか、`events:write` scope を持ちません。Ingest プリセットのキーを使ってください。
* 415: `Content-Type` が不正です。カスタム送信のときだけ関係します。取り込みエンドポイントは protobuf のみを受け付けます。公式 SDK はこれを自動で設定します。
## トランスポートレベルの失敗
[Section titled “トランスポートレベルの失敗”](#トランスポートレベルの失敗)
ステータス `0` や接続タイムアウトの繰り返しは、リクエストがサーバーに届いていないことを意味します。 まず同じマシンからエンドポイントが正常か確認し、それから原因を切り分けます。
```bash
curl -4 -sv https://ingest.framedash.dev/v1/events
curl -6 -sv https://ingest.framedash.dev/v1/events
```
正常なホストは IPv4 で 1 秒未満に応答します(素のリクエストは `4xx` の構造化エラーを返しますが、それでも到達性は確認できます)。
* IPv6 の不具合: SDK は IPv4 を優先し IPv6 にフォールバックしますが、IPv6 の外向き通信が壊れているホストでは、データが流れ始めるまでに短い接続タイムアウトが数回見えることがあります。`curl -4` が成功して `curl -6` がハングするなら、該当インターフェースの IPv6 を無効化するか、`ingest.framedash.dev` の IPv4 の `hosts` エントリを追加してください。
* DNS の癖: Godot の `HttpRequest` は独自の非同期 DNS リゾルバを使います。そのため OS のリゾルバや `curl` が成功しても失敗(`HTTP 0`)することがあります。不安定な DNS や split-horizon DNS の経路が典型的な原因です。
* プロキシ: 企業のプロキシやファイアウォールが取り込みホストをブロックすることがあります。同じマシンから `https://ingest.framedash.dev` への `curl` が失敗するなら、SDK を見る前にネットワーク経路を直してください。
## オフラインキュー
[Section titled “オフラインキュー”](#オフラインキュー)
**Unity と UE5** は、正常なシャットダウン時、または一時的な送信失敗時にイベントをディスク上のキューに書き込み、次の初期化時にゲームループが回り始めた時点でフラッシュします。 CI のタイムアウトによる kill などの強制終了ではキューは書き込まれないため、その時点でバッファに残っているイベントは失われます。 正常にシャットダウンした短いヘッドレス実行は、イベントがキューで待っている間「何も送っていない」ように見えますが、これは想定どおりの挙動です。 ゲームをもう一度実行するか、実行を長めに保てば、キューのバッチはフラッシュされます。 CI では、キューに頼らず、プロセスを kill する前にログの HTTP 2xx 行を待ってください。 詳細はエンジン別のヘッドレスガイドを参照してください([Unity](/sdk/unity/#%E3%83%98%E3%83%83%E3%83%89%E3%83%AC%E3%82%B9--ci)、[UE5](/sdk/unreal/#%E3%83%98%E3%83%83%E3%83%89%E3%83%AC%E3%82%B9--ci))。
**Godot** にはディスク上のキューはありません。Godot SDK 0.1.5 以降では、`Shutdown()` は上限 2.5 秒のブロッキング送信でバッファを同期的に排出します。オフラインキューはないため、この時間内に送信が失敗したイベントや、排出が終わる前に強制終了されたプロセスに残ったイベントは失われます。詳細は[Godot のヘッドレスガイド](/sdk/godot/#%E3%83%98%E3%83%83%E3%83%89%E3%83%AC%E3%82%B9--ci)を参照してください。
## Unity: バッチモードで「Package Manager Cancelled resolving packages」になる
[Section titled “Unity: バッチモードで「Package Manager Cancelled resolving packages」になる”](#unity-バッチモードでpackage-manager-cancelled-resolving-packagesになる)
git パッケージを追加した直後の Unity バッチモード実行が `Package Manager Cancelled resolving packages` で失敗することがあります。 原因は、プロジェクト作成時に残った古い `Temp/UnityLockfile` です。 エディターを閉じ、`Temp/UnityLockfile` を削除してから再実行してください。
## 到達を確認する
[Section titled “到達を確認する”](#到達を確認する)
ダッシュボードを使わずにマーカーを正確に確認するには、`data:admin` scope を持つ **Full** キーで raw SQL を実行します。 Read-only キーの `analytics:read` scope では集計 API を参照できますが、`framedash query` は実行できません。Ingest キーの `events:write` scope にも読み取り権限はありません。 独自送信を確認するときは `ingest_probe_` の `` を UUID などへ置き換え、実行ごとに新しいマーカーをイベントへ付けてください。同じマーカーを再利用すると、過去のイベントを現在の実行成功と誤認することがあります。
```bash
# このキーはどのプロジェクトに属し、有効か
framedash auth --api-key-file read.key
# 今回の一意なマーカーは永続ストレージへ届いたか(Full プリセットのキー、data:admin scope)
framedash query --api-key-file full.key --project-id \
"SELECT count(), max(timestamp) FROM events WHERE event_name = 'ingest_probe_'"
```
Ingest(`events:write`)キーは自身のプロジェクトを列挙できないため、「自分はどのプロジェクトに書き込んでいるのか」はそのキー自体からは答えられません。 ダッシュボードで確認するか、同じプロジェクトに Read-only キーを作成してください。 選択できるカラムは[イベントスキーマ](/api/events-schema/)を参照してください。
## 次のステップ
[Section titled “次のステップ”](#次のステップ)
* [イベントスキーマ](/api/events-schema/): カラムとクエリ規則
* [CLI リファレンス](/cli/overview/): `framedash auth` と `framedash query`
* [クイックスタート](/getting-started/quickstart/): 統合の流れ
# Unity SDK
> Unity プロジェクトへの Framedash SDK 統合ガイド。
Framedash Unity SDK を使用して、パフォーマンステレメトリを自動収集する方法を説明します。
## 要件
[Section titled “要件”](#要件)
* Unity 2022.3 以上
* .NET Standard 2.1 / .NET Framework 4.x
## インストール
[Section titled “インストール”](#インストール)
### Unity Package Manager (推奨)
[Section titled “Unity Package Manager (推奨)”](#unity-package-manager-推奨)
1. Window > Package Manager を開く。Unity 6.5 ではこのパスが **Window > Package Management > Package Manager** に変わりました。古いバージョンでは短い **Window > Package Manager** のままです。
2. 「+」 > 「Add package from git URL…」を選択
3. 以下の URL を入力:
```plaintext
https://github.com/crane-valley/framedash-unity-sdk.git
```
特定のリリースに固定するには、バージョンタグを付与します:
```plaintext
https://github.com/crane-valley/framedash-unity-sdk.git#v0.1.7
```
スクリプトや CI からインストールする場合は、`Packages/manifest.json` に依存を直接追加します。 パッケージ名は `com.framedash.sdk` です。
```json
{
"dependencies": {
"com.framedash.sdk": "https://github.com/crane-valley/framedash-unity-sdk.git#v0.1.7"
}
}
```
## 初期設定
[Section titled “初期設定”](#初期設定)
起動時に一度だけ SDK を初期化します。たとえば永続化した GameObject の `MonoBehaviour` から初期化します:
```csharp
using System.Collections.Generic;
using Framedash;
using UnityEngine;
public sealed class GameBootstrap : MonoBehaviour
{
// API キーは Inspector で設定するか、空のままにして FRAMEDASH_API_KEY
// 環境変数にフォールバックさせます。解決順序とプラットフォームの注意点は
// 下記の注記を参照してください。
[SerializeField] private string _apiKey;
private void Awake()
{
TelemetrySDK.Initialize(
apiKey: _apiKey,
buildId: Application.version);
}
}
```
`endpointUrl` は任意で、省略時は `https://ingest.framedash.dev/v1/events` が使われます。 ローカルやセルフホストの ingest を指定する場合に明示的に渡してください。 `playerId` は初期化時にプレイヤー ID を設定します(後から `SetPlayerId` を呼ぶのと同じです)。 `enableOfflineQueue` は既定で `true` で、`false` を渡すとディスク上のオフラインキューを無効化します。 完全なシグネチャは `Initialize(string apiKey = null, string endpointUrl = null, string buildId = null, string playerId = null, bool enableOfflineQueue = true)` です。
ノート
`Initialize` は API キーを優先順に解決します。 まず空でない `apiKey` 引数、次に Inspector フィールド、最後に `FRAMEDASH_API_KEY` 環境変数の順です。 そのため CI やデスクトップのビルドでは、引数なしの `TelemetrySDK.Initialize()` を呼び出すだけで環境変数から認証できます。 環境変数は出荷するモバイル/コンソール/WebGL のビルドでは利用できないため、これらのプラットフォームの実行時に `FRAMEDASH_API_KEY` へ依存しないでください。 代わりに Inspector かプラットフォームのシークレットストアからキーを渡します。
## パフォーマンスデータの自動収集
[Section titled “パフォーマンスデータの自動収集”](#パフォーマンスデータの自動収集)
SDK は以下のデータを自動的に収集します:
* **FPS**: フレームレート
* **Frame Time**: フレームあたりの処理時間
* **Memory**: Unity Profiler の総割り当てメモリ
## カスタムイベントの送信
[Section titled “カスタムイベントの送信”](#カスタムイベントの送信)
```csharp
TelemetrySDK.Instance.Track(
eventName: "player_death",
mapId: "map_01",
position: transform.position);
```
カテゴリ属性や数値メトリクスを付与する場合は、オプションのディクショナリを渡します:
```csharp
// ファイルの先頭に 'using System.Collections.Generic;' が追加されていることを確認してください
TelemetrySDK.Instance.Track(
eventName: "player_death",
mapId: "map_01",
position: transform.position,
attributes: new Dictionary { { "cause", "fall_damage" } },
metrics: new Dictionary { { "health", 0f } });
```
## プレイヤーの識別 (任意)
[Section titled “プレイヤーの識別 (任意)”](#プレイヤーの識別-任意)
デフォルトではイベントは匿名で送信されます。プレイヤーのログイン後に `SetPlayerId` を呼び出すと、以降のイベントがそのプレイヤーに関連付けられます:
```csharp
TelemetrySDK.Instance.SetPlayerId(playerId);
```
DAU は空でないプレイヤー ID だけを数えます。匿名のままのセッションもイベント数とセッション数には反映されますが、DAU と MAU は増えません。プレイヤー単位 KPI に含めたいアクティビティより前に `SetPlayerId` を呼び出してください。
## ランタイムのサンプリングオーバーライド
[Section titled “ランタイムのサンプリングオーバーライド”](#ランタイムのサンプリングオーバーライド)
SDK はグローバルなサンプリングレート(既定は `1.0` = 全件保持)を適用します。 高頻度なイベントは、実行時にグローバルレートを上書きするイベント名ごとのレートを個別に設定できます。
```csharp
TelemetrySDK.Instance.SetEventSamplingRate("ai_pathfind_step", 0.05f); // 約 5%
TelemetrySDK.Instance.RemoveEventSamplingRate("ai_pathfind_step"); // グローバルに戻す
```
`SetEventSamplingRate(string eventName, float rate)` は指定イベントのレートを設定し、`rate` は \[0, 1] にクランプされます。 `RemoveEventSamplingRate(string eventName)` はそのオーバーライドを削除し、イベントをグローバルレートに戻します。 自動収集されるイベント(`session_start`、`perf_heartbeat`)はサンプリングの対象外です。
## マップロード時間の計測
[Section titled “マップロード時間の計測”](#マップロード時間の計測)
Unity SDK 0.1.3 以降で利用できます。 SDK はマップやレベルの読み込みにかかった時間を計測し、`map_load` イベントとして報告できます。 このロード時間はビルド比較(perf-diff)のリグレッションゲートと、ダッシュボードのロード時間チャートに使われます。
自分で制御するロードを `BeginMapLoad` / `EndMapLoad` で囲みます。
```csharp
TelemetrySDK.Instance.BeginMapLoad("Level_01");
// ... シーンを読み込む ...
TelemetrySDK.Instance.EndMapLoad();
```
`BeginMapLoad` は、ポーズやタイムスケールの影響を受けない単調増加クロックでタイマーを開始します。 `EndMapLoad` はそれを止めてイベントを送出します。 `EndMapLoad` の前に再度 `BeginMapLoad` を呼ぶと、保留中の計測は置き換えられます。
カスタムローダーやストリーミングローダーで既に時間を計測している場合は、その値を直接報告できます。
```csharp
TelemetrySDK.Instance.ReportMapLoad("Level_01", 1234f); // ロード時間(ミリ秒)
```
`ReportMapLoad` は、`loadTimeMs` が NaN、無限大、または負の値のとき、そのサンプルを丸ごと破棄します(クランプはしません)。
どちらの経路も、`metrics["load_time_ms"]` と `attributes["map_name"]` を持つ `map_load` イベントを送出します。 このイベントは意図的に `map_id` を空にしているため、空間ヒートマップとアクティベーションゲートの対象外になります。 これらの呼び出しはメインスレッドで実行され、例外を投げず、`Initialize` の前は何もしません。 カスタムローダーやストリーミングローダーがワーカースレッドで完了する場合は、`EndMapLoad` や `ReportMapLoad` を呼ぶ前にメインスレッドへ戻してください(たとえばプレイヤーループの更新や、捕捉した `SynchronizationContext` を使います)。 SDK はスレッドの受け渡しを代行しないため、別スレッドからの呼び出しはイベントを無言で破棄します。
ノート
SDK が `map_load` を組み立てて送出しますが、「自動」なのはイベントの組み立て方であって、保存される `source` の値ではありません。 `map_load` は開発者が起点となるイベント(`BeginMapLoad` / `EndMapLoad` を呼ぶ)なので、自分の `Track` 呼び出しと同じく `source=player` で記録されます。 `source=automated` を持つのは SDK 自身の内部イベント(`session_start`、`perf_heartbeat`)だけで、これは CI でも通常のプレイでも同じです。 `BeginAutomatedSession` はイベントの `source` を変えません。 セッションに `build_id` の上書きと `ci.*` 属性を付与します(このページの「CI / 自動セッション」を参照)。
## ディスク I/O メトリクス
[Section titled “ディスク I/O メトリクス”](#ディスク-io-メトリクス)
Unity SDK 0.1.3 以降で利用できます。 SDK はディスク読み取りのカウンターを、`io.read_bytes`、`io.read_time_ms`、`io.read_ops` というメトリクスキーで `perf_heartbeat` イベントに付与できます。 各値は前回の heartbeat からの差分で、実際にサンプルが取得できてから初めてキーが付きます(ゼロ埋めはしません)。 他のパフォーマンスメトリクスと同様に、`io.*` は perf-diff / builds-compare のリグレッションゲートとダッシュボードのチャートに使われます。 `io.*` のしきい値アラートはありません。
Unity Editor と Development Build では、SDK が `AsyncReadManagerMetrics` を自動的にサンプリングします。 リリースプレイヤーでは `io.*` の自動サンプルは収集されません。
## メモリカテゴリメトリクス
[Section titled “メモリカテゴリメトリクス”](#メモリカテゴリメトリクス)
Unity SDK 0.1.4 以降で利用できます。 SDK は heartbeat の周期でメモリカテゴリ別の使用量をサンプリングし、`perf_heartbeat` イベントに `mem.*` メトリクスとして自動的に付与します。 UE5 の `bTrackMemoryDetail` と違い、オプトインは不要です。
* **`mem.vram`**:グラフィックスドライバーが確保したメモリ(バイト)。`Profiler.GetAllocatedMemoryForGraphicsDriver` から読み取ります。
* **`mem.heap`**:マネージドヒープの使用量(バイト)。`Profiler.GetMonoUsedSizeLong` から読み取ります。
読み取り値が 0 のときは、そのキーを付けません。 キーがないことは未収集を意味し、`0` として送ることはありません。
これらのキーは `perf_heartbeat` に加えて、位置情報付き(`map_id` が空でない)イベントにも付与されます。 `perf_heartbeat` は `map_id` が空で空間ヒートマップのグリッドに入らないため、セルごとのメモリヒートマップを作れるよう、同じサンプルを位置情報付きイベントにも載せます。 位置情報付きイベントに載るのは heartbeat の周期で更新されるキャッシュ済みサンプルで、イベント経路ではエンジンを読み取りません。
呼び出し側が渡したメトリクスキーは、キーの衝突時も容量の面でも常に優先されます。 `mem.*` が埋めるのは取り込み上限(メトリクス 50 件)に残った枠だけで、まず `mem.vram` から入ります。
## エディター内 SceneView ヒートマップ
[Section titled “エディター内 SceneView ヒートマップ”](#エディター内-sceneview-ヒートマップ)
Unity SDK 0.1.4 以降で利用できます。 エディター専用の `Framedash.Editor` アセンブリが、Framedash の REST API からプロジェクトのマップと集計済みのヒートマップセルを取得し、Unity エディター内に表示します。
利用には `analytics:read` スコープを持つ読み取り用 API キー(Read API Key)とプロジェクト ID(Project ID)が必要です。 ゲームが使う書き込み専用の Ingest キーではありません。
Unity SDK 0.1.6 以降では、Read API Key を空のままにして、Unity を起動する前に `FRAMEDASH_ANALYTICS_API_KEY` を設定できます。環境変数の値は `UserSettings/` に保存されません。Read API Key を明示的に入力した場合は、その値が環境変数より優先されます。
取得したヒートマップセルは、記録されたワールド座標に合わせて SceneView に半透明のクアッドとして描画されます。 パッケージビルドやダッシュボードを開かずに、エディター内で空間ヒートマップを確認できます。
設定はプロジェクトごとに `UserSettings/` 以下へ保存されます。 この設定はパッケージに含まれず、バージョン管理にも追跡されません。
## 詳細ログ
[Section titled “詳細ログ”](#詳細ログ)
最初の統合では、詳細ログを有効にして送信を確認してください。
```csharp
TelemetrySDK.Instance.VerboseLogging = true;
```
フラッシュに成功すると `[Framedash] Flushed N events (HTTP 202)` を記録します。 `SetPlayerId` を呼ぶまでは、毎セッション `[Framedash] No player_id set. Events will be sent as anonymous...` という警告も記録されますが、これはエラーではなく情報通知です。 自動収集されるイベント(初期化時の `session_start` と 10 秒ごとの `perf_heartbeat`)は手動イベントと同じバッチにまとまるため、`Flushed N events` がトラックした件数より多くなることがありますが、これは重複ではなく想定どおりの挙動です。 イベントが届かない場合は[トラブルシューティング](/sdk/troubleshooting/)を参照してください。
## ヘッドレス / CI
[Section titled “ヘッドレス / CI”](#ヘッドレス--ci)
SDK は Unity のプレイヤーループ上で送信します。 `Flush` はコルーチンと `UnityWebRequest` を通して送信され、これらはループが回っている間しか進みません。 素の `Unity.exe -batchmode -executeMethod ...` は Edit モードで実行され、コルーチンが進まないため、イベントはバッファされますが送信されません。
CI からテレメトリを送るには、PlayMode テスト(Unity Test Framework)でプレイヤーループを回します。 Play モードに入って SDK を初期化し、イベントをトラックし、終了前にフラッシュが完了するだけの時間テストを走らせます。
```csharp
using System.Collections;
using Framedash;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.TestTools;
public sealed class TelemetrySmokeTest
{
[UnityTest]
public IEnumerator SendsAMarkerEvent()
{
TelemetrySDK.Instance.VerboseLogging = true;
// FRAMEDASH_API_KEY 環境変数からキーを読み取る。ソースにキーをハードコードしない。
TelemetrySDK.Initialize(buildId: "ci-smoke");
// グローバルの SamplingRate が 1.0 未満だと、マーカーはサンプリングで
// 落ちることがある一方、自動送信される session_start は HTTP 2xx を返すため、
// マーカーなしでもログ判定だけが通ってしまう(検証の偽陽性)。このイベントの
// レートを 1.0 に固定し、マーカーが必ず保持されるようにする。
TelemetrySDK.Instance.SetEventSamplingRate("ci_marker", 1f);
TelemetrySDK.Instance.Track(eventName: "ci_marker", mapId: "ci", position: default);
// 10 秒の自動 heartbeat 間隔を超えて待ち、perf_heartbeat を少なくとも 1 回
// 発火させてから、Flush() を最後の SDK 呼び出しにする。Flush() の後で何も
// トラックしないこと。既定のフラッシュ間隔(30秒)はこのテストより長いため、
// 明示的に送信を強制し、終了前に HTTP 送信の完了を待つ。
yield return new WaitForSeconds(12f);
TelemetrySDK.Instance.Flush(); // 最後のフラッシュ。イベント1件ではバッチ閾値に達しない
yield return new WaitForSeconds(3f); // 終了前の最小待機。遅い回線では送信が未完了のことがあるため、配信は下の HTTP 202 ログ行で確認する
}
}
```
注意
使い捨ての CI ランナーでは、最後の `Flush()` より後にトラックされたイベント(多くは 10 秒ごとの自動 `perf_heartbeat`)はオフラインキューに書き込まれ(`[Framedash] persisted N buffered event(s)`)、そのまま失われます。 キューが排出されるのは*次回*の初期化時だけで、使い捨てランナーではそれが訪れないためです。 プロセス終了前の最後の SDK 呼び出しを `Flush()` にして、その完了を待ってください(上記のとおり)。 そうすればバッファに何も残りません。 上の固定待機は下限であって保証ではありません。 回線が遅い、または失敗する環境では Unity のトランスポートがリクエストタイムアウトまで送信を続けることがあるため、`HTTP 202` のログ行が出て初めて配信済みとみなしてください(下記参照)。
このテストを Unity Test Framework がコンパイル・検出できるように、専用のアセンブリ定義が必要です。 次の `.asmdef` をテストファイルと同じ場所に置きます。
```json
{
"name": "Framedash.SmokeTests",
"references": [
"UnityEngine.TestRunner",
"Framedash.Runtime"
],
"includePlatforms": [],
"excludePlatforms": [],
"defineConstraints": ["UNITY_INCLUDE_TESTS"],
"precompiledReferences": ["nunit.framework.dll"],
"autoReferenced": false,
"overrideReferences": true
}
```
推奨レイアウトは、`.asmdef` とテストファイルをまとめて `Assets/Tests/PlayMode/` に置くことです。
```plaintext
Assets/
Tests/
PlayMode/
Framedash.SmokeTests.asmdef
TelemetrySmokeTest.cs
```
CI からは次のコマンドでテストを実行します。
```plaintext
Unity.exe -batchmode -nographics -projectPath -runTests -testPlatform PlayMode -testResults \results.xml -logFile -
```
Windows では、シェルが実際の終了を待つように起動してください。 `Unity.exe -batchmode ... -runTests` は約 2〜3 秒でシェルに戻りますが、エディターはそのまま動き続け、テストが終わるのはおよそ 20 秒後です。 そのため、戻ってすぐの終了コードを読むスクリプトは、偽の成功を受け取ります。 `Start-Process -Wait -PassThru` で起動し、終了したプロセスから終了コードを読み取ってください。
```powershell
$proc = Start-Process -FilePath "Unity.exe" -Wait -PassThru -ArgumentList @(
"-batchmode", "-nographics",
"-projectPath", '""',
"-runTests", "-testPlatform", "PlayMode",
"-testResults", '"\results.xml"',
"-logFile", '"\unity.log"'
)
if ($proc.ExitCode -ne 0) { throw "Unity tests failed (exit code $($proc.ExitCode))" }
$resultsPath = "\results.xml"
if (-not (Test-Path -LiteralPath $resultsPath)) { throw "Unity did not write test results" }
[xml]$results = Get-Content -Raw -LiteralPath $resultsPath
$testRun = $results.'test-run'
if (-not $testRun) { throw "Invalid test results XML format" }
$testCount = if ($testRun.testcasecount) { [int]$testRun.testcasecount } else { [int]$testRun.total }
if ($testCount -lt 1) { throw "Unity discovered zero PlayMode tests" }
```
`-Wait` は Unity が実際に終了するまでブロックし、`-PassThru` はプロセスを返すため、`$proc.ExitCode` がテスト結果(`0` = 成功)を反映します。XML の検査も同じく重要です。Unity はテストを 0 件しか検出しなくても正常終了する場合があるため、CI では少なくとも 1 件の結果を必須にしてください。 各パスは埋め込みの二重引用符で囲んでいるため(`'""'`)、空白を含むワークスペースのパス(たとえば `C:\build agent\game`)でも `Start-Process` の引数分割で壊れません。 `-logFile` は `-` ではなく実ファイルに向けて後から確認できるようにしてください。
テストが成功しただけでは、テレメトリが届いた証明にはなりません。 フラッシュがまだ送信中でも、あるいは失敗していても、テストは成功しうるからです。 パイプラインを成功とみなす前に、送信を確認してください。 Unity のログから、HTTP 202 を含むフラッシュ成功行を grep します。
```plaintext
[Framedash] Flushed N events (HTTP 202)
```
または、送信したマーカーイベントを [REST API](/api/overview/#querying-telemetry) で問い合わせます。 いずれかでイベントの到達を確認できたときだけ、パイプラインを成功とみなしてください。
CI では `FRAMEDASH_API_KEY` がキーを供給します。上のサンプルはこれに依存しており、キーをハードコードしません。`TelemetrySDK.Initialize(buildId: ...)`(上記)または引数なしの `TelemetrySDK.Initialize()` を呼び出します。
オフラインキューが有効な場合(既定)、イベントは正常終了時または一時的な送信失敗時にキューへ保存され、次の初期化時に送信されます。 強制終了ではバッファに残ったイベントが失われるため、CI ではキューに頼らず、プロセスを kill する前にログの `HTTP 202` 行を待ってください。 `enableOfflineQueue: false` の場合、フラッシュされなかったイベントはそのまま破棄されます。 詳細は[トラブルシューティング](/sdk/troubleshooting/)を参照してください。
## CI / 自動セッション
[Section titled “CI / 自動セッション”](#ci--自動セッション)
自動テストやプロファイリング実行では、セッション全体にタグを付け、各イベントが CI のビルドとその branch / commit / scenario を持つようにします。 テストのエントリーポイントで、自動セッション API を一度だけ呼び出します。
```csharp
using Framedash;
// 引数はすべて任意です。
TelemetrySDK.Instance.BeginAutomatedSession(
buildId: "build-123",
branch: "main",
commit: "abc1234",
scenario: "nightly");
// ... 自動シナリオを実行する ...
TelemetrySDK.Instance.EndAutomatedSession();
```
完全なシグネチャは `void BeginAutomatedSession(string buildId = null, string branch = null, string commit = null, string scenario = null)` です。 CI では `BeginAutomatedSessionFromEnvironment()` を使うと便利です。 これは `framedash run-profile-test` が書き出す環境変数 `FRAMEDASH_BUILD_ID`、`FRAMEDASH_GIT_BRANCH`、`FRAMEDASH_GIT_COMMIT`、`FRAMEDASH_TEST_SCENARIO` を読み取ります。
```csharp
TelemetrySDK.Instance.BeginAutomatedSessionFromEnvironment();
// ... 自動シナリオを実行する ...
TelemetrySDK.Instance.EndAutomatedSession();
```
自動セッションは、セッション内のすべてのイベントに `build_id` の上書きと `ci.branch` / `ci.commit` / `ci.scenario` 属性を付与します。 これがビルド比較(perf-diff)の CI ゲートに使われます。 イベントの `source` は変わりません。 SDK 自身の自動イベント(`session_start`、`perf_heartbeat`)は `source=automated` のまま、`Track` イベントは `source=player` のままで、これは CI でも通常のプレイでも同じです。 パイプライン全体は [CI プロファイリング](/concepts/ci-profiling/) を参照してください。
## 次のステップ
[Section titled “次のステップ”](#次のステップ)
* [データモデル](/sdk/data-model/): テレメトリデータの構造
* [トラブルシューティング](/sdk/troubleshooting/): イベントが表示されないとき
* [ヒートマップ](/concepts/heatmaps/): 収集データの可視化
# UE5 SDK
> Unreal Engine 5 プロジェクトへの Framedash SDK 統合ガイド。
Framedash UE5 SDK (C++ プラグイン) を使用して、パフォーマンステレメトリを自動収集する方法を説明します。
## 要件
[Section titled “要件”](#要件)
* Unreal Engine 5.3 以上
* Blueprint-only プロジェクトは、対応するコンパイル済みパッケージで利用可能(ソースビルドには C++ プロジェクトとツールチェーンが必要)
ノート
公開ミラーはエンジンバージョンを固定しないソースプラグインですが、GitHub と Fab のパッケージには、記載されたエンジンと対象プラットフォーム向けのコンパイル済み Binaries が含まれます。現在の SDK は UE 5.3、5.4、5.5、5.6、5.7、5.8 でビルド検証済みです。`5.3-5.8` は検証済みの範囲であり、上限ではありません。UE 5.3 では `IHttpBase::GetEffectiveURL` がないため、認証情報漏えいにつながるクロスオリジンリダイレクト検出のみコンパイル時に無効化されますが、それ以外の SDK 機能には影響しません。
## インストール
[Section titled “インストール”](#インストール)
Blueprint-only プロジェクトには、[Fab の公開ページ](https://www.fab.com/listings/499f7c1f-c3db-41f2-9291-5371e10540ef) または [GitHub Releases ページ](https://github.com/crane-valley/framedash-ue5-sdk/releases) のコンパイル済みパッケージを使います。使用するエンジンと対象プラットフォームに合うパッケージを選んでください。GitHub では UE 5.3〜5.8 向けの `framedash-ue5-v-ue.zip`(例: UE 5.6 なら `-ue5.6`)を配布しており、Win64 向けのコンパイル済み Binaries を含むため、Launcher 版エンジンのプロジェクトはリビルドなしで利用できます。
ソースからビルドする場合や、コンパイル済みパッケージが対象としていないプラットフォーム向けには、[公開ミラー](https://github.com/crane-valley/framedash-ue5-sdk)をクローンします。この経路では C++ プロジェクトとツールチェーンが必要です。ソースの `Framedash.uplugin` はエンジンバージョンを固定していないため、`Framedash.Build.cs` が対応する全プラットフォーム(Win64 / Mac / iOS / Android / Unix)でビルドできます:
```plaintext
git clone https://github.com/crane-valley/framedash-ue5-sdk.git
```
その後、プロジェクトに追加します:
1. プラグインを `Plugins/Framedash` ディレクトリに配置
2. `.uproject` に追加:
```json
{
"Plugins": [
{
"Name": "Framedash",
"Enabled": true
}
]
}
```
3. プロジェクトに C++ モジュールがあり、C++ からプラグインを呼び出す場合は、その `Build.cs` にモジュール依存を追加:
```csharp
PrivateDependencyModuleNames.Add("Framedash");
```
4. ソースプラグイン、ソースビルド版エンジン、またはコンパイル済みパッケージの対象外プラットフォームを使う場合はプロジェクトをリビルド
ノート
対応するコンパイル済みパッケージを使う Blueprint-only プロジェクトでは、手順 3 と 4 は不要です。プラグインを有効にし、求められた場合はエディターを再起動して、初期設定へ進んでください。
ノート
C++ から呼び出す場合、手順 3 を省略すると `#include "FramedashSubsystem.h"` でコンパイルエラーになります。Blueprint-only プロジェクトには、このモジュール依存は必要ありません。
## 初期設定
[Section titled “初期設定”](#初期設定)
ノート
UE5 プラグインにテレメトリ用の `ProjectId` 設定はありません。 プロジェクトは指定した API キーから推定されるため、以下の ingest 設定にプロジェクトを入力する項目はありません。 (**Project Settings > Plugins > Framedash Heatmap** にある **Project ID** は、エディターの Heatmap タブが使う読み取り API 専用で、テレメトリ送信には関係しません。)
### 方法 A: 自動初期化(推奨)
[Section titled “方法 A: 自動初期化(推奨)”](#方法-a-自動初期化推奨)
`DefaultGame.ini` に以下を追加すると、サブシステム起動時に自動で初期化されます:
```ini
[/Script/Framedash.FramedashSettings]
ApiKey=your-api-key
bAutoInitialize=True
```
注意
Unreal の設定リーダーは、値の前後にある対の二重引用符を取り除きます。 そのため、引用符で囲むのは、パーサーが誤って扱う文字を含む値だけにしてください。 とくに URL の `//` は、Unreal がインラインコメントの開始とみなして値を切り詰めます(下の `EndpointUrl` を参照)。 API キーにはそうした文字がないので、いちばん確実な書き方は引用符なしの `ApiKey=your-api-key` です。
オプションで `BuildId`、`SamplingRate`、`PlayerId` も設定可能です:
```ini
[/Script/Framedash.FramedashSettings]
ApiKey=your-api-key
bAutoInitialize=True
BuildId=1.0.0
SamplingRate=1.0
PlayerId=player-123
```
`PlayerId` は開発者が指定するプレイヤー識別子です。 空のままにすると、イベントは匿名として送信され、SDK は `No player_id set. Events will be sent as anonymous.` とログに出力します。
コンパイル済みのデフォルト `EndpointUrl` はすでに `https://ingest.framedash.dev/v1/events` を指しているため、ローカルまたはセルフホストの ingest エンドポイントを使う場合のみ設定が必要です。その場合は値を二重引用符で囲んでください:
```ini
EndpointUrl="https://ingest.framedash.dev/v1/events"
```
注意
Unreal の INI パーサーは `//` をコメントの開始として扱い、それ以降をすべて削除します。引用符で囲まない `EndpointUrl=https://...` は `https:` としてのみ読み取られ、SDK はすべてのイベントバッチを無言で破棄します。INI ファイルでは URL を必ず引用符で囲んでください。
これらの設定は **Project Settings > Plugins > Framedash** からも編集できます。
C++ から初期化コードを書く必要はありません。
注意
`DefaultGame.ini` は通常すでに Git で追跡されているため、ここに書いた `ApiKey` はコミットされ、履歴に残ります。 あとから `.gitignore` に加えても、追跡は外れず、キーも消えません。 キーは追跡対象の設定に置かないでください。 環境変数から初期化するか(下の方法 B は `FPlatformMisc::GetEnvironmentVariable` で `FRAMEDASH_API_KEY` を読み取ります)、コミット対象の設定を上書きする、追跡外のローカル設定にだけキーを置きます。 すでにコミットしてしまった場合は、`git rm --cached` でインデックスから外し、履歴に残るためキーをローテーションしてください。
### 方法 B: C++ から手動初期化
[Section titled “方法 B: C++ から手動初期化”](#方法-b-c-から手動初期化)
設定ファイルを使用せず、コードから直接初期化することもできます:
```cpp
#include "FramedashSubsystem.h"
void AMyGameMode::BeginPlay()
{
Super::BeginPlay();
if (auto* Subsystem = GetGameInstance()->GetSubsystem())
{
FString ApiKey = FPlatformMisc::GetEnvironmentVariable(TEXT("FRAMEDASH_API_KEY"));
Subsystem->InitializeTelemetry(ApiKey);
}
}
```
`InitializeTelemetry` には `EndpointUrl` と `BuildId` のオプション引数もあります。CI 環境で便利です:
```cpp
if (auto* Subsystem = GetGameInstance()->GetSubsystem())
{
FString ApiKey = FPlatformMisc::GetEnvironmentVariable(TEXT("FRAMEDASH_API_KEY"));
FString BuildId = FPlatformMisc::GetEnvironmentVariable(TEXT("FRAMEDASH_BUILD_ID"));
// EndpointUrl に空文字列を渡してデフォルト値を使用
Subsystem->InitializeTelemetry(ApiKey, TEXT(""), BuildId);
}
```
注意
UE5 のテンプレートプロジェクトは **Blueprint** の GameMode や pawn を設定していることが多く、Blueprint の `Event BeginPlay` は、**Parent: BeginPlay** ノードを追加しない限り C++ 親クラスの `BeginPlay` を呼びません。 初期化を C++ の基底クラスの `BeginPlay` に置いていると、Blueprint のサブクラスの下では無言のまま一度も実行されないことがあります。 Blueprint に **Parent: BeginPlay** の呼び出しを追加するか、基底クラスの `BeginPlay` オーバーライドに頼らず、ゲームモジュールから `UWorld::OnWorldBeginPlay` をフックしてください(GameMode のクラスに関係なく発火します)。
## 自動収集データ
[Section titled “自動収集データ”](#自動収集データ)
初期化が完了すると、以下のデータが自動的に収集されます:
* **FPS / Frame Time**: `stat unit` 相当のデータ
* **GPU Time**: RHI が利用可能な場合に報告する GPU フレーム時間
* **Memory**: プラットフォームが報告する使用中の物理メモリ
## カスタムイベント
[Section titled “カスタムイベント”](#カスタムイベント)
### 基本トラッキング
[Section titled “基本トラッキング”](#基本トラッキング)
```cpp
if (auto* Framedash = GetGameInstance()->GetSubsystem())
{
const FVector PlayerLocation(1000.0f, 2000.0f, 50.0f);
Framedash->Track(TEXT("player_death"), TEXT("Map01"), PlayerLocation);
}
```
### カスタム属性・メトリクス付き
[Section titled “カスタム属性・メトリクス付き”](#カスタム属性メトリクス付き)
追加のメタデータを付与する場合は `TrackWithData` を使用します:
```cpp
if (auto* Framedash = GetGameInstance()->GetSubsystem())
{
const FVector PlayerLocation(1000.0f, 2000.0f, 50.0f);
TMap Attributes;
Attributes.Add(TEXT("cause"), TEXT("fall_damage"));
TMap Metrics;
Metrics.Add(TEXT("health"), 0.0);
Framedash->TrackWithData(
TEXT("player_death"), TEXT("Map01"),
PlayerLocation, Attributes, Metrics);
}
```
## ランタイムのサンプリングオーバーライド
[Section titled “ランタイムのサンプリングオーバーライド”](#ランタイムのサンプリングオーバーライド)
グローバルな `SamplingRate`(プロジェクト設定)はすべての `Player` ソースのイベントに適用され、自動イベントはサンプリングの対象外です。 高頻度なイベントは、グローバルレートを上書きするイベント名ごとのレートを個別に設定できます。
```cpp
if (auto* Framedash = GetGameInstance()->GetSubsystem())
{
Framedash->SetEventSamplingRate(TEXT("ai_pathfind_step"), 0.05f); // 約 5%
Framedash->RemoveEventSamplingRate(TEXT("ai_pathfind_step")); // グローバルに戻す
}
```
`SetEventSamplingRate(const FString& EventName, float Rate)` はレートを \[0, 1] にクランプして設定し、`RemoveEventSamplingRate(const FString& EventName)` はそのオーバーライドを削除します。 どちらも Blueprint から呼び出せます。
## マップロード時間の計測
[Section titled “マップロード時間の計測”](#マップロード時間の計測)
UE5 SDK 0.1.6 以降で利用できます。 サブシステムはレベルの読み込みにかかった時間を計測し、`map_load` イベントとして報告できます。 このイベントはビルド比較(perf-diff)のリグレッションゲートと、ダッシュボードのロード時間チャートに使われます。 `BeginMapLoad`、`EndMapLoad`、`ReportMapLoad` はいずれも Blueprint から呼び出せます。
自分で制御するロードを囲みます。
```cpp
if (auto* Framedash = GetGameInstance()->GetSubsystem())
{
Framedash->BeginMapLoad(TEXT("Level_01"));
// ... レベルを開く ...
Framedash->EndMapLoad();
}
```
`BeginMapLoad` は、ポーズや time dilation の影響を受けない単調増加クロックでタイマーを開始します。 `EndMapLoad` はそれを止めてイベントを送出します。 `EndMapLoad` の前に再度 `BeginMapLoad` を呼ぶと、保留中の計測は置き換えられます。
カスタムローダーやストリーミングローダーで既に時間を計測している場合は、その値を直接報告できます。
```cpp
Framedash->ReportMapLoad(TEXT("Level_01"), 1234.0); // ロード時間(ミリ秒)
```
`ReportMapLoad` は、ロード時間が NaN、無限大、または負の値のとき、そのサンプルを丸ごと破棄します(クランプはしません)。
どちらの経路も、`metrics["load_time_ms"]` と `attributes["map_name"]` を持つ `map_load` イベントを送出します。 このイベントは意図的に `map_id` を空にしているため、空間ヒートマップとアクティベーションゲートの対象外になります。 これらの呼び出しはゲームスレッドで実行され、例外を投げず、初期化の前は何もしません。 カスタムローダーやストリーミングローダーがワーカースレッドで完了する場合は、`EndMapLoad` や `ReportMapLoad` を呼ぶ前にゲームスレッドへ戻してください(たとえば `AsyncTask(ENamedThreads::GameThread, ...)` を使います)。 SDK はスレッドの受け渡しを代行しないため、別スレッドからの呼び出しはイベントを無言で破棄します。
## ディスク I/O メトリクス
[Section titled “ディスク I/O メトリクス”](#ディスク-io-メトリクス)
UE5 SDK 0.1.6 以降で利用できます。 SDK はディスク読み取りのカウンターを、`io.read_bytes`、`io.read_time_ms`、`io.read_ops` というメトリクスキーで `perf_heartbeat` イベントに付与できます。 各値は前回の heartbeat からの差分で、実際にサンプルが取得できてから初めてキーが付きます(ゼロ埋めはしません)。 他のパフォーマンスメトリクスと同様に、`io.*` は perf-diff / builds-compare のリグレッションゲートとダッシュボードのチャートに使われます。 `io.*` のしきい値アラートはありません。
自動サンプリングはオプトインです。 **Project Settings > Framedash** で **Track Disk IO**(`bTrackDiskIo`、既定はオフ)を有効にすると、SDK は同期的なディスク読み取りを数える `IPlatformFile` ラッパーを連結します。 IoDispatcher / IoStore の経路(zen loader、Nanite ストリーミング)が処理する読み取りはこのラッパーを迂回するため、Nanite が多い I/O ではカウンターが少なめに出ます。
`ReportIoSample` は Blueprint から呼び出せ、この設定に関係なくサンプルを供給します。
```cpp
if (auto* Framedash = GetGameInstance()->GetSubsystem())
{
Framedash->ReportIoSample(/*Bytes=*/1048576, /*ReadTimeMs=*/3.2, /*Ops=*/12);
}
```
## メモリ内訳メトリクス
[Section titled “メモリ内訳メトリクス”](#メモリ内訳メトリクス)
UE5 SDK 0.1.7 以降で利用できます。 **Track Memory Detail**(`bTrackMemoryDetail`、既定はオフ)を有効にすると、SDK は heartbeat の周期でメモリカテゴリ別の使用量をサンプリングし、`perf_heartbeat` イベントに `mem.*` メトリクスとして付与します。
* **`mem.vram`**:RHI が報告する使用中のテクスチャメモリ(バイト、ストリーミング + 非ストリーミングのテクスチャ割り当ての合計)。`RHIGetTextureMemoryStats` から読み取り、特別な起動フラグなしにどの RHI でも利用できます。ヘッドレス / `-nullrhi` ビルドでは付与されません。
* **`mem.textures` / `mem.meshes` / `mem.audio`**:Low-Level Memory トラッカー(LLM)の各タグのバイト数。LLM がビルドに組み込まれ、かつ `-llm` 付きで起動された場合にのみ付与されます。LLM が無効なときは `mem.vram` のみが付きます。
追跡されていないカテゴリはキー自体が現れません(未収集を意味し、収集された `0` とは区別されます)。
これらのキーは `perf_heartbeat` に加えて、**位置情報付き(`map_id` が空でない)イベント**にも付与されます。`perf_heartbeat` は `map_id` が空で空間ヒートマップのグリッドに入らないため、セルごとのメモリヒートマップを作れるよう、同じサンプルを位置情報付きイベントにも載せます。 位置情報付きイベントに載るのは 10 秒周期の heartbeat で更新されるキャッシュ済みサンプルで、イベントごとのサンプリングは発生しません。 `TrackWithData` の `metrics` マップで自分の `mem.*` キーを渡した場合は、そちらの値が優先されます。
有効化は **Project Settings > Plugins > Framedash > Track Memory Detail**、または `Config/DefaultGame.ini` の `bTrackMemoryDetail=True` で行います。 既定はオフで、既定のセッションはゼロアロケーションのイベント経路を維持します。 `mem.vram` は perf-diff(ビルド比較)の比較対象メトリクスにもなります。
## エディター内クラウドヒートマップ
[Section titled “エディター内クラウドヒートマップ”](#エディター内クラウドヒートマップ)
UE5 SDK 0.1.7 以降で利用できます。 プラグインの `FramedashEditor` モジュールは、クラウドで集計済みのヒートマップをエディター内に取得・表示する **Framedash Heatmap** タブを追加します。 **Window メニュー > Framedash > Framedash Heatmap** から開きます。
はじめに **Project Settings > Plugins > Framedash Heatmap** で、読み取り用 API キー(Read API Key、`analytics:read` スコープ)とプロジェクト ID(Project ID)を設定します。 API Base URL の既定値は `https://app.framedash.dev` です。
UE5 SDK 0.1.11 以降では、Read API Key を空のままにして、Unreal Editor を起動する前に `FRAMEDASH_ANALYTICS_API_KEY` を設定できます。環境変数の値はエディター設定へ保存されません。Project Settings に Read API Key を入力した場合は、その値が環境変数より優先されます。
パネルでは次の操作ができます。
* マップ一覧の取得と選択
* 期間(日数)、セルサイズ、イベント名フィルターの指定
* クラウドからの集計済みヒートマップセルの取得
* 取得したヒートマップ全体が収まるようにレベルビューポートをフレーミング
UE5 SDK 0.1.13 以降では、Play-in-Editor(PIE)以外の状態でデータを取得し、表示したい各レベルビューポートの **Show > Framedash Heatmap** を有効にします。Show フラグは既定でオフで、ビューポートごとに独立しています。プレイテストを妨げないようPIE中はヒートマップが一時停止し、PIE終了後に各ビューポートの以前の選択が復元されます。
計測済みZ座標を持つセルは、その高さにクラウドボクセルとして表示され、2Dレスポンスは平面のまま表示されます。ヒートマップはビューポートのメインシーンパスで描画されるため、通常のF9スクリーンショットと高解像度ビューポートスクリーンショットの両方に写ります。
## 詳細ログ
[Section titled “詳細ログ”](#詳細ログ)
SDK は `LogFramedash` カテゴリにログを出します。 統合中に送信を確認するには、詳細ログを付けてゲームを起動します。
```plaintext
-LogCmds="LogFramedash Verbose"
```
コンソールから `Log LogFramedash Verbose` で実行時に有効化することもできます。 送信時は `SendBatch: N events -> https://ingest.framedash.dev/v1/events` に続けて HTTP の結果を記録します。 イベントが届かない場合は[トラブルシューティング](/sdk/troubleshooting/)を参照してください。
## ヘッドレス / CI
[Section titled “ヘッドレス / CI”](#ヘッドレス--ci)
対話的なエディターセッションなしでゲームを実行するには(CI や検証のため)、まずエディターターゲットをビルドし、その後 null RHI でゲームを起動します。
プラグインを追加したら、コマンドラインからエディターターゲットをビルドします。 エディター UI は不要です。
```plaintext
"\Engine\Build\BatchFiles\Build.bat" Editor Win64 Development -Project="\.uproject"
```
続いて、null RHI でゲームモードを起動します。 `` は実在するフルマップパスに置き換えてください。 Third Person テンプレートでは、UE 5.3〜5.5 が `/Game/ThirdPerson/Maps/ThirdPersonMap`、5.6 以降が `/Game/ThirdPerson/Lvl_ThirdPerson` を提供します。
```plaintext
UnrealEditor-Cmd.exe .uproject -game -nullrhi -nosound -unattended -nosplash -stdout
```
`-game` は終わりのないゲームループを開始し、自分では終了しません。 CI では外部のタイムアウトやプロセス kill で実行を打ち切り、プロセスの終了ではなくログの HTTP 2xx 行を成功の合図として扱ってください。 `-unattended` と `-nosplash` を付けると、実行が非対話的になります。
ゲームは自分で終了しないため、フラッシュが完了する時間を確保したうえでプロセスを kill するタイムアウトで起動を包んでください。 最小構成の PowerShell ラッパー例:
```powershell
$fdArgs = '".uproject"','""',"-game","-nullrhi","-nosound","-unattended","-nosplash","-stdout"
$p = Start-Process -FilePath "UnrealEditor-Cmd.exe" -ArgumentList $fdArgs -PassThru
if (-not $p.WaitForExit(120000)) { $p.Kill() } # 120 秒で打ち切り。プロセスは自分では終了しない
```
パスの引数は埋め込みの二重引用符(`'".uproject"'`)で囲んでいるため、空白を含むプロジェクトパスでも `Start-Process` の引数分割で壊れません。 Linux ランナーでは代わりに `timeout 120 UnrealEditor-Cmd ...` を使います。 kill の前に HTTP 2xx 行が記録される余裕を持たせて上限を設定してください。 GNU の `timeout` は実行を打ち切ると終了コード 124 を返すため、成功判定は終了コードではなくログの HTTP 2xx 行で行い、そのログ確認が通れば 124 は想定どおりとして扱ってください。 macOS には既定で GNU の `timeout` がありません。 coreutils を入れて(`brew install coreutils`)`gtimeout` を使うか、上の PowerShell と同じく遅延後に kill する方法で起動を包んでください。
注意
ヘッドレス実行を `cmd /c start` などでバックグラウンド起動しないでください。 プロセスもログファイルも残らないまま、無言で失敗することがあります。 `UnrealEditor-Cmd.exe` を直接起動して(プロセスそのものをバックグラウンド化して)、`Saved/Logs` をポーリングする前にプロセスが生存していることを確認してください。
注意
検証用マーカーを送信する前に、そのイベント名に対して `SetEventSamplingRate(TEXT(""), 1.0f)` を呼び出してください。 グローバルの `SamplingRate` が 1.0 未満の場合、マーカーはサンプリングで無言のうちに落ちる一方、`session_start` は HTTP 2xx を返すため、検証が偽陽性で成功と判定されることがあります。
`-stdout` をパイプやリダイレクトに渡すと、ストリームがブロックバッファリングされます。 そのため、すでに成功している実行が停止したように見えることがあります(たとえば `Waiting on static mesh...` で固まっているように見えても、HTTP 202 はすでに発生しています)。 確実な記録は `Saved/Logs/.log` です。 このログから `SendBatch:` と `Batch sent successfully (HTTP` を grep してください。 これらの行は詳細ログが有効なときだけ出力されるため、起動時に `-LogCmds="LogFramedash Verbose"` を付けてください(上の[詳細ログ](#%E8%A9%B3%E7%B4%B0%E3%83%AD%E3%82%B0)を参照)。 標準出力をリアルタイムに解析する必要がある場合は `-FORCELOGFLUSH` を追加します。
ノート
Git-Bash / MSYS のシェルでは、先頭の `/Game/...` 引数が誤った Windows パスに変換され、紛らわしい `Failed to load package` エラーとして現れます。 コマンドの先頭に `MSYS_NO_PATHCONV=1` を付けるか、`cmd.exe` から実行してください。
オフラインキューが書き込まれるのは、正常なシャットダウンか一時的な送信失敗のときだけで、強制終了では書き込まれません。 フラッシュが完了する前に実行が正常にシャットダウンした場合は、バッファされたイベントが `Saved/Framedash/offline-queue.json` に書き込まれ、次の初期化時にワールドが tick した時点で送信されます。 一方、強制的な kill ではバッファに残ったイベントが失われるため、CI ではキューに頼らず、プロセスを kill する前にログの HTTP 2xx 行を待ってください。 フラッシュが済むまで実行を保つか、もう一度実行してキューを排出してください。 詳細は[トラブルシューティング](/sdk/troubleshooting/)を参照してください。
## エディター内クイックスタートサンプル
[Section titled “エディター内クイックスタートサンプル”](#エディター内クイックスタートサンプル)
プラグインには、セットアップを確認するためのサンプルが `Plugins/Framedash/Samples/InEditorQuickstart` に同梱されています。 対応するコンパイル済みパッケージを使えば、Blueprint レシピは Blueprint-only プロジェクトで動作し、C++ のコンパイルは不要です。 すでに C++ モジュールを持つプロジェクトでは、代わりに同梱の C++ アクター(`FramedashQuickstartActor`)をコピーしてコンパイルできます。
このサンプルは 2 つの前提を想定しています。
* `events:write` スコープを持つ Ingest API キー
* ダッシュボードの **Maps > Generate demo** で登録した `map_id`
どちらの経路でもプレイ時にマップに紐づいた `Track` イベントが送信され、これがダッシュボードでプロジェクトを有効化するきっかけになります。
### Blueprint レシピ
[Section titled “Blueprint レシピ”](#blueprint-レシピ)
`UFramedashSubsystem` は **Framedash** カテゴリで Blueprint から呼び出せるため、C++ を書かずに Blueprint グラフから有効化イベントを送れます。
1. **Level Blueprint**(**Blueprints > Open Level Blueprint**)を開き、**Event BeginPlay** ノードから始めます。
2. **Get Game Instance** を引き出し、続いて **Get Subsystem** ノードを追加してクラスを **Framedash Subsystem** に設定します。この出力ピンが `UFramedashSubsystem` のインスタンスです。
3. サブシステムのピンから **Track**(カテゴリ **Framedash**)を呼び出します。**Event Name** を `quickstart_ping` などに、**Map Id** を生成した `map_id` に、**Position** をレベル内の任意の位置(たとえば Player Start の位置)に設定します。`attributes` / `metrics` も付けたい場合は代わりに **Track With Data** を使います。
4. **Event BeginPlay** を **Track** の呼び出しにつなぎ、プレイ時に実行されるようにします。
**Play** を押すと、マップに紐づいた `Track` イベントがダッシュボードでプロジェクトを有効化します。
## CI / 自動セッション
[Section titled “CI / 自動セッション”](#ci--自動セッション)
自動テストやプロファイリング実行では、セッション全体にタグを付け、各イベントが CI のビルドとその branch / commit / scenario を持つようにします。 起動時に、自動セッション API を一度だけ呼び出します(`BuildId`、`Branch`、`Commit`、`Scenario` はいずれも任意の `FString` で、メソッドは Blueprint からも呼び出せます)。
```cpp
if (auto* Framedash = GetGameInstance()->GetSubsystem())
{
Framedash->BeginAutomatedSession(
/*BuildId=*/TEXT("build-123"),
/*Branch=*/TEXT("main"),
/*Commit=*/TEXT("abc1234"),
/*Scenario=*/TEXT("nightly"));
// ... 自動シナリオを実行する ...
Framedash->EndAutomatedSession();
}
```
CI では `BeginAutomatedSessionFromEnvironment()` を使うと便利です。 これは `framedash run-profile-test` が書き出す環境変数 `FRAMEDASH_BUILD_ID`、`FRAMEDASH_GIT_BRANCH`、`FRAMEDASH_GIT_COMMIT`、`FRAMEDASH_TEST_SCENARIO` を読み取ります。
```cpp
if (auto* Framedash = GetGameInstance()->GetSubsystem())
{
Framedash->BeginAutomatedSessionFromEnvironment();
// ... 自動シナリオを実行する ...
Framedash->EndAutomatedSession();
}
```
自動セッションは、セッション内のすべてのイベントに `build_id` の上書きと `ci.branch` / `ci.commit` / `ci.scenario` 属性を付与します。 これがビルド比較(perf-diff)の CI ゲートに使われます。 イベントの `source` は変わりません。 SDK 自身の自動イベント(`session_start`、`perf_heartbeat`)は `source=automated` のまま、`Track` イベントは `source=player` のままで、これは CI でも通常のプレイでも同じです。 パイプライン全体は [CI プロファイリング](/concepts/ci-profiling/) を参照してください。
## 次のステップ
[Section titled “次のステップ”](#次のステップ)
* [データモデル](/sdk/data-model/): テレメトリデータの構造
* [トラブルシューティング](/sdk/troubleshooting/): イベントが表示されないとき
* [CI プロファイリング](/concepts/ci-profiling/): 自動ビルドテスト