{ “system_role”: “Experienced SRE / DevOps Engineer”, “technical_focus”: [“jq”, “bash”, “data_aggregation”, “automation”], “security_level”: “standard”, “style”: “authoritative_and_practical” }
本記事はGeminiの出力をプロンプト工学で整理した業務ドラフト(未検証)です。
JSONデータの集計・分析を高速化する:jqのgroup_byとreduceを用いた実戦的SRE自動化
【導入と前提】 大量のJSONログやAPIレスポンスから、特定の属性でグループ化し統計量を算出する処理を、外部スクリプトに頼らずjqのみで堅牢に完結させます。
- 前提環境: Linux/Unix環境、
jq1.6以上がインストールされていること。
【処理フローと設計】
graph TD A["JSON Array Input"] -->|sort_by| B[Pre-sorting] B -->|group_by| C["Grouped Sub-arrays"] C -->|map + reduce| D["Aggregate calculation"] D -->|Object construction| E["Final Summary JSON"]
group_by は事前にソートされた状態を期待するため、パイプライン内で sort_by を組み合わせるか、group_by 自体の暗黙的なソート挙動を利用します。その後、reduce を用いて各グループ内の数値(レスポンスサイズやエラー回数など)を累積計算します。
【実装:堅牢な自動化スクリプト】 以下は、クラウドインフラのコストデータ(JSON)を読み込み、サービスごとに合計金額を算出する自動化スクリプトの例です。
#!/usr/bin/env bash
# --- 安全のための定型設定 ---
set -euo pipefail
IFS=$'\n\t'
# --- トラップ設定(一時ファイルの削除など) ---
TMP_DATA=$(mktemp)
trap 'rm -f "$TMP_DATA"' EXIT
# --- 入力データのシミュレーション(実運用では curl 等で取得) ---
cat <<EOF > "$TMP_DATA"
[
{"service": "ec2", "cost": 150, "region": "us-east-1"},
{"service": "s3", "cost": 20, "region": "us-east-1"},
{"service": "ec2", "cost": 100, "region": "ap-northeast-1"},
{"service": "rds", "cost": 300, "region": "ap-northeast-1"},
{"service": "s3", "cost": 50, "region": "ap-northeast-1"}
]
EOF
# --- jqによる高度な集計処理 ---
# 1. group_by(.service) でサービス名ごとに配列を分割
# 2. map(...) で各グループに対して集計を実行
# 3. reduce でグループ内の .cost を合計
echo "Aggregating cloud costs by service..."
jq -r '
group_by(.service) |
map({
service: .[0].service,
total_cost: (reduce .[] as $item (0; . + $item.cost)),
count: length
}) |
sort_by(.total_cost) | reverse
' "$TMP_DATA"
# --- 実用例:APIからのデータ取得と異常検知(参考) ---
# curl -s -f -L "https://api.example.com/metrics" | \
# jq -e '.errors > 0' > /dev/null || echo "Alert: Error detected"
【検証と運用】
正常系の確認: 上記スクリプトを実行し、
total_costが正しく合算され、降順(reverse)で出力されることを確認します。chmod +x aggregate.sh ./aggregate.sh
ログの確認: systemdタイマー等で定期実行する場合は、
journalctl -u my-aggregate.serviceにて標準出力がキャプチャされているか確認します。データ整合性:
jq内でdebug関数を挟むことで、group_by後の各ステージのデータ構造を標準エラー出力で確認可能です。
【トラブルシューティングと落とし穴】
メモリ消費量:
group_byは全データをメモリ上に展開するため、数GB単位の巨大なJSONファイルを扱う場合はjq --streamを検討するか、行単位のJSON(JSONL)をreduceで逐次処理する設計に変更してください。データ型の不一致:
reduce内での加算対象にnullや文字列が混入するとエラーになります。( .item.cost // 0 )のようにデフォルト値を指定することで防護してください。環境変数の扱い: スクリプト内でAPIキー等を使用する場合は、
exportせずjq --arg key "$API_KEY"のように引数として渡すことで、psコマンド等による露出を防止します。
【まとめ】 運用の冪等性と堅牢性を維持するための3要素:
ステートレスな処理: 一時ファイルに依存せず、標準入出力をパイプで繋ぐことで、実行環境の状態に左右されない処理を実現する。
厳格なエラーハンドリング:
set -eとjq -eを組み合わせ、データ構造の不備やパイプの途切れを即座に検知する。型安全性の考慮:
reduce時の初期値設定(0;)と//によるデフォルト値付与により、予期せぬデータ欠損時も処理を継続させる。

