--- title: "How to debug a GenServer like Sherlock using IEx" subtitle: "A Sherlock Holmes approved guide 🕵" date: 2019-11-08 draft: false tags: [dev, programming, elixir, production, debug] --- # Elixir, the path to functional programming ⚗️ With my [**Rust** rediscovery](https://blog.papey.fr/post/03-bites-the-rust/) a lot of _functional programming_ concepts became less obscure. In order to go deeper into this paradigm I chose _Elixir_ a **powerful** general purpose, _functional programming_ language, compiled and executed inside the _Erlang_ virtual machine (**BEAM**). But why _Elixir_, if _Erlang_ exists ? Because : Elixir, is Erlang with underpants - Athoune Unlike _Erlang_, the _Elixir_ syntax is clear and elegant. The language comes with everything you need, included : interactive shell, deps tooling, building tooling and more… Even if _José Valim_, the _Elixir_ creator was a core _Ruby_ dev, _Elixir_ is completely different since this is a _functional programming_ language. No mutation, no inheritance, no classes, only **pure** functions. Pray your only true god, the pipe operator `|>` operator, used to compose functions. Now, I know, the only thing you want is code and examples, so let's take a quick look at some basic _Elixir_ stuff using the interactive shell **IEx**. A simple addition : {{< highlight exs >}} iex(1)> 2 + 2 4 {{< /highlight >}} A simple addition, inside a list {{< highlight exs >}} iex(1)> 2 + 2 iex(5)> list = [1,2,3,4][1, 2, 3, 4] iex(6)> Enum.map(list, fn e -> e + 1 end) [2, 3, 4, 5] {{< /highlight >}} List splitting (head and tail) {{< highlight exs >}} iex(7)> [head | tail] = list [1, 2, 3, 4] iex(8)> head 1 iex(9)> tail [2, 3, 4] {{< /highlight >}} Another important aspect of Elixir is _pattern matching_ used to match values, data structures and much more, let's try it : {{< highlight exs >}} iex(11)> x = {:this, :is, :a, :test} {:this, :is, :a, :test} iex(12)> {a, b, c, d} = x {:this, :is, :a, :test} iex(13)> a :this iex(14)> b :is iex(15)> c :a iex(16)> d :test {{< /highlight >}} Using _pattern matching_ you can assign values but also destructure data to simplify interaction with it. Feels the hype growing ? Nice ! As usual, I like a real project to experiment on something. In the _Elixir_ case, I started a Discord bot project called [o2m](https://github.com/papey/o2m). The main idea of this bot is to send alert messages on a specific channel when a new episode from a selected podcast is available. Today, I was struggling with a bug on a production instance of _o2m_. The last episode was not fetched correctly and the action that write a _"There is a new episode_" message was not triggered correctly. To debug and inspect the current state of the application I used IEx **in production**. # Base ingredient of a good Elixir : Mix 🧙 Combined with IEx, there is _Mix_. Shipped with _Elixir_, this a build tool used for the following application related tasks : - creating - setting up needed deps - testing - compiling The combo killer here is to start IEx inside the _Mix_ project, in order to have all the dependencies imported inside the interactive shell {{< highlight exs >}} iex -S mix {{< /highlight >}} After that, there is a lot of useful commands like `recompile` to refresh and recompile new code **while your code is running**. Yes, this is something that _Elixir_ do by default, hot code reloading. When your code is ready, you want to deploy it. With _Mix_ the standard way is to used the `release` command {{< highlight sh >}} MIX_ENV=production mix release {{< /highlight >}} This will create a precompile and packaged unit, with runtime included. With this, you do not have to install _Erlang_ or _Elixir_ on your production server. Boom. If you look carefully, there is an interesting message and the end of the command output : {{< highlight sh >}} Release created at \_build/prod/rel/o2m! # To start your system _build/prod/rel/o2m/bin/o2m start Once the release is running: # To connect to it remotely _build/prod/rel/o2m/bin/o2m remote # To stop it gracefully (you may also send SIGINT/SIGTERM) _build/prod/rel/o2m/bin/o2m stop To list all commands: _build/prod/rel/o2m/bin/o2m {{< /highlight >}} Particularly, To connect to it remotely This means I can have access to an interactive shell on production while my code is running, hooray 🎆 # Sherlocking a GenServer 🔎 Did you read the title ? We are talking about _GenServer_ here ! So _what the fuck_ is this ? Taken from the [documentation](https://hexdocs.pm/elixir/GenServer.html) : A GenServer is a process like any other Elixir process and it can be used to keep state, execute code asynchronously and so on. The advantage of using a generic server process (GenServer) implemented using this module is that it will have a standard set of interface functions and include functionality for tracing and error reporting. It will also fit into a supervision tree. In _Elixir_, this is the default and common module used to implement client-server behaviors. Here is the example from the documentation {{< highlight elixir >}} defmodule Stack do use GenServer # Callbacks @impl true def init(stack) do {:ok, stack} end @impl true def handle_call(:pop, \_from, [head | tail]) do {:reply, head, tail} end @impl true def handle_cast({:push, element}, state) do {:noreply, [element | state]} end end {{< / highlight >}} Basically, this is a data structure with a state responding to triggers using handlers that update or retrieve the current state To launch and interact with the server, in IEx : {{< highlight exs >}} iex(41)> {:ok, pid} = GenServer.start_link(Stack, [:hello]) iex(42)> GenServer.call(pid, :pop) :hello iex(43)> GenServer.cast(pid, {:push, :world}) :ok iex(44)> GenServer.call(pid, :pop) :world {{< /highlight >}} What if, I want to access the current state, of the GenServer ? In _Erlang_, there is the `sys` module with the `get_state/2` [function](http://erlang.org/doc/man/sys.html#get_state-2) available But, this is _Erlang_, and we use _Elixir_ ! We're doomed ? No ! Because everything available in _Erlang_ is available inside _Elixir_ using the `:` operator. {{< highlight erl >}} iex(18)> :io.format("Hello World~n") Hello World :ok {{< /highlight >}} So, with our `sys` example : {{< highlight exs >}} iex(19)> :sys.get_state(pid) [:!, :world] {{< /highlight >}} Nice ! Now we can get state of a GenServer using the PID ! Now, let's move from local machine to prod. In this case, processus are handled by a **Supervisor** but first things first, we want a IEx shell inside our running app. In order to illustrate this last part, I will be using one of my prod instances of _o2m_ {{< highlight sh >}} o2m@16557a733b59:/opt/o2m\$ ./prod/rel/o2m/bin/o2m remote Erlang/OTP 22 [erts-10.5.3][source] [64-bit][smp:2:2] [ds:2:2:10][async-threads:1] [hipe] Interactive Elixir (1.9.2) - press Ctrl+C to exit (type h() ENTER for help) iex(o2m@16557a733b59)1> {{< /highlight >}} Ok but, what is the _pid_ of the _GenServer_ I want to inspect ? I don't know ! Here the first solution could be outputting _pid_ to _stdout_ but, imagine that our application kills and restart GenServer, on demand or our application is flooding _stdout_ because of some errors, this is not a viable solution. First, we could list all processus, {{< highlight exs >}} iex(o2m@16557a733b59)3> Supervisor.which_children(O2M.Supervisor) [ {O2M, #PID<0.2368.0>, :worker, [O2M]}, {"jobs-https://feed.ausha.co/bj5li17QPONy", #PID<0.2365.0>, :worker, [Jobs]}, {"jobs-https://feed.ausha.co/yJeEUGlLVq0o", #PID<0.2362.0>, :worker, [Jobs]}, {"jobs-https://anchor.fm/s/b3b7468/podcast/rss", #PID<0.2358.0>, :worker, [Jobs]} ] {{< /highlight >}} Where `O2M.Supervisor` is the dedicated _Supervisor_ of my application Now I can identify the GenServer I want to inspect, let's take the `jobs-https://anchor.fm/s/b3b7468/podcast/rss` one, with associated pid `0.2358.0` (the last element of the list, here), here comes the fun {{< highlight exs >}} iex(o2m@16557a733b59)13> {_, pid, _, \_} = Supervisor.which_children(O2M.Supervisor) |> List.last {"jobs-https://anchor.fm/s/b3b7468/podcast/rss", #PID<0.2358.0>, :worker, [Jobs]} iex(o2m@16557a733b59)14> pid #PID<0.2358.0> {{< /highlight >}} Then, I can use the pid value to get _GenServer_ state and inspect it to see if everything is ok : {{< highlight exs >}} iex(o2m@16557a733b59)15> :sys.get_state(pid) {"https://anchor.fm/s/b3b7468/podcast/rss", %{ date: "Mon, 04 Nov 2019 09:00:00 GMT", show: "Harry Cover, le podcast des meilleures reprises", title: "Yes we can work it out !", url: "https://anchor.fm/leotot8/episodes/Yes-we-can-work-it-out-e8n4d3" }} {{< /highlight >}} How ! Impressive ! It was a little bit Sherlock Holmes oriented debugging but that was fun. Keep in mind that this is a really simple operation here, from IEx everything is possible from starting new GenServers to modify state of a specific one and much more. I said it at the beginning, **Elixir is powerful**.