💨

サーバーのアクセスログをPythonで抽出して見える化した話

2024/07/27に公開

まえがき

とある案件でアクセスが急に増えて、サーバーが落ちてしまうという現象が起きていた。

なぜアクセス数が急増したか追っていくと

  • ユーザーがキーボードにものを置いてEnterが押しっぱなしになっていた
  • ユーザーがクリックやキーボード操作など何度も素早く行って、負荷が上がった
    ということが起きていた。

その後、フロントに連打対策を実装したため上記事象は発生しなくなったが、当時ログを見て解析することが手作業でかなり大変だったため、Pythonでほぼ自動化してアクセスの状況を見れるようにした話

環境

自分たちの扱っていた環境はAWSでEC2が構築されており、ロードバランサを介して2つのWebサーバーが動いていた。ロードバランサは半分ずつの割合でWebサーバー1かWebサーバー2に割り振っている。

つまり、どちらのサーバーにも常にアクセスがある状態であるため、アクセスログ解析する時は両方のサーバーのログを1つにしてみるようにする必要がある。

実装方針

まずは、サーバーのログを見ないといけないが、サーバー上でゴニョゴニョするのは、間違えた時にサーバーに危害を加えるリスクがあるため、ログはサーバーからローカルにダウンロードして解析する方針にした。

大方針は以下のように考えた。

  1. Pythonにてサーバーにアクセスしてログをローカルにダウンロード
  2. ダウンロードしたログを解析して、2つのサーバーのログを1つにする
  3. ログを見やすくするために可視化

実際の実装

WebサーバーはApacheで動いていたため、Apacheログを取得するようにした。
リアルタイムのログを取得する場合は、最新のログのみ取得
過去ログを含めてある程度の期間を取得する場合は、サーバー上に約1ヶ月分ログが残っているため全てを取得するようにした。

なお、ログローテーションが組まれており、ログは1日経つと圧縮される。1ヶ月以上経ったログはS3にコピーされて、サーバー上から消える仕組みになっていた。

Apacheログは素の状態だとかなり扱いにくいため、Pythonにて項目を分割後、2つのサーバーのログを1つにして、pandasのDataframeの形式で一旦保存するようにした。
ApacheログはGETやPOSTなどのすべての記録が残っているため、かなりデータ量が多い。
ある程度細分化して保存しないと1つのファイルサイズが大きくなり扱いにくくなってしまう。

一旦、日付ごとDataframeを残す方針にして1つのファイルサイズは数百MBとなるようにした。

データ解析する際も狙いの日付で起こったことを調べたい場合は、その日付のDataframeを読み込んで解析すれば良いし、数日分なら複数読み込んで結合すれば良いし、何より数百MBのDatafmeを読み込むのにも数秒で終わるため、あれやこれやと考えながら行うデータ解析作業がやりやすい。

今のところいい分け方ができたと思う。

Discussion