Top takeaways
本記事は 「Monitor Elasticsearch with the New Relic Ruby agent」の抄訳記事になります。
Elasticsearchは、2010年のリリース以来、分散型データストアとしてもっとも人気のある検索および分析エンジンのひとつです。オープンソースのツールであり、関連性の高い検索結果を高速でユーザーに提供します。ストリーミングサービスで番組を検索したり、アプリで食料品の宅配を注文するときには、Elasticsearchがそのジャーニーの一部に使用されていることが多いでしょう。
ElasticsearchをRubyアプリケーションの他の部分と関連づけて監視することは、Elasticsearchクラスタへのリクエストに関連するパフォーマンスの問題やエラーを特定、解決するのに役立ちます。
New RelicのRubyエージェントのバージョン8.12.0は、Elasticsearch gemのバージョン7.xおよび8.xの自動インストゥルメンテーションを採用し、お使いのElasticsearchの実装が長期的にどう機能するか、より完全な全体像を提供します。Elasticsearchは自動でインストゥルメンテーションされるため、Elasticsearchクライアントからのリクエストを監視するために必要なことは、Rubyエージェントをバージョン8.12.0以降にアップグレードするだけです。
このブログ記事では、New RelicのチームがElasticsearchでRubyのメタプログラミングをどのようにインストゥルメントしたのか、Rubyエージェントのアップデート方法、そして必要に応じてクエリをキャプチャまたは難読化するためにRubyエージェントをどう設定すればいいのかをご紹介します。
Elasticsearchのメタプログラミングのインストゥルメンテーション
New RelicのRubyエージェントは、メタプログラミングの技法を使用して、自分たちが監視をしたい、また一般に使用されているライブラリの公開メソッドに、New Relicのインストゥルメンテーションコードを挿入します。Elasticsearch gemを含む多くのライブラリは、コールバックやフックの使用を想定して設計されていません。これを機能させるため、メタプログラミングを使用してカスタムインストゥルメンテーションメソッドをこれらのライブラリに追加します。
自動的にデフォルトでModule#prepend
と呼ばれる手法を使用し、既存のメソッドの継承チェーンにインストゥルメンテーションコードを挿入しますが、これらの2つの手法に矛盾が生じる場合にはalias_method
チェーンを使用します。以下は、チェーンを使用したソースコードの例です。
to_instrument = if ::Gem::Version.create(::Elasticsearch::VERSION) <
::Gem::Version.create("8.0.0")
::Elasticsearch::Transport::Client
else
::Elastic::Transport::Client
end
to_instrument.class_eval do
include NewRelic::Agent::Instrumentation::Elasticsearch
alias_method(:perform_request_without_tracing, :perform_request)
alias_method(:perform_request, :perform_request_with_tracing)
def perform_request(*args)
perform_request_with_tracing(*args) do
perform_request_without_tracing(*args)
end
end
Rubyエージェントは、より柔軟に処理が行えるよう、どちらのインストゥルメンテーションのオプションも提供します。New Relic は、デフォルトで Module#prepend
を使用しますが、アプリケーションでNew Relicエージェントと同じメソッドでメソッドチェーンを使用する別のgemが使われている場合、エラーが発生することがあります。そのため、メソッド連鎖 (alias_method
) と Module#prepend
は、特定の状況でしか一緒に使うことができません。適切に使われなかった場合、これらは無限再帰を生じる可能性があります。SystemStackError
向けのトラブルシューティングガイドでは、インストゥルメンテーションメソッドのひとつで何らかの衝突が生じた場合に、これら2つのオプションについて詳細に説明していますのでご覧ください。
次の画像は、New RelicのElasticsearchライブラリの自動インストゥルメンテーションのデフォルトのオプションを示しています。詳細については、Rubyエージェントドキュメントを参照してください。
New RelicのRubyエージェントは、ランタイムのperform_request
メソッドにインストゥルメンテーションコードを挿入します。Elasticsearch Ruby gemは、このメソッドを通じてすべてのAPIコールを送信するためです。
New RelicのRubyエージェントは、Elasticsearch gemのバージョン7.xおよび8.xをサポートします。
perform_request
メソッドには、アップデートや削除など、特定のオペレーションタイプについての情報は含まれません。この問題の解決策として、どのメソッドがperform_request
の呼び出しを担っているかを見るには、 caller_locations
を確認すればいいことが分かりました。
caller_locations
が使用されるコードは以下の通りです。
def nr_operation
operation_index = caller_locations.index do |line|
string = line.to_s
string.include?('lib/elasticsearch/api') && !string.include?(OPERATION)
end
return nil unless operation_index
caller_locations[operation_index].to_s.split('`')[-1].gsub(/\W/, "")
end
これにより、Elasticsearchに呼び出される特定のオペレーションが提示されるため、スパンに正しいオペレーションタイプを紐づけることができます。
以下の画像は、New RelicでのElasticsearchのスパンのディストリビューティッド(分散)トレーシングを示しています。
Elasticsearchのスパンはdb.instance
という属性を持ち、Elasticsearchのリクエストの送信元のクラスタ名を表示します。これは、特定のクラスタでエラーやパフォーマンスの問題が発生しているかどうかの特定に役立ちます。また、Spanはperform_requestに渡されたクエリパラメータを記録しますが、デフォルトでは機密情報を保護するために難読化されています。
以下の画像は、クラスタ名のdb.instance
属性やクエリパラメーターのdb.statement
など、Elasticsearchのアップデートスパンに記録された属性を示しています。
Elasticsearchの設定オプション
New Relicでは、capture_queries
とobfuscate_queries
の2つの設定オプションが用意されています。どちらもデフォルトで有効化されています。
elasticsearch.capture_queries
が有効化されていると、エージェントはリクエストに送られるクエリの記録を試みます。また、機密情報を隠蔽するために obfuscate_queries を追加しました。これらのオプションは、newrelic.yml
ファイルか環境変数を通じて設定ができます。
以下の画像は、New Relicのelasticsearch.capture_queries
の設定を示しています。
次の画像では、New RelicのRubyエージェントのelasticsearch.obfuscate_queries
の設定を説明しています。
Rubyエージェントのアップグレード
Rubyエージェントをアップグレードして、Elasticsearchの監視を開始できます。New RelicのRubyエージェントのバージョン8.xでは、Tiltスレッド(8.2.0)、スレッド(8.7.0)、gRPC(8.10.0)、ログインコンテクストのあるRubyのロガークラス(8.6.0)の新しいインストゥルメンテーションが可能です。また、いくつかのバグ修正と、code-level metrics(8.10.0)などの強化も含まれます。
New Relicと連携する
Rubyエージェントは、オープンソースソフトウェアです。私たちのソースコードへの貢献や改善へのご提案をぜひお寄せください。また、コミュニティへのご参加もお待ちしています。今後、何をしたいか、またどんな機能をご要望かについて、ぜひお聞かせください。GitHubでつながりましょう。
次のステップ
まだNew Relicをお使いいただいていない場合は、無料でNew Relicの使用を開始できます。無料アカウントには、毎月100GBの無料データ取り込み、1名の無料フルアクセスユーザー、および無制限の無料Basicユーザーが含まれます。
本ブログに掲載されている見解は著者に所属するものであり、必ずしも New Relic 株式会社の公式見解であるわけではありません。また、本ブログには、外部サイトにアクセスするリンクが含まれる場合があります。それらリンク先の内容について、New Relic がいかなる保証も提供することはありません。