<p><!-- [META]
STYLE: SRE_EXPERT_DOC
FORMAT: MARKDOWN
REQUIRED_ELEMENTS: [HIDDEN_METADATA, DISCLOSURE_BADGE, MERMAID, SHELL_BEST_PRACTICE, TROUBLESHOOTING]
JQS_TOPICS: [group_by, reduce, aggregation]
-->
本記事は<strong>Geminiの出力をプロンプト工学で整理した業務ドラフト(未検証)</strong>です。</p>
<h1 class="wp-block-heading">jqを活用したJSONデータの高度なグループ化と集計の自動化手法</h1>
<h2 class="wp-block-heading">【導入と前提】</h2>
<p>APIレスポンスやログ等のJSON配列を、特定のキーで集計・要約してSREのモニタリング効率を向上させます。</p>
<ul class="wp-block-list">
<li><strong>実行環境</strong>: Linux (Ubuntu/RHEL等), <code>jq</code> 1.6以上, <code>curl</code></li>
</ul>
<h2 class="wp-block-heading">【処理フローと設計】</h2>
<div class="wp-block-merpress-mermaidjs diagram-source-mermaid"><pre class="mermaid">
graph TD
A["Raw JSON Data"] -->|jq 'group_by'| B["Nested Arrays by Key"]
B -->|jq 'map/reduce'| C["Aggregated Object"]
C -->|STDOUT| D["Summary Report / Alerting"]
</pre></div>
<p><code>group_by</code> で対象キーごとに配列を分割し、<code>map</code> と <code>reduce</code> を組み合わせて「合計」「平均」「カウント」などの集計処理を一括で行う設計です。</p>
<h2 class="wp-block-heading">【実装:堅牢な自動化スクリプト】</h2>
<p>以下は、クラウドのリソース使用量ログ(JSON)を取得し、サービス単位でコストを集計するスクリプトの例です。</p>
<div class="codehilite">
<pre data-enlighter-language="generic">#!/usr/bin/env bash
# ---------------------------------------------------------
# script: aggregate_resource_costs.sh
# description: JSON配列をサービス名でグループ化し、合計コストを算出する
# ---------------------------------------------------------
set -euo pipefail # エラー発生で停止、未定義変数参照禁止、パイプエラーの伝播
trap 'rm -f "$TMP_DATA"' EXIT # 終了時に一時ファイルを確実に削除
# 設定
readonly API_ENDPOINT="https://api.example.com/v1/billing/usage"
readonly TMP_DATA=$(mktemp) # セキュアな一時ファイルの作成
# 1. データ取得(リトライ処理付き)
echo "Fetching usage data..."
curl -s -S -L \
--retry 3 \
--retry-delay 2 \
-H "Authorization: Bearer ${API_TOKEN:-}" \
"$API_ENDPOINT" -o "$TMP_DATA" || { echo "Error: Failed to fetch data"; exit 1; }
# 2. jqによる高度な集計処理
# group_by(.service) : サービス名ごとに配列を分割
# map({...}) : 各グループに対して集計オブジェクトを作成
# reduce : (オプション) 更に大きな集計を行う場合に利用
echo "Aggregating data..."
jq -r '
group_by(.service) |
map({
service: .[0].service,
total_cost: (map(.amount) | add),
count: length,
average_usage: (if length > 0 then (map(.amount) | add) / length else 0 end)
}) |
sort_by(.total_cost) | reverse
' "$TMP_DATA"
# 3. 特定条件でのフィルタリング例 (reduce活用)
# 全サービスの総計を1つのオブジェクトで出す場合
echo "Calculating grand total..."
jq -r '
reduce .[] as $item (0; . + $item.amount) |
{grand_total: .}
' "$TMP_DATA"
</pre>
</div>
<h2 class="wp-block-heading">【検証と運用】</h2>
<h3 class="wp-block-heading">正常系の確認</h3>
<p>スクリプトを実行し、標準出力に整形されたJSONが表示されるか確認します。</p>
<div class="codehilite">
<pre data-enlighter-language="generic">./aggregate_resource_costs.sh | jq .
</pre>
</div>
<h3 class="wp-block-heading">ログ確認と異常検知</h3>
<p>システム構成に組み込む場合、<code>systemd-cat</code> を経由させることで <code>journalctl</code> での追跡が可能になります。</p>
<div class="codehilite">
<pre data-enlighter-language="generic"># systemdタイマー等で実行する場合のログ確認
journalctl -u resource-aggregation.service -f
</pre>
</div>
<h2 class="wp-block-heading">【トラブルシューティングと落とし穴】</h2>
<ol class="wp-block-list">
<li><p><strong>メモリ消費量</strong>:
<code>group_by</code> は入力全体をメモリ上に展開するため、数GB単位の巨大なJSONファイルを扱うとOOM(Out Of Memory)が発生する可能性があります。その場合は、<code>jq -c '.[]'</code> でストリーム処理を検討してください。</p></li>
<li><p><strong>型変換の失敗</strong>:
数値フィールドに文字列が混入している場合、<code>add</code> 演算子がエラーになります。<code>(.amount | tonumber)</code> のように明示的なキャストを推奨します。</p></li>
<li><p><strong>環境変数の保護</strong>:
<code>API_TOKEN</code> などの機密情報はスクリプト内にハードコードせず、<code>export</code> するか、CI/CDのSecretマネージャーから注入してください。</p></li>
</ol>
<h2 class="wp-block-heading">【まとめ】</h2>
<p>運用の冪等性と堅牢性を維持するための3つのポイント:</p>
<ol class="wp-block-list">
<li><p><strong>型安全性の確保</strong>: <code>tonumber</code> や <code>default(0)</code> を使い、不正なJSON入力でもスクリプトを落とさない。</p></li>
<li><p><strong>一時ファイルの管理</strong>: <code>trap</code> コマンドを使用して、異常終了時でもゴミを残さない。</p></li>
<li><p><strong>リトライロジック</strong>: ネットワークの瞬断に備え、<code>curl</code> の <code>--retry</code> オプションを適切に設定する。</p></li>
</ol>
本記事はGeminiの出力をプロンプト工学で整理した業務ドラフト(未検証)です。
jqを活用したJSONデータの高度なグループ化と集計の自動化手法
【導入と前提】
APIレスポンスやログ等のJSON配列を、特定のキーで集計・要約してSREのモニタリング効率を向上させます。
- 実行環境: Linux (Ubuntu/RHEL等),
jq 1.6以上, curl
【処理フローと設計】
graph TD
A["Raw JSON Data"] -->|jq 'group_by'| B["Nested Arrays by Key"]
B -->|jq 'map/reduce'| C["Aggregated Object"]
C -->|STDOUT| D["Summary Report / Alerting"]
group_by で対象キーごとに配列を分割し、map と reduce を組み合わせて「合計」「平均」「カウント」などの集計処理を一括で行う設計です。
【実装:堅牢な自動化スクリプト】
以下は、クラウドのリソース使用量ログ(JSON)を取得し、サービス単位でコストを集計するスクリプトの例です。
#!/usr/bin/env bash
# ---------------------------------------------------------
# script: aggregate_resource_costs.sh
# description: JSON配列をサービス名でグループ化し、合計コストを算出する
# ---------------------------------------------------------
set -euo pipefail # エラー発生で停止、未定義変数参照禁止、パイプエラーの伝播
trap 'rm -f "$TMP_DATA"' EXIT # 終了時に一時ファイルを確実に削除
# 設定
readonly API_ENDPOINT="https://api.example.com/v1/billing/usage"
readonly TMP_DATA=$(mktemp) # セキュアな一時ファイルの作成
# 1. データ取得(リトライ処理付き)
echo "Fetching usage data..."
curl -s -S -L \
--retry 3 \
--retry-delay 2 \
-H "Authorization: Bearer ${API_TOKEN:-}" \
"$API_ENDPOINT" -o "$TMP_DATA" || { echo "Error: Failed to fetch data"; exit 1; }
# 2. jqによる高度な集計処理
# group_by(.service) : サービス名ごとに配列を分割
# map({...}) : 各グループに対して集計オブジェクトを作成
# reduce : (オプション) 更に大きな集計を行う場合に利用
echo "Aggregating data..."
jq -r '
group_by(.service) |
map({
service: .[0].service,
total_cost: (map(.amount) | add),
count: length,
average_usage: (if length > 0 then (map(.amount) | add) / length else 0 end)
}) |
sort_by(.total_cost) | reverse
' "$TMP_DATA"
# 3. 特定条件でのフィルタリング例 (reduce活用)
# 全サービスの総計を1つのオブジェクトで出す場合
echo "Calculating grand total..."
jq -r '
reduce .[] as $item (0; . + $item.amount) |
{grand_total: .}
' "$TMP_DATA"
【検証と運用】
正常系の確認
スクリプトを実行し、標準出力に整形されたJSONが表示されるか確認します。
./aggregate_resource_costs.sh | jq .
ログ確認と異常検知
システム構成に組み込む場合、systemd-cat を経由させることで journalctl での追跡が可能になります。
# systemdタイマー等で実行する場合のログ確認
journalctl -u resource-aggregation.service -f
【トラブルシューティングと落とし穴】
メモリ消費量:
group_by は入力全体をメモリ上に展開するため、数GB単位の巨大なJSONファイルを扱うとOOM(Out Of Memory)が発生する可能性があります。その場合は、jq -c '.[]' でストリーム処理を検討してください。
型変換の失敗:
数値フィールドに文字列が混入している場合、add 演算子がエラーになります。(.amount | tonumber) のように明示的なキャストを推奨します。
環境変数の保護:
API_TOKEN などの機密情報はスクリプト内にハードコードせず、export するか、CI/CDのSecretマネージャーから注入してください。
【まとめ】
運用の冪等性と堅牢性を維持するための3つのポイント:
型安全性の確保: tonumber や default(0) を使い、不正なJSON入力でもスクリプトを落とさない。
一時ファイルの管理: trap コマンドを使用して、異常終了時でもゴミを残さない。
リトライロジック: ネットワークの瞬断に備え、curl の --retry オプションを適切に設定する。
ライセンス:本記事のテキスト/コードは特記なき限り
CC BY 4.0 です。引用の際は出典URL(本ページ)を明記してください。
利用ポリシー もご参照ください。
コメント