{ “category”: “SRE_DEVOPS_TIPS”, “topic”: “JQ_ADVANCED_AGGREGATION”, “tools”: [“jq”, “bash”, “curl”], “version”: “1.0.0” }
本記事はGeminiの出力をプロンプト工学で整理した業務ドラフト(未検証)です。
jqを駆使したJSONログの高度な集計:group_byとreduceによる分析自動化
【導入と前提】
APIレスポンスやログのJSON配列を特定キーでグループ化・統計処理し、システム状態の可視化を自動化・堅牢化します。
OS: 汎用Linux (Ubuntu/RHEL等)
ツール:
jq1.6以上,curl7.0以上前提: 構造化されたJSON配列データ(例:クラウドのメトリクスやCIビルド履歴)の存在。
【処理フローと設計】
graph TD
A["JSON Input"] --> B["Map/Filter: 前処理"]
B --> C{"Aggregation Logic"}
C --> D["group_by: キーによる群構造化"]
C --> E["reduce: 累積・ハッシュ変換"]
D --> F["Summary Output"]
E --> F
前処理: 不要なフィールドを除去し、メモリ消費を抑えます。
group_by: 配列を特定のキーでソート・分割し、階層構造を作ります。
reduce: 配列を走査しながらオブジェクト(連想配列)を構築し、計算量を最適化します。
【実装:堅牢な自動化スクリプト】
#!/usr/bin/env bash
# --- 実行時エラー制御 ---
set -euo pipefail
IFS=$'\n\t'
# 一時ファイル管理
TMP_DATA=$(mktemp /tmp/api_response.XXXXXX.json)
trap 'rm -f "$TMP_DATA"' EXIT # スクリプト終了時に必ず削除
# --- 設定・ターゲット ---
# 例: GitHub APIから特定リポジトリのイベントを取得(ダミー)
API_URL="https://api.github.com/repos/stedolan/jq/events"
echo "INFO: データの取得中..."
# curlの堅牢な実行
# -s: 進捗非表示, -S: エラー表示, -L: リダイレクト追従, --retry: 失敗時再試行
if ! curl -sSL --retry 3 "$API_URL" -o "$TMP_DATA"; then
echo "ERROR: データの取得に失敗しました。" >&2
exit 1
fi
echo "INFO: 集計の実行 (group_by & reduce)..."
# --- 高度なjq処理 ---
# 1. group_by を使ったイベントタイプ別カウント
# 2. reduce を使ったメモリ効率の良い集計
cat "$TMP_DATA" | jq -r '
# 処理1: イベントタイプでグループ化してカウント
group_by(.type) | map({
type: .[0].type,
count: length
}) |
# 処理2: reduce を使い、特定ユーザーのアクション数をハッシュ化
(reduce .[] as $item ({}; .[$item.type] = $item.count)) as $summary |
# 最終的な構造化出力
{
generated_at: (now | strflocaltime("%Y-%m-%d %H:%M:%S")),
event_summary: $summary,
top_event: (group_by(.type) | sort_by(length) | last | .[0].type)
}
'
【検証と運用】
正常系の確認
スクリプトを実行し、標準出力に構造化されたJSONが返ってくることを確認します。
bash aggregate_logs.sh
ログ確認と監視
cronやsystemd timerで運用する場合、標準エラー出力を logger または journalctl に飛ばします。
# systemd ユニットでの確認例 journalctl -u my-jq-aggregator.service --since "1 hour ago"
【トラブルシューティングと落とし穴】
メモリ制限と
group_by:group_byは内部でデータをソートするため、巨大なJSONファイル(数GB)ではメモリを大量に消費します。その場合は、jq -cで一行ずつreduceを使ってストリーム処理することを検討してください。
型変換エラー:
- JSON内の数値が文字列として渡される場合、
tonumberを忘れると集計(add等)で実行時エラーが発生します。
- JSON内の数値が文字列として渡される場合、
機密情報:
curlでトークンを渡す際は、set -x(デバッグモード)を無効化するか、環境変数を直接出力しないように注意してください。
【まとめ】
運用の冪等性を維持するための3つのポイント:
入力データの不変性: 元データを加工せず、パイプラインの最終段で整形する。
アトミックな書き出し: 集計結果をファイルに保存する場合、一時ファイルに書き出してから
mvすることで中途半端な状態を防ぐ。スキーマ検証:
jq内でselect(has("target_key"))を使い、予期せぬ構造のデータが混入しても処理を継続または安全にスキップさせる。


コメント