Visualizing Elixir Processes with Ubigraph

After my RedDotRubyConf 2014 talk, a few of the audience came up to me and asked how I did this:

I also promised a few of you on Twitter that I would get around documenting how I put that part of the presentation together – so here goes:

Step 1: Get UbiGraph

Head over to the UbiGraph download page to grab a copy of UbiGraph.

Step 2: Install and run UbiGraph

I’m using a Mac, so these instructions should more or less apply to Linux too. So:

  • Unzip the file
  • cd into the folder
  • chmod +x bin/ubigraph
  • ./bin/ubigraph

If everything goes well, you should see a blank black screen pop up.

Step 3: Grab the sample project

First, grab the sample project:

git clone git@github.com:benjamintanweihao/erlubi_demo.git

Note that this project requires at least Elixir v0.15.x. Install the required dependencies with mix deps.get .

Step 4: The fun begins!

Next, run the project from iex with iex -S mix

The project already contains erlubi , a Ubigraph Erlang Client and Process Visualizer. The cool thing to notice that this is an Erlang library, but as you will soon see, Elixir has no problems running it due to its Erlang interoperability.

In iex , launch the Ubigraph client:

iex> :erlubi_tracer.run

Notice that since we are running an Erlang library, we have to prefix the module with a colon ( : ). You will notice some blue and red balls spring to life.

Let’s create more processes (red balls!). Notice that the process ids of the created children are stored in the pids variable:

iex> pids = Enum.map 1..100, fn _ -> {:ok, pid} = Suppy.SupervisorB.start_child; pid end

You will see a cluster of 100 red balls being created. Now, let’s kill all the them.

iex> Enum.map pids, fn pid -> Process.exit(pid, :kill) end

When you do this, you will see the cluster of red balls shrinking at first. Wait a little while more, and you will see the supervisor restarting all the workers again. Fault tolerance FTW!

This is partly made possible by the insane restart values I used for the supervisor:

defmodule Suppy.SupervisorB do
  use Supervisor

  def start_link do
    :supervisor.start_link({:local, __MODULE__}, __MODULE__, [])
  end

  def start_child do
    :supervisor.start_child(__MODULE__, [])
  end

  def init(_args) do
    IO.puts "Starting #{__MODULE__} (#{inspect self})..."

    children = [
      worker(Suppy.WorkerC, [])
    ]

    supervise(children, strategy: :simple_one_for_one,
                         restart: :permanent,
                    max_restarts: 1_000_000,
                     max_seconds: 1_000_000)
  end

end

This makes sure that the supervisor will always restart the workers no matter how fast I kill them. Note that while this makes for a great demo, please use more sane restart values in production.

我来评几句
登录后评论

已发表评论数()

相关站点

+订阅
热门文章