observer_cli

Build StatusGitHub tagMIT LicenseHex.pm VersionHex.pm Downloads

Visualize Erlang/Elixir Nodes On The Command Line base on recon. Document in detail.

Goal


Installation

Erlang

%% rebar.config
{deps, [observer_cli]}
%% erlang.mk
dep_observer_cli = hex 1.5.1

Elixir

# mix.exs
def deps do
[{:observer_cli, "~> 1.5"}]
end

How-To

Try in local shell.

%% rebar3 project
rebar3 shell
1> observer_cli:start().
%% mix project
iex -S mix
iex(1)> :observer_cli.start

Monitor remote node

%% rebar3 project
rebar3 shell --name 'observer_cli@127.0.0.1'
1> observer_cli:start('target@host', 'magic_cookie').
%% mix project
iex --name "observer_cli@127.0.0.1" -S mix
iex(1)> :observer_cli.start(:'target@host', :'magic_cookie')

ensure observer_cli application been loaded on target node.

Escriptize

  1. cd path/to/observer_cli/
  2. rebar3 escriptize to generate an escript executable containing the project's and its dependencies' BEAM files. Place script(_build/default/bin/observer_cli) anywhere in your path and use observer_cli command.
  3. observer_cli TARGETNODE [TARGETCOOKIE REFRESHMS] to monitor remote node.

DEMO

HomeNetworkSystemEtsMnesiaApplicationDocumentProcessPort

How to write your own plugin?

If you need to customize some of your internal metrics and integrate it into observer_ci, you only need to write a observer_cli_plugin behaviour in a few simple steps to get a nice presentation.

  1. Configure observer_cli,tell observer_cli how to find your plugin.
%% module - Specific module implements plugin behavior. It's mandatory.
%% title - Menu title. It's mandatory.
%% shortcut - Switch plugin by shortcut. It's mandatory.
%% interval - Refresh interval ms. It's optional. default is 1500ms.
%% sort_column - Sort the sheet by this index. It's optional default is 2.
{plugins,
[
#{module => observer_cli_plug_behaviour1, title => "XPlug",
interval => 1500, shortcut => "X", sort_column => 3},
#{module => observer_cli_plug_behaviour2, title => "YPlug",
interval => 1600, shortcut => "Y", sort_column => 3}
]
}

  1. Write observer_cli_plugin behaviour. observer_cli_plugin has 3 callbacks.

2.1 attributes.

-callback atributes(PrevState) -> {[Rows], NewState} when
Rows :: #{content => string()|integer()|{byte, pos_integer()},
width => pos_integer(), color => binary()}.

for example:

attributes(PrevState) ->
Attrs =
[
[
#{content => "XXX Ets Size", width => 20},
#{content => ets:info(xxx,size), width => 10},
#{content => "Pool1 Size", width => 15},
#{content => application:get_env(app,pool1_size), width => 30},
#{content => "XYZ1 Process Mem", width => 18,
#{content => {byte, element(2, erlang:process_info(xyz1, memory))}, width => 16}
],
[
#{content => "YYY Ets Size", width =>20},
#{content => ets:info(yyy,size), width => 10},
#{content => "Pool2 Size", width =>15},
#{content => application:get_env(app,pool2_size), width => 30},
#{content =>"XYZ2 Process Mem", width =>18},
#{content => {byte, element(2, erlang:process_info(xyz2, memory))}, width => 16}
],
[
#{content => "ZZZ Ets Size", width =>20},
#{content => ets:info(zzz,size), width => 10},
#{content => "Pool3 Size", width =>15},
#{content => application:get_env(app,pool3_size), width => 30},
#{content => "XYZ3 Process Mem", width =>18},
#{content => {byte, element(2, erlang:process_info(xyz3, memory))}, width => 16}
]
],
NewState = PrevState,
{Attrs, NewState}.

-callback sheet_header() -> [SheetHeader] when
SheetHeader :: #{title => string(), width => pos_integer(), shortcut => string()}.

for example:

sheet_header() ->
[
#{title => "Pid", width => 25},
#{title => "Status", width => 25},
#{title => "Memory", width => 24, shortcut => "S"},
#{title => "Reductions", width => 24, shortcut => "R"},
#{title => "Message Queue Len", width => 25, shortcut => "Q"}
].
-callback sheet_body(PrevState) -> {[SheetBody], NewState} when
PrevState :: any(),
SheetBody :: list(),
NewState :: any().

for example:

sheet_body(PrevState) ->
Body =
[begin
[
Pid,
element(2, erlang:process_info(Pid, status)),
element(2, erlang:process_info(Pid, memory)),
element(2, erlang:process_info(Pid, reductions)),
element(2, erlang:process_info(Pid, message_queue_len))
]
end||Pid <- erlang:processes()
],
NewState = PrevState,
{Body, NewState}.

Support F/B to page up/down.

A more specific plugin can collect linux system information such as kernel vsn, loadavg, disk, memory usage, cpu utilization, IO statistics.


Changelog


Contributors


zhongwencool

💻

Dimitrios Zorbas

💻

taotao

💻

Trevor Brown

💻

Zaiming Shi

💻

License

See the LICENSE file for license rights and limitations (MIT).