Skip to content

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 タブ (サマリ — 推奨) ​

  1. アプリを起動
  2. コントロールパネル → 「デバッグ・性能」タブ
  3. 上から 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 が見える。

使い方:

  1. Debug タブ → Telemetry カード → 「詳細を別ウィンドウで開く」
  2. ウィンドウ上部の 時間レンジ chip (1h / 6h / 24h / 3d / 7d) で対象期間を切替
  3. event (prefix) / sessionId / text 検索 に値を入れて 再検索
  4. テーブルの各行左の ▽ で展開すると 1 record の 生 JSON が見える
  5. 右上の 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.jsonl

dev 版で legacy userData を踏んでいる場合は

%APPDATA%\streaming-overlay-manager\logs\telemetry-YYYY-MM-DD.jsonl

どちらに書かれているかは Debug タブの「Telemetry」カードに表示される currentFile で確実に分かる。

1 行 = 1 event の JSON ​

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 ​

powershell
# 今日のファイル
$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-Object

jq snippet (WSL / git-bash 等) ​

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 に下記を貼る:

javascript
// 今日のサマリ
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.quitwindow-all-closed で flush
app.crashuncaughtException / unhandledRejection / render-process-gone / child-process-gone(AppLifecycle)
error.mainuncaughtException、および main の Logger.error すべて(source: 'logger')。Logger.setErrorSink 経由で loggerErrorSink.ts が [Tag] を where に抽出し、role(manager / recorder / viewer)・Error の message / stack / code を付ける。同じ失敗は 10 分に 1 回、telemetry 自身のログは除外
error.rendererrenderer の window.onerror / unhandledrejection / TabErrorBoundary、および renderer の Logger.error すべて(where: 'logger:<entry>'。electronAPI ラッパーの IPC 失敗や ok:false が該当。60 秒 dedupe)
error.unhandled-rejectionunhandledRejection
error.rate-limitIPC track が 100/sec を超えて drop した時
error.queue-overflowTelemetryService queue が 1000 件超で drop した時
error.db-writeDB 書き込み失敗。起動時の 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)