Resque の計測

New Relic Ruby エージェントには、Web アプリケーションの計測に加えて、Resque ジョブも計測できます。

ジョブの引数の保存

Ruby エージェントのバージョン 3.6.9 以降では、トランザクショントレースとトレースエラーでにおいて、Resque ジョブの引数を取得できる設定が Rubyエージェントにあります。この設定は、失敗したジョブの再現時に特に役立ちます。ジョブの引数に機密情報が含まれている場合を考慮し、デフォルトでこの機能はオフです。有効にするには、以下のようにエージェントのバージョンに合わせて newrelic.yml を編集します。

newrelic_rpm 3.6.9 から 3.11.X の場合

resque.capture_params: true

newrelic_rpm 3.12.0 以上の場合

attributes.include: job.resque.args.*
この機能は、トランザクショントレースやトレースエラーの HTTP リクエストパラメータをキャプチャするかどうかを制御する、capture_params 設定とは違うものです。これらの2つ設定は、個別に設定できます。

Resque のバージョン 1.23.1 以上

バージョン 1.23.1 以上の Resque を実行している場合は、New Relic の Resque 計測を利用するには、通常の手順に従ってエージェントをインストールしていれば、特にやることはありません。

例外: 古いバージョンの Resque を実行しており、before_first_forkbefore_forkafter_forkNewRelic::Agent メソッドへの呼び出しが残っている場合は、Resque 1.23.1 以降にアップグレードし、その後これらの呼び出しを削除してください。

代わりのフォークモード

resque-multi-job-forks gem や resque-jobs-per-fork gem は、Resque のフォーク動作を変更します。個々のジョブごとにフォークするのではなく、ジョブのバッチごとに 1回フォークします。同様に、Resque でフォークを完全に無効にするには、FORK_PER_JOB 環境変数に false に設定します。

これらの別のフォークモードをアプリで使うには、Ruby エージェントのバージョンが 3.9.7 以降であることを確認してください。以前のバージョンのエージェントは、これらの代替フォークモードでは正しく動作しません。3.9.7 にアップグレードする場合は、エージェントがこれらの環境で動作するようにするために、以前使用していた可能性がある manual_startafter_fork などのNewRelic::Agent メソッドへの直接呼び出しをすべて削除してください。

旧 Resque バージョン (< 1.23.1)

1.23.1 より古いバージョンの Resque で New Relic の Ruby エージェントを使用することは可能ですが、より役に立つ情報を得るために Resque 1.23.1 以上にアップグレードすることを強くお勧めします。

多くのアプリケーションでは、Resque (before_fork, after_forkなど)の公開フックを使って、Resque ジョブの生存期間中に、重要な箇所にカスタムコードを挿入しています。New Relic Ruby エージェントも、これらのフックを使って、計測できるようにしています。

1.23.1 より古いバージョンの Resque では、フックを複数回定義できません。最後の定義が優先されます。(相互に上書きすることなく、フックを複数回定義できるようになっている) 1.23.1 以上のバージョンにアップグレードできない場合、以下のように New Relic コードを追加して、Resque フックを変更できます。

注: カスタムコードのないフックの定義は省略できます。その場合、エージェントによって自動的にインストールされます。

例:

Resque.before_first_fork do
  # ... your custom hook code ...
  NewRelic::Agent.manual_start(:dispatcher   => :resque,
                               :sync_startup => true,
                               :start_channel_listener => true)
end

Resque.before_fork do |job|
  # ... your custom hook code ...
  NewRelic::Agent.register_report_channel(job.object_id)
end

Resque.after_fork do |job|
  # ... your custom hook code ...
  NewRelic::Agent.after_fork(:report_to_channel => job.object_id,
                             :report_instance_busy => false)
end

Resque と X-RAY セッション

X-Ray セッション のスレッドプロファイリングは、Resque では使用できません。X-Ray 機能を使って、トランザクショントレースを収集できますが、スレッドプロファイル情報は表示されません。

デッドドロックジョブ

一部の顧客(特にジョブスループットが非常に高いユーザー)から、Ruby エージェントを有効にした Resque ワーカープロセスで断続的なデッドロックに陥いったと報告を受けています。このデッドロックは、Ruby エージェントが New Relic サーバーにデータを送信するために使用するバックグラウンドスレッドと Resque のフォーク動作との間におけるの相性の悪さに起因するものです。

これらの問題に対処する方法は、以下の2つあります。

  • Resque プロセスを起動するときに、FORK_PER_JOB 環境変数を false に設定して、Resqueのフォーク動作を無効にします。
  • Ruby の標準ライブラリの resolv-replace ライブラリを使って、Ruby のネイティブ DNS 解決コードを純粋な Rubyバージョンに置き換えます。

Ruby エージェントは、Resque マスタープロセスのバックグラウンドスレッドを使って、New Relic サーバーにデータを送信します。いくつかの環境では、このスレッドは DNS 解決中 (New Relic サーバーのホスト名を解決時)にネイティブロックを取得します。

メインの Resque マスタープロセスのメインスレッドが fork を呼び出して、子プロセスを作成している間、このネイティブロックがバックグラウンドスレッドによって保持されている場合、フォークされた子プロセスで保持されているとマークされます。ただし、fork は呼び出し元のスレッドのみをコピーするため、ネイティブロックを保持していたバックグラウンドスレッドは子プロセスに存在しないため、ネイティブロックは決して解放されません。子プロセスが DNS 解決を試みると、同じネイティブロックとデッドロックを取得しようとします。Ruby のデフォルト DNS 解決パスの代わりに resolv-replace を使って、この GitHub の問題を回避します。