PHPログファイルを最大限に活用する:実用ガイド
公開: 2022-03-11ログは、フリーランスのphp開発者が自由に使える最も過小評価され、十分に活用されていないツールの1つであると言うことができます。 彼らが提供できる情報は豊富ですが、開発者が問題を解決しようとするときにログが最後に表示されることは珍しくありません。
実際、多くの場合、PHPログファイルは、問題が発生したときに手がかりを探す最初の場所である必要があります。 多くの場合、それらに含まれる情報により、厄介なバグを追跡するために髪を抜くのにかかる時間を大幅に短縮できます。
しかし、おそらくさらに重要なのは、少しの創造性と先見の明があれば、ログファイルを活用して、使用情報と分析の貴重なソースとして機能させることができるということです。 ログファイルをクリエイティブに使用すると、次のような質問に答えることができます。自分のサイトにアクセスするために最も一般的に使用されているブラウザはどれですか。 サーバーからの平均応答時間はどれくらいですか? サイトルートへのリクエストの割合はどのくらいでしたか? 最新のアップデートを導入してから、使用法はどのように変化しましたか? そして、はるかに。
この記事では、ログファイルが提供するメリットを最大化するために、ログファイルを構成する方法と、ログファイルに含まれる情報を処理する方法に関するヒントをいくつか紹介します。
この記事はPHP開発者向けのロギングに技術的に焦点を当てていますが、ここに示されている情報の多くは技術にとらわれず、他の言語や技術スタックにも関連しています。
注:この記事は、Unixシェルに関する基本的な知識があることを前提としています。 この知識が不足している人のために、Unixシステムでログファイルにアクセスして読み取るために必要なコマンドのいくつかを紹介する付録が提供されています。
PHPログファイルのサンプルプロジェクト
この記事で説明するプロジェクトの例として、Symfony Standardを実用的なプロジェクトとして取り上げ、Debian 7 Wheezyでrsyslogd
、 nginx
、およびPHP-FPM
を使用してセットアップします。
composer create-project symfony/framework-standard-edition my "2.6.*"
これにより、優れたUIを備えた実用的なテストプロジェクトがすぐに得られます。
ログファイルを構成するためのヒント
ログファイルの価値を最大化するためにログファイルを構成する方法についてのいくつかの指針を以下に示します。
エラーログ構成
エラーログは、ログの最も基本的な形式を表します。 つまり、問題が発生したときに追加情報と詳細をキャプチャします。 したがって、理想的な世界では、エラーが発生せず、エラーログが空になるようにする必要があります。 ただし、問題が発生した場合(常に発生するように)、エラーログはデバッグトレイルで最初に停止するものの1つである必要があります。
エラーログは通常、設定が非常に簡単です。
1つには、すべてのエラーメッセージとクラッシュメッセージを、ユーザーに表示されるのとまったく同じ形式でエラーログに記録できます。 いくつかの単純な構成では、エンドユーザーはサイトでこれらの醜いエラートレースを確認する必要はありませんが、DevOpsはシステムを監視し、これらのエラーメッセージを詳細に確認できます。 PHPでこの種のロギングを設定する方法は次のとおりです。
log_errors = On error_reporting = E_ALL error_log = /path/to/my/error/log
ライブサイトのログファイルに含めることが重要なもう1つの行は、エラーの詳細レベルがユーザーに表示されないようにするためです。
display_errors = Off display_startup_errors = Off
システムログ( syslog
)構成
オープンソースの世界には、次のような多くの一般的に互換性のあるsyslog
デーモンの実装があります。
-
syslogd
およびsysklogd
BSDファミリーシステム、CentOS、MacOSXなどで最もよく見られます syslog-ng
–最新のGentooおよびSuSEビルドのデフォルトrsyslogd
–オペレーティングシステムのDebianおよびFedoraファミリーで広く使用されています
(注:この記事では、例としてrsyslogd
を使用します。)
基本的なsyslog構成は、一般に、システム全体のログファイル(通常は/var/log/syslog
です。ディストリビューションによっては/var/log/messages
または/var/log/system.log
の場合もあります)にログメッセージをキャプチャするのに適しています。使用しています)。
システムログはいくつかのログ機能を提供し、そのうちの8つ( LOG_LOCAL0
からLOG_LOCAL7
)はユーザーがデプロイしたプロジェクト用に予約されています。 たとえば、ログレベル(エラー、警告、情報、デバッグなど)に基づいて4つの個別のログファイルに書き込むようにLOG_LOCAL0
を設定する方法は次のとおりです。
# /etc/rsyslog.d/my.conf local0.err /var/log/my/err.log local0.warning /var/log/my/warning.log local0.info -/var/log/my/info.log local0.debug -/var/log/my/debug.log
これで、ログメッセージをLOG_LOCAL0
ファシリティに書き込むたびに、エラーメッセージは/var/log/my/err.log
に送られ、警告メッセージは/var/log/my/warning.log
に送られます。 ただし、syslogデーモンは、「このレベル以上」のルールに基づいて各ファイルのメッセージをフィルタリングすることに注意してください。 したがって、上記の例では、すべてのエラーメッセージは、構成された4つのファイルすべてに表示され、警告メッセージはエラーログを除くすべてに表示され、情報メッセージは情報ログとデバッグログに表示され、デバッグメッセージはdebug.log
にのみ送信されます。 。
もう1つの重要な注意事項。 上記の構成ファイルの例の情報およびデバッグレベルファイルの前の-
記号は、これらのファイルへの書き込みを非同期で実行する必要があることを示しています(これらの操作は非ブロッキングであるため)。 これは通常、情報ログとデバッグログには問題ありませんが(ほとんどの場合推奨されます)、エラーログ(およびおそらく警告ログ)への書き込みを同期させるのが最善です。
重要度の低いレベルのログ(本番サーバーなど)をシャットダウンするには、関連するメッセージを/dev/null
に(つまり、どこにも)リダイレクトするだけです。
local0.debug /dev/null # -/var/log/my/debug.log
特に、この記事の後半で説明するPHPログファイルの解析の一部をサポートするのに役立つ特定のカスタマイズの1つは、ログメッセージの区切り文字としてタブを使用することです。 これは、 /etc/rsyslog.d
に次のファイルを追加することで簡単に実行できます。
# /etc/rsyslog.d/fixtab.conf $EscapeControlCharactersOnReceive off
そして最後に、構成を変更した後、それらを有効にするために、syslogデーモンを再起動することを忘れないでください。
service rsyslog restart
サーバーログの構成
書き込み可能なアプリケーションログやエラーログとは異なり、サーバーログは、リクエストごとに対応するサーバーデーモン(Webサーバー、データベースサーバーなど)によって排他的に書き込まれます。 これらのログに対する唯一の「制御」は、サーバーがログ機能の構成を許可する範囲です。 これらのファイルには多くの情報が含まれている可能性がありますが、多くの場合、サーバーの「内部」で何が起こっているのかを明確に把握する唯一の方法です。
MySQLストレージバックエンドを使用してnginx環境にSymfonyStandardサンプルアプリケーションをデプロイしましょう。 使用するnginxホスト構成は次のとおりです。
server { server_name my.log-sandbox; root /var/www/my/web; location / { # try to serve file directly, fallback to app.php try_files $uri /app.php$is_args$args; } # DEV # This rule should only be placed on your development environment # In production, don't include this and don't deploy app_dev.php or config.php location ~ ^/(app_dev|config)\.php(/|$) { fastcgi_pass unix:/var/run/php5-fpm.sock; fastcgi_split_path_info ^(.+\.php)(/.*)$; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param HTTPS off; } # PROD location ~ ^/app\.php(/|$) { fastcgi_pass unix:/var/run/php5-fpm.sock; fastcgi_split_path_info ^(.+\.php)(/.*)$; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param HTTPS off; # Prevents URIs that include the front controller. This will 404: # http://domain.tld/app.php/some-path # Remove the internal directive to allow URIs like this internal; } error_log /var/log/nginx/my_error.log; access_log /var/log/nginx/my_access.log; }
上記の最後の2つのディレクティブに関して、 access_log
は一般的なリクエストログを表し、 error_log
はエラー用です。また、アプリケーションエラーログと同様に、問題を警告する追加の監視を設定して、迅速に対応できるようにする価値があります。
注:これは意図的に過度に単純化されたnginx構成ファイルであり、例としてのみ提供されています。 セキュリティとパフォーマンスにはほとんど注意を払わないため、「実際の」環境でそのまま使用しないでください。
これは、ブラウザでhttp://my.log-sandbox/app_dev.php/
/var/log/nginx/my_access.log
入力し、 Enter
を押した後、/ var / log / nginx/my_access.logに表示されるものです。
192.168.56.1 - - [26/Apr/2015:16:13:28 +0300] "GET /app_dev.php/ HTTP/1.1" 200 6715 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.90 Safari/537.36" 192.168.56.1 - - [26/Apr/2015:16:13:28 +0300] "GET /bundles/framework/css/body.css HTTP/1.1" 200 6657 "http://my.log-sandbox/app_dev.php/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.90 Safari/537.36" 192.168.56.1 - - [26/Apr/2015:16:13:28 +0300] "GET /bundles/framework/css/structure.css HTTP/1.1" 200 1191 "http://my.log-sandbox/app_dev.php/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.90 Safari/537.36" 192.168.56.1 - - [26/Apr/2015:16:13:28 +0300] "GET /bundles/acmedemo/css/demo.css HTTP/1.1" 200 2204 "http://my.log-sandbox/app_dev.php/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.90 Safari/537.36" 192.168.56.1 - - [26/Apr/2015:16:13:28 +0300] "GET /bundles/acmedemo/images/welcome-quick-tour.gif HTTP/1.1" 200 4770 "http://my.log-sandbox/app_dev.php/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.90 Safari/537.36" 192.168.56.1 - - [26/Apr/2015:16:13:28 +0300] "GET /bundles/acmedemo/images/welcome-demo.gif HTTP/1.1" 200 4053 "http://my.log-sandbox/app_dev.php/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.90 Safari/537.36" 192.168.56.1 - - [26/Apr/2015:16:13:28 +0300] "GET /bundles/acmedemo/images/welcome-configure.gif HTTP/1.1" 200 3530 "http://my.log-sandbox/app_dev.php/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.90 Safari/537.36" 192.168.56.1 - - [26/Apr/2015:16:13:28 +0300] "GET /favicon.ico HTTP/1.1" 200 6518 "http://my.log-sandbox/app_dev.php/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.90 Safari/537.36" 192.168.56.1 - - [26/Apr/2015:16:13:30 +0300] "GET /app_dev.php/_wdt/e50d73 HTTP/1.1" 200 13265 "http://my.log-sandbox/app_dev.php/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.90 Safari/537.36"
これは、1つのページを提供するために、ブラウザーが実際に9つのHTTP呼び出しを実行することを示しています。 ただし、そのうちの7つは、プレーンで軽量な静的コンテンツへのリクエストです。 ただし、それらは依然としてネットワークリソースを使用し、これはさまざまなスプライトと縮小化手法を使用して最適化できるものです。
これらの最適化については別の記事で説明しますが、ここで重要なのは、静的コンテンツへのリクエストを、別のlocation
ディレクティブを使用して個別にログに記録できることです。
location ~ \.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|pdf|txt|tar|wav|bmp|rtf|js)$ { access_log /var/log/nginx/my_access-static.log; }
nginx location
は単純な正規表現のマッチングを実行するため、サイトにディスパッチする予定の静的コンテンツ拡張機能をいくつでも含めることができます。
このようなログの解析は、アプリケーションログの解析と同じです。
言及する価値のある他のログ
言及する価値のある他の2つのPHPログは、デバッグログとデータストレージログです。
デバッグログ
nginxログのもう1つの便利な点は、デバッグログです。 構成のerror_log
行を次のように置き換えることでオンにできます(nginxデバッグモジュールがインストールされている必要があります)。
error_log /var/log/nginx/my_error.log debug;
同じ設定がApacheまたは使用する他のWebサーバーにも適用されます。
ちなみに、デバッグログは、 error_log
ディレクティブで構成されていても、エラーログとは関係ありません。
デバッグログは確かに冗長である可能性がありますが(たとえば、単一のnginxリクエストで127KBのログデータが生成されます!)、それでも非常に便利です。 ログファイルをくぐり抜けるのは面倒で面倒かもしれませんが、デバッグプロセスを加速するのに大いに役立つ手がかりと情報をすばやく提供できることがよくあります。
特に、デバッグログは、nginx構成、特にlocation
マッチングやrewrite
チェーンなどの最も複雑な部分のデバッグに非常に役立ちます。
もちろん、本番環境ではデバッグログを有効にしないでください。 また、使用するスペースの量と保存する情報の量は、サーバーに大量のI / O負荷をかけることを意味し、システム全体のパフォーマンスを大幅に低下させる可能性があります。
データストレージログ
別の種類のサーバーログ(デバッグに役立ちます)は、データストレージログです。 MySQLでは、次の行を追加することでそれらをオンにできます。
[mysqld] general_log = 1 general_log_file = /var/log/mysql/query.log
これらのログには、データベース要求を時系列で処理しているときにシステムによって実行されるクエリのリストが含まれているだけです。これは、さまざまなデバッグやトレースのニーズに役立ちます。 ただし、パフォーマンスに影響を与える余分な不要なI / O負荷が発生するため、実稼働システムでは有効のままにしないでください。
ログファイルへの書き込み
PHP自体は、ログファイルを開いたり、書き込んだり、閉じたりするための関数を提供します(それぞれ、 openlog()
、 syslog()
、およびcloselog()
)。
また、Monolog(SymfonyおよびLaravelユーザーの間で人気)などのPHP開発者向けの多数のロギングライブラリや、CakePHPに組み込まれたロギング機能などのさまざまなフレームワーク固有の実装もあります。 一般に、Monologのようなライブラリは、 syslog()
呼び出しをラップするだけでなく、他のバックエンド機能やツールを使用することもできます。

ログへの書き込み方法の簡単な例を次に示します。
<?php openlog(uniqid(), LOG_ODELAY, LOG_LOCAL0); syslog(LOG_INFO, 'It works!');
ここでopenlog
を呼び出します:
- スクリプトの存続期間内に各システムログメッセージに一意の識別子を付加するようにPHPを構成します
- 最初の
syslog()
呼び出しが発生するまでsyslog接続を開くのを遅らせるように設定します LOG_LOCAL0
をデフォルトのログ機能として設定します
上記のコードを実行した後のログファイルの内容は次のようになります。
# cat /var/log/my/info.log Mar 2 00:23:29 log-sandbox 54f39161a2e55: It works!
PHPログファイルの価値を最大化する
理論と基本にすべて慣れてきたので、サンプルのSymfonyStandardプロジェクトにできるだけ少ない変更を加えるだけでログからどれだけのことが得られるかを見てみましょう。
まず、スクリプトsrc/log-begin.php
(ログを適切に開いて構成するため)とsrc/log-end.php
(正常に完了したことに関する情報をログに記録するため)を作成しましょう。 簡単にするために、すべてのメッセージを情報ログに書き込むだけであることに注意してください。
# src/log-begin.php <?php define('START_TIME', microtime(true)); openlog(uniqid(), LOG_ODELAY, LOG_LOCAL0); syslog(LOG_INFO, 'BEGIN'); syslog(LOG_INFO, "URI\t{$_SERVER['REQUEST_URI']}"); $browserHash = substr(md5($_SERVER['HTTP_USER_AGENT']), 0, 7); syslog(LOG_INFO, "CLIENT\t{$_SERVER['REMOTE_ADDR']}\t{$browserHash}"); <br /> # src/log-end.php <?php syslog(LOG_INFO, "DISPATCH TIME\t" . round(microtime(true) - START_TIME, 2)); syslog(LOG_INFO, 'END');
そして、 app.php
でこれらのスクリプトを要求しましょう:
<?php require_once(dirname(__DIR__) . '/src/log-begin.php'); syslog(LOG_INFO, "MODE\tPROD"); # original app.php contents require_once(dirname(__DIR__) . '/src/log-end.php');
開発環境では、 app_dev.php
にもこれらのスクリプトが必要です。 そのためのコードは、 MODE
をPROD
ではなくDEV
に設定することを除いて、上記と同じです。
また、呼び出されているコントローラーを追跡したいので、 Acme\DemoBundle\EventListener\ControllerListener
のControllerListener::onKernelController()
メソッドの先頭にもう1行追加しましょう。
syslog(LOG_INFO, "CONTROLLER\t" . get_class($event->getController()[0]));
これらの変更により、合計で15行のコードが追加されますが、まとめて豊富な情報が得られることに注意してください。
ログファイルのデータを分析する
手始めに、各ページの読み込みを処理するために必要なHTTPリクエストの数を見てみましょう。
ロギングの構成方法に基づいた、1つのリクエストのログの情報は次のとおりです。
Mar 3 12:04:20 log-sandbox 54f58724b1ccc: BEGIN Mar 3 12:04:20 log-sandbox 54f58724b1ccc: URI /app_dev.php/ Mar 3 12:04:20 log-sandbox 54f58724b1ccc: CLIENT 192.168.56.1 1b101cd Mar 3 12:04:20 log-sandbox 54f58724b1ccc: MODE DEV Mar 3 12:04:23 log-sandbox 54f58724b1ccc: CONTROLLER Acme\DemoBundle\Controller\WelcomeController Mar 3 12:04:25 log-sandbox 54f58724b1ccc: DISPATCH TIME 4.51 Mar 3 12:04:25 log-sandbox 54f58724b1ccc: END Mar 3 12:04:25 log-sandbox 54f5872967dea: BEGIN Mar 3 12:04:25 log-sandbox 54f5872967dea: URI /app_dev.php/_wdt/59b8b6 Mar 3 12:04:25 log-sandbox 54f5872967dea: CLIENT 192.168.56.1 1b101cd Mar 3 12:04:25 log-sandbox 54f5872967dea: MODE DEV Mar 3 12:04:28 log-sandbox 54f5872967dea: CONTROLLER Symfony\Bundle\WebProfilerBundle\Controller\ProfilerController Mar 3 12:04:29 log-sandbox 54f5872967dea: DISPATCH TIME 4.17 Mar 3 12:04:29 log-sandbox 54f5872967dea: END
これで、各ページの読み込みが実際には2つのHTTPリクエストで処理されることがわかりました。
実際、ここで言及する価値のある2つのポイントがあります。 まず、ページの読み込みごとに2つのリクエストは、開発モードでSymfonyを使用するためのものです(これはこの記事全体で行いました)。 /app-dev.php/
URLチャンクを検索することで、開発モードの呼び出しを識別できます。 次に、各ページのロードがSymfonyアプリへの2つの後続のリクエストで提供されるとしましょう。 以前にnginxアクセスログで見たように、実際にはより多くのHTTP呼び出しがあり、そのうちのいくつかは静的コンテンツ用です。
では、デモサイトを少し見て(ログファイルにデータを蓄積するために)、これらのログから他に何を学べるかを見てみましょう。
ログファイルの開始以降、合計でいくつのリクエストが処理されましたか?
# grep -c BEGIN info.log 10
それらのいずれかが失敗しましたか(スクリプトは最後に到達せずにシャットダウンしましたか)?
# grep -c END info.log 10
BEGIN
レコードとEND
レコードの数が一致していることがわかります。これは、すべての呼び出しが成功したことを示しています。 (PHPスクリプトが正常に完了しなかった場合、 src/log-end.php
スクリプトの実行には到達していません。)
サイトルートへのリクエストの割合はどのくらいでしたか?
# `grep -cE "\s/app_dev.php/$" info.log` 2
これは、サイトルートが2ページ読み込まれたことを示しています。 以前に、(a)ページの読み込みごとにアプリへのリクエストが2つあり、(b)合計10のHTTPリクエストがあることを知ったので、サイトルートへのリクエストの割合は40%(つまり、2x2 / 10)でした。
サイトルートへのリクエストの処理を担当するコントローラークラスはどれですか?
# grep -E "\s/$|\s/app_dev.php/$" info.log | head -n1 Mar 3 12:04:20 log-sandbox 54f58724b1ccc: URI /app_dev.php/ # grep 54f58724b1ccc info.log | grep CONTROLLER Mar 3 12:04:23 log-sandbox 54f58724b1ccc: CONTROLLER Acme\DemoBundle\Controller\WelcomeController
ここでは、リクエストの一意のIDを使用して、その単一のリクエストに関連するすべてのログメッセージを確認しました。 これにより、サイトルートへのリクエストの処理を担当するコントローラークラスがAcme\DemoBundle\Controller\WelcomeController
であると判断できました。
サブネット
192.168.0.0/16
のIPを持つどのクライアントがサイトにアクセスしましたか?
# grep CLIENT info.log | cut -d":" -f4 | cut -f2 | sort | uniq 192.168.56.1
この単純なテストケースで予想されるように、私のホストコンピューターだけがサイトにアクセスしました。 これはもちろん非常に単純な例ですが、それが示す機能(サイトへのトラフィックのソースを分析できる機能)は明らかに非常に強力で重要です。
私のサイトへのトラフィックのどれくらいがFireFoxからのものですか?
Firefox User-Agentのハッシュとして1b101cd
を使用しているので、この質問に次のように答えることができます。
# grep -c 1b101cd info.log 8 # grep -c CLIENT info.log 10
回答:80%(つまり、8/10)
応答が遅いリクエストの割合はどれくらいですか?
この例では、応答を提供するのに5秒以上かかることを「遅い」と定義します。 によると:
# grep "DISPATCH TIME" info.log | grep -cE "\s[0-9]{2,}\.|\s[5-9]\." 2
回答:20%(つまり、2/10)
誰かがGETパラメータを提供したことがありますか?
# grep URI info.log | grep \?
いいえ、Symfony標準はURLスラッグのみを使用しているので、これはまた、誰もサイトをハッキングしようと試みていないことをここで示しています。
これらは、ログファイルをクリエイティブに活用して、貴重な使用情報や基本的な分析を生成する方法の、比較的基本的な例のほんの一握りです。
心に留めておくべき他の事柄
物事を安全に保つ
もう1つの注意点は、セキュリティです。 リクエストをログに記録することは良い考えだと思うかもしれませんが、ほとんどの場合、そうです。 ただし、機密性の高い可能性のあるユーザー情報をログに保存する前に、削除する場合は十分に注意することが重要です。
ファイティングログファイルの肥大化
ログファイルは常に情報を追加するテキストファイルであるため、絶えず増え続けています。 これはよく知られている問題であるため、ログファイルの増加を制御するためのかなり標準的なアプローチがいくつかあります。
最も簡単なのは、ログをローテーションすることです。 ログのローテーションとは、次のことを意味します。
- さらに書き込むために、ログを定期的に新しい空のファイルに置き換えます
- 履歴のために古いファイルを保存する
- ディスク領域を解放するのに十分に「古くなった」ファイルを削除する
- これらのファイルの変更が発生したときに、アプリケーションが統合されたログに書き込めることを確認します
このための最も一般的な解決策はlogrotate
で、これはほとんどの*nixディストリビューションがプリインストールされた状態で出荷されます。 ログをローテーションするための簡単な構成ファイルを見てみましょう。
/var/log/my/debug.log /var/log/my/info.log /var/log/my/warning.log /var/log/my/error.log { rotate 7 daily missingok notifempty delaycompress compress sharedscripts postrotate invoke-rc.d rsyslog rotate > /dev/null endscript }
もう1つのより高度なアプローチは、 rsyslogd
自体に、現在の日付と時刻に基づいて動的に作成されたメッセージをファイルに書き込むようにすることです。 これには、古いファイルを削除するためのカスタムソリューションが必要ですが、DevOpsが各ログファイルの時間枠を正確に管理できるようにします。 この例の場合:
$template DynaLocal0Err, "/var/log/my/error-%$NOW%-%$HOUR%.log" $template DynaLocal0Info, "/var/log/my/info-%$NOW%-%$HOUR%.log" $template DynaLocal0Warning, "/var/log/my/warning-%$NOW%-%$HOUR%.log" $template DynaLocal0Debug, "/var/log/my/debug-%$NOW%-%$HOUR%.log" local1.err -?DynaLocal0Err local1.info -?DynaLocal0Info local1.warning -?DynaLocal0Warning local1.debug -?DynaLocal0Debug
このように、 rsyslog
は1時間ごとに個別のログファイルを作成し、それらをローテーションしてデーモンを再起動する必要はありません。 このソリューションを実現するために、5日より古いログファイルを削除する方法は次のとおりです。
find /var/log/my/ -mtime +5 -print0 | xargs -0 rm
リモートログ
プロジェクトが成長するにつれて、ログからの情報の解析はますます多くのリソースを必要とします。 これは、余分なサーバー負荷を作成することを意味するだけではありません。 また、ログを解析するときにCPUとディスクドライブにピーク負荷がかかることを意味します。これにより、ユーザーのサーバー応答時間が低下する可能性があります(最悪の場合、サイトがダウンする可能性もあります)。
これを解決するには、集中ログサーバーのセットアップを検討してください。 これに必要なのは、UDPポート514(デフォルト)が開いている別のボックスです。 rsyslogd
に接続をリッスンさせるには、構成ファイルに次の行を追加します。
$UDPServerRun 514
これがあれば、クライアントのセットアップは次のように簡単になります。
*.* @HOSTNAME:514
(ここで、 HOSTNAME
はリモートログサーバーのホスト名です)。
結論
この記事では、ログファイルが以前に想像していたよりもはるかに価値のある情報を提供できるクリエイティブな方法のいくつかを示しましたが、可能なことのほんの一部にすぎないことを強調することが重要です。 ログに記録できる範囲、範囲、および形式はほぼ無制限です。 つまり、ログから抽出したい使用状況または分析データがある場合は、後で解析および分析しやすい方法でログに記録するだけで済みます。 さらに、その分析は、 grep
、 sed
、 awk
などの標準のLinuxコマンドラインツールを使用して実行できることがよくあります。
実際、PHPログファイルは非常に強力なツールであり、非常に有益です。
資力
GitHubのコード:https://github.com/isanosyan/toptal-blog-logs-post-example
付録:Unixシェルでのログファイルの読み取りと操作
ここでは、ログファイルの読み取りと操作に精通している、より一般的な*nixコマンドラインツールの簡単な紹介を示します。
cat
はおそらく最も単純なものです。 ファイル全体を出力ストリームに出力します。 たとえば、次のコマンドはlogfile1
をコンソールに出力します。cat logfile1
>
文字を使用すると、ユーザーは出力を別のファイルなどにリダイレクトできます。 ターゲットストリームを書き込みモードで開きます(つまり、ターゲットコンテンツを消去します)。tmpfile
の内容をlogfile1
の内容に置き換える方法は次のとおりです。cat logfile1 > tmpfile
>>
出力をリダイレクトし、追加モードでターゲットストリームを開きます。 ターゲットファイルの現在の内容が保持され、新しい行が下部に追加されます。 これにより、logfile1
内容がtmpfile
に追加されます。cat logfile1 >> tmpfile
grep
はファイルをいくつかのパターンでフィルタリングし、一致する行のみを出力します。 以下のコマンドは、Bingo
メッセージを含むlogfile1
の行のみを出力します。grep Bingo logfile1
cut
は、単一の列の内容を(1から始まる番号で)印刷します。 デフォルトでは、列間の区切り文字としてタブ文字を検索します。 たとえば、YYYY-MM-DD HH:MM:SS
形式のタイムスタンプでいっぱいのファイルがある場合、これにより、年のみを印刷できます。cut -d"-" -f1 logfile1
head
は、ファイルの最初の行のみを表示しますtail
は、ファイルの最後の行のみを表示しますsort
は、出力の行をソートしますuniq
は重複行を除外しますwc
は単語(または-l
フラグとともに使用される場合は行)をカウントします|
(つまり、「パイプ」記号)は、あるコマンドからの出力を次のコマンドへの入力として提供します。 パイプはコマンドを組み合わせるのに非常に便利です。 たとえば、一連のタイムスタンプ内で発生する2014年の月を見つける方法は次のとおりです。grep -E "^2014" logfile1 | cut -d"-" -f2 | sort | uniq
ここでは、最初に「2014年から始まる」正規表現と行を照合し、次に月を削減します。 最後に、 sort
とuniq
の組み合わせを使用して、オカレンスを1回だけ出力します。