ElasticsearchをIntelliJでデバッグできるようにする

Elasticsearchを基礎から理解しようシリーズです。

前回の回数を都度見に行くの面倒なので、今回から回数を数えるのをやめました。

目的

Elasticsearchのコードを読むのにデバッガーを使いたいのでIntelliJで設定していきます。

色々はじめてで詰まったので忘備録がてらメモを残します。

環境

公式ドキュメント

Elasticsearchのリポジトリにコントリビュートやテストに関してのドキュメントがあるので参考にしてください。

elasticsearch/CONTRIBUTING.md at main · elastic/elasticsearch · GitHub elasticsearch/TESTING.asciidoc at v7.9.2 · elastic/elasticsearch · GitHub

また、少し古いですが公式ブログにも記載があります。

www.elastic.co

手順

IntelliJプロジェクトを設定する

はじめての人は上記ブログコントリビュートのドキュメントをみてインポートしてください。

とくにSDKを色々インストールしている場合は注意が必要です。

The minimum IntelliJ IDEA version required to import the Elasticsearch project is 2020.1 Elasticsearch builds using Java 17. When importing into IntelliJ you will need to define an appropriate SDK. The convention is that this SDK should be named "17" so that the project import will detect it automatically.

ドキュメントにも記載があるとおり、SDKを17にする必要があります。

私は最初、別のバージョンのSDKで適当に開いて適当な設定をしていたため、ビルドができませんでした。

実行できるか確認する

リポジトリのルートディレクトリで以下のコマンドを実行してビルドせずにElasticsearchが起動するか確認します。

cd ~/適当なpath/elastic/elasticsearch
./gradlew :run

以下のログのあと、いくつかログが流れていれば成功です。

[2022-12-11T13:52:15,863][INFO ][o.e.h.AbstractHttpServerTransport] [runTask-0] publish_address {127.0.0.1:9200}, bound_addresses {[::1]:9200}, {127.0.0.1:9200}
[2022-12-11T13:52:15,865][INFO ][o.e.n.Node               ] [runTask-0] started

次のコマンドで確認することもできます。

curl -u elastic:password localhost:9200

実行 / デバッグ構成(Run/Debug Configuration)の設定

IntelliJのメニューから, Run > Edit Configurations ...を開きます。

Remote Jvm DebugにDebug Elasticsearchという名前で以下のように設定します。 これはすでにあるかもしれません。

  • Debugger modeで 「Listen to remote JVM」を選択
  • Auto restartにチェックいれる
  • portを5005にする

This will instruct all JVMs (including any that run cli tools such as creating the keyring or adding users) to suspend and initiate a debug connection on port incrementing from 5005. As such the IDE needs to be instructed to listen for connections on this port. Since we might run multiple JVMs as part of configuring and starting the cluster it’s recommended to configure the IDE to initiate multiple listening attempts. In case of IntelliJ, this option is called "Auto restart" and needs to be checked.

from TESTING.asciidoc

後ほど説明しますが、先程実行した ./gradlew :run タスクはリモートデバッグ機能があります。 このリモートデバッグ機能がport:5005でデバッグ接続しようとするため、必ず先にIntelliJ側でデバッグ構成を起動しておく必要があります

デバッグ接続する

先程説明した通り、実際にデバッグ構成を起動してリモートデバッグ接続を行います。

  • IntelliJ側で「Debug Elasticsearch」を選択して起動する
  • ./gradlew run --debug-jvm を実行して、リモートデバッグオプションを指定してElasticsearchを起動する

先程同様、ログが流れるか curl -u elastic:password localhost:9200 でレスポンスが返ってくればOKです。

もし先にデバッグ構成を起動せずに、リモートデバッグ接続を場合は以下のエラーがでます。

Running elasticsearch in debug mode, node{::runTask-0} expecting running debug server on port 5005
   Exec output and error:
   | Output for ./bin/elasticsearch-keystore:ERROR: transport error 202: connect failed: Connection refused
   | ERROR: JDWP Transport dt_socket failed to initialize, TRANSPORT_INIT(510)
   | JDWP exit error AGENT_ERROR_TRANSPORT_INIT(197): No transports initialized 

ブレークポイントつけて試してみる

では実際に適当なところで処理をとめてみます。

どんなリクエストでも必ず通るであろうRestRequestクラスの適当なところにポイントをつけます。

そして、curl -u elastic:password localhost:9200/_stats など適当なエンドポイントへリクエストしてみます。 指定したところで止まっているのが確認できました。

参考

Failing to run on Intellij in debug mode - #4 by amitkg - Elasticsearch - Discuss the Elastic Stack