mcpField
M
macbook-metrics-setup

macbook-metrics-setup

github.com/davidondrejクラウド・DevOps4.2k96 回インストール今日更新
リポジトリ

macbook-metrics-setup について

macbook-metrics-setupは、Macの指標を長期にわたりローカルで収集する仕組みの構築方法を説明します。低負荷でシステムをサンプリングしてSQLiteに保存し、launchdによる定期実行と、プライベートGitHubリポジトリへのバックアップを扱います。

主な機能

  1. 01毎分のシステム指標収集
  2. 02測定データのSQLite保存
  3. 03collect、doctor、reportコマンド
  4. 04launchdによる収集の定期実行
  5. 05プライベートGitHubリポジトリへのDBバックアップ

活用シーン

  1. 01Macのシステムリソース変化の長期記録
  2. 02収集処理とサンプラーの動作確認
  3. 03指定期間の指標概要の確認
  4. 04DBスナップショットのプライベートリポジトリへの保存

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/davidondrej/skills --skill macbook-metrics-setup

インストール後、Claude Code で/macbook-metrics-setupを入力して読み込まれたか確認します。

詳細

MacBook メトリクスのセットアップ

自分で完全に管理できる、低オーバーヘッドで長期運用可能な Mac メトリクスコレクターの構築方法です。 クラウドもテレメトリーもアカウントも不要です。必要なのは、1 つのバイナリ、1 つの SQLite ファイル、2 つの launchd ジョブ、1 つのプライベート GitHub リポジトリだけです。

基本方針(構築前にお読みください)

  1. ローカルのみで、決定論的です。 コレクターはネットワークへの 呼び出しを一切行わず、LLM を使用せず、分析データも送信しません。誰でも コードを読んで、何が書き込まれるかを正確に把握できる必要があります。
  2. データはリポジトリの外部にある ~/Library/Application Support/<project>/ に保存します。再インストールや git 操作によって測定データが変更されることはありません。
  3. 低オーバーヘッドは必須要件です。 サンプルは 1 分に 1 回、リリースビルド、 LowPriorityIO を使用します。モニター自体が負荷の原因になってはいけません。
  4. 文書化されていない読み取り値は nullable のままにし、エラーを明示します。 GPU 使用率と SMC 温度の読み取りには、macOS のアップデートで動作しなくなる可能性のあるプライベートインターフェースを 使用します。値は nullable な列に保存し、エラーを表面化させてください。 値を捏造してはいけません。
  5. 決定事項は記録します。 アーキテクチャ上の選択はすべて docs/adr/ に ADR として記録し、 スキーマの変更はすべて docs/database/ に番号付きの SQL ファイルとして記録します。 エージェントと人間は、契約として ADR に従います。
  6. プロセス単位のトラッキングはオプトインです。 システム全体の収集を デフォルトとします。特定のアプリ(例:Electron IDE)の監視は、独自の ADR を通じてのみ追加する、 分離された別のコレクターです。

リポジトリ構成

Sources/<ProjectLib>/     # samplers, SQLite storage, report generation
Sources/<project-cli>/    # thin CLI: collect | doctor | report
launchd/                  # plist templates with __PLACEHOLDER__ tokens
scripts/                  # install.sh, uninstall.sh, sync.sh
docs/adr/                 # numbered architecture decision records
docs/database/            # numbered SQL migrations
backups/                  # git-tracked SQLite snapshots (written by sync)

Swift + SwiftPM が自然な選択です(ネイティブの IOKit/Mach API を使い、依存関係がゼロです)が、 このアーキテクチャはコンパイル言語であればどれでも利用できます。

データ収集

  • システム全体の CPU 使用率、GPU 使用率、メモリ(使用量/ワイヤード/圧縮済み/ メモリプレッシャー)、スワップ、ディスク容量と IO のバイト数/操作数カウンター、 ネットワークのバイト数/パケット数カウンター、バッテリー、サーマル状態、温度、ファン回転数をサンプリングします。
  • OS の累積カウンター(ディスク/ネットワーク)は、インターバルごとの差分として保存します。
  • 1 分に 1 行を SQLite に書き込みます(WAL モード)。1 年でも約 50 万行にすぎません。 長期間のレポートを高速化するには、15 分単位のロールアップテーブルを追加します。
  • CLI の動詞:collect(サンプルを 1 回取得して終了)、doctor(現在の読み取り値を表示し、 サンプラーの故障時には明示的に失敗)、report --hours N(テキストの概要)。

2 つの launchd ジョブ

どちらも ~/Library/LaunchAgents/ にあるユーザー用 LaunchAgent です。root も デーモンも不要です。テンプレートはリポジトリに保存し、install.sh でプレースホルダーを埋めます。

1. コレクター — 60 秒ごとに collect を指定してバイナリを実行します: RunAtLoad true、StartInterval 60、ProcessType Background、 LowPriorityIO true を設定し、標準出力/標準エラーを ~/Library/Logs/<project>/ に出力します。 プロセスは 1 秒未満で実行を終えて終了します。スケジューラーは launchd です (launchctl list で PID が -、ステータスが 0 と表示されていれば正常です)。

2. GitHub 同期 — 3 時間ごとに scripts/sync.sh を実行します (StartInterval 10800)。このスクリプトは次の処理を行います:

# snapshot safely while the DB is live, then normalize for git
sqlite3 "$db_path" ".backup '$tmp'"
sqlite3 "$tmp" 'PRAGMA journal_mode=DELETE;'   # fold WAL into one file
mv -f "$tmp" backups/metrics.sqlite3
# commit ONLY the backups path, skip if unchanged, push to a PRIVATE repo
git add backups && git commit -m "Backup metrics database $(date '+%Y-%m-%d %H:%M')" -- backups
git push origin HEAD

稼働中の WAL データベースを cp でコピーしてはいけません。必ず sqlite3 .backup を使用してください。 メトリクスから日々の活動パターンが分かるため、リポジトリはプライベートに保ってください。

install.sh のパターン

swift build -c release
# run the binary from Application Support, NOT the repo build dir,
# so rebuilds/branch switches never break the running job
install -m 755 .build/release/<project> "$data_dir/bin/"
install -m 644 launchd/<label>.plist ~/Library/LaunchAgents/
sed -i '' -e "s|__EXECUTABLE__|$binary|" ... "$agent_path"   # fill placeholders
plutil -lint "$agent_path"                                    # validate before loading
launchctl bootout "gui/$UID" "$agent_path" 2>/dev/null || true  # idempotent reinstall
launchctl bootstrap "gui/$UID" "$agent_path"

uninstall.sh はその逆を行います。両方のエージェントを bootout し、plist を削除します。 com.<yourname>.<project> のようなリバース DNS 形式のラベルを使用してください。

インストールの確認

launchctl list | grep <project>          # exit status 0 = last run OK
sqlite3 "$db" "SELECT datetime(MAX(timestamp),'unixepoch','localtime') FROM raw_samples;"
# must be under a minute old; also run the doctor verb

サンプルの取得が止まった場合は、まず ~/Library/Logs/<project>/stderr.log を確認してください。

オプション:分離されたアプリ単位のモニター

アプリを 1 つ(例:メモリリークのある Electron IDE)監視する場合は、独自のスキーマ、インストールスクリプト、 ADR を備えた、別のオプトイン型コレクターを追加します。バンドルパスでアプリのプロセスを特定し (名前の部分一致では特定しないでください)、proc_pid_rusage/proc_pidinfo でプロセス単位の CPU/RSS/ディスク IO を読み取ります。低コストで、root も不要です。 また、ループ内で ps を起動してはいけません。それ自体が既知の遅延原因です。

コメント