LogDig: Apache LogViewer

Apacheログビューアー

Apacheのアクセスログ解析にはOSS/商用問わず現在では数多くのソフトウェアがあり、 AnalogWebalizerなどが有名ですが、 LogDigではそれらのような統計やユーザーの動向を知るという目的では無く、よりミクロな視点で個々のアクセスログに注目するものになります。

勿論膨大な量のアクセスログをただ羅列するだけでは意味がありませんので、 LogDigでは目的の情報を素早く取得出来るような下記の機能を搭載しています。

  • アクセス時間/ホスト名/リクエストファイル/ユーザーエージェントなどでの複数条件でのソート
  • 特定の値を持つログの抽出/非表示
  • それぞれのデータタイプでの集計
  • 個々のユーザー毎に設定可能なログフィルター機能
  • 1ページに表示されるログ数の設定と、ページ切替

これらのデータ操作をサーバー側スクリプトを経由して行うのでは無く、全てクライアント側のWebブラウザ上のJavaScriptにより実装しているという点がLogDigの最も大きな特徴となります。


またこのような特徴の為、1まとまりのログデータは一度に全てまとめてクライアント側に送る事になりますので、 十数万項目以上に及ぶデータをそのまま利用するのは現実的ではありません。 また一万件程度データであっても、JSON文字列からJSONオブジェクトへの変換に非常に時間が掛かる場合もあります。(ブラウザ毎の差異が大きい)

そこでそのような大量のデータの場合には、 サーバー側でのデータ変換時に必要に応じログの取捨選択(画像ファイルやjs/cssファイルへのリクエストログデータをJSONデータ化しないなど)を行う事も必要となります。


クライアント側のJavaScriptとサーバー側のPHP共にMITライセンス形態での公開となります。

Demoページ / Download

クライアント側でのデータ操作(ソート/抽出/集計/ページ切替)

このスクリプトは、サーバー側ではデータ(JSON)生成だけを行い、 表示整形や基本的なデータ操作は全てクライアント側(JavaScript)で行う汎用的なシステムとして開発したものですので、 ログビューアーとしての利用は勿論、商品やサービス一覧などのような 同一フォーマットによる多数のデータの集合として構成されるページ/サイトに対応可能です。

コスト的あるいはサーバーの利用形態によりサーバー側でのデータ操作スクリプト設置が難しいサイトには勿論、 多くのサイトでのサーバーの負荷軽減や転送量削減に有効なソリューションであり、 また、データをAjaxでは無くJSONファイルとして提供する場合には、高機能のオフラインコンテンツとしても利用出来ます。

当社では、各種データ形式に対応するカスタマイズも行っておりますので、 関心のあるサイト運営者様はこちらよりご連絡下さい。

単一あるいは複数タイプによるデータソート機能
特定の値を持つログデータの
抽出/除外/集計機能
複数ページ構成でのページ切替機能
サーバー側スクリプトの処理と設定
クライアント側スクリプトの設定

単一あるいは複数タイプによるデータソート

LogDigの基本機能であるデータソートを行います。 ここで説明した操作は、Demoページで実際に試す事が可能ですので、 説明と合わせて利用して頂くとより判りやすいかと思われます。


データソート

表形式で提示されるデータ群に対する定番操作であるデータソート(並び替え)です。 数値データの場合には数値全体の大小で(0,1,2,11,22...)、文字列データの場合には一文字毎の文字コード比較で('0','1','11','2','22'...)ソートが行われます。

ソートは、表示しているページのデータだけでは無く、全ページのデータを対象とし、それぞれのデータタイプ(日付、ホスト名など)毎での昇順/降順ソートを行い、 その結果に従いデータの再構成を行います。


データテーブルのタイプの項目をクリックする事により、そのタイプでのソートが行われます(図S-1)。

データのソート
図S-1: データの昇順ソート

指定のタイプの状態が未ソートの場合には昇順ソートを行い、ソートされている場合に再びクリックした場合には、現在のソートとは逆順のソートを行います(図S-2)。

データの逆順ソート
図S-2: データの逆順ソート

指定のタイプでソートされているか否かは、タイプの背景色で判断出来、昇順か降順ソートかはタイプの名前の書体(通常:昇順ソート/斜体:降順ソート)で示されます(図S-3)。

ソート状態の確認
図S-3: 指定データタイプ(時間)でのソート状態の確認。
左から、未ソート/昇順ソート/降順ソート

複数データタイプでのソート

上記のような単一データタイプだけのソートでは、ソート対象の値が同一の場合には、その他の項目の内容は順不同の並び(正確には直前のデータの並びの影響を受ける)となります。 そこで、指定のタイプで同一内容のログが出現した場合には、その同一内容のデータ群の中でさらに別のタイプでのソートを行う事を可能にするのが、 この複数データタイプでのソートになります。

複数タイプでのソート指定では単一のソートとは違い、 まずCtrlキーを押しながらタイプの項目をクリックし、ソート対象候補として登録を行います。 このCtrl+クリックでの登録をソート対象となる全てのタイプで行いますが、この登録順がそのままソートの優先順位になります。

複数ソート登録
図S-4: 複数タイプのソート登録。

ソート対象として登録されたタイプの項目では、背景色が変わり、タイプ名にアンダーラインが付き、 さらにソートの優先順の数字がタイプ名の前に追加されます(図S-4)。 これにはCSS2の生成されたコンテンツ(Generated content)を利用していますので、IE6など一部のブラウザでは表示されません。

また、登録されたタイプの項目のCtrl+クリックで、そのタイプでのソートの昇順/降順を切替出来ます(図S-5)。

複数ソートタイプでのソート方向の切替
図S-5: 複数タイプのソートでのソート方向の切替。

複数ソート対象の登録が完了した後、登録されたいずれかのタイプの項目をクリックする事で、データソートが行われます(図S-6)。

複数ソートの実行
図S-6: 複数タイプソートの実行。

図S-7が、1.ホスト(昇順) 2.ファイル(昇順) 3.時間(昇順)の順で複数ソートを行った結果のデータの一部となります。 まずホスト名で昇順ソートを行い、ホスト名が同一のデータに関してはファイル名でソート。さらにファイル名も同一の場合には、 時間でソートを行っているのが見て取れるかと思います。

複数ソートが行ったデータ
図S-6: 複数タイプソート後のデータ。

特定の値を持つデータの抽出と除外、集計機能

ここでは、あるデータタイプでの特定の値を持つログデータの抽出と除外と集計という、個々の値に注目したデータ操作を行います。


操作対象データ

まず、これらの操作対象となるデータについて説明します。

LogDigではログデータをサーバー側からAjaxで取得し、それにクライアント側でフィルターを適用しログの選別を行います。 このフィルターで選別を行ったデータ群が復元可能な初期データとなり、同時にデフォルト状態での操作対象データとなります。

前項のデータソートでは、単にこの操作対象データを並び替えるだけですので、何度行っても操作対象データに変化はありませんが、 ここで説明するデータの抽出/除外では、操作対象データ自体から対象外データを削除しますので、同一データの抽出/除外であっても前回の操作内容によって結果は異なります。


図E-1での操作では、ホスト名がi8991sa4apl.example.or.jpのデータを操作対象データから除外しています。 対象となるデータがログ全体で10個あった為に、除外後の操作対象データ数が492個から482個に減少しています。

複数ソートが行ったデータ
図E-1: データ除外後の操作対象データ数の変化。

このように抽出/除外を行った後には操作対象データが変化し、 今後行うデータ操作に関しても、(基本的に)この減少したデータ群に対して行う事になります。 これは例えるなら、サーチエンジンでの絞込み検索のような操作となります。


他の条件で一からデータ操作を行う為に毎回サーバーからAjaxによりデータを再取得するのは非常に無駄ですので、 フィルター適用後の初期データを操作対象データとして復元するリセット機能も勿論LogDigには搭載しています。

初期データの復元
図E-2: 初期データの復元。

図E-2で示す通り、~のアクセスログという情報表示部分をクリックする事で、初期データを操作対象データとして復元する事が可能です。


データの抽出

あるタイプでの特定の値を持つログデータだけを抽出します。現時点では任意の文字列での検索機能はありませんので、 直接個々のデータに対し操作を行う必要があります。

特定データの抽出は、その値が格納されたテーブルセルへのCtrl+クリックで行います。 図E-3では、現在の操作対象データの中から、リクエストファイル名が/demo/tips_noscript.htmlのログデータの抽出を行い、 その抽出結果が図E-4となります。

特定の値を持つデータの抽出
図E-3: 特定の値を持つデータの抽出。
データの抽出結果
図E-4: データ抽出後のデータテーブル。

データの除外

データの抽出とは逆に、特定の値を持つログデータだけを現在の操作対象データから削除します。

特定データの除外は、その値が格納されたテーブルセルへのShift+クリックで行います。 図E-5は、リクエストファイル名が/gadget/fhconvert/fhconvert_gg.jsのログデータを除外する操作となります。

特定の値を持つデータの除外
図E-5: 特定データの除外。

初期データを対象としたデータの抽出/除外

上記で説明した通り、抽出/除外などのデータ操作は現在の操作対象データ群に対して行い、その抽出/除外などの操作をした結果生成されたデータ群が新たな操作対象データとなります。 よって、そのような操作を繰り返す毎に操作対象データ数も減少しますが、減少した中で新たに注目した特定の値を持つデータがあった場合には、 既にその値を持つ他のログデータが操作対象データより削除されている可能性も十分考えられます。

そのような場合には、ここまでに説明した方法だけでは、一度操作対象データを初期データにリセットし、 一からソートや抽出/除外を駆使しその特定値を持つログデータを検索する事になります。


そこでLogDigでは、現在の操作対象データでは無く、初期データを対象とした操作が可能ですので、 ログ全体を対象とした特定の値を持つデータに対する操作が容易に行えます。

例えば図E-3のような操作を行った結果の図E-4のデータテーブルに、Googlebotからのアクセス記録が見つかり、 初期データ全体からGooglebotからのアクセスログを抽出したいような場合には、 ユーザーエージェントデータタイプのGooglebotのセルに対しAlt+クリックを行います(図E-6)。

初期データからのデータの抽出
図E-6: 初期データからのデータの抽出。

また、特定の値を持つログデータだけを初期データから除外したデータが欲しい場合には、Alt+Shift+クリックでその操作が可能です。


集計機能

現在の操作対象データにおいて、データタイプ別にそれぞれの値の出現回数を表示する集計機能も、LogDigでは利用可能です。

この集計機能は、勿論出現頻度を調べる用途でも使われますが、それと同時にデータタイプの中でのユニークな値を列挙する事にもなりますので、 Alt+クリックでの初期データからの抽出機能と組み合わせ、特定の値を持つログデータを素早く抽出する用途にも適します。


特定データタイプでの集計は、そのタイプ項目をShift+クリックする事で行われます(図E-7)。

特定データタイプでの集計
図E-7: 特定データタイプでの集計。

集計結果は、出現回数の降順ソート順で表示されます(図E-8)。 さらに、この集計結果が現在の操作対象データとなっていますので、ここでもデータタイプでのソートなどの操作が可能となります。

特定データタイプでの集計結果
図E-8: 特定データタイプでの集計結果。

複数データタイプを対象とした集計機能

集計機能としては、単一のデータタイプを対象とした集計だけでは無く、複数のデータタイプの値の組み合わせでの集計も行う事が出来ます。

複数データタイプでのソートと同様に、タイプ項目へのCtrl+クリックにより操作対象タイプとして登録します。 操作実行では、ソートの場合には単にクリックでしたが、集計ではここでShift+クリックする事で行われます(図E-9)。

複数データタイプでの集計
図E-9: 複数データタイプでの集計。

複数タイプのソートでは、操作対象の登録順はソートの優先順位でしたが、集計の場合は、登録順がデータテーブルでの並び順となります。 図E-10では、Stat-ファイルという順で登録が行われましたので、その登録順に従った並びとなっています。 これにより、より注目したいタイプ、あるいはレイアウト的な見易さを考えたデータタイプの並びを自由に指定出来ます。

複数データタイプでの集計結果
図E-10: 複数データタイプでの集計結果。

複数ページ構成でのページ切替機能

LogDigでは数万件のデータを扱う事が出来ますが、勿論それらの全データを1つのテーブル上に展開する事は現実的ではありません。

そこでサーバー側でページ生成を行うような多くのWebアプリケーションと同様に、 一定個数のデータ表示を行うテーブルを1ページとし、そのデータを切り替える事で全てのデータにアクセス出来るという複数ページ構成が可能です。

これは、個々のデータの視認性の向上に加え、レイアウト的にテーブル設置エリアが限られるケースでの有効なソリューションとなります。


ページ情報

現在のデータとページについての図P-1のような情報項目とページ操作コントロールが、データテーブルの上下に表示されます。

901-1000/8861 (10/89) |‹‹‹67891011121314›››|

図P-1: ページ情報。

901-1000/8861は、データ総数[8861]の中で現在表示されているデータが901番目から1000番目という事であり、 (10/89)は総ページ数89中での現在表示されているページが10ページ目という事を意味します。

このデータ情報の隣に並ぶのがページ操作コントロールです。


ページ移動操作

ページ移動操作は、ページ操作コントロールにある数値/記号をクリックする事で行われます。

|‹›|はそれぞれ最初のページと最後のページを表示します。 これは文字通り最初のページ(1ページ)と最後のページ(この例では89ページ)に移動出来るコントロールとなります。

‹‹››は、現在表示されているページをページリンク表示数分だけ前後に移動します。 この例のように現在の表示ページが10ページであるケースで、 ページを進める(››)をクリックした場合には、右端に表示されている14ページの次の15ページに移動するのでは無く、 15ページが左端に表示される事になる19ページ目に移動します。 要するに、現在表示されているページリンクが表示されなくなる範囲での最小(戻る場合は最大)のページに移動する機能となります。

はそれぞれ前のページと次のページに移動します。

6 7 8 9などの数字は、その数値のページに直接移動するページリンクです。背景色が他と異なる数字は現在表示中のページとなります。


また、データのソートや抽出を行った場合には、表示ページは1ページ目に自動的に戻るようになっています。


サーバー側スクリプト(PHP)での処理と設定

LogDigではデータ操作のほとんどをクライアント側で行いますが、アクセスログをLogDigで利用する形式(JSON)への変換や、 Ajaxリクエストに対応し指定の日付のログデータを返すなどの処理が、サーバー側スクリプトで必要となります。


JSONへの変換

Combined形式のApacheのログファイルは、1つのログデータだけでも数百Bytesにも及び、 またリアルタイムに次々と出力されるという特性の為に、データの集合として扱う場合には同一内容の項目が複数回現れるなど、 かなり冗長なデータ構造となっています。

そこで、JavaScriptでの利用に適したJSON形式に変換すると同時に、 個々のデータタイプ(ホスト名やユーザーエージェントなど)を、それぞれの配列に格納し、個々のログではその配列へのインデックスを保持するという、 RDBMSでの正規化のような加工を行います。

JSONデータの正規化
図: JSON変換における正規化

さらにこの正規化処理では、各データタイプ配列で文字列の昇順ソートも行います。これにより個々のログでのインデックスの値の大小は、そのままソート順となりますので、 クライアント側でのソート操作が文字列の比較では無く単純な整数値比較になり、負荷軽減が期待出来ます。


JSONファイル作成

元のアクセスログファイルからJSONファイルを生成するタイミングは、コマンドライン(あるいはcronなど)での引数に日付を指定しての実行時、 あるいはAjaxリクエスト処理時に、JSONファイルが存在しない場合に指定の日付のファイルが作成されます。

AjaxでのJSONファイル作成では、クライアントからのリクエストがタイムアウトするまでに作成されなければなりませんので、 数万行程度のログなら大抵問題無いと思われますが、それ以上のログやgethostbyaddrが遅い環境では、cronなどで定期的にJSONファイルの生成を行った方が良さそうです。

また、大量のアクセスログがある場合には、それほど必要では無いアクセス情報(画像ファイル/CSS/JSなど)を、 LogDig用のJSONデータには登録しないようにする事をお勧めします。

JSONファイルはgzipで圧縮を行いますので、LogDig設置に伴うディスク容量の使用量を最小限に留めます。


Ajaxリクエスト

サーバー側スクリプトではデータ操作を行いませんので、 クライアントからのリクエストに対応したサーバー側の処理としては、

  • A. 指定の日付のアクセスログ自体が存在しない場合にはエラー
  • B. JSONファイルが未作成の場合には、JSONファイルを作成しそのJSONデータを送信
  • C. JSONファイルが存在している場合は、ファイルを読み込みそのままクライアントに送る

と、このように非常に単純なものとなります。


設定

サーバー側スクリプトの設定では、アクセスログの場所/ファイル名と変換した後のJSONファイルの保存場所の設定を行います。

ここまで、個々のアクセスログは日付毎と説明してきましたが、実際にはWebサーバーでのアクセスログの管理方法に依存します。 access_log_20090401などとして日付単位でのアクセスログのローテートが行われる場合には、20090401がログIDとなりますが、 これが月単位や特定のログだけを抽出するような場合にはまたログIDも変わってきます。

クライアント側でのログ指定でも、この任意の形式のログIDをそのまま利用する形となりますので、 クライアント側とサーバー側共に、20090401などの特定のフォーマットでのチェックは行いません。 が、このログIDはそのままファイル名として利用しますので、英数字.-_以外の文字は削除し、 英数字.(ピリオド)-(ハイフン)_(アンダーバー)だけで構成される任意の文字列が指定可能となります。


LOGPREFIX

アクセスログの場所とログIDの前に追加されるログ共通の文字列を指定します。
phpスクリプトからアクセスログが保存されるディレクトリへの相対パスが../../log/であり、 ログファイル名がaccess_log_20090401のような形式(20090401が個々のログを識別するログID)である場合には、下記のような記述となります。

define( 'LOGPREFIX', '../../log/access_log_' );
LOGSUFFIX

ログファイル名で、ログIDの後に追加されるログ共通の文字列を指定します。
access_log_20090401を例にしますと、ログID(20090401)の後には何も追加しませんので、そのような場合には空のままで構いません。

define( 'LOGSUFFIX', '' );
LDGPREFIX

アクセスログを変換した、LogDigで利用するJSON形式のファイルの場所とログIDの前に追加される文字列を指定します。
アクセスログとは別のディレクトリに保存するような場合には、phpスクリプトではディレクトリの作成は行いませんので、作成済みである必要があります。

define( 'LDGPREFIX', '../../ldg/access_log_' );
LDGSUFFIX

JSON形式のファイル名で、ログIDの後に追加される文字列を指定します。
JSON形式のファイルはgzip圧縮を行いますので、.gzを追加すると共に、 通常のアクセスログとは区別する意味で、デフォルトでは拡張子.ldgも追加します。

define( 'LDGSUFFIX', '.ldg.gz' );

これらの設定とは別に、LogDig自体にはアクセス制限機能はありませんので、htaccessなどでの認証やIP制限設定が別途必要となります。

また、クライアント側で利用するフィルター機能などの設定値はCookieに保存されますが、そのCookie情報はサーバー側で利用する事は有りません。 が、パス範囲の及ぶファイルリクエスト時には毎回Cookieも送られ、転送量を増加させる要因ともなりますので、 Cookieのパスに設定されるhtmlファイルは最下層のディレクトリに置くという事もお勧めします。


クライアント側スクリプト(JavaScript)の設定

LogDigはJavaScript FrameworkであるMooTools1.2を利用しています。


LOGURL

ajaxリクエストの送信先URL。
サーバー側スクリプト(php)を指定します。

LOGURL: 'http://example.com/php/logdig.php'
AJAXGET

ajaxリクエストにおいてGETかPOSTのどちらを利用するか。
trueならGET、falseならPOST。

AJAXGET: true
SITEDOMAIN / FLTSUFFIX

デフォルトフィルターに設定する指定ドメインからのリファラとリクエストファイル情報。正規表現パターンとして扱い、両方共に空文字列では無い場合に有効。

多くの場合、通常のHTMLファイルには画像ファイルやcss/jsファイルなどが含まれ、 当然それら多数の関連ファイルへのリクエストもログファイルに残ります。が、それらが実際に必要となるケースは少ないと思われますので、 それらのログを非表示にする為のデフォルトフィルター用の設定となります。

この例では、^https?:\/\/([\w\-]*\.)*example\.co\.jpのようなリファラが設定(実際は\wに含まれる_や、-から始まるホスト名は無効ですが、Cookieとして保存する場合のサイズを考え簡易指定)された、 .gif/.jpg/.png/.ico/.css/.jsの拡張子があるファイルへのリクエストのログが非表示になります。

SITEDOMAIN: 'example\\.co\\.jp'
FLTSUFFIX: '((\\.gif)|(\\.jpg)|(\\.png)|(\\.ico)|(\\.css)|(\\.js))$'
MAXSORT

複数ソートでの最大項目選択数。
複数のタイプを指定してソートを行う場合のソート項目数です。 例えばファイル名でソートし、同一のファイル名である場合には、さらにその中でリファラでソート、さらにリファラも同一値である場合には時間でソートなど。 この場合にはソート項目数は3となります。

MAXSORT: 4
TBLORDER

データタイプの表示順設定。
ログ表示テーブルでのデータタイプ表示順と、どのタイプを表示するかの設定です。 指定可能なデータタイプは、DATE:アクセス日時 / HOST:ホスト名 / REQ:リクエストファイル / STAT:httpステータス / SIZE:サイズ / REFER:リファラ / UA:ユーザーエージェント

TBLORDER: ['DATE','HOST','REQ','STAT','REFER','UA']
PAGE - LOGPERPAGE / MAXPAGELINK

ページ関連設定。LOGPERPAGEは、1ページに表示されるログ数。MAXPAGELINKは、同時に表示するページリンクの最大数。

ログデータ数が1000、LOGPERPAGEが50、MAXPAGELINKが5という設定の場合には、 1ページに表示されるログデータが50個、総ページ数が20, 現在の表示ページが1ページ目の場合にはページリンク表示は1 2 3 4 5の5つとなります。

PAGE: {
LOGPERPAGE: 100,
MAXPAGELINK: 9
}

WebJADE