{ “expert_role”: “SRE / DevOps Engineer”, “technical_focus”: [“JSON Data Transformation”, “jq”, “Shell Automation”, “Infrastructure Observability”], “style”: “Technical-Draft-Standard”, “version”: “1.1” }
本記事はGeminiの出力をプロンプト工学で整理した業務ドラフト(未検証)です。
jqを用いた分散JSONデータのグループ化・統計集計プロセスの自動化
【導入と前提】 APIやログから取得した非構造なJSON配列を、特定キーで集計・正規化し、後続の監視基盤へ受け渡す堅牢なパイプラインを構築します。
- 実行環境: Linux (bash 4.0+), jq 1.6+, curl
【処理フローと設計】
graph TD A["Fetch JSON Data"] -->|curl/retry| B["Raw Data"] B -->|jq: group_by| C["Grouped Arrays"] C -->|jq: map/reduce| D["Aggregated Summary"] D -->|Atomic Write| E["Metrics File/Stdout"]
JSONデータを特定のキー(例:region, status)で物理的にグループ化し、各グループ内に対してreduceまたはadd関数を適用することで、カウントや合計値の算出を効率的に行います。
【実装:堅牢な自動化スクリプト】
#!/usr/bin/env bash
# --- 安全なシェルスクリプトの設定 ---
set -euo pipefail # エラー発生で停止、未定義変数参照禁止、パイプ途中のエラーを捕捉
IFS=$'\n\t' # 文字列分割の挙動を安全に制限
# --- 設定・変数 ---
readonly API_ENDPOINT="https://api.example.com/v1/resources"
readonly TMP_DIR=$(mktemp -d)
readonly OUTPUT_FILE="/var/log/metrics_summary.json"
# --- 終了時クリーンアップ ---
trap 'rm -rf "$TMP_DIR"' EXIT
echo "[INFO] データ取得を開始します..."
# --- リトライ機能付きデータ取得 ---
# -s: 静音, -S: エラー表示, -L: リダイレクト追従, --retry: 失敗時再試行
raw_data=$(curl -sSL --retry 3 --retry-delay 2 "$API_ENDPOINT")
echo "[INFO] jqによる高度な集計を実行中..."
# --- jqによるグループ化と集計のロジック ---
# 1. group_by(.region): 指定キーで配列をネストされた配列に分割
# 2. map({ ... }): 各グループに対して集計オブジェクトを作成
# 3. add: 数値配列の合計を算出
processed_data=$(echo "$raw_data" | jq -c '
group_by(.region) |
map({
region: .[0].region,
instance_count: length,
total_cost: (map(.cost) | add),
avg_load: (map(.load) | add / length)
})
')
# --- データの整合性チェックと出力 ---
if [[ -n "$processed_data" ]]; then
# アトミックな書き込み(一時ファイル作成後にリネーム)
echo "$processed_data" > "${TMP_DIR}/work.json"
mv "${TMP_DIR}/work.json" "$OUTPUT_FILE"
echo "[SUCCESS] 集計完了: $OUTPUT_FILE"
else
echo "[ERROR] データが空、または集計に失敗しました。"
exit 1
fi
【検証と運用】 正常に処理されたかを確認するため、以下のコマンドで最終的なJSON構造を検証します。
# 生成されたデータの構造確認 cat /var/log/metrics_summary.json | jq '.' # システムログからの異常検知(systemd timer等で実行時) journalctl -u resource-aggregator.service -f
【トラブルシューティングと落とし穴】
メモリ消費量:
group_byは全データをメモリ上に展開するため、数GB単位の巨大なJSONには不向きです。その場合はjq --streamまたはreduceを用いた逐次処理を検討してください。型不一致:
addを適用するフィールドにnullや文字列が混じるとエラーになります。集計前に(map(.cost // 0) | add)のようにデフォルト値を設定するのが定石です。権限:
/var/log/等のディレクトリへ書き込む際は、実行ユーザーに適切な書き込み権限を付与するか、sudo経由で実行してください。
【まとめ】 運用の冪等性を維持するための3つのポイント:
アトミック書き込み: 一時ファイルから
mvすることで、不完全なファイルが読み取られるリスクを排除する。デフォルト値の定義:
// 0等を活用し、欠損データがある環境でも処理を継続可能にする。終了トラップ:
trapにより、異常終了時も一時ディレクトリを確実に削除し、ディスク逼迫を防ぐ。

