-
Notifications
You must be signed in to change notification settings - Fork 9
logging
Herokuにおけるログとは、アプリケーションが実行中のプロセス、システムコンポーネント、後方で実行されるサービスの各アウトプットから収集された時系列イベントのストリームのことです。HerokuのLogplexは、このような多種多様なソースからのログのストリームを単一のチャンネルへルーティングし、実に理解し易いログを収集するための基盤を提供します。
Herokuは、アプリケーションから3つのカテゴリのログを収集します。:
- App logs - アプリケーションからのアウトプットです。アプリケーション、アプリケーションサーバー、ライブラリ内から生成されるログを含むこととなります。(ログのフィルターが可能です:
--source app
) - System logs - アプリケーションに代わって、Herokuのインフラが実行するアクションに関するメッセージ群です。以下のようなアクションがあります。: クラッシュしたプロセスの再起動、web dynoをアイドリングさせる、またはアイドリングから復帰させる、アプリケーションの問題によりエラーページを提供すると言ったアクションです。(ログのフィルターが可能です:
--source heroku
) - API logs - あなたとその他開発者による管理者権限のアクションに関するメッセージ群です。以下のようなアクションがあります。: 新たなコードのデプロイ、プロセス形式のスケーリング、メンテナンスモードのOn・Offと言ったアクションです。(ログのフィルターが可能です:
--source heroku --ps api
)
Logplexはログのメッセージをページ順に並べて表示するように設計されており、保存するためには設計されていません。統合されたログの最後の1500行を維持します。長い期間のログを保存するためには別のサービスの使用を推奨します。更なる情報はシステムログを外部へドレイン(排出)するの項目を参照してください。
標準出力(stdout
)、または標準エラー出力(stderr
)に書き込まれるものは全てログに保存されます。このことは、シンプルな出力文を追加すれば、アプリケーションコードのどこからでもログを取れることを意味します。
Rubyでは、このような感じです。:
:::ruby
puts "Hello, logs!"
Javaでは、このような感じです。:
:::java
System.err.println("Hello, logs!");
System.out.println("Hello, logs!");
Herokuでサポートされる全ての他の言語も同じ事をいうことができます。
リアルタイムなロギングを利用するために、アプリケーションが実行しているだろうログバッファリングを無効化する必要があるかもしれません。例えば、Rubyの場合以下のコードをconfig.ru
に追加してください :
$stdout.sync = true
いくつかのフレームワークはデフォルトでstdout
以外の場所にログを出力します。この場合は、特別な設定が必要になるでしょう。例えばRuby on RailsのActiveSupportによるTaggedLoggerを使用している場合、stdout
でログを残すために以下のコードをあなたのアプリケーションの設定に追加するべきでしょう :
:::ruby
config.logger = Logger.new(STDOUT)
ログをフェッチするには:
:::term
$ heroku logs
2010-09-16T15:13:46-07:00 app[web.1]: Processing PostController#list (for 208.39.138.12 at 2010-09-16 15:13:46) [GET]
2010-09-16T15:13:46-07:00 app[web.1]: Rendering template within layouts/application
2010-09-16T15:13:46-07:00 app[web.1]: Rendering post/list
2010-09-16T15:13:46-07:00 app[web.1]: Rendered includes/_header (0.1ms)
2010-09-16T15:13:46-07:00 app[web.1]: Completed in 74ms (View: 31, DB: 40) | 200 OK [http://myapp.heroku.com/]
2010-09-16T15:13:46-07:00 heroku[router]: GET myapp.heroku.com/posts queue=0 wait=0ms service=1ms bytes=975
2010-09-16T15:13:47-07:00 app[worker.1]: 2 jobs processed at 16.6761 j/s, 0 failed ...
この例では、アプリケーションの1web dynoからのログ、HerokuのHTTPルーターからのログ、アプリケーションの1ワーカーからのログを含んだ出力となっています。
logsコマンドは、デフォルトで100行のログを検索します。
ログを検索する時に、ログがいつも正しい順序に並んでいる訳ではないことに気付くかもしれません。特に複数のコンポーネントが内包されている場合はそうです。これは分散コンピューティングの弊害の様な物です。ログは多くのソース(ルータノード、Dynoなど)を期限とし、logplexによって一つのストリームへと集められます。もし、ログを整え、アプリケーションによって要求される順番で生成する必要があるならは、それをするかはユーザ次第です。
--num
(または、-n
オプション)を使うことで、1500行までのログをフェッチすることが可能です。:
:::term
$ heroku logs -n 200
Herokuはログの履歴の最後の1500行しか残しません。もし1500行以上残したいのならば、ログ用のアドオンを使用するか、自分のシステムログのドレインを作成してください。
ログの各行は、以下のような形式でフォーマットされています。:
タイムスタンプ ソース[プロセス]: メッセージ
- タイムスタンプ - プロセス及びコンポーネントにより、ログが生成された日付と時間
-
ソース - アプリケーションの全プロセス(webプロセス、バックグラウンドワーカー、cron)は、
app
と表示されます。Herokuの全システムコンポーネント(HTTPルーター、プロセスマネージャー)は、heroku
と表示されます。 -
プロセス - ログへ書き込みを行うプロセス、またはコンポーネントの名称のことです。例えば、worker #3は、
worker.3
と表示され、HerokuのHTTPルーターは、router
と表示されます。 - メッセージ - ログの各行の中身のことです。
tail -f
コマンドと良く似ていますが、realtime tailは直近のログを表示し、ストリームされるリアルタイムなログを取得するため、セッションを解放した状態に保ちます。アプリケーションからの生のログストリームを参照することで、アプリケーションの動きを洞察し、現状の問題をデバグすることが可能です。
--tail
(または、-t
)を使うことでログを追跡(tail)することが可能です。
:::term
$ heroku logs --tail
作業が終わりましたら、Ctrl-Cを押し、セッションを終了させて下さい。
特定のソース、特定のプロセス、またはその両方からログをフェッチしたい場合、--source
(または、-s
)と--ps
(または、-p
)のフィルタリング引数を使うことが可能です。:
:::term
$ heroku logs --ps router
2012-02-07T09:43:06+00:00 heroku[router]: GET devcenter.heroku.com/stylesheets/dev-center/library.css dyno=web.5 queue=0 wait=0ms service=3ms status=200 bytes=1753
2012-02-07T09:43:06+00:00 heroku[router]: GET devcenter.heroku.com/articles/bundler dyno=web.6 queue=0 wait=0ms service=61ms status=200 bytes=20375
$ heroku logs --source app
2012-02-07T09:45:47+00:00 app[web.1]: Rendered shared/_search.html.erb (1.0ms)
2012-02-07T09:45:47+00:00 app[web.1]: Completed 200 OK in 83ms (Views: 48.7ms | ActiveRecord: 32.2ms)
2012-02-07T09:45:47+00:00 app[worker.1]: [Worker(host:465cf64e-61c8-46d3-b480-362bfd4ecff9 pid:1)] 1 jobs processed at 23.0330 j/s, 0 failed ...
2012-02-07T09:46:01+00:00 app[web.6]: Started GET "/articles/buildpacks" for 4.1.81.209 at 2012-02-07 09:46:01 +0000
$ heroku logs --source app --ps worker
2012-02-07T09:47:59+00:00 app[worker.1]: [Worker(host:260cf64e-61c8-46d3-b480-362bfd4ecff9 pid:1)] Article#record_view_without_delay completed after 0.0221
2012-02-07T09:47:59+00:00 app[worker.1]: [Worker(host:260cf64e-61c8-46d3-b480-362bfd4ecff9 pid:1)] 5 jobs processed at 31.6842 j/s, 0 failed ...
プロセスによるフィルタリングの場合、基本名称の--ps web
、完全一致名称の--ps web.1
のどちらも使用可能です。
フィルターされたアウトプットのリアルタイムストリームを取得するために、--tail
を使い、フィルタリングの切替を組み合わせることも可能です。
:::term
$ heroku logs --source app --tail
Logplexのドレイン(外部への排出機能)は、Herokuのログを外部のシステムログ管理用サーバーへ長期間アーカイブするために、転送することを許可しています。Herokuのシステムログのパケットを取得可能とするためには、Logplexのドレイン、またはシステムログ管理用サーバー自体を設定する必要があります。この設定の後で、システムログのURL(ホスト名とポート番号を含む)をドレインとして追加する必要があります。
ドレインするログは、 RFC5424に沿ってフォーマットされます。これらはRFC6587で説明されるTCPプロトコルとoctet counting framing methodを経由し伝達されます。
ログ監視系のサービスを見つけるには、Herokuアドオンを訪問して下さい。
ドレインを作る際、d.9173ea1f-6f14-4976-9cf0-7cd0dafdcdbc
のような見た目のユニークなドレインIDが割り当てられます。あなたのアプリケーションのドレインIDはheroku drains -x
を実行することで発見する事ができます。
:::term
$ heroku drains -x
syslog://logs.example.com (d.9173ea1f-6f14-4976-9cf0-7cd0dafdcdbc)
この識別子はドレインからの全てのログのメッセージに書き込まれます。
Jan 1 01:01:01 d.9173ea1f-6f14-4976-9cf0-7cd0dafdcdbc app[web.1] Your message here.
IDは別のドレインから送られるログメッセージを同じドレインURLに分けるために使う事が出来ます。別のアプリケーション上にある同じURLへ向いているドレインは違うIDを持ちます。ドレインIDはドレインがある限り同じ物がつかわれます。しかし、ドレインを消したり、同じドレインを追加し直したりすると変わります。
Ubuntuとrsyslogを使い、スタンドアローンのEC2インスタンスを実行することが可能です。始めるにあたり、インスタンスを起動し、Herokuのサーバーをシステムログのポートへアクセス可能とする設定をして下さい。
:::term
$ ec2-run-instances -t t1.micro ami-6006f309
$ ec2-authorize default -P tcp -p 514 -u 098166147350 -o logplex
インスタンス起動後、インスタンスへssh接続し、/etc/rsyslog.conf
を編集し、以下の行を追加して下さい。:
# provides TCP syslog reception
$ModLoad imtcp
$InputTCPServerRun 514
# provides timestamps similar to other heroku logs
$ActionFileDefaultTemplate RSYSLOG_FileFormat
rsyslogを再起動します。:
:::term
$ restart rsyslog
インスタンスが、Herokuからのシステムログを受信する準備が整いました。EC2インスタンスのパブリックIPアドレス、またはホスト名をドレインのaddコマンドへコピー&ペーストして下さい。:
:::term
$ heroku drains:add syslog://host1.example.com:514
Drain syslog://host1.example.com:514 added to myapp
複数のドレインを追加することも可能です。:
:::term
$ heroku drains:add syslog://host2.example.com:9999
Drain syslog://host2.example.com:9999 added to myapp
稼働しているドレインのリストを表示することも可能です。:
:::term
$ heroku drains
syslog://host1.example.com:514
syslog://host2.example.com:9999
ドレインをリムーブするには、下記のコマンドを実行して下さい。:
:::term
$ heroku drains:remove syslog://two.example.org:584
Removing syslog drain... done
EC2のセキュリティグループをお使いの場合、ドレイン追加時に使用されるホスト名が、インスタンス(Amazonの北米東部リージョンに属していなければならない)の10/8のネットワークのプライベートIPアドレスとして解決されなければなりません。EC2のパブリックIPアドレスをお使いの場合、またはパブリックIPアドレスへ解決されるホスト名をお使いの場合、logplexはドレインへの接続が不可能となります。