anchor.diff:          pong ->
               ok;
           _OtherAnswer ->
  -            usage(),
               io:format(standard_error, "Invalid remote node specified or a connection could not be made!~n", []),
               halt(3)
       end.
   
  -collect_stats(ParsedOptions) ->
  +print_metric(Scheme, Category, Key, Value, Timestamp) when is_atom(Key) ->
  +    print_metric(Scheme, Category, atom_to_list(Key), Value, Timestamp);
  +print_metric(Scheme, Category, Key, Value, Timestamp) when is_list(Key) ->
  +    io:format("~s.~s.~s ~B ~B~n", [Scheme, Category, Key, Value, Timestamp]).
  +
  +print_metric(Scheme, Key, Value, Timestamp) when is_atom(Key) ->
  +    print_metric(Scheme, atom_to_list(Key), Value, Timestamp);
  +print_metric(Scheme, Key, Value, Timestamp) when is_list(Key) ->
  +    io:format("~s.~s ~B ~B~n", [Scheme, Key, Value, Timestamp]).
  +
  +fetch_rpc_metric(Node, M, F, A, Callback, Debug) when is_list(Node) ->
  +    fetch_rpc_metric(list_to_atom(Node), M, F, A, Callback, Debug);
  +fetch_rpc_metric(Node, M, F, A, Callback, Debug) when is_atom(Node), is_atom(M), is_atom(F), is_list(A), is_function(Callback), is_atom(Debug) ->
  +    case rpc:call(Node, M, F, A) of
  +        {badrpc, Reason} when Debug =:= true ->
  +            io:format(standard_error, "RPC call failed with reason: ~p~n", [Reason]),
  +            error;
  +        {badrpc, _Reason} when Debug =:= false ->
  +            error;
  +        Result ->
  +            Callback(Result)
  +    end.
  +
  +collect_metrics(ParsedOptions) ->
       Scheme = lists:flatten(proplists:get_value(scheme, ParsedOptions, element(2, inet:gethostname())), ".erlang"),
       RemoteNode = proplists:get_value(remote, ParsedOptions, "erlang@localhost.localdomain"),
  +    Debug = proplists:get_value(debug, ParsedOptions, false),
  +    Processes = proplists:get_value(processes, ParsedOptions, []),
       {Mega, Secs, _Micro} = erlang:now(),
       Timestamp = Mega * 1000000 + Secs,
       % Memory statistics
  -    case rpc:call(list_to_atom(RemoteNode), erlang, memory, []) of
  -        MemoryMetrics when is_list(MemoryMetrics) ->
  -            lists:foreach(fun({Key, Value}) ->
  -                ActualKey = Scheme ++ ".memory." ++ atom_to_list(Key),
  -                io:format("~s ~B ~B~n", [ActualKey, Value, Timestamp])
  -            end, MemoryMetrics);
  -        _ ->
  -            % Catch-all state, we don't want to pollute metrics output
  -            ok
  -    end,
  +    fetch_rpc_metric(RemoteNode, erlang, memory, [], fun(MemoryMetrics) ->
  +        lists:foreach(fun({Key, Value}) ->
  +            print_metric(Scheme, "memory", Key, Value, Timestamp)
  +        end, MemoryMetrics)
  +    end, Debug),
       % Total number of processes
  -    case rpc:call(list_to_atom(RemoteNode), erlang, processes, []) of
  -        Processes when is_list(Processes) ->
  -            io:format("~s ~B ~B~n", [Scheme ++ ".processes", erlang:length(Processes), Timestamp]);
  -        _ ->
  -            % Catch-all state, we don't want to pollute metrics output
  -            ok
  -    end,
  +    fetch_rpc_metric(RemoteNode, erlang, processes, [], fun(LiveProcesses) ->
  +        print_metric(Scheme, "processes", erlang:length(LiveProcesses), Timestamp)
  +    end, Debug),
       % Context switches
  -    case rpc:call(list_to_atom(RemoteNode), erlang, statistics, [context_switches]) of
  -        {Switches, 0} when is_integer(Switches) ->
  -            io:format("~s ~B ~B~n", [Scheme ++ ".context_switches", Switches, Timestamp]);
  -        _ ->
  -            % Catch-all state, we don't want to pollute metrics output
  -            ok
  -    end,
  +    fetch_rpc_metric(RemoteNode, erlang, statistics, [context_switches], fun({Switches, 0}) ->
  +        print_metric(Scheme, "context_switches", Switches, Timestamp)
  +    end, Debug),
       % GC Metrics
  -    case rpc:call(list_to_atom(RemoteNode), erlang, statistics, [garbage_collection]) of
  -        {NumberofGCs, WordsReclaimed, 0} when is_integer(NumberofGCs), is_integer(WordsReclaimed) ->
  -            io:format("~s ~B ~B~n", [Scheme ++ ".number_of_gcs", NumberofGCs, Timestamp]),
  -            io:format("~s ~B ~B~n", [Scheme ++ ".words_reclaimed", WordsReclaimed, Timestamp]);
  -        _ ->
  -            % Catch-all state, we don't want to pollute metrics output
  -            ok
  -    end,
  +    fetch_rpc_metric(RemoteNode, erlang, statistics, [garbage_collection], fun({NumberofGCs, WordsReclaimed, 0}) ->
  +        print_metric(Scheme, "number_of_gcs", NumberofGCs, Timestamp),
  +        print_metric(Scheme, "words_reclaimed", WordsReclaimed, Timestamp)
  +    end, Debug),
       % I/O Metrics
  -    case rpc:call(list_to_atom(RemoteNode), erlang, statistics, [io]) of
  -        {{input, Input}, {output, Output}} when is_integer(Input), is_integer(Output) ->
  -            io:format("~s ~B ~B~n", [Scheme ++ ".input_io_bytes", Input, Timestamp]),
  -            io:format("~s ~B ~B~n", [Scheme ++ ".output_io_bytes", Output, Timestamp]);
  -        _ ->
  -            % Catch-all state, we don't want to pollute metrics output
  -            ok
  -    end,
  +    fetch_rpc_metric(RemoteNode, erlang, statistics, [io], fun({{input, Input}, {output, Output}}) ->
  +            print_metric(Scheme, "input_io_bytes", Input, Timestamp),
  +            print_metric(Scheme, "output_io_bytes", Output, Timestamp)
  +    end, Debug),
       % Total number of scheduler reductions
  -    case rpc:call(list_to_atom(RemoteNode), erlang, statistics, [reductions]) of
  -         {TotalReductions, _ReductionsSinceLastCall} when is_integer(TotalReductions) ->
  -            io:format("~s ~B ~B~n", [Scheme ++ ".reductions", TotalReductions, Timestamp]);
  -        _ ->
  -            % Catch-all state, we don't want to pollute metrics output
  -            ok
  -    end,
  +    fetch_rpc_metric(RemoteNode, erlang, statistics, [reductions], fun({TotalReductions, _ReductionsSinceLastCall}) ->
  +            print_metric(Scheme, "reductions", TotalReductions, Timestamp)
  +    end, Debug),
       % Total nubmer of processes in the run_queue of each scheduler
  -    case rpc:call(list_to_atom(RemoteNode), erlang, statistics, [run_queue]) of
  -         RunQueue when is_integer(RunQueue) ->
  -            io:format("~s ~B ~B~n", [Scheme ++ ".run_queue", RunQueue, Timestamp]);
  -        _ ->
  -            % Catch-all state, we don't want to pollute metrics output
  -            ok
  -    end,
  +    fetch_rpc_metric(RemoteNode, erlang, statistics, [run_queue], fun(RunQueue) ->
  +            print_metric(Scheme, "run_queue", RunQueue, Timestamp)
  +    end, Debug),
  +    % Process-specific info
  +    lists:foreach(fun(Process) ->
  +        fetch_rpc_metric(RemoteNode, erlang, whereis, [list_to_atom(Process)], fun(Pid) ->
  +            fetch_rpc_metric(RemoteNode, erlang, process_info, [Pid], fun(ProcessInfo) ->
  +                print_metric(Scheme, "process_info", Process ++ ".message_queue_len", proplists:get_value(message_queue_len, ProcessInfo, 0), Timestamp),
  +                print_metric(Scheme, "process_info", Process ++ ".total_heap_size", proplists:get_value(total_heap_size, ProcessInfo, 0), Timestamp),
  +                print_metric(Scheme, "process_info", Process ++ ".heap_size", proplists:get_value(heap_size, ProcessInfo, 0), Timestamp),
  +                print_metric(Scheme, "process_info", Process ++ ".reductions", proplists:get_value(reductions, ProcessInfo, 0), Timestamp),
  +                GCInfo = proplists:get_value(garbage_collection, ProcessInfo, []),
  +                print_metric(Scheme, "process_info", Process ++ ".minor_gcs", proplists:get_value(minor_gcs, GCInfo, 0), Timestamp)
  +            end, Debug)
  +        end, Debug)
  +    end, Processes),
       ok.
  
positive.code:         "-s" ->
              [Scheme|NewOptions] = Options,
              parse_options(NewOptions, [{scheme, Scheme}|ParsedOptions]);
          "-c" ->
              [Cookie|NewOptions] = Options,
              parse_options(NewOptions, [{cookie, Cookie}|ParsedOptions]);
  
negative.code: %% for metrics gathering (great for Graphite)
  %%
  %% Usage:
  %% ./erlang_stats.erl -c epic_erlang_cookie -n metrics@127.0.0.1 -r epic_erlang_app@127.0.0.1 -s prod.epic_erlang_app -p named_process1 -d true
  %%
  %% Copyright 2013 Panagiotis Papadomitsos <pj@ezgr.net>.
  %%
  