システム・サービスに関するログ・各種情報を取得する事により、トラブルシューティング、パフォーマンスチューニングのみならず、ビジネス上の成果の確認、UIの改善等にも役立ちます。ただ、闇雲に情報を取得しても、効果は上がらず労力ばかりがかかってしまいます。本記事ではログ・メトリクスの収集の目的を明らかにし、その為に必要な点を実例を挙げながら説明していきます。
「ログ」取得の目的
Retty開発担当の鹿島です。Webサービスに限らず、ITのシステムを運用していれば、何らかの形で「ログ」の取得・保存をしている事かと思います。そもそも、それらは何のために保存されているのでしょうか。まずは、「ログ」を保存する目的を明らかにし、その観点から各種の「ログ」について見ていきたいと思います。
開発や運用経験のある方であれば、
「ログにxxxに関する情報が出ていれば、障害解決がスムーズなのに......」
とか、あるいは逆に
「ログが大量過ぎて重要な情報が探しにくい!」
などと思った経験があると思います。ログを取得する目的を明確にする事により、こうした事の大半は避けられると考えています。
ログを取得する目的は色々ありますが、大雑把に以下の4つに分類できると思います。
- 障害発生時のトラブルシューティング
- パフォーマンス改善
- ビジネス上の成果の確認
- UIの改善
今回の記事では、この中から主に最初の2つを扱います。なお、本記事内で言う「ログ」は、いわゆるシステム関連のログだけでなく各種指標・メトリクスを含みます。詳しくは後ほど説明します。
障害発生時のトラブルシューティング
さて、ログを取得する理由として一番最初に思い当たるのは、障害発生時のトラブルシューティングだと思います。システムが応答しない、予期しない異常な動作をするなどの障害が起きた際に、ログを参照することによって以下のような事実が特定されると期待されます。
- 障害発生日時
- 障害発生箇所
- 障害の原因
- 障害による影響範囲
逆に言うと、これらを特定できるようにログを取得する必要があるということです。
パフォーマンス改善
システム関連で、次に思い浮かぶのがパフォーマンス改善です。システムの応答速度、各モジュールの処理速度などを記録しておき、どの部分がボトルネックになっているのかを特定し、改善につなげていきます。
ビジネス上の成果の確認
システム面から少し上のレイヤーにあがって考えると、ビジネス上の成果が確認できるような情報を記録しておく事も、広い意味で「ログ」と言えます。分かりやすい例をいくつか挙げると、
- ECサイト等のコンバージョン率(どの位の割合のユーザーが製品購入・資料請求等の「ゴール」に到達したか)
- ページ閲覧数
- サービス継続率
などがあります。
UIの改善
Webサイト/サービスでは、UIの変更の度にクリック率、ページ離脱率などを確認して改善につなげるのは一般的だと思います。また、同じページ/システムでUIの異なるバージョンを複数用意し、どのバージョンが一番良い結果だったかを確認する、という手法も比較的良く行われます。
このとき取得するものは、クリック率、離脱率、ページ滞在時間などの一般的な情報ですが、場合によってはマウスの位置などを取得する場合もあります。
「ログ」の種類
前項ではログ取得の主な目的について説明しました。ただ、ひと口に「ログ」と言ってもいろいろな種類があり、前項で説明した目的に応じて、異なる種類のログが使われます。ここでは主なログの種類について説明します。
サーバーログ
「ログ」と聞いて一番最初に思い浮かぶのはこれではないでしょうか。サーバログには以下のようなものがあります。
- OSレベルのログ
- UNIX系OSのsyslog, Windowsの各種イベントログなど
- サーバーソフトウェアのログ
- Apache、MySQL、Postfixなど、各種サーバーのログなど
これらのログは、主に以下のような目的に用いられます。
- 障害発生時のトラブルシューティング
- パフォーマンス改善
運用管理・監視ツールのログ
以前の記事でご紹介した通り、RettyではAmazon CloudWatchやNagiosなどを監視目的に使っていますが、監視目的以外にも、リソース状況を確認するために運用管理ツールを導入している企業も多いと思います。
これらのツールで取得できる情報には、以下のようなものがあります。
- OSレベル
- CPU使用率、キュー長、メモリ使用量、スワップイン/スワップアウト、I/Oなど
- サーバーレベル
- DB接続プールの使用状況、キューサーバーのメッセージ長、JVMの空きヒープサイズ
これらの情報を取得できる運用管理・監視ツールには、例えばオープンソースではZabbixやGangliaなどがあります。またUNIX系のsarやWindows系のパフォーマンスモニターなどもこれに含めてもいいかもしれません。
こうした情報の、主な取得目的は以下の通りです。
- 障害発生時のトラブルシューティング
- パフォーマンス改善
Webアクセスログ
ApacheやIISなどのアクセスログについては、既にご紹介しました。ここで言う「Webアクセスログ」とはGoogle Analytics等のWebアクセス解析ツールのログを指しています。
取得できる情報はツールによって異なりますが、主なものとして以下のような種類があります。
- ユーザー、クライアントの情報
- ブラウザ、OS、アクセス元の国や地域
- 過去のサイト訪問回数
- 流入元
- リファラー
- 検索キーワード
- 広告
- ユーザーの行動アクション
- ページ閲覧
- ページ内のボタンクリック
- 滞在時間
- コンバージョン(購入完了ページに到達、など)
こうした情報の主な取得目的は、以下の2つだと思います。
- ビジネス上の成果の確認
- UIの改善
アプリケーションログ(カスタムログ)
アプリケーションログとは、自社のために開発したアプリケーションが独自に出力するログの事です。出力する内容、量、頻度は自由に決められますが、そのぶん設計にはある程度の知識と経験が必要とされます。
システムで取得できる内容は全てアプリケーションログに出力できますので、今までに挙げたログでは取得できない情報をアプリケーション独自のログに出力すると良いでしょう。
なお、ログの主な出力先としては、ファイルとデータベースの2通りが考えられます[1]。主なメリット・デメリットを以下の表にまとめます。
ファイル | データベース | |
---|---|---|
メリット |
|
|
デメリット |
|
|
[1] | 大規模分散環境でのログ収集・解析は本記事の対象外です。 |
「ログ」設計に関するポイント
ここまでの記事を読まれた方であれば、
- ログ取得の目的を事前に明らかにして
- そのためにどのログにどういった情報を保存するか
を設計する事が大切だということはご理解されたかと思います。
ここではログの取得や管理に関する設計について、基本的なポイントをいくつか説明していきます。
取得した情報をもとに行動を起こせるようにする
少し前に話題になった『リーンスタートアップ』(エリック・リース著、日経BP刊)という書籍をご存じでしょうか? この書籍を読まれた方ならば、「行動につながる評価基準(Actionable Metrics)」という言葉が何度も出てきたことを覚えているかもしれません。
これと同じような話ですが、メトリクスやログの設計に関する第一のポイントとして、「取得した情報を見て具体的な行動を起こせるか?」という点を挙げたいと思います。
詳しく説明する前に、まずは具体的なシナリオとして、いくつか例を挙げたいと思います。
ディスク使用量が80%を超えた場合、不要なファイルが削除できないか、あるいはディスクの増設を検討する
アプリケーションログにエラーコード100番台が記録された場合には、営業時間外でも即座に原因調査を行う
あるクエリーがN秒以上かかる事が1日にN回以上発生した場合、クエリーの改善、インデックスの追加等を検討する
- 今回リリースした追加機能Aにより、ページIでのアクションXの数が増加すると期待される
- 日次でのXの数が20%以上増加した場合、本機能をページII, IIIにも展開する
- 増加率が5%から20%の場合は、デザイン等の改善を行って増加率の推移を観察する
- 増加率が5%未満(負の値も含む)は、本機能をページIから削除する
こうしたシナリオのように行動できようになるためには、以下のような事が必要だと考えます。
具体的な目的・シナリオを先に考えて、そこから必要な情報を特定する
どういった情報を取得するか?を考える前に、どういった事を検知・確認・改善したいかを具体的に考えます。
例えば、
- A機能はコア機能なので、ここの応答時間は常に0.5秒以下になるようにする
- Bページへの流入が一番多いので、まずはこのページからのコンバージョン率を現在の4%から8%まで改善する
- C機能を使っているユーザーが有料ユーザーになる割合が高いので、C機能への導線を確認・改善したい
といったことです。
重要なシナリオから順に対応する
上に挙げたような具体的なシナリオを考えてみると、沢山の項目が出てくると思いますが、それらの全てに対応する事はできません。優先順位の高いものから順に対応していきます。
トラブルシューティングが目的のログ取得に関しては、前回の監視の記事も参考になるかと思います。パフォーマンス改善、UI改善、ビジネス上の成果の確認が目的の場合も、重要と思われる指標、機能から順に対応していきます。
大雑把な情報ではなく、具体的・詳細な情報を取得する
ここまでの事を実践していれば自明な事かもしれませんが、想定したシナリオの通り動けるように、なるべく具体的な指標を取る必要があります。以下に2つほど例を挙げます。
- 例1:Facebook APIとの通信でエラーが発生した場合検知したい
- 悪い例:Facebook SDK内で発生したException $eをcatchし、$e->getMessage()のみを表示
良い例:上記に加えて、エラーコード、SDKに渡したパラメーター等も表示する - 例2:ユーザー登録数の推移を調べる
- 悪い例:ユーザー登録数のみを計測
良い例:ページ単位、デバイス(PC、iPhone、iPad、Android等)単位での登録数
不必要なものを取り過ぎない
「取得した情報をもとに行動を起こせるように」情報を取得するように設計しておけば、あまり起きないことかもしれませんが、「そのうち使うかもしれない」という理由で情報を何でも取得してしまうのは、以下の理由からオススメできません。
- 容量の増加によるコストの増加
- これは説明不要でしょう
- 管理コストの増加
- ログは取ったら取りっぱなしという訳ではなく、集計したり、ローテーション・バックアップしたりする、古いものは削除したりします。ログの量が増えると、これらの管理にかかる時間が増えます
- パフォーマンスの低下
- 取得する情報が多くなるとその分パフォーマンスが低下します。特にアクセスの多いサービスの場合は、顕著に影響が現れると思います
まずは始める
ここまで色々書いてきましたが、スタートアップ企業ではスピードが重要です。まずは始めて、徐々に改善していけばいいと思います。
どのようなログを取得しているか、Rettyでの実例
ここまでで「ログ」取得の設計に関して、ある程度は理解されたかと思いますので、ここではRettyで具体的にどのような情報を取得しているのかについて説明していきます。
トラブルシューティングが目的のもの
Rettyは、LAMP構成がベースとなっていますので、以下のようなログを取得しています。
Apacheのerror_log
PHPのプログラム内で発生したエラーはここに書き込まれます。これに関しては特別な事はしていません。error_reportingは以下の通りです。
error_reporting = E_ALL & ~E_DEPRECATED
エラーログに書き込む情報は本記事の前半で説明したように、トラブルシューティングのための行動が起こせる程度に詳細な情報を書き込むようにします。
具体的に気をつけているのは、以下のような(基本的な)事です。
- エラー発生時のエラーメッセージ・スタックトレースに加え、メソッドに対する引数もログに出力する
- 使用するログレベルの数は抑える
まず1番目に関してですが、実際のログを例に挙げて説明します(一部改変しています)。例えば以下のようなログが出力されたとします。これはFacebook SDKが吐くエラーメッセージを表示しただけのものです。
[Wed Aug 1 1:01:01 2012] [ERR] [client xxx.xx.xxx.xxx] Could not retrieve data from URL. in /var/www/html/path/to/somelib.php on line 123
行数を見れば、どこでエラーが発生したかはすぐ分かります。これは実際にはOpen Graphのデータ送信処理で発生したエラーによるものです。しかし、これだけの情報では実際のコードを見ない限り、なぜエラーが発生したのかがすぐには分かりません。これではトラブルシューティングに時間がかかってしまいます。
そこで例えば、エラーメッセージの中にデータを送信したユーザーのFacebookユーザーIDと、送信したOpen GraphオブジェクトのURLがあればどうでしょうか。
[Wed Aug 1 1:01:01 2012] [ERR] [client xxx.xx.xxx.xxx] Facebook ID = nnnnn, Object URL = http://retty.me/path/to/object, message = Could not retrieve data from URL. in /var/www/html/path/to/somelib.php on line 123
送信したオブジェクトに問題があるのか、送信したユーザーアカウントに問題があるのか、といった切り分けがすぐにできると思います。
つぎに2番目の「利用するログレベルの数」に関してですが、例えば以下のようなログレベルの定義があるとします。
- Emergency: system is unusable
- Alert: action must be taken immediately
- Critical: critical conditions
- Error: error conditions
- Warning: warning conditions
- Notice: normal but significant condition
- Informational: informational messages
- Debug: debug-level messages
この例でCriticalとErrorの違いは何でしょうか。また、Criticalが発生した時にはどのような対処をすればよく、Errorが発生した時にはどのような対処をすればよいのでしょうか。
システム・アプリケーションの規模にもよりますが、一般的にはログレベルの数を多くしすぎると運用が曖昧になり、取得した情報をもとに行動を起こせるようにする(Actionable)という本来の目的から外れてしまいがちです。そうした理由から、Rettyでは使用するログレベルの数を、現状では3つに抑えています。
ログ取得に関しては数多くのプラクティスがあります。ここでは基本的なものを2つ紹介しましたが、詳細は関連する書籍やWebサイトなどを参考にして下さい。
アプリケーションログ
アプリケーションログは用途別に何種類かあり、ファイル、DBのどちらも使っています。トラブルシューティング目的で取得しているもののうち主なものとしては、ユーザー単位のアクセス履歴があります。
Rettyでは、ユーザーさんから「xxをしたけど上手くいかなかった」といったお問い合わせを頂いた際に、素早く原因究明して返答できることを重要だと考えています。その目的を達成する事が、アクセス履歴取得の目的の1つです。
ユーザー履歴は、取ろうと思えばいくらでも細かく取ることができるのですが、トラブルシューティングに関して言うと、重要な操作(ユーザー登録、投稿)に関連する情報を多めに取得し、それ以外の情報はそれほどたくさん取得していません。
パフォーマンス改善
パフォーマンス改善、ボトルネック調査のために使用しているのは、主に以下の3つです。
- MySQL slow query log
- Apacheの応答時間
- Amazon CloudWatch
それぞれについて見て行きます。
MySQL slow query log
Rettyの大半の処理は何らかの形でDBを使用するため、DBのパフォーマンスがユーザー体験にダイレクトに影響します。MySQL slow query logはその名の通り、時間のかかった遅いクエリーをログに記録するというものです。
詳細に関しては こちら を参照して下さい。MySQL以外でも、PostgreSQL等の主要なRDBMSでは同種の機能がありますので、このような機能は必ず使うことを推奨します。
何秒以上かかったクエリーを記録するかはシステムの性格によりますが、Rettyでは0.5秒以上かかったクエリーを記録するようにしています。対象となるクエリーが多すぎても少なすぎても問題となりますので、この値は随時調整してもいいと思います。
ログに記録された遅いクエリーはEXPLAIN文で実行計画を確認し、クエリーの修正、あるいはインデックスの追加などの対策を実施します。
Apacheの応答時間
Apacheのデフォルトの設定には含まれませんが、設定を変更することによりHTTPリクエストがあってから応答を返すまでの時間を計測してログに出力できます。詳細は Apacheのドキュメント を参照して下さい。
ここでも具体的なアクションを起こせるように、「応答までにx秒以上かかっているページがあれば、関連するモジュールを調査する」といった基準を決めておくと良いと思います。また必要に応じてログ監視などを組み合わせるのも良いと思います。ログ監視に関しては 前回の記事 も参考にしてみて下さい。
Amazon CloudWatch
前回の監視の回にもAmazon CloudWatchについて少し説明しましたが、Amazon CloudWatchはディスクI/O、メモリ関連、ネットワーク関連などの各種指標を保存しています。パフォーマンスの低下が発生した場合、それらを参照して改善に活かす事ができます。
とはいえRettyでは、これらの値はそれほど細かくは見ていません。現在のサービスのステージとして、細かい指標を見ながらシステムの細かいチューニングを行わないと大きなパフォーマンスの問題が発生するという事はあまりなく、どちらかと言うとシステム全般のアーキテクチャや非効率なクエリーを見直す事によって、パフォーマンスの問題が改善される事がほとんどだからです。
ビジネス上の成果の確認、UI改善
ビジネス上の成果の確認とUI改善の2つは、情報を取得する方法が「システム外部の情報」という点で類似しているので、ここで合わせて説明します。なお、今回の記事では概要を説明するだけに留め、別の機会に詳細をご説明しようと思います。
これらの目的のため、Rettyで取得している情報は以下の2つです。
- Google Analytics
- アプリケーションログ
Google Analytics
Google Analyticsはご存知の通り、無料で使う事ができます。デフォルトでも数多くの情報を取得できますが、それ以外の情報を取得したい場合には「カスタムイベント」や「カスタム変数」を組み合わせる事で、かなりの情報が取得できます。
またレポートをカスタマイズできるので、自前のアプリケーションログ取得、レポートシステムを作る前に、まずはGoogle Analyticsで実現できないかを考えてみると良いと思います。
Google Analyticsの詳細に関しては、以下のドキュメントなどを確認して下さい。
アプリケーションログ
Google Analyticsで取れない情報のうち必要と思われるものは、全てアプリケーションログとして取得しています。
Rettyでは、行ったお店への「投稿」、他の人の投稿に対して「行きたい」ボタンを押す、などの行動を、いかにユーザーさんに沢山してもらうか、という点が重要です。そうした「ゴール」につながる行動、そこに至る導線に関しては、なるべく多くの情報を取得して、具体的な改善に素早く繋げられるようにしています。
なお英語ですが、最近人から教えてもらった情報で参考になるものがありましたのでご紹介しておきます。ソーシャルゲームのZyngaがメトリクスをどのように使っているか、というプレゼンテーションの動画です。タイトルで検索すれば、PDFファイルもダウンロードできると思います。
まとめ
ログを収集・解析する上では、まず目的・ゴールを明確にした上で、必要な情報を取得する必要があります。「必要な情報」というのは、そのログを見た時に具体的な行動が起こせる位に詳細かどうか、というのが基本的な判断ポイントとなります。
そうした流れで考えていくと、取るべき情報は山のように考えつくかと思いますが、まずは優先順位の高いものから順に始めて、徐々に改善していくのが良いと思います。
執筆者紹介
鹿島和郎
ソーシャルグルメサイト「Retty」の開発・インフラ全般を担当。過去には米企業でのオフショア開発拠点の立ち上げから国内SIerでの運用保守業務まで、広く浅く経験している何でも屋。
Rettyは、「行った」お店の投稿・共有、友達・趣味嗜好の合う人のオススメから「行きたい」お店をリスト化、スマートフォンで現在地周辺のお店をリストから検索などできるサービスで、Facebook、Twitterアカウントがあれば無料で使用可能。PC、iPhone、Androidに対応。
現在Rettyではインターン・アルバイトを募集しています。ご興味のある方はリンク先まで。