Skip to content

Instantly share code, notes, and snippets.

@eiri
Created March 3, 2015 16:44
Show Gist options
  • Save eiri/4c684bc1765257cc4ade to your computer and use it in GitHub Desktop.
Save eiri/4c684bc1765257cc4ade to your computer and use it in GitHub Desktop.
Walks erlang VM's process tree and prints PlantUML diagram of it on a standard output
#!/usr/bin/env escript
%% -*- erlang -*-
%%! -hidden -setcookie cookie
-mode(compile).
main(["-?"]) ->
usage();
main(Args) ->
case get_pid(Args) of
{ok, Node, Pid} ->
io:format("@startuml~n"),
io:format("skinparam monochrome true~n"),
walk(Node, [Pid]),
io:format("@enduml~n");
{error, Error} ->
io:format("Error: ~s~n", [Error]),
usage()
end.
usage() ->
io:format("Usage: proc_tree.escript [node] [reg_name]~n~n").
get_pid([]) ->
get_pid([atom_to_list(node()), "init"]);
get_pid([Name]) ->
get_pid([atom_to_list(node())|[Name]]);
get_pid([StrNode, Name]) ->
Node = list_to_atom(StrNode),
pong = net_adm:ping(Node),
case rpc:call(Node, erlang, whereis, [list_to_atom(Name)]) of
undefined ->
{error, unknown_name};
{badrpc, Error} ->
io:format("~p~n", [Error]),
{error, badrpc};
Pid ->
{ok, Node, Pid}
end;
get_pid(_Args) ->
{error, unvalid_args}.
walk(Node, Pids) ->
walk(Node, Pids, dict:new()).
walk(_, [], _) ->
ok;
walk(Node, [Pid|Rest], Reg) ->
Info = rpc:call(Node, erlang, process_info,
[Pid, [registered_name, links]]),
maybe_print_vertex(Pid, lists:keyfind(registered_name, 1, Info), Reg),
Chld = print_edges(Pid, lists:keyfind(links, 1, Info)),
walk(Node, Rest ++ Chld, dict:store(Pid, Pid, Reg)).
maybe_print_vertex(Pid, Name, Reg) ->
case dict:is_key(Pid, Reg) of
true -> ok;
false -> print_vertex(Pid, Name)
end.
print_vertex(Pid, {registered_name, []}) ->
io:format("object ~s {~n~n}~n", [pid(Pid)]);
print_vertex(Pid, {registered_name, Name}) ->
io:format("object ~s {~n name = ~s~n}~n", [pid(Pid), Name]).
print_edges(Pid, Links) ->
print_edges(Pid, Links, []).
print_edges(_Pid, {links, []}, Acc) ->
lists:reverse(Acc);
print_edges(Pid, {links, [L|Rest]}, Acc) when is_pid(L) andalso L > Pid ->
io:format("~s -- ~s~n", [pid(Pid), pid(L)]),
print_edges(Pid, {links, Rest}, [L|Acc]);
print_edges(Pid, {links, [_|Rest]}, Acc) ->
print_edges(Pid, {links, Rest}, Acc).
pid(Pid) ->
L = pid_to_list(Pid),
string:substr(L, 2, length(L) - 2).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment