Skip to content

Commit

Permalink
bump to 1.8.0 (#105)
Browse files Browse the repository at this point in the history
* fix: doc don't show when otp 27

* feat: support show ets size and go to specific pid

* chore: bump to 1.8.0

* chore: remove eqwalizer_rebar3 deps

* chore: add dialyzer for ci
  • Loading branch information
zhongwencool authored Oct 21, 2024
1 parent 505b3ac commit 19b2011
Show file tree
Hide file tree
Showing 15 changed files with 210 additions and 92 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/erlang.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,6 @@ jobs:
run: rebar3 compile
- name: xref
run: rebar3 xref
- name: dialyzer
run: rebar3 dialyzer

13 changes: 9 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@ Visualize Erlang/Elixir Nodes On The Command Line base on [recon](https://github
%% rebar.config
{deps, [observer_cli]}
%% erlang.mk
dep_observer_cli = hex 1.7.5
dep_observer_cli = hex 1.8.0
```

**Elixir**

```elixir
# mix.exs
def deps do
[{:observer_cli, "~> 1.7"}]
[{:observer_cli, "~> 1.8"}]
end
```

Expand Down Expand Up @@ -89,7 +89,7 @@ _build/dev/rel/example/bin/example rpc ":observer_cli.start"

### DEMO

<img src="https://user-images.githubusercontent.com/3116225/39091211-55554414-4622-11e8-8b28-bd3b5c7e17a6.jpg" width="100%" alt="Home"> </img>
<img src="https://github.com/user-attachments/assets/ce797033-732a-4178-a9c5-df4de559ed0c" width="100%" alt="Home"> </img>

### How to write your own plugin?

Expand Down Expand Up @@ -255,7 +255,12 @@ Support F/B to page up/down.
---

### Changelog

- 1.8.0
- Support `<Pid` to jump to specific pid.
- Show process's label if it's set with [proc_lib:set_label(Label)](https://www.erlang.org/doc/apps/stdlib/proc_lib.html#set_label/1)
- Show The number of bytes in the output distribution queue on System View. This queue sits between the Erlang code and the port driver, using undocumented function`erlang:dist_get_stat/1`.
- Fix Doc View not show when otp version = 27

- 1.7.5
- Fix crash when mnesia table with external copies.
Which `mnesia:table_info(TabName, storage_type)` returns tuple `{ext, _, _}`
Expand Down
4 changes: 2 additions & 2 deletions mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ defmodule ObserverCli.MixProject do
def project do
[
app: :observer_cli,
version: "1.7.5",
version: "1.8.0",
language: :erlang,
description: "observer in shell",
deps: [
{:recon, "~> 2.5.1"},
{:recon, "~> 2.5.6"},
]
]
end
Expand Down
2 changes: 1 addition & 1 deletion mix.lock
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
%{
"recon": {:hex, :recon, "2.5.1", "430ffa60685ac1efdfb1fe4c97b8767c92d0d92e6e7c3e8621559ba77598678a", [:mix, :rebar3], [], "hexpm"},
"recon": {:hex, :recon, "2.5.6", "9052588e83bfedfd9b72e1034532aee2a5369d9d9343b61aeb7fbce761010741", [:mix, :rebar3], [], "hexpm", "96c6799792d735cc0f0fd0f86267e9d351e63339cbe03df9d162010cefc26bb0"},
}
10 changes: 2 additions & 8 deletions rebar.config
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,12 @@
]}.
{deps_dir, "deps"}.
{deps, [
recon,
{eqwalizer_support,
{git_subdir, "https://github.com/whatsapp/eqwalizer.git", {branch, "main"},
"eqwalizer_support"}}
recon
]}.

{project_plugins, [
rebar3_format,
erlfmt,
{eqwalizer_rebar3,
{git_subdir, "https://github.com/whatsapp/eqwalizer.git", {branch, "main"},
"eqwalizer_rebar3"}}
erlfmt
]}.

{escript_main_app, observer_cli}.
Expand Down
11 changes: 3 additions & 8 deletions rebar.lock
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
{"1.2.0",
[{<<"eqwalizer_support">>,
{git_subdir,"https://github.com/whatsapp/eqwalizer.git",
{ref,"0c099bbfa2fba1869d60e239c9b2cf2b6fb31ea9"},
"eqwalizer_support"},
0},
{<<"recon">>,{pkg,<<"recon">>,<<"2.5.5">>},0}]}.
[{<<"recon">>,{pkg,<<"recon">>,<<"2.5.6">>},0}]}.
[
{pkg_hash,[
{<<"recon">>, <<"C108A4C406FA301A529151A3BB53158CADC4064EC0C5F99B03DDB8C0E4281BDF">>}]},
{<<"recon">>, <<"9052588E83BFEDFD9B72E1034532AEE2A5369D9D9343B61AEB7FBCE761010741">>}]},
{pkg_hash_ext,[
{<<"recon">>, <<"632A6F447DF7CCC1A4A10BDCFCE71514412B16660FE59DECA0FCF0AA3C054404">>}]}
{<<"recon">>, <<"96C6799792D735CC0F0FD0F86267E9D351E63339CBE03DF9D162010CEFC26BB0">>}]}
].
78 changes: 39 additions & 39 deletions src/observer_cli.app.src
Original file line number Diff line number Diff line change
@@ -1,39 +1,39 @@
{application, observer_cli,
[
{description, "Visualize Erlang Nodes On The Command Line"},
{vsn, "1.7.5"},
{modules, [
observer_cli
]},
{registered, []},
{applications, [
kernel,
stdlib,
recon
]},
{files, ["include",
"LICENSE*",
"mix.exs",
"mix.lock",
"README.md",
"rebar.config",
"rebar.lock",
"src"]},
{build_tools, ["mix", "rebar3"]},
{env, [
{scheduler_usage, disable},
{plugins,
[
%% 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 options. default is 1500ms.
%% sort_column - Sort the sheet by this index. It's options default is 2.
%% #{module => observer_cli_plug_1, title => "Example-1", interval => 1500, shortcut => "S", sort_column => 3},
%% #{module => observer_cli_plug_2, title => "Example-2", interval => 1600, shortcut => "D", sort_column => 2}
]}
]},
{licenses, ["MIT"]},
{links, [{"Github", "https://github.com/zhongwencool/observer_cli"}]}
]}.
{application, observer_cli, [
{description, "Visualize Erlang Nodes On The Command Line"},
{vsn, "1.8.0"},
{modules, [
observer_cli
]},
{registered, []},
{applications, [
kernel,
stdlib,
recon
]},
{files, [
"include",
"LICENSE*",
"mix.exs",
"mix.lock",
"README.md",
"rebar.config",
"rebar.lock",
"src"
]},
{build_tools, ["mix", "rebar3"]},
{env, [
{scheduler_usage, disable},
{plugins, [
%% 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 options. default is 1500ms.
%% sort_column - Sort the sheet by this index. It's options default is 2.

%% #{module => observer_cli_plug_1, title => "Example-1", interval => 1500, shortcut => "S", sort_column => 3},
%% #{module => observer_cli_plug_2, title => "Example-2", interval => 1600, shortcut => "D", sort_column => 2}
]}
]},
{licenses, ["MIT"]},
{links, [{"Github", "https://github.com/zhongwencool/observer_cli"}]}
]}.
11 changes: 9 additions & 2 deletions src/observer_cli.erl
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
-spec start() -> no_return | {badrpc, term()}.
start() -> start(#view_opts{}).

-spec start(Node) -> no_return | {badrpc, term()} when Node :: atom() | non_neg_integer().
-spec start(Node) -> no_return | {badrpc, term()} when
Node :: atom() | non_neg_integer() | #view_opts{}.
start(Node) when Node =:= node() ->
start(#view_opts{});
start(Node) when is_atom(Node) ->
Expand Down Expand Up @@ -138,6 +139,9 @@ manager(StorePid, RenderPid, Opts, LastSchWallFlag) ->
NewPages = observer_cli_lib:update_page_pos(StorePid, NewPage, Pages),
clean(Resource),
start(Opts#view_opts{home = Home#home{cur_page = NewPage, pages = NewPages}});
{go_to_pid, Pid} ->
clean(Resource),
observer_cli_process:start(home, Pid, Opts);
_ ->
manager(StorePid, RenderPid, Opts, LastSchWallFlag)
end.
Expand Down Expand Up @@ -289,6 +293,7 @@ render_memory_process_line(MemSum, PortParallelism, Interval) ->
AtomMem = proplists:get_value(atom_used, Mem),
BinMem = proplists:get_value(binary, Mem),
EtsMem = proplists:get_value(ets, Mem),
EtsLen = erlang:length(ets:all()),
{
BytesIn,
BytesOut,
Expand Down Expand Up @@ -349,7 +354,7 @@ render_memory_process_line(MemSum, PortParallelism, Interval) ->
?W("Gc Count", 20),
?W(GcCount, 24),
?NEW_LINE,
?W("Ets", 10),
?W("Ets/" ++ erlang:integer_to_list(EtsLen), 10),
?W({byte, EtsMem}, 12),
?W(EtsMemPercent, 6),
?W(LogKey, 25),
Expand Down Expand Up @@ -777,6 +782,8 @@ choose_name(IsName) when is_atom(IsName) ->
choose_name(_) ->
undefined.

%% proc_lib:get_label/1 is not exported before OTP 27
-dialyzer([{nowarn_function, [choose_lable/1]}]).
choose_lable(Pid) ->
case
erlang:function_exported(proc_lib, get_label, 1) andalso
Expand Down
2 changes: 1 addition & 1 deletion src/observer_cli_application.erl
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

%% @doc List application info

-spec start(ViewOpts) -> no_return when ViewOpts :: view_opts().
-spec start(ViewOpts) -> quit when ViewOpts :: view_opts().
start(#view_opts{app = App, auto_row = AutoRow} = ViewOpts) ->
Pid = spawn_link(fun() ->
?output(?CLEAR),
Expand Down
46 changes: 26 additions & 20 deletions src/observer_cli_help.erl
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,21 @@ render_worker(Interval) ->
Text = "Interval: " ++ integer_to_list(Interval) ++ "ms",
Menu = observer_cli_lib:render_menu(doc, Text),
?output([?CURSOR_TOP, Menu]),
render_doc(Text),
erlang:send_after(Interval, self(), redraw),
receive
redraw ->
render_worker(Interval);
quit ->
MenuQ = observer_cli_lib:render_menu(doc, Text),
HelpQ = render_help(),
LastLine = observer_cli_lib:render_last_line("q(quit)"),
?output([?CURSOR_TOP, MenuQ, HelpQ, ?UNDERLINE, ?GRAY_BG, LastLine, ?RESET_BG, ?RESET])
ok
end.

render_doc(Text) ->
MenuQ = observer_cli_lib:render_menu(doc, Text),
HelpQ = render_help(),
LastLine = observer_cli_lib:render_last_line("q(quit)"),
?output([?CURSOR_TOP, MenuQ, HelpQ, ?UNDERLINE, ?GRAY_BG, LastLine, ?RESET_BG, ?RESET]).

render_help() ->
[
"|\e[44m1. Start Mode\e[49m \n",
Expand All @@ -57,22 +61,24 @@ render_help() ->
"| \e[48;2;80;80;80m1.3\e[0m observer_start:start(Node, Cookie).\n",

"|\e[44m2. HOME(H) Commands\e[49m \n",
"| \e[48;2;80;80;80m` \e[0m enable/disable schedule usage.\n",
"| \e[48;2;80;80;80mPageDown \e[0m pd or F(forward).\n",
"| \e[48;2;80;80;80mPageUp \e[0m pu or B(back).\n",
"| \e[48;2;80;80;80mr \e[0m switch mode to reduction(proc_count).\n",
"| \e[48;2;80;80;80mrr \e[0m switch mode to reduction(proc_window).\n",
"| \e[48;2;80;80;80mm \e[0m switch mode to memory(proc_count).\n",
"| \e[48;2;80;80;80mmm \e[0m switch mode to memory(proc_window).\n",
"| \e[48;2;80;80;80mb \e[0m switch mode to bin memory(proc_count).\n",
"| \e[48;2;80;80;80mbb \e[0m switch mode to bin memory(proc_window).\n",
"| \e[48;2;80;80;80mmq \e[0m switch mode to message queue len(proc_count).\n",
"| \e[48;2;80;80;80mmmq \e[0m switch mode to message queue len(proc_window).\n",
"| \e[48;2;80;80;80mt \e[0m switch mode to total heap size(proc_count).\n",
"| \e[48;2;80;80;80mtt \e[0m switch mode to total heap size(proc_window).\n",
"| \e[48;2;80;80;80m3000 \e[0m set interval time to 3000ms, the integer must >= 1500.\n",
"| \e[48;2;80;80;80m13 \e[0m choose the 13th process(green line), the integer must in top list.\n",
"| \e[48;2;80;80;80mp \e[0m pause/unpause the view.\n",
"| \e[48;2;80;80;80m` \e[0m enable/disable schedule usage.\n",
"| \e[48;2;80;80;80mPageDown \e[0m pd or F(forward).\n",
"| \e[48;2;80;80;80mPageUp \e[0m pu or B(back).\n",
"| \e[48;2;80;80;80mr \e[0m switch mode to reduction(proc_count).\n",
"| \e[48;2;80;80;80mrr \e[0m switch mode to reduction(proc_window).\n",
"| \e[48;2;80;80;80mm \e[0m switch mode to memory(proc_count).\n",
"| \e[48;2;80;80;80mmm \e[0m switch mode to memory(proc_window).\n",
"| \e[48;2;80;80;80mb \e[0m switch mode to bin memory(proc_count).\n",
"| \e[48;2;80;80;80mbb \e[0m switch mode to bin memory(proc_window).\n",
"| \e[48;2;80;80;80mmq \e[0m switch mode to message queue len(proc_count).\n",
"| \e[48;2;80;80;80mmmq \e[0m switch mode to message queue len(proc_window).\n",
"| \e[48;2;80;80;80mt \e[0m switch mode to total heap size(proc_count).\n",
"| \e[48;2;80;80;80mtt \e[0m switch mode to total heap size(proc_window).\n",
"| \e[48;2;80;80;80m3000 \e[0m set interval time to 3000ms, the integer must >= 1500.\n",
"| \e[48;2;80;80;80m13 \e[0m choose the 13th process(green line), the integer must in top list.\n",
"| \e[48;2;80;80;80m<0.43.0> \e[0m choose the <0.43.0> process, the pid does not need to be in the top list.\n",
"| \e[48;2;80;80;80m<431 or >431 \e[0m choose the <0.431.0> process, the pid does not need to be in the top list.\n",
"| \e[48;2;80;80;80mp \e[0m pause/unpause the view.\n",

"|\e[44m5. Reference\e[49m \n",
"|More information about recon:proc_count/2 and recon:proc_window/3 \n",
Expand Down
19 changes: 16 additions & 3 deletions src/observer_cli_lib.erl
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,11 @@ uptime() ->
[?W(?GREEN, Time, 16)].

%% @doc 0.982342 -> 98.23%, 1 -> 100.0%
-spec to_percent(float()) -> string().
to_percent(Float) when Float < 0.1 -> [$0, erlang:float_to_list(Float * 100, [{decimals, 2}]), $%];
to_percent(Float) when Float < 1 -> [erlang:float_to_list(Float * 100, [{decimals, 2}]), $%];
to_percent(undefined) -> "******";
to_percent(_) -> "100.0%".

-spec to_list(term()) -> list().
to_list(Atom) when is_atom(Atom) -> atom_to_list(Atom);
to_list(Integer) when is_integer(Integer) -> integer_to_list(Integer);
to_list(Pid) when is_pid(Pid) -> erlang:pid_to_list(Pid);
Expand Down Expand Up @@ -251,14 +249,29 @@ parse_cmd(ViewOpts, Module, Args) ->
hide;
"`\n" ->
scheduler_usage;
[$< | PidStr] ->
to_pid(PidStr);
[$> | PidStr] ->
to_pid(PidStr);
%% {error, estale}|{error, terminated}
{error, _Reason} ->
quit;
Number ->
parse_integer(Number)
end.

-spec next_redraw(reference(), pos_integer()) -> reference().
-spec to_pid(string()) -> {go_to_pid, pid()} | quit.
to_pid(Str) ->
case string:tokens(Str, ".<>\n") of
[X, Y, Z] ->
{go_to_pid, list_to_pid("<" ++ X ++ "." ++ Y ++ "." ++ Z ++ ">")};
[Y] ->
{go_to_pid, list_to_pid("<0." ++ Y ++ ".0>")};
_ ->
quit
end.

-spec next_redraw(reference() | ?INIT_TIME_REF, pos_integer()) -> reference().
next_redraw(LastTimeRef, Interval) ->
LastTimeRef =/= ?INIT_TIME_REF andalso erlang:cancel_timer(LastTimeRef),
erlang:send_after(Interval, self(), redraw).
Expand Down
3 changes: 3 additions & 0 deletions src/observer_cli_mnesia.erl
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ get_table_list(HideSys, Attr) ->
_ -> get_table_list2(Owner, HideSys, Attr)
end.

-dialyzer([{nowarn_function, [get_table_list2/3]}]).
get_table_list2(Owner, HideSys, Attr) ->
{registered_name, RegName} = process_info(Owner, registered_name),
WordSize = erlang:system_info(wordsize),
Expand All @@ -213,6 +214,8 @@ get_table_list2(Owner, HideSys, Attr) ->
end,
lists:foldl(CollectFun, [], mnesia:system_info(tables)).

-dialyzer([{nowarn_function, [with_storage_type/2]}]).

with_storage_type(Id, Tab0) ->
Storage = mnesia:table_info(Id, storage_type),
with_storage_type(Id, Storage, Tab0).
Expand Down
4 changes: 1 addition & 3 deletions src/observer_cli_plugin.erl
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,7 @@ manager(ChildPid, SheetCache, ViewOpts) ->
start(ViewOpts#view_opts{plug = PlugOpts#plug{plugs = NewPlugs}});
{error, _} ->
manager(ChildPid, SheetCache, ViewOpts)
end;
_ ->
manager(ChildPid, SheetCache, ViewOpts)
end
end.

update_plugins(CurIndex, Lists, UpdateItems) ->
Expand Down
6 changes: 6 additions & 0 deletions src/observer_cli_process.erl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

-include("observer_cli.hrl").

-dialyzer([
{nowarn_function, [
render_worker/7, render_reduction_memory/4, get_chart_format/1, chart_format/2
]}
]).

-export([start/3]).

%% lists:foldl(fun(_X, Acc) -> queue:in('NaN', Acc) end, queue:new(), lists:seq(1, 5))
Expand Down
Loading

0 comments on commit 19b2011

Please sign in to comment.