メトリクスデータのエクスポート

metricsopspreproc の各サブコマンドはいずれも、機械処理向けの構造化出力フォーマットをサポートします。アドホックな分析には jq のような JSON プロセッサと組み合わせるか、データベースやダッシュボードに投入してください。

ファイルごとのメトリクスを JSON でエクスポートする

bca metrics \
    --paths src/ \
    -O json \
    --output-dir /tmp/metrics

これは解析対象のソースファイルごとに 1 つの JSON ファイルを /tmp/metrics/ 以下に書き出します。出力ファイル名は入力パスにフォーマットの拡張子を付加したものです — src/lib.rssrc/lib.json ではなく src/lib.rs.json になります。手で読むつもりなら --pretty を使ってください:

bca metrics -p src/ --pretty -O json --output-dir /tmp/metrics

実行全体をツリーではなく 1 つのファイルにまとめるには --output <file> を使います。単一の集約ドキュメント(ファイルごとの結果のトップレベル JSON 配列)を書き出します:

bca metrics -p src/ -O json --output /tmp/metrics.json

CBOR(-O cbor)は最もコンパクトなフォーマットですが、バイナリのため出力先(--output または --output-dir)が必要です。JSON、TOML、YAML は出力先が指定されない場合いずれも stdout にストリームでき、パイプラインに便利です。

bca diff で 2 つのメトリクス実行を比較する

bca diff は 2 つの JSON メトリクス実行を比較し、メトリクスごとに、どのファイルが変化したか(旧 → 新)に加えて、2 つのセット間で追加・削除されたファイルを報告します。各サイドは単一のファイル別 JSON ドキュメント、またはそれらのディレクトリツリー全体(metrics -O json --output-dir <dir> 形式が書き出すもの)なので、一般的なワークフローは 2 回の bca metrics 実行を別々のディレクトリへ出力することです:

# 「変更前」の状態を取得する。
bca metrics -p src/ -O json --output-dir /tmp/before

# ...変更を加える(例: tree-sitter 文法のバンプ)...

# 「変更後」の状態を取得して diff を取る。
bca metrics -p src/ -O json --output-dir /tmp/after
bca diff /tmp/before /tmp/after

出力はファイルごとの差分をメトリクス名でまとめます — bca list-metrics が出力するのと同じ名前です(cyclomaticcognitivesloc、…):

2 metric(s) changed, 1 added file(s), 0 removed file(s)

## Added files
  src/new_module.rs.json

## cyclomatic (2 change(s))
  src/lib.rs.json.sum  12 → 14
  src/lib.rs.json.max   4 → 6

## halstead (1 change(s))
  src/lib.rs.json.effort  5820.3 → 7104.9

便利なフラグ:

  • --format markdown はスティッキーな PR コメント向け、--format json は安定した機械可読スキーマ向け(CI コンシューマー)です。
  • --min-change <N> は絶対変化量が N 以上の差分のみを報告します(デフォルトの 0 はあらゆる変化を報告します)。
  • --metric <name>(繰り返し可能)は diff を特定のメトリクスに限定します。

--since で git ref と比較する

「コミットしていない変更はメトリクスに何をしたか?」という対話的なケースでは、--since <ref> が 2 回キャプチャする手間を省きます。変更前サイドとして git ref 時点のツリーを解析し、現在の作業ツリー(または明示的に指定した変更後サイドのツリー)と比較します:

# 変更前 = HEAD~1 時点のツリー。変更後 = 現在の作業ツリー。
bca diff --since HEAD~1 -p src/

# 変更後 = 作業ツリーの代わりに明示的なツリー(例: 2 つ目のチェックアウト)。
# 唯一の位置引数が変更後サイドになる。
bca diff --since main /path/to/other-checkout -p src/

--since は ref のツリーを一時ディレクトリに実体化し(git archive 経由)、それに対して同じメトリクスウォークを実行してから diff を取ります — 一時ツリーはエラー時も含めて自動的に削除されます。同じ -p/--paths-I/--include-X/--exclude の選択が両サイドに適用されるため、同一のファイルセットを解析します。選択パスはリポジトリルート相対で、相対パスでなければなりません。作業ツリー側は(ref の全ツリー git archive に合わせて)リポジトリルートに固定されるため、bca diff --since はどのサブディレクトリから実行しても同じ結果になります。絶対パスの --paths は拒否されます(終了コード 1)— 展開された ref ツリーを指せないためです。

ベストエフォートの bca check --since とは異なり、bca diff --since は明示的な要求です。解決できない ref、git の欠如、git 管理外の作業ディレクトリはハードエラー(終了コード 1)になります。--since は位置引数を最大 1 つ(変更後サイド)しか取りません。2 つ渡すとエラーです。

bca diff は成功時に 0 で終了します — ゲートではなく情報提供です — ただしオプトインの --exit-code フラグを渡すと、フィルタ後の diff が空でない場合に 2 で終了します。これは、文法バンプがメトリクスを退行させていないことの検証に使われていた、かつての json-minimal-tests + split-minimal-tests.py チェーンを置き換えるものです。utils/check-grammar-crate.py ヘルパーは現在、内部で bca diff を呼び出します。

ツリー全体から単一のメトリクスを取り出す

ストリームされた JSON 出力を jq と組み合わせて、ファイルごとに 1 つの値を抽出します:

bca metrics -p src/ -O json \
  | jq -c '{file: .name, mi: .metrics.mi.visual_studio}'

同じ考え方はどのメトリクスにも使えます — cyclomatic.sumcognitive.sumloc.sloc など。カタログを見るには bca list-metrics descriptions を実行してください。

実行時にメトリクスカタログを発見する

CLI を駆動するツールはメトリクス名をハードコードすべきではありません。バイナリに尋ねてください:

bca list-metrics                # 1 行につき 1 つの名前
bca list-metrics descriptions   # 名前 + 概要

これはコードジェネレーター、スキーマ定義、タブ補完に適した入力です。

オペランドとオペレーターを抽出する(Halstead)

ops はファイルごとに生のオペランド・オペレーターのリストを出力します。これは、組み込みレポートが示す範囲を超えた Halstead 系メトリクス計算への入力になります:

bca ops \
    --include "*.rs" \
    --paths src/ \
    -O json --pretty \
    --output-dir /tmp/ops

1 回の指定につきグロブ 1 つ。 --include--exclude は出現ごとにちょうど 1 つの値を取ります。複数のグロブにはフラグを繰り返してください(--include "*.rs" --include "*.py")。後続の位置引数パスが飲み込まれることはありません。= 形式(--include="*.rs")も使えます。

各出力ファイルは入力パスを /tmp/ops/ 以下にミラーします。

どちらのリストもソート済みなので、変更のないソースに対して ops を再実行するとバイト単位で同一の出力が得られます — 実行間で差分を取ったり、リポジトリにコミットしたり、キャッシュキーとして使ったりしても安全です。

ツリーからコメントを除去する

strip-comments は、コメント構文を理解しない下流のツールでもコードを利用できるようにソースを書き換えます。出力ルーティングには 3 つのモードがあります:

  • stdout(デフォルト)。 どちらのフラグもない場合、除去済みソースは stdout にストリームされます — パイプライン内の単一ファイルに最適です。
  • --output / -o <FILE>(単一ファイル)。 除去済みソースを <FILE> に書き出し、入力はそのまま残します。入力ファイルが 1 つの場合にのみ意味を持ち、--in-place とは相互排他です。
  • --in-place(複数ファイル)。 マッチした各入力ファイルをディスク上で書き換えます。ツリー全体にはこれを使ってください。--output とは相互排他です。
# コメントを除去した単一ファイルをストリーム出力する。
bca strip-comments --paths src/lib.rs

# 除去済みの単一ファイルを新しいパスに書き出す(入力は変更しない)。
bca strip-comments --paths src/lib.rs --output src/lib.stripped.rs

# src/ 内のすべての Python ファイルをインプレースで書き換える。
bca strip-comments --include "*.py" --paths src/ \
    --in-place

--in-place は破壊的です — 事前にツリーがコミット済みまたはバックアップ済みであることを確認してください。--in-place--output の両方を渡すのは使用方法エラーです。