稼働中の Elixir/Erlang アプリケーションをお手軽デバッグトレースできる erlyberly が超便利！

# erlyberly って何？

erlyberly は、Erlang の他、Elixir, [LFE](http://lfe.io/) (Lisp Flavoured Erlang - Elang VM 上で動作する Lisp) といった Erlang 系言語向けのデバッグトレースがビジュアルに出来る GUI ソフトウェア。Java で出来ているので JDK (8u20 以上が必要) が入っている環境であれば動作する。

百聞は一見に如かず、というわけで、まずはスクリーンショットから。

<img width="1448" alt="erlyberly.png" src="https://qiita-image-store.s3.amazonaws.com/0/69065/366a64e8-aa55-8e8d-af01-7c8cb93d0d39.png">

Erlang 系言語にはコマンドラインのデバッガは幾つかあるが、視覚的にデバッグ・トレースできるものは余り見当たらない。

# 豊富な機能

できることは [GitHub](https://github.com/andytill/erlyberly) の READ.md に貼られているキャプチャ画像を眺めるとだいたいのことが分かるが、ざっと洗い出すと以下の機能がある。

* 実行時に指定した関数（複数可）に対してトレースを設定できる
  * 動いているシステムにブレークポイントを張れる
* 関数呼び出しと結果（戻り値）を見ることができる
* [例外のハイライト表示](https://github.com/andytill/erlyberly#see-calls-that-threw-exceptions)
* 不完全な関数呼び出しを表示できる
* プロセスの状態を取得・表示できる
* 稼働中のシステムにアタッチできる
* (関数名・モジュール名などの) フィルタリング機能
* 再起動してもトレースを自動的に継続できる (開発時に便利)
* モジュールや関数のソースコードを表示できる
* モジュールや関数の抽象コードを表示できる
* 関数の呼び出しグラフを表示できる
* [クラッシュレポート通知](https://github.com/andytill/erlyberly#get-notified-of-crash-reports)を表示できる
* クロスプラットフォーム(OSX, Linux Ubuntu, RHEL, CentOS など)

と、実際に Elixir/Erlang で開発をしはじめると欲しくなる機能が満載である。

## ユースケース

* 指定した関数が実行された時に、関数の引数・戻り値をトレースできる
* Erlang VM 全体のメモリ使用量のスナップショットを取得できる
* Erlang プロセス毎のメモリ(ヒープ、スタック)使用量のスナップショットを取得できる

が有り難い。特に、メモリ使用量に関しては、その場・その時の「スナップショット」なので、いったん取得したメモリ使用量の円グラフは消さない限り残るようになっており、パフォーマンス計測などのユースケースを前提によく考えられた仕様となっている。

これらが実際、どういう局面に使えるかというと、

* 特定の環境でしか発生しない事象がある
* デバッグログを埋め込みたいが範囲が広すぎる
* 既製の Erlang アプリケーションで発生するエラーを知りたい
* 外部ライブラリ側でエラーが発生しているが原因を特定したい

このようなケースで威力を発揮する。

特にリモート稼働中のアプリケーションと接続して内部の状態を覗けるのは大変便利で、例えば「PUSH通知サービスプロバイダ(FCM, APNs)からの応答がおかしいみたいだけど、ログを仕込んでいない」「アプリケーションに手を入れず原因を知りたい」といったケースでは特に有り難みを感じるだろうと思われる。

関数の中の任意の行にブレークポイントを張ってデバッグする、という事はできないが、そこまでしたいケースであればローカル環境で [IntelliJ の Elixir Plugin](https://github.com/KronicDeth/intellij-elixir) を使ってブレークポイントを貼ってデバッグトレースするか、もっと簡単に `IO.inspect` でプリントデバッグすることで使い分けている。

Erlang node と Erlang cookie さえあれば自分で開発しているアプリケーションだけでなく既製の Erlang アプリケーションをデバッグできる点もポイントが高い。つまり [RabbitMQ](https://www.rabbitmq.com/) や [Riak](http://basho.com/products/) で意味不明な例外が発生して吐かれたクラッシュダンプファイルを眺めて途方に暮れていた著者のような人も、erlyberly からサーバに繋いでどこで例外が発生したのかをトレースする事が出来るようになる。

## 本番環境では使ってはいけない

便利な機能満載の erlyberly だが、基本的に production 環境で使うことは想定されていない。最初の接続の時に Erlang node 名と Erlang cooki を設定していることからもわかるように、erlyberly 自身が Erland ノードとして動いているため、Erlang 内部に精通していない限りは基本的に高負荷となる本番環境などでの使用はやめておいたほうがいい。

# インストール手順
JDK (JDK 8u20以上) をインストールしている場合は以下のワンライナーでダウンロード・起動する。

```
git clone https://github.com/andytill/erlyberly.git && cd erlyberly && ./mvnw clean compile install assembly:single && java -jar target/*runnable.jar
```

# 簡単な使い方

erlyberly が起動すると以下のようなダイアログが表示されるので Target Node と Cookie を設定し Connect ボタンを押す（Target Node とは Erlang Node のことで、Cookie は Erlang Cookie のこと）。

<img width="512" alt="接続ノード" src="https://qiita-image-store.s3.amazonaws.com/0/69065/9f4ff4fd-7eeb-e03d-2e27-90caaa839035.png">

ちなみに Auto Connect? にチェックを入れると、Erlang ノードを落としても再起動すると自動的に接続してくれる。ローカル開発環境で頻繁に開発中のアプリケーションを停止→起動→停止→起動..している場合は接続が切れる度に一々 erlyberly を接続しなおさなくて済む。このように、一見すると何気ないが、痒いところに手が届く使い心地がこの erlyberly の最大の魅力であるといっても過言ではない。

## 使用例：開発中の Phoenix アプリケーションに接続してデバッグする

例えば Phoenix アプリケーションで通常、

```
iex -S mix phx.server
```

のように起動しているところを

```
iex --name mynode@localhost --cookie mycookie -S mix phx.server
```

と `--name [ノード名]` と `--cookie [クッキー名]` をつけて起動する。そうすると erlyberlyから接続できるようになる。

distillery などでリリースファイルを作成しリモートサーバにデプロイしている場合などは vm.args で Erlang node 名と Erlang cookie を設定できるので、そこで設定した値を接続時に設定すればリモートノードに対しても同様に erlyberly でデバッグすることができる。

なお、プロセスのメモリスナップショットの取り方は少し分かりづらいが、以下のような操作で取得できる。

<img width="1572" alt="円グラフの出し方" src="https://qiita-image-store.s3.amazonaws.com/0/69065/ef75e0a2-8f58-7e63-7336-e4bdb5a922e8.png">

一旦繋がってしまえばあとはボタンを押すなり右クリックのコンテキストメニューで色々と試すことができるので細かい説明は省くが、このように気軽に触ってみることで色々と試せるのは GUI アプリケーションだからこそで、CLI には無い特長だと言える。

チェックボックスにチェックをして開発中のAPIを叩いてレスポンスの Map オブジェクトを眺めてみたり、負荷テストの前後で円グラフマークをクリックして比較するなど、好きなように触ってみよう。

# erlyberly のココがいい！

沢山ある機能のうち、ココが特に良い！というものを列挙してみる。

## 気配りの聞いた設定画面

![preferences.png](https://qiita-image-store.s3.amazonaws.com/0/69065/a7ed0203-58d8-d1ec-f349-25ee2649f2dd.png)

### Hide Processes on Startup 
「起動時にプロセスを表示しない」起動オプション

何万〜何百万という Erlang プロセスを起動するアプリケーションでは有用、というかチェック必須の項目。大量の Erlang プロセス情報の一覧を取得するとサーバに負荷をかけてしまうため、特に負荷の高い環境に接続する時はこのチェックをするのを忘れないように注意しよう。

### Display Erlang/Elixir/LFE Terms

デバッグ対象の言語にチェックを付けておくと、モジュール名を適切に表示してくれる。例えば Erlang Terms だと`Elixir.Agent` となってしまうが、Elixir Terms にチェックをつけておけばモジュール名の表示が `Agent` より適切に表示されるようになる。

## 細かいメモリの使用状況が分かる

erlyberly では

* Erlang VM 全体のメモリ使用割合
* Erlang プロセス毎のヒープ

の2種類のメモリ情報を取得し円グラフで表示できる。

Erlang Memory では

* processes
* code
* ets
* binary
* atom

などの項目別にそれぞれメモリ使用量が表示されるが、これらの細かい意味については

[Erlang Run-Time System Application (ERTS) リファレンス・マニュアルの erlang:memory の項目](http://erlang.org/doc/man/erlang.html#memory-0) に詳しい。それほど難しい話でないので、 Erlang に限らず Elixir などの Alt Erlang 言語を運用管理する際は、是非目を通しておきたい。

## Abstract code も見える

プロセスを右クリックするとコンテキストメニューが表示されるがその中に `Source code` と `Abstract code` という2つの項目がある。`Source code` はそのものズバリだが、`Abstract code` とは何だろう？

クリックして開くと Erlang term で書かれたコード片が表示される。調べるとこれは BEAM に渡される機械語コードのアセンブリ表現のようだ（間違っていたらすみません）。このあたりの仕組みは [BEAM 本のコンパイラの章](https://happi.github.io/theBeamBook/#CH-Compiler) に詳しく記載されている。

# まとめ　〜Erlang VM の学習に〜

細々したことを書いてしまったが、erlyberly は何より「使っていて楽しい」アプリケーションだと感じた。デバッグ・トレースといった実用的でよく練られた機能はもちろんのこと、操作していると「あのライブラリの中はどうやって動いてるんだろ？」とか「Elixir の標準モジュールは実際どう動いているの？どれだけメモリ食ってるの？」などなど、ソファーに寝転んでネットサーフィンに興じるような気軽さで、Erlang VM の世界を「掘って掘って掘りまくる！（by [ねぽりんぱほりん](http://www4.nhk.or.jp/nehorin/)）」ことができるのである。

これは Smalltalk 環境にも通じるものがある。Smalltalk ではシステムブラウザでオブジェクトの森を探検していくことができるが（しかも動的に変更することまで出来てしまう！）、erlyberly を使ってみた感じはこの体験にとても良く似ている。

そういった意味で、erlyberly はデバッグ・トレースの機能もさることながら、Erlang の森を探検する学習ツールとして重宝するので手元に置いていつでも使えるようにしておきたいと思った。流行りの Elixir から入ったけれど Erlang のことはちょっと…と敷居の高さを感じ敬遠しがちな人にとっても、有用だと思う。