jqによるインフラメトリクスの高度な集計自動化:group_byとreduceによるデータ構造化
【導入と前提】 APIから取得した肥大化したJSONを、サービス単位やステータス単位で集計・加工し、監視やレポート出力を堅牢に自動化します。
- 前提条件: OS: GNU/Linux (Ubuntu/CentOS等), ツール:
jq1.6+,curl7.x以上
【処理フローと設計】
graph TD A["JSON Data Source"] -->|curl| B["Raw JSON Data"] B -->|jq group_by| C["Nested Array by Key"] C -->|jq reduce| D["Aggregated Object"] D -->|Output| E["Report / Monitoring Alert"]
JSON配列を特定のキーでグルーピングし、その後reduce関数を用いて各グループの数値を合計、または特定のフラグをマージするパイプラインを構築します。
【実装:堅牢な自動化スクリプト】 以下は、クラウドサービスの使用量(仮)を取得し、サービス名ごとにコストを合算する実戦的なスクリプトです。
#!/usr/bin/env bash
# --- 安全設定 ---
set -euo pipefail
# -e: エラー発生時に即座に終了
# -u: 未定義変数の参照時にエラー
# -o pipefail: パイプ内のエラーを拾う
# --- 一時ファイルの管理 ---
TMP_RAW=$(mktemp)
trap 'rm -f "$TMP_RAW"' EXIT # 終了時に確実に削除
# --- 設定項目 ---
API_ENDPOINT="https://api.example.com/v1/metrics"
API_TOKEN="${API_TOKEN:-default_token}" # 環境変数から取得、デフォルト値設定
# --- データ取得 (リトライ処理付き) ---
echo "Fetching usage data..." >&2
curl -sSfL \
--retry 3 \
--retry-delay 2 \
-H "Authorization: Bearer ${API_TOKEN}" \
"${API_ENDPOINT}" -o "$TMP_RAW" || {
echo "Error: Failed to fetch data after retries." >&2
exit 1
}
# --- 高度なjq処理 ---
# 1. group_by(.service): サービス名で配列を分割
# 2. map({key: .[0].service, value: map(.cost) | add}): 各グループを{名前, 合計}に変換
# 3. from_entries: オブジェクト形式に整形
# 4. reduce: 最終的な集約(ここでは例として総計を計算)
echo "Processing data with jq..." >&2
cat "$TMP_RAW" | jq -r '
group_by(.service)
| map({
"service": .[0].service,
"total_cost": (map(.cost) | add),
"count": length
})
| {
"summary": .,
"grand_total": (reduce .[] as $item (0; . + $item.total_cost)),
"timestamp": now | strftime("%Y-%m-%dT%H:%M:%SZ")
}
'
# systemd-timerで使用する場合の注意:
# このスクリプトを定期実行し、結果をファイルに出力、またはzabbix-sender等に渡す
【検証と運用】
正常系の確認: サンプルJSONファイルを読み込ませ、出力が期待通りの階層構造(
summary配列とgrand_total)になっているか確認します。cat mock.json | jq -f script.jqログ確認:
systemd-timer等で実行している場合は、以下のコマンドで標準エラー出力(>&2)のログを確認します。journalctl -u my-usage-report.service -n 50
【トラブルシューティングと落とし穴】
null値の混入:
add関数はnullを含むとエラーになる場合があります。map(.cost // 0)のようにデフォルト値を設定してください。メモリ消費:
group_byは全データをメモリ上に展開してソートします。数GB単位のJSONを扱う場合はreduceのみを使用してストリーム処理(inputs)を検討してください。権限問題:
mktempで作成されるファイルのパーミッションに注意してください。通常は実行ユーザーのみ読み書き可能です。
【まとめ】 運用の冪等性と堅牢性を維持するための3要素:
エラーハンドリングの徹底:
set -o pipefailとcurlのリトライオプションを組み合わせ、中間状態での異常停止を防ぐ。スキーマの変化への耐性:
jq内で// 0や?(Optional chaining) を活用し、APIレスポンスの軽微な構造変更でスクリプトを落とさない。副作用の最小化:
trapによる一時ファイルのクリーンアップを徹底し、実行環境にゴミを残さない。
この記事の更新履歴
この記事は、生成AIを活用した自動レビュー・更新フローにより内容を見直し、必要な修正を反映しています。
2026年9月20日
- 削除記事冒頭の未検証ドラフトを示すメタデータと注記を削除しました。

