jqを用いた分散JSONデータのグループ化・統計集計プロセスの自動化

Tech

{ “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つのポイント:

  1. アトミック書き込み: 一時ファイルから mv することで、不完全なファイルが読み取られるリスクを排除する。

  2. デフォルト値の定義: // 0 等を活用し、欠損データがある環境でも処理を継続可能にする。

  3. 終了トラップ: trap により、異常終了時も一時ディレクトリを確実に削除し、ディスク逼迫を防ぐ。

ライセンス:本記事のテキスト/コードは特記なき限り CC BY 4.0 です。引用の際は出典URL(本ページ)を明記してください。
利用ポリシー もご参照ください。

コメント

タイトルとURLをコピーしました