本番アクセスログから現実的な負荷テストシナリオを設計する方法

Development
スポンサーリンク
スポンサーリンク

はじめに

JMeterの基本的な使い方は JMeterとは?基本概念とインストール で、ブラウザ操作をシナリオとして記録する方法は シナリオ記録実践ガイド で解説しました。この2つを押さえれば、「動くシナリオ」は作れます。

ですが、負荷テストの担当者として実際に業務で向き合うと、もっと手前に大きな壁があることに気づきます。それは、**「そのシナリオ、本当に本番の使われ方に近いんですか?」**という問いです。

この記事では、筆者が実務のWebアプリケーション負荷テストで実際に行った、本番のApache access_logからアクセスパターンを抽出してシナリオ設計に反映させる工程を、AIエージェントとの実際のやり取りをベースに一般化してまとめます。検索してもほとんど情報が出てこない領域ですが、負荷テストの「結果の信頼性」を左右する、地味だが非常に重要な工程です。

社内情報の取り扱いについて:この記事で示すログ・画面名・IPアドレス・数値はすべて説明用のダミーデータです。実際に筆者が扱った本番データそのものは一切含まれていません。


スポンサーリンク

この記事で分かること

  • 「思いつきのシナリオ」がなぜ負荷テストの結果を無意味にしてしまうのか
  • 本番のApache access_logからgrepで実アクセスパターンを抽出する具体的な手順
  • 既存のExcel設計資料をAIエージェントに読み込ませてMarkdown化・再利用可能な形に構造化するアイデア
  • 抽出したアクセスパターンをJMeterのスレッドグループ・Think Time設定に落とし込む流れ
  • 本番ログを扱う上での注意点(アクセス権限・個人情報マスキング等)

スポンサーリンク

1. なぜ「思いつきのシナリオ」では負荷テストが意味をなさないのか

負荷テストのシナリオを作るとき、つい「よく使われていそうな画面」を経験と勘で並べてしまいがちです。ログイン→一覧画面→検索→詳細→ログアウト、のような「いかにもありそうな流れ」です。

しかし、これには大きな落とし穴があります。負荷テストは「本番に近い負荷をかけて、本番で起きうる問題を事前に見つける」ことが目的です。シナリオが実際の使われ方とズレていれば、以下のような事態が起こります。

  • 実際にはほとんど使われない画面に負荷をかけて「問題なし」と結論づけてしまう(本当のボトルネックを見逃す)
  • 逆に、実際には少人数しか同時操作しない画面を過大な同時ユーザー数でテストし、不要な改修コストをかけてしまう
  • 本番でよく発生する「検索条件を変えて何度も再検索する」といった連続操作を再現できず、DBキャッシュ効果込みの楽観的な結果しか得られない

筆者が担当した案件でも、最初は「画面ごとのアクセス数」を集計したExcelの調査資料(時間帯別・画面別のアクセス回数一覧)だけがあり、これをもとにシナリオを検討していました。ですが、AIエージェントに相談する中で次の指摘を受け、認識を改めることになりました。

画面アクセス数だけでは「その画面に何人がアクセスしたか」しか分かりません。負荷テストのシナリオ設計に必要なのは、それに加えて「操作順序」「操作間隔(Think Time)」「同時セッション数」の3つです。

つまり、集計済みのサマリーデータは「入口」に過ぎず、生のaccess_logまで遡って初めて実態に近いシナリオが組める、ということです。


2. 本番Apache access_logから実アクセスパターンを抽出する

ここからが本題です。本番のaccess_logは通常、数GB〜数十GB単位で溜まっているため、全量を持ち出すのは現実的ではありません。「何を知りたいか」から逆算して、必要な範囲だけをgrepで抜き出すのがポイントです。

2-1. access_logのフォーマットを確認する

まず対象システムのaccess_logがどのフォーマットで出力されているかを確認します。よくあるCombined Log Format+レスポンスタイム付与のパターンだと、以下のようなイメージになります(以下はすべて説明用のダミーデータです)。

10.0.0.23 - - [10/Aug/2026:09:03:12 +0900] "GET /dummy-app/order/init.do HTTP/1.1" 200 15234 187
10.0.0.23 - - [10/Aug/2026:09:03:34 +0900] "POST /dummy-app/order/search.do HTTP/1.1" 200 8123 342
10.0.0.45 - - [10/Aug/2026:09:03:36 +0900] "POST /dummy-app/receiving/regist.do HTTP/1.1" 200 512 1204

この1行から読み取れる情報は多いです。

項目読み取れる情報
送信元IPセッション(ユーザー)単位の追跡キー
タイムスタンプ操作間隔(Think Time)の算出元
URLパス画面・処理の遷移順序
HTTPメソッドGET=画面表示系、POST=検索・登録系の目安
末尾の数値(レスポンスタイム)性能ベースラインの把握、重い処理の特定

2-2. 抽出1:ピーク時間帯を丸ごと抜く(最優先)

まずは「その時間、同時に何人がどんなリクエストを投げていたか」の全体像を掴むため、ピークと思われる時間帯を丸ごと抽出します。

grep "10/Aug/2026:09:0" /var/log/apache2/access_log \
  > extract_access_log_0900-0910.log

日付・時刻の文字列パターンでgrepするだけなので単純ですが、「その時間帯に何件のリクエストが飛んでいたか」「業務系リクエストと静的リソース(css/js/img等)の比率」がすぐ見えるのが利点です。

2-3. 抽出2:アクティブなユーザー(IP)を特定する

次に、その時間帯で特にアクセス数が多かった送信元を洗い出します。awksort の組み合わせが定番です。

# 時間帯を絞ったログから、アクセス数の多い送信元IPトップ10を確認
grep "10/Aug/2026:09:" /var/log/apache2/access_log \
  | awk '{print $1}' | sort | uniq -c | sort -rn | head -10

このコマンド1本で、「その時間帯にヘビーに操作していたユーザー」の見当がつきます。負荷テストのシナリオで再現すべき「代表的な操作パターン」の候補が、ここから見えてきます。

2-4. 抽出3:特定ユーザーの1セッションを追跡し、操作フローを再現する

トップに挙がったIPを対象に、そのユーザーの全リクエストを時系列で抜き出すと、1人のユーザーが実際にどの画面をどんな間隔で操作していたかが丸ごと再現できます。

grep "10.0.0.23" /var/log/apache2/access_log \
  | grep "09:0" \
  > extract_access_log_user_10.0.0.23_09h.log

これを整理すると、以下のような「実測の操作フロー」が得られます(数値・画面名はすべて説明用のダミーです)。

09:03:12  /dummy-app/menu/init.do        (187ms)  メインメニュー表示
09:03:20  /dummy-app/menu/clickButton.do (98ms)   メニュー選択
09:03:34  /dummy-app/order/init.do       (245ms)  発注入力画面 起動
09:03:52  /dummy-app/order/search.do     (342ms)  ★検索実行(1回目)
09:04:29  /dummy-app/order/search.do     (318ms)  ★検索実行(2回目・条件変更)
09:04:41  /dummy-app/order/regist.do     (1204ms) ★登録処理

このレベルまで見えると、「画面表示→検索を複数回繰り返す→条件を変えて再検索→最後に登録」という現実的な操作単位のブロックが見えてきます。タイムスタンプの差分を取れば、操作間隔(Think Time)も実測値として算出できます。

区間実測間隔
メニュー表示→選択約8秒
選択→画面起動約14秒
起動→検索1回目約18秒
検索1回目→2回目約37秒
検索2回目→登録約12秒

「Think Timeは何となく30秒にしておく」ではなく、実測で「検索操作の間隔はおよそ20〜40秒」という根拠が持てるようになります。

2-5. Windows端末での代替手段

grepやawkが使える環境がない場合や、ログサイズが大きすぎて素直なgrepでは処理が重い場合は、PowerShellの Select-StringGet-Content +オブジェクト集計でも同様の集計が可能です。抽出済みのログをAIエージェントに読み込ませて、リクエスト数の分単位推移・IPごとの集計・レスポンスタイムのパーセンタイル(50%ile、90%ile等)まで一気に統計化してもらう、という使い方も実務では有効でした。人力でExcelに貼り付けて集計するより圧倒的に早く、かつ「異常値(極端に遅いリクエスト)」にも気づきやすくなります。


3. 抽出データが教えてくれるシナリオ設計の勘所

生ログを解析すると、Excelのサマリーだけでは分からなかった以下のような情報が見えてきます。

  • 書き込み系(登録・更新)処理の比率:DBへの書き込みを伴う処理は読み取り系より負荷が高いため、比率を正確に再現する価値が大きい
  • 同一画面への「検索を繰り返す」実務パターン:1回の検索で終わらず、条件を変えて何度も検索するのが実際の使われ方であるケースは多い。シナリオも1回のリクエストで終わらせず、ループさせて再現すべき
  • 異常に遅いリクエストの存在:CSV出力や大量データ処理など、一部のリクエストだけ突出して遅いケースがある。これは負荷テストのシナリオに含めるかどうかを意図的に判断する材料になる(含めないと本番相当の負荷にならないが、含めすぎるとテスト結果が偏る)

こうした「量」だけでなく「質」の情報が、実データを見ることで初めて手に入ります。


4. 既存のExcel設計資料をAIエージェントでMarkdown化・構造化する

もう一つ、実務で効果があった工程を紹介します。負荷テストのノウハウは往々にして過去の別システムでの実施手順がExcelにまとまっている形で社内に眠っています。今回のケースでも、別システムで過去に作成された「JMeterシナリオ作成手順書」(環境構築・シナリオ記録・実行方法などをシート分けしたExcel)がありました。

これをそのまま参照したかったのですが、AIエージェント(Kiro/Claude Code等のCLIエージェント)は標準ではExcelのバイナリ形式を直接読み取れません。ここで実務上有効だったアプローチが以下の2つです。

方法A:CSVに変換してから読み込ませる

Excel側で各シートを「CSV UTF-8」で書き出し、テキストファイルとして配置する方法です。シンプルですが、シートが多いと手間がかかります。

方法B:PowerShellのCOM経由でAIエージェントに直接読ませる

Windows環境であれば、PowerShellのCOMオブジェクト(New-Object -ComObject Excel.Application)を使ってExcelアプリケーションを裏で操作し、シートの内容をテキストとして取得できます。AIエージェントにこの手順を依頼すると、変換作業なしで元のExcelの構成(シート名・表形式)を保ったままMarkdownとして整理してもらえます。

実際には、以下のような構成で整理し直してもらいました。

# 対象システム JMeter負荷テスト手順書(Markdown化)

## 環境構築
- Java/JMeterのバージョン対応表
- インストール手順

## シナリオ作成時の注意点
- ループ実行しても問題ない操作かの確認
- 複数スレッドで同時実行しても問題ない操作かの確認
- 日付など、実施日に依存するパラメータの動的化方針

## シナリオ記録手順
- HTTPプロキシサーバーの設定〜記録〜復元までの手順

## 実行と計測
- スレッド数/Ramp-up/ループ回数の設定例
- 非GUIモードでのコマンドライン実行例

これにより、紙(Excel)でしか存在しなかった過去のノウハウが、AIエージェントが検索・参照できるMarkdown資料として再利用可能になり、新しい対象システム向けにカスタマイズする際の土台として使えるようになりました。「Excelは読めないから手打ちで転記する」という手間を省ける、という意味で地味に効果の大きい工程です。

補足:Excel内に埋め込まれた画像(スクリーンショットや図解)まではAIエージェントが自動で読み取れないケースが多く、その部分は別途チャットへの手動貼り付けなどで補完する必要がありました。表・テキスト情報の構造化は自動化できても、画像情報は人手を挟む前提で考えておくのが実務的です。


5. 抽出したアクセスパターンをJMeterシナリオに落とし込む

ここまでの解析結果を、実際のJMeterのスレッドグループ設定に反映していきます。

5-1. スレッド数・Ramp-up

「ユニークIP数=同時アクセスユーザー数」ではない点に注意が必要です。ある時間帯にアクセスしてきたユニークIPが多くても、その全員が同じ瞬間に操作していたとは限りません。実測のリクエスト密度(1分あたりのリクエスト数)と1ユーザーあたりの操作ペースから逆算し、「同時にアクティブだったであろうセッション数」を見積もったうえでスレッド数を決めます。

例)ユニークIP数が多くても、実際に同時にアクティブなセッションは
    その6〜8割程度に収まることが多い、という前提で調整する

5.2. Think Time(Uniform Random Timer)

2-4で実測した操作間隔をもとに、JMeterの「Uniform Random Timer」の最小値・最大値を設定します。「検索操作の間隔は実測で20〜40秒だった」であれば、そのままレンジとして反映できます。固定値(Constant Timer)ではなく、実測のばらつきをレンジで表現できるUniform Random Timerの方が、実際のユーザー行動に近いゆらぎを再現できます。

5-3. 操作比率の再現(Throughput Controller / 重み付け)

抽出したログから算出した「書き込み系〇%・照会系〇%・画面遷移系〇%」といった構成比を、JMeterの「Throughput Controller」や、コントローラを複数用意して実行頻度に重み付けする方法で再現します。1本のシナリオを全スレッドが同じ順序でなぞるのではなく、実測の比率に応じて「このスレッドは照会だけを繰り返す」「このスレッドは登録中心」といったユーザータイプ別のシナリオを複数用意し、それぞれの比率でスレッドを配分する構成が実態に近づきます。

5-4. テストデータのバリエーション

実測ログから、同じ処理でも複数のユーザーが異なる検索条件・入力データで操作していることが分かります。CSV Data Set Configで複数パターンのテストデータを用意し、スレッドごとに異なる値を使わせることで、DBキャッシュだけが効いてしまう非現実的に速い結果を避けられます。


6. 実務での注意点:本番ログの取り扱い

本番のaccess_logやアプリケーションログには、IPアドレス・ユーザーID・場合によっては入力データそのものが含まれます。負荷テストのために便利だからといって無造作に扱ってよいものではありません。実務では最低限、次の点を徹底しました。

  • アクセス権限の確認:本番ログの取得・閲覧は、情報システム部門などログへの正式なアクセス権限を持つ担当者が行い、許可されたメンバー以外に共有しない
  • 必要な範囲だけを抜き出す:全量をコピーせず、「対象時間帯」「対象IP」など目的に応じた範囲だけをgrepで抽出する(2章の手法はこの観点でも有効)。ログの持ち出し自体を最小化できる
  • 作業後の削除:解析用に一時的に抽出したログファイルは、シナリオ設計が完了したら削除する。ローカル端末や共有フォルダに残さない
  • 記事・資料化する際のマスキング:この記事のように社外に知見を共有する場合は、IPアドレス・画面名・URLパス・ユーザーIDなどをすべてダミーデータに置き換える(実データの数値そのものを転記しない)
  • 社内の情報管理規程の確認:本番ログの取り扱いに関するルールは組織によって異なるため、着手前に情報管理部門・上長に確認を取る

「実データに近づけたシナリオを作る」ことと「実データをそのまま扱う」ことは別問題です。目的を達成するのに必要な情報の粒度まで抽象化・匿名化してから手元に置く、という意識が重要になります。


まとめ

  • 画面アクセス数の集計だけでは、負荷テストのシナリオ設計には情報が不足している。操作順序・Think Time・同時セッション数まで踏み込む必要がある
  • 本番のApache access_logは、①時間帯 → ②アクティブユーザー → ③1セッションの操作フロー、という順に絞り込んでgrepすれば、現実的なボリュームで実アクセスパターンを抽出できる
  • 過去のExcel設計資料は、AIエージェント(PowerShell COM経由での読み取りなど)を使ってMarkdown化しておくと、次のプロジェクトでも再利用できる資産になる
  • 抽出したデータは、スレッド数・Think Time・操作比率・テストデータのバリエーションという形でJMeterシナリオに反映する
  • 本番ログはアクセス権限・保管期間・マスキングを徹底して扱う。実データに近づけることと、実データをそのまま持ち出すことは別問題

「思いつき」ではなく「実測」に基づいたシナリオを組めるようになると、負荷テストの結果そのものへの説得力が大きく変わります。

シナリオが実データに近づいてくると、次にぶつかるのが「JSESSIONIDなど動的な値をどう扱うか」という問題です。次の記事では、このsessionKeyの動的化でハマったポイントを実体験ベースで解説します。

👉 次のステップ:sessionKey動的化のハマりどころ

まだ読んでいない方は、基礎編もあわせてどうぞ。

コメント