{"id":5387,"date":"2016-05-10T19:41:48","date_gmt":"2016-05-10T22:41:48","guid":{"rendered":"http:\/\/blog.plataformatec.com.br\/?p=5387"},"modified":"2016-10-31T16:57:16","modified_gmt":"2016-10-31T18:57:16","slug":"tracing-and-observing-your-remote-node","status":"publish","type":"post","link":"http:\/\/blog.plataformatec.com.br\/2016\/05\/tracing-and-observing-your-remote-node\/","title":{"rendered":"Tracing and observing your remote node"},"content":{"rendered":"
Today we will continue exploring techniques for debugging and tracing Elixir code that are so important for running and understanding production systems.<\/p>\n
In the past, we have discussed:<\/p>\n
The examples above always connected to systems running locally. Given Elixir’s and the Erlang VM focus on distributed systems, you may have wondered: can we use the VM capabilities to trace and observe remote nodes?<\/p>\n
Certainly!<\/p>\n
Your application runs as part of the Erlang Runtime System, which is often called a node, as it may connect to other machines. Before we establish such connections, let’s get to know some concepts and then configure our applications.<\/p>\n
Erlang Port Mapper Daemon<\/strong>, EPMD, acts as a name server on all hosts involved in distributed Erlang communications. When an Erlang node starts, the node has a name and it obtains an address from the host OS kernel. The default port the daemon runs on is 4369 but you can change it with the You can run Depending on your firewall configuration, the port 4369 from EPMD is blocked by default. We will use port forwarding to redirect our local EPMD port to the remote EPMD with Therefore, when we start a node locally, it will attempt to register itself to the EPMD running on port 4369, which is effectively forwarded to the remote EPMD. Once our local node registers itself to the remote EPMD, it will be able to find all remote nodes running on the remote EPMD.<\/p>\n Imagine we want to trace or observe a Phoenix project. In our case, our project was released using exrm<\/a> and our release path in production has a directory called The file We added a name to your application, set a port range where remote nodes may connect to and chose a cookie secret. If your server was already running, you will need to restart it after changing After restarting our application, we should see it registered in the remote EPMD:<\/p>\n After our application is started, we need to change our Now let’s start the tracing tool locally with the proper cookie options. The tracing tool will register itself to the remote EPMD, via port forwarding, and find our remote application. Once the Erlyberly is started, you should see the following in the remote EPMD:<\/p>\n We can also observe a remote system using ssh port forwarding. One option is to establish a remote shell, as explained in the IEx documentation<\/a>:<\/p>\n Now you are connected directly to a remote node and you can introspect it as well as start tools like Observer.<\/p>\n Alternatively, you can start a new local shell with the same cookie as the remote node:<\/p>\n The local shell should be registered in the remote EPMD alongside the remote system:<\/p>\n With Observer open, we can now change the inspected node using the menu ‘Nodes > Connect node’. In the prompt we can fill in the node name. In our example the node is <\/p>\n You may receive an error similar to the one below when you try to connect through Observer:<\/p>\n This occurs because the Do you use other techniques to connect to remote nodes? Share your tips with a comment below.<\/p>\n Today we will continue exploring techniques for debugging and tracing Elixir code that are so important for running and understanding production systems. In the past, we have discussed: how to debug your application how to trace systems with Erlyberly how to use the observer to introspect applications. The examples above always connected to systems running … \u00bb<\/a><\/p>\n","protected":false},"author":18,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"ngg_post_thumbnail":0,"footnotes":""},"categories":[1],"tags":[247,143,245],"aioseo_notices":[],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"http:\/\/blog.plataformatec.com.br\/wp-json\/wp\/v2\/posts\/5387"}],"collection":[{"href":"http:\/\/blog.plataformatec.com.br\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/blog.plataformatec.com.br\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/blog.plataformatec.com.br\/wp-json\/wp\/v2\/users\/18"}],"replies":[{"embeddable":true,"href":"http:\/\/blog.plataformatec.com.br\/wp-json\/wp\/v2\/comments?post=5387"}],"version-history":[{"count":8,"href":"http:\/\/blog.plataformatec.com.br\/wp-json\/wp\/v2\/posts\/5387\/revisions"}],"predecessor-version":[{"id":5396,"href":"http:\/\/blog.plataformatec.com.br\/wp-json\/wp\/v2\/posts\/5387\/revisions\/5396"}],"wp:attachment":[{"href":"http:\/\/blog.plataformatec.com.br\/wp-json\/wp\/v2\/media?parent=5387"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/blog.plataformatec.com.br\/wp-json\/wp\/v2\/categories?post=5387"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/blog.plataformatec.com.br\/wp-json\/wp\/v2\/tags?post=5387"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}ERL_EPMD_PORT<\/code> environment variable <\/a>.<\/p>\n
epmd -names<\/code> to check the port and the nodes connected:<\/p>\n
user@localhost:~$ epmd -names\nepmd: up and running on port 4369 with data:\nname myapp at port 43316\n<\/code><\/pre>\n
SSH Port Forwarding<\/h2>\n
ssh<\/code>:
ssh user@myapp.com -L4369:localhost:4369<\/code>.<\/p>\n
Configuring the Phoenix application<\/h2>\n
running-config<\/code>. In this directory we can find the files
sys.config<\/code> and
vm.args<\/code>.<\/p>\n
vm.args<\/code> is responsible for configuring our application when it starts. Let’s change it as follows:<\/p>\n
## Name of the node\n-name myapp@127.0.0.1\n-kernel inet_dist_listen_min 9001 inet_dist_listen_max 9001\n\n## Cookie for distributed erlang (you want a really long cookie)\n-setcookie my_cookie\n<\/code><\/pre>\n
vm.args<\/code>.<\/p>\n
user@localhost:~$ epmd -names\nepmd: up and running on port 4369 with data:\nname myapp at port 9001\n<\/code><\/pre>\n
Tracing application<\/h2>\n
ssh<\/code> command to forward to EPMD and our application ports:
ssh user@myapp.com -L4369:localhost:4369 -L9001:localhost:9001<\/code>.<\/p>\n
user@localhost:~$ epmd -names\nepmd: up and running on port 4369 with data:\nname myapp at port 9001\nname erlyberly-1460466831146 at port 54420\n<\/code><\/pre>\n
Observing application<\/h2>\n
$ iex --name mylocalmachine@127.0.0.1 --cookie my_cookie --remsh myapp@127.0.0.1\n<\/code><\/pre>\n
$ iex --name mylocalmachine@127.0.0.1 --cookie my_cookie\nErlang\/OTP 18 [erts-7.3] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]\n\nInteractive Elixir (1.2.4) - press Ctrl+C to exit (type h() ENTER for help)\niex(mylocalmachine@127.0.0.1)1> :observer.start()\n:ok\n<\/code><\/pre>\n
user@localhost:~$ epmd -names\nepmd: up and running on port 4369 with data:\nname mylocalmachine at port 50055\nname myapp at port 9001\n<\/code><\/pre>\n
myapp@127.0.0.1<\/code>.<\/p>\n
Troubleshooting<\/h3>\n
16:38:44.278 [error] [node: :\"mylocalmachine@127.0.0.1\", call: {:observer_backend, :sys_info, []}, reason: {:badrpc, {:EXIT, {:undef, [{:observer_backend, :sys_info, [], []}, {:rpc, :\"-handle_call_call\/6-fun-0-\", 5, [file: 'rpc.erl', line: 206]}]}}}]\n<\/code><\/pre>\n
:observer_backend<\/code> is disabled. You can enable it by adding the
:runtime_tools<\/code> to your application
mix.exs<\/code> file. You can get more details in the Runtime tools documentation<\/a>.<\/p>\n
\n
\n
\n<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"