Telemetry の見方
WingStats Manager は 本人専用のローカル telemetry を取得しています (送信は一切しません)。 このページは「集めた event を実際にどう見るか」を 3 つの手段で説明します。
spec:
.spec-workflow/specs/local-telemetry/(リポジトリ内 spec。docs サイト外) 制約: 外部送信は絶対にしない。CI でyarn telemetry:network-gateがelectron/services/telemetry/配下に fetch / axios / http.request / sendBeacon 等が混入していないかを grep で検証する。
4 つの確認手段
| 手段 | 向き | 必要なもの | おすすめ度 |
|---|---|---|---|
| A1. アプリ内 Debug タブ (サマリ) | 日常の状況把握、件数 / カテゴリ / 直近エラーの観察 | アプリ起動だけ | ⭐⭐⭐ |
| A2. 詳細ウィンドウ (別ウィンドウ) | 全 record を filter / ページングで詳しく見たい / CSV エクスポート | アプリ起動 + Debug タブの「詳細を別ウィンドウで開く」 | ⭐⭐⭐ |
| B. JSONL ファイルを直接読む | 全 event を厳密に確認 / grep / awk 集計 / 過去日付の参照 | エクスプローラ + テキストエディタ or jq / PowerShell | ⭐⭐ |
| C. Chrome devtools (renderer 側) | renderer 内部の挙動を ad-hoc に確認したい時 | dev mode (yarn dev:electron) | ⭐ (開発時のみ) |
A1. アプリ内 Debug タブ (サマリ — 推奨)
- アプリを起動
- コントロールパネル → 「デバッグ・性能」タブ
- 上から 2 枚目のカード 「Telemetry (ローカル専用)」 を見る
確認できること:
- 過去 24 時間の 合計件数 と カテゴリ別内訳 (chip)
- 直近 error event 10 件 (時刻 / event 名 / where / message)
- browser-automation.login-check の count / 成功率 / 平均 ms
- match.saved の dataSource 内訳 (log / api / merged)
- 今日の JSONL ファイルパス (コピーボタン付き)
- **「詳細を別ウィンドウで開く」**ボタン → A2 を起動
- **「ディレクトリを開く」**ボタン (Explorer で
<userData>/logs/を開く) - 右上の 🔄 で再読込
配信中 / 本番中はタブを開かなければ計測はゼロです (Debug タブは active 時のみ計測)。
A2. 詳細ウィンドウ (別ウィンドウ — 全 record 探索)
Debug タブの「詳細を別ウィンドウで開く」ボタンから起動する独立ウィンドウ (telemetry.html / TelemetryDetailView)。main process の telemetry 読み取り API (listRecords / exportCsv) を IPC 経由で叩くため、サマリでは出てこない 全 record が見える。
使い方:
- Debug タブ → Telemetry カード → 「詳細を別ウィンドウで開く」
- ウィンドウ上部の 時間レンジ chip (1h / 6h / 24h / 3d / 7d) で対象期間を切替
- event (prefix) / sessionId / text 検索 に値を入れて 再検索
- テーブルの各行左の ▽ で展開すると 1 record の 生 JSON が見える
- 右上の CSV エクスポート で現在の filter 条件 (最大 5000 件) を CSV 保存
CSV の列: ts,sessionId,event,propsJson (propsJson はネストもそのまま JSON 文字列)。
詳細ウィンドウは singleton。既に開いていればボタンで focus されるだけで増殖しない。 Debug タブとは独立して残るので、main ウィンドウ側でタブを切り替えても閉じない。
B. JSONL ファイルを直接読む
ファイル場所
%APPDATA%\wingstats-manager\logs\telemetry-YYYY-MM-DD.jsonldev 版で legacy userData を踏んでいる場合は
%APPDATA%\streaming-overlay-manager\logs\telemetry-YYYY-MM-DD.jsonlどちらに書かれているかは Debug タブの「Telemetry」カードに表示される
currentFileで確実に分かる。
1 行 = 1 event の JSON
{
"ts": "2026-05-24T11:22:14.730Z",
"sessionId": "9a8b...e3",
"event": "browser-automation.login-check",
"props": { "ok": true, "ms": 312 },
"schemaVersion": 1
}スキーマ詳細は electron/services/telemetry/types.ts を参照。
PowerShell snippet
# 今日のファイル
$file = Join-Path $env:APPDATA "wingstats-manager\logs\telemetry-$(Get-Date -Format yyyy-MM-dd).jsonl"
# 全 event を読む
Get-Content $file | ForEach-Object { $_ | ConvertFrom-Json }
# カテゴリ別件数
Get-Content $file | ForEach-Object {
($_ | ConvertFrom-Json).event -replace '\..*$',''
} | Group-Object | Sort-Object Count -Descending
# error だけ取り出す
Get-Content $file | ForEach-Object {
$r = $_ | ConvertFrom-Json
if ($r.event -like 'error.*') { "$($r.ts) $($r.event) $($r.props | ConvertTo-Json -Compress)" }
}
# login-check の成功率
Get-Content $file | ForEach-Object {
($_ | ConvertFrom-Json)
} | Where-Object event -eq 'browser-automation.login-check' | ForEach-Object {
if ($_.props.ok -or $_.props.success) { 'ok' } else { 'fail' }
} | Group-Objectjq snippet (WSL / git-bash 等)
FILE="$APPDATA/wingstats-manager/logs/telemetry-$(date +%Y-%m-%d).jsonl"
# カテゴリ別件数
jq -r '.event | split(".")[0]' "$FILE" | sort | uniq -c | sort -rn
# error だけ取り出す
jq 'select(.event | startswith("error."))' "$FILE"
# 過去 1 時間の event
since=$(date -u -d "-1 hour" +"%s")
jq --argjson s "$since" 'select((.ts | fromdateiso8601) >= $s)' "$FILE"C. Chrome devtools (renderer)
dev mode (yarn dev:electron) で起動中なら、Manager ウィンドウで Ctrl+Shift+I で devtools を開いて Console に下記を貼る:
// 今日のサマリ
const s = await window.electronAPI.telemetry.getSummary(24);
console.log(s);
// ファイル情報
const i = await window.electronAPI.telemetry.getInfo();
console.log(i);
// ad-hoc event を打って動作確認
window.electronAPI.telemetry.track('error.renderer', { where: 'devtools-test', message: 'hello' });ただし renderer から見える範囲は IPC 経由のみ。main プロセスの直内部状態を直接 inspect したい場合は dev 起動時に electron --inspect 等を使う (詳細は割愛)。
診断バンドル(不具合報告用の zip export)
Debug タブ → Telemetry カードの 「診断バンドルを作成」 ボタンで、調査に必要なログ一式を サニタイズ済みの zip としてワンボタンで出力できる(spec: telemetry-error-reporting Phase 1 P1-b)。
- 含まれるもの:
telemetry-*.jsonl全世代(最大 14 日)/update.log・update-recorder.log・update-viewer.logと各.prev(プロセス別のログ) /env.json(version・mode・OS・Electron version) - 含まれないもの:
storageState.json(認証 token)/matches.db/user-settings.json。実装は<userData>/logs/以外を読まない構造(electron/services/diagnostics/DiagnosticBundleService.ts) - 追加マスク(
electron/services/diagnostics/sanitizeBundleText.ts): 同梱テキストに対してC:\Users\<名前>//home/<名前>→<HOME>- URL の query / fragment(token の載る経路)→
?<REDACTED> UID: 1046101022のようにラベル付きで出る UID →<UID>
- マスクされないもの:
update.log中のプレイヤー名は形式が定まらず機械的に落とせない。 telemetry JSONL 側は収集時点で hash6 化されているので影響を受けるのは update.log だけ。 公開 issue に添付する前に中身を一度眺めるようユーザーに案内する - 隣の 「GitHub で報告」 ボタンで issue 新規作成画面が開くので、生成した zip を添付して報告する
開発者にログを送る(アプリ内から直接送信)
同じカードの 「開発者にログを送る」 ボタンで、zip を手で添付せずに開発者へ直接送れる (spec: docs/superpowers/specs/2026-09-02-diagnostic-report-upload-design.md)。
- 症状カテゴリと「何をしていたら起きたか」(10 文字以上)が必須。連絡先は任意
- 送信前に「送信されるもの」の一覧・マスク件数・伏せられなかった名前の件数を表示し、 「中身を見る」でサニタイズ済みの実テキストを確認できる。同意チェックを入れるまで送信ボタンは無効
- 期間は既定で直近 3 日。変えるとプレビューを取り直し、同意もリセットされる
- 送信は押したときの 1 回だけ(自動リトライなし)。失敗時は理由別の文言を出し、ネットワーク系の 失敗ではローカルに zip を自動保存してその場所を表示する
- 成功すると受付番号
R-xxxxxxxxが出る。GitHub issue にはこの番号だけ貼ればよい - サーバ側の zip は 30 日で自動削除(設定タブの常時送信 90 日とは別)。送信先・保持期間・ マスクの限界はダイアログ内に明記している

受け側(Worker /v1/bundle / R2 / Discord 通知)の運用は telemetry-remote.md を参照。
telemetry を止めたい時
| 手段 | 方法 |
|---|---|
| 環境変数 | WINGSTATS_TELEMETRY=0 を立ててからアプリ起動 |
| CLI フラグ | WingStats Manager.exe --no-telemetry |
| ファイル削除 | <userData>/logs/telemetry-*.jsonl を削除すれば集計値が 0 になる |
止めても本体機能には影響しません (telemetry は append-only な観測専用のため)。
イベント一覧 (参考)
allowlist は electron/services/telemetry/types.ts の TelemetryEvent を参照。 本日時点で配線済みのものは:
| イベント | 発火場所 |
|---|---|
app.start | 起動 critical path 完了直後 |
app.quit | window-all-closed で flush |
app.crash | uncaughtException / unhandledRejection / render-process-gone / child-process-gone(AppLifecycle) |
error.main | uncaughtException、および main の Logger.error すべて(source: 'logger')。Logger.setErrorSink 経由で loggerErrorSink.ts が [Tag] を where に抽出し、role(manager / recorder / viewer)・Error の message / stack / code を付ける。同じ失敗は 10 分に 1 回、telemetry 自身のログは除外 |
error.renderer | renderer の window.onerror / unhandledrejection / TabErrorBoundary、および renderer の Logger.error すべて(where: 'logger:<entry>'。electronAPI ラッパーの IPC 失敗や ok:false が該当。60 秒 dedupe) |
error.unhandled-rejection | unhandledRejection |
error.rate-limit | IPC track が 100/sec を超えて drop した時 |
error.queue-overflow | TelemetryService queue が 1000 件超で drop した時 |
error.db-write | DB 書き込み失敗。起動時の DB 初期化(initDatabase / phase=startup・retry-after-delete)、試合保存(LogWatcherHandlers.saveToDb / MatchHandlers.*)、API レスポンス保存(BrowserAutomation.saveApiResponse)、battle detail の player 挿入 / battle_id 書き戻し(ApiResponseWriter.*)、reinitializeDatabase。props に SQLite の code(SQLITE_READONLY / SQLITE_BUSY 等)が入る |
error.login | ログインできない。source: 'browser' = checkLoginStatus が確認できず(method に timeout 等)、source: 'api' = battle-record API が not login を返した(endpoint 名) |
error.browser-automation | ブラウザ連携の失敗。BrowserAutomationService.onError を通るものすべて(起動 / URL 拒否 / Chrome 未検出 / ナビゲーション / ワークフロー)。where は start / running |
「ユーザーに影響する失敗は必ず届く」の担保
個別の track() 配線に頼らず、Logger.error を通るものは main / renderer とも自動で error.* になる (上の表の source: 'logger' / where: 'logger:*')。main には 100 か所超、renderer の electronAPI ラッパーにも多数の Logger.error があり、これまでは update.log に残るだけで開発者には届かなかった。 Recorder(GUI なし)や Viewer で黙って失敗するケースも、この経路で D1 に出る。
調査時は D1 で json_extract(props_json,'$.role') と '$.where' で絞る。役割別の典型:
| role | 出やすい失敗(where) |
|---|---|
| recorder | [Recorder](RecorderAutoStart の起動 / ログイン窓 / 全件同期)、[Watcher]、[DB] |
| viewer | [DB] の SQLITE_READONLY(read-only 接続への誤書き込み)、WS 接続 |
| manager | [DB]、[BrowserAutomation]、[Milestone]、更新チェック |
error.db-write / error.login / error.browser-automation はリモート送信の errors レベル(既定)に含まれ、 記録した瞬間に 5 秒後の早期送信が予約される(telemetry-remote.md)。 従来の browser-automation.error / browser-automation.login-check は errors レベルでは送られないため、 把握したい失敗はこの 3 つの error.* として別途記録している。 | browser-automation.start / .stop / .login-check / .error | BrowserAutomationService | | log-watcher.start / .stop / .phase-changed | LogWatcherHandlers | | match.detected / .saved / .skipped | LogWatcherHandlers | | api.fetch | BattleRecordApiClient(直叩き) | | api.response | responseListener(ブラウザ自動化) | | api.reconcile | MatchReconciler |
JSONL の保持期間は 14 日(TelemetryService の既定値。1 ファイル 20MB 上限は据え置き)。
関連
- リモート telemetry(opt-in 送信)の運用 — ユーザーから自動で届くエラーを D1 で調べる手順
- Tab Roles — なぜ Debug タブに置くか
- Local Telemetry Spec —
.spec-workflow/specs/local-telemetry/(要件 / 設計 / タスク) scripts/dev/telemetry-network-gate.ps1— network 送信パターン検出 (CI / pre-commit gate)