aboutsummaryrefslogtreecommitdiffstats
path: root/lib/observer/src
diff options
context:
space:
mode:
Diffstat (limited to 'lib/observer/src')
-rw-r--r--lib/observer/src/observer_alloc_wx.erl56
-rw-r--r--lib/observer/src/observer_app_wx.erl4
-rw-r--r--lib/observer/src/observer_lib.erl25
-rw-r--r--lib/observer/src/observer_perf_wx.erl7
-rw-r--r--lib/observer/src/observer_procinfo.erl8
-rw-r--r--lib/observer/src/observer_sys_wx.erl98
-rw-r--r--lib/observer/src/observer_wx.erl58
7 files changed, 157 insertions, 99 deletions
diff --git a/lib/observer/src/observer_alloc_wx.erl b/lib/observer/src/observer_alloc_wx.erl
index 220276ac0c..77609b11ce 100644
--- a/lib/observer/src/observer_alloc_wx.erl
+++ b/lib/observer/src/observer_alloc_wx.erl
@@ -53,25 +53,29 @@ start_link(Notebook, Parent) ->
init([Notebook, Parent]) ->
try
- Panel = wxPanel:new(Notebook),
+ TopP = wxPanel:new(Notebook),
Main = wxBoxSizer:new(?wxVERTICAL),
+ Panel = wxPanel:new(TopP),
+ GSzr = wxBoxSizer:new(?wxVERTICAL),
BorderFlags = ?wxLEFT bor ?wxRIGHT,
- Carrier = make_win(alloc, Panel, Main, BorderFlags bor ?wxTOP),
- Utilz = make_win(utilz, Panel, Main, BorderFlags),
-
- MemWin = {MemPanel,_} = create_mem_info(Panel),
- wxSizer:add(Main, MemPanel, [{flag, ?wxEXPAND bor BorderFlags bor ?wxBOTTOM},
- {proportion, 1}, {border, 5}]),
- wxWindow:setSizer(Panel, Main),
+ Carrier = make_win(alloc, Panel, GSzr, BorderFlags bor ?wxTOP),
+ Utilz = make_win(utilz, Panel, GSzr, BorderFlags),
+ wxWindow:setSizer(Panel, GSzr),
+ wxSizer:add(Main, Panel, [{flag, ?wxEXPAND},{proportion,2}]),
+
+ MemWin = create_mem_info(TopP),
+ wxSizer:add(Main, MemWin, [{flag, ?wxEXPAND bor BorderFlags bor ?wxBOTTOM},
+ {proportion, 1}, {border, 5}]),
+ wxWindow:setSizer(TopP, Main),
Windows = [Carrier, Utilz],
PaintInfo = setup_graph_drawing(Windows),
- {Panel, #state{parent= Parent,
- panel = Panel,
- wins = Windows,
- mem = MemWin,
- paint = PaintInfo,
- time = setup_time()
- }
+ {TopP, #state{parent= Parent,
+ panel = Panel,
+ wins = Windows,
+ mem = MemWin,
+ paint = PaintInfo,
+ time = setup_time()
+ }
}
catch _:Err ->
io:format("~p crashed ~p: ~p~n",[?MODULE, Err, erlang:get_stacktrace()]),
@@ -84,12 +88,14 @@ setup_time() ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
handle_event(#wx{id=?ID_REFRESH_INTERVAL, event=#wxCommand{type=command_menu_selected}},
- #state{panel=Panel, appmon=Old, wins=Wins0, time=#ti{fetch=F0} = Ti0} = State) ->
+ #state{active=Active, panel=Panel, appmon=Old, wins=Wins0, time=#ti{fetch=F0} = Ti0} = State) ->
case interval_dialog(Panel, Ti0) of
Ti0 -> {noreply, State};
#ti{fetch=F0} = Ti -> %% Same fetch interval force refresh
Wins = [W#win{max=undefined} || W <- Wins0],
{noreply, precalc(State#state{time=Ti, wins=Wins})};
+ Ti when not Active ->
+ {noreply, State#state{time=Ti}};
Ti -> %% Changed fetch interval, drop all data
{noreply, restart_fetcher(Old, State#state{time=Ti})}
end;
@@ -120,7 +126,7 @@ handle_info({Key, {promise_reply, {badrpc, _}}}, #state{async=Key} = State) ->
{noreply, State#state{active=false, appmon=undefined}};
handle_info({Key, {promise_reply, SysInfo}},
- #state{async=Key, panel=Panel, samples=Data, active=Active, wins=Wins0,
+ #state{async=Key, panel=_Panel, samples=Data, active=Active, wins=Wins0,
time=#ti{tick=Tick, disp=Disp0}=Ti} = S0) ->
Disp = trunc(Disp0),
Next = max(Tick - Disp, 0),
@@ -131,7 +137,6 @@ handle_info({Key, {promise_reply, SysInfo}},
if Active ->
update_alloc(S0, Info),
State = precalc(S1),
- catch wxWindow:refresh(Panel),
{noreply, State};
true ->
{noreply, S1}
@@ -193,7 +198,8 @@ precalc(#state{samples=Data0, paint=Paint, time=Ti, wins=Wins0}=State) ->
State#state{wins=Wins}.
-update_alloc(#state{mem={_, Grid}}, Fields) ->
+update_alloc(#state{mem=Grid}, Fields) ->
+ wxWindow:freeze(Grid),
Max = wxListCtrl:getItemCount(Grid),
Update = fun({Name, BS, CS}, Row) ->
(Row >= Max) andalso wxListCtrl:insertItem(Grid, Row, ""),
@@ -203,6 +209,7 @@ update_alloc(#state{mem={_, Grid}}, Fields) ->
Row + 1
end,
wx:foldl(Update, 0, Fields),
+ wxWindow:thaw(Grid),
Fields.
alloc_info(SysInfo) ->
@@ -249,9 +256,9 @@ sum_alloc_one_instance([],BS,CS,TotalBS,TotalCS) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
create_mem_info(Parent) ->
- Panel = wxPanel:new(Parent),
Style = ?wxLC_REPORT bor ?wxLC_SINGLE_SEL bor ?wxLC_HRULES bor ?wxLC_VRULES,
- Grid = wxListCtrl:new(Panel, [{style, Style}]),
+ Grid = wxListCtrl:new(Parent, [{style, Style}]),
+
Li = wxListItem:new(),
AddListEntry = fun({Name, Align, DefSize}, Col) ->
wxListItem:setText(Li, Name),
@@ -266,12 +273,7 @@ create_mem_info(Parent) ->
lists:foldl(AddListEntry, 0, ListItems),
wxListItem:destroy(Li),
- Sizer = wxBoxSizer:new(?wxVERTICAL),
- wxSizer:add(Sizer, Grid, [{flag, ?wxEXPAND bor ?wxLEFT bor ?wxRIGHT},
- {border, 5}, {proportion, 1}]),
- wxWindow:setSizerAndFit(Panel, Sizer),
- {Panel, Grid}.
-
+ Grid.
create_menus(Parent, _) ->
View = {"View", [#create_menu{id = ?ID_REFRESH_INTERVAL, text = "Graph Settings"}]},
diff --git a/lib/observer/src/observer_app_wx.erl b/lib/observer/src/observer_app_wx.erl
index 0e01429aa7..cef83037d0 100644
--- a/lib/observer/src/observer_app_wx.erl
+++ b/lib/observer/src/observer_app_wx.erl
@@ -302,7 +302,9 @@ handle_info({delivery, _Pid, app, _Curr, {[], [], [], []}},
handle_info({delivery, Pid, app, Curr, AppData},
State = #state{panel=Panel, appmon=Pid, current=Curr, usegc=UseGC,
app_w=AppWin, paint=#paint{font=Font}}) ->
- GC = make_gc(AppWin, UseGC),
+ GC = if UseGC -> {?wxGC:create(AppWin), false};
+ true -> {false, wxWindowDC:new(AppWin)}
+ end,
setFont(GC, Font, {0,0,0}),
App = build_tree(AppData, GC),
destroy_gc(GC),
diff --git a/lib/observer/src/observer_lib.erl b/lib/observer/src/observer_lib.erl
index 5d5ac37ce9..7c1337025f 100644
--- a/lib/observer/src/observer_lib.erl
+++ b/lib/observer/src/observer_lib.erl
@@ -128,8 +128,8 @@ display_info(Frame, Info) ->
Add = fun(BoxInfo) ->
case create_box(Panel, BoxInfo) of
{Box, InfoFs} ->
- wxSizer:add(Sizer, Box, [{flag, ?wxEXPAND bor ?wxALL},
- {border, 5}]),
+ wxSizer:add(Sizer, Box,
+ [{flag, ?wxEXPAND bor ?wxALL}, {border, 5}]),
wxSizer:addSpacer(Sizer, 5),
InfoFs;
undefined ->
@@ -432,12 +432,12 @@ create_box(Panel, {scroll_boxes,Data}) ->
{OuterBox, Boxes};
create_box(Parent, Data) ->
- {Title, Align, Info} = get_box_info(Data),
+ {Title, _Align, Info} = get_box_info(Data),
Top = wxStaticBoxSizer:new(?wxVERTICAL, Parent, [{label, Title}]),
Panel = wxPanel:new(Parent),
Box = wxBoxSizer:new(?wxVERTICAL),
- LeftSize = get_max_width(Panel,Info),
- RightProportion = [{flag, Align bor ?wxEXPAND}],
+ LeftSize = 30 + get_max_width(Panel,Info),
+ RightProportion = [{flag, ?wxEXPAND}],
AddRow = fun({Desc0, Value0}) ->
Desc = Desc0++":",
Line = wxBoxSizer:new(?wxHORIZONTAL),
@@ -453,14 +453,19 @@ create_box(Parent, Data) ->
link_entry(Panel,Value);
_ ->
Value = to_str(Value0),
- TCtrl = wxStaticText:new(Panel, ?wxID_ANY,Value),
- length(Value) > 50 andalso
- wxWindow:setToolTip(TCtrl,wxToolTip:new(Value)),
- TCtrl
+ case length(Value) > 100 of
+ true ->
+ Shown = lists:sublist(Value, 80),
+ TCtrl = wxStaticText:new(Panel, ?wxID_ANY, [Shown,"..."]),
+ wxWindow:setToolTip(TCtrl,wxToolTip:new(Value)),
+ TCtrl;
+ false ->
+ wxStaticText:new(Panel, ?wxID_ANY, Value)
+ end
end,
wxSizer:add(Line, 10, 0), % space of size 10 horisontally
wxSizer:add(Line, Field, RightProportion),
- wxSizer:add(Box, Line, [{proportion,1},{flag,?wxEXPAND}]),
+ wxSizer:add(Box, Line, [{proportion,1}]),
Field;
(undefined) ->
undefined
diff --git a/lib/observer/src/observer_perf_wx.erl b/lib/observer/src/observer_perf_wx.erl
index 45af08026a..1010a6af4c 100644
--- a/lib/observer/src/observer_perf_wx.erl
+++ b/lib/observer/src/observer_perf_wx.erl
@@ -142,6 +142,8 @@ handle_event(#wx{id=?ID_REFRESH_INTERVAL, event=#wxCommand{type=command_menu_sel
#ti{fetch=F0} = Ti -> %% Same fetch interval force refresh
Wins = [W#win{max=undefined} || W <- Wins0],
{noreply, precalc(State#state{time=Ti, wins=Wins})};
+ Ti when Old =:= undefined ->
+ {noreply, State#state{time=Ti}};
Ti -> %% Changed fetch interval, drop all data
{noreply, restart_fetcher(node(Old), State#state{time=Ti})}
end;
@@ -762,7 +764,10 @@ make_gc(Panel,UseGC) ->
destroy_gc({GC, DC}) ->
(GC =/= false) andalso ?wxGC:destroy(GC),
- wxPaintDC:destroy(DC).
+ case DC =/= false andalso wx:getObjectType(DC) of
+ false -> ok;
+ Type -> Type:destroy(DC)
+ end.
haveGC() ->
try
diff --git a/lib/observer/src/observer_procinfo.erl b/lib/observer/src/observer_procinfo.erl
index cff5fbb474..fe2aa11450 100644
--- a/lib/observer/src/observer_procinfo.erl
+++ b/lib/observer/src/observer_procinfo.erl
@@ -370,7 +370,7 @@ process_info_fields(Pid) ->
{"Priority", priority},
{"Trap Exit", trap_exit},
{"Reductions", reductions},
- {"Binary", binary},
+ {"Binary", fun(Data) -> stringify_bins(Data) end},
{"Last Calls", last_calls},
{"Catch Level", catchlevel},
{"Trace", trace},
@@ -437,6 +437,11 @@ filter_monitor_info() ->
[Pid || {process, Pid} <- Ms]
end.
+stringify_bins(Data) ->
+ Bins = proplists:get_value(binary, Data),
+ [lists:flatten(io_lib:format("<< ~s, refc ~w>>", [observer_lib:to_str({bytes,Sz}),Refc]))
+ || {_Ptr, Sz, Refc} <- Bins].
+
local_pid_str(Pid) ->
%% observer can observe remote nodes
%% There is no function to get the local
@@ -449,7 +454,6 @@ local_pid_str(Pid) ->
global_pid_node_pref(Pid) ->
%% Global PID node prefix : X of <X.Y.Z>
string:strip(string:sub_word(pid_to_list(Pid),1,$.),left,$<).
-
io_get_data(Pid) ->
Pid ! {self(), get_data_and_close},
diff --git a/lib/observer/src/observer_sys_wx.erl b/lib/observer/src/observer_sys_wx.erl
index b9b407cb0a..fa824995f7 100644
--- a/lib/observer/src/observer_sys_wx.erl
+++ b/lib/observer/src/observer_sys_wx.erl
@@ -48,40 +48,51 @@ start_link(Notebook, Parent) ->
init([Notebook, Parent]) ->
SysInfo = observer_backend:sys_info(),
- {Info, Stat} = info_fields(),
+ {Sys, Mem, Cpu, Stats} = info_fields(),
Panel = wxPanel:new(Notebook),
Sizer = wxBoxSizer:new(?wxVERTICAL),
- TopSizer = wxBoxSizer:new(?wxHORIZONTAL),
- {FPanel0, _FSizer0, Fields0} =
- observer_lib:display_info(Panel, observer_lib:fill_info(Info, SysInfo)),
- {FPanel1, _FSizer1, Fields1} =
- observer_lib:display_info(Panel, observer_lib:fill_info(Stat, SysInfo)),
- wxSizer:add(TopSizer, FPanel0, [{flag, ?wxEXPAND}, {proportion, 1}]),
- wxSizer:add(TopSizer, FPanel1, [{flag, ?wxEXPAND}, {proportion, 1}]),
+ HSizer0 = wxBoxSizer:new(?wxHORIZONTAL),
+ {FPanel0, _FSizer0, Fields0} = observer_lib:display_info(Panel, observer_lib:fill_info(Sys, SysInfo)),
+ {FPanel1, _FSizer1, Fields1} = observer_lib:display_info(Panel, observer_lib:fill_info(Mem, SysInfo)),
+ wxSizer:add(HSizer0, FPanel0, [{flag, ?wxEXPAND}, {proportion, 1}]),
+ wxSizer:add(HSizer0, FPanel1, [{flag, ?wxEXPAND}, {proportion, 1}]),
+
+ HSizer1 = wxBoxSizer:new(?wxHORIZONTAL),
+ {FPanel2, _FSizer2, Fields2} = observer_lib:display_info(Panel, observer_lib:fill_info(Cpu, SysInfo)),
+ {FPanel3, _FSizer3, Fields3} = observer_lib:display_info(Panel, observer_lib:fill_info(Stats, SysInfo)),
+ wxSizer:add(HSizer1, FPanel2, [{flag, ?wxEXPAND}, {proportion, 1}]),
+ wxSizer:add(HSizer1, FPanel3, [{flag, ?wxEXPAND}, {proportion, 1}]),
+
BorderFlags = ?wxLEFT bor ?wxRIGHT,
- wxSizer:add(Sizer, TopSizer, [{flag, ?wxEXPAND bor BorderFlags bor ?wxTOP},
- {proportion, 0}, {border, 5}]),
+ wxSizer:add(Sizer, HSizer0, [{flag, ?wxEXPAND bor BorderFlags bor ?wxTOP},
+ {proportion, 0}, {border, 5}]),
+ wxSizer:add(Sizer, HSizer1, [{flag, ?wxEXPAND bor BorderFlags bor ?wxBOTTOM},
+ {proportion, 0}, {border, 5}]),
wxPanel:setSizer(Panel, Sizer),
Timer = observer_lib:start_timer(10),
{Panel, #sys_wx_state{parent=Parent,
parent_notebook=Notebook,
panel=Panel, sizer=Sizer,
- timer=Timer, fields=Fields0 ++ Fields1}}.
+ timer=Timer, fields=Fields0 ++ Fields1++Fields2++Fields3}}.
create_sys_menu(Parent) ->
View = {"View", [#create_menu{id = ?ID_REFRESH, text = "Refresh\tCtrl-R"},
#create_menu{id = ?ID_REFRESH_INTERVAL, text = "Refresh interval"}]},
observer_wx:create_menus(Parent, [View]).
+update_syspage(#sys_wx_state{node = undefined}) -> ignore;
update_syspage(#sys_wx_state{node = Node, fields=Fields, sizer=Sizer}) ->
SysInfo = observer_wx:try_rpc(Node, observer_backend, sys_info, []),
- {Info, Stat} = info_fields(),
- observer_lib:update_info(Fields, observer_lib:fill_info(Info, SysInfo) ++
- observer_lib:fill_info(Stat, SysInfo)),
+ {Sys, Mem, Cpu, Stats} = info_fields(),
+ observer_lib:update_info(Fields,
+ observer_lib:fill_info(Sys, SysInfo) ++
+ observer_lib:fill_info(Mem, SysInfo) ++
+ observer_lib:fill_info(Cpu, SysInfo) ++
+ observer_lib:fill_info(Stats, SysInfo)),
wxSizer:layout(Sizer).
info_fields() ->
- Info = [{"System and Architecture",
+ Sys = [{"System and Architecture",
[{"System Version", otp_release},
{"ERTS Version", version},
{"Compiled for", system_architecture},
@@ -90,34 +101,35 @@ info_fields() ->
{"SMP Support", smp_support},
{"Thread Support", threads},
{"Async thread pool size", thread_pool_size}
- ]},
- {"CPU's and Threads",
- [{"Logical CPU's", logical_processors},
- {"Online Logical CPU's", logical_processors_online},
- {"Available Logical CPU's", logical_processors_available},
- {"Schedulers", schedulers},
- {"Online schedulers", schedulers_online},
- {"Available schedulers", schedulers_available}
- ]}
- ],
- Stat = [{"Memory Usage", right,
- [{"Total", {bytes, total}},
- {"Processes", {bytes, processes}},
- {"Atoms", {bytes, atom}},
- {"Binaries", {bytes, binary}},
- {"Code", {bytes, code}},
- {"ETS", {bytes, ets}}
- ]},
- {"Statistics", right,
- [{"Up time", {time_ms, uptime}},
- {"Max Processes", process_limit},
- {"Processes", process_count},
- {"Run Queue", run_queue},
- {"IO Input", {bytes, io_input}},
- {"IO Output", {bytes, io_output}}
- ]}
- ],
- {Info, Stat}.
+ ]}],
+
+ Cpu = [{"CPU's and Threads",
+ [{"Logical CPU's", logical_processors},
+ {"Online Logical CPU's", logical_processors_online},
+ {"Available Logical CPU's", logical_processors_available},
+ {"Schedulers", schedulers},
+ {"Online schedulers", schedulers_online},
+ {"Available schedulers", schedulers_available}
+ ]}
+ ],
+ Mem = [{"Memory Usage", right,
+ [{"Total", {bytes, total}},
+ {"Processes", {bytes, processes}},
+ {"Atoms", {bytes, atom}},
+ {"Binaries", {bytes, binary}},
+ {"Code", {bytes, code}},
+ {"ETS", {bytes, ets}}
+ ]}],
+ Stats = [{"Statistics", right,
+ [{"Up time", {time_ms, uptime}},
+ {"Max Processes", process_limit},
+ {"Processes", process_count},
+ {"Run Queue", run_queue},
+ {"IO Input", {bytes, io_input}},
+ {"IO Output", {bytes, io_output}}
+ ]}
+ ],
+ {Sys, Mem, Cpu, Stats}.
%%%%%%%%%%%%%%%%%%%%%%% Callbacks %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/lib/observer/src/observer_wx.erl b/lib/observer/src/observer_wx.erl
index eba603eab5..30bd4043e4 100644
--- a/lib/observer/src/observer_wx.erl
+++ b/lib/observer/src/observer_wx.erl
@@ -65,7 +65,8 @@
node,
nodes,
prev_node="",
- log = false
+ log = false,
+ reply_to=false
}).
start() ->
@@ -229,14 +230,13 @@ handle_event(#wx{id = ?ID_CDV, event = #wxCommand{type = command_menu_selected}}
spawn(crashdump_viewer, start, []),
{noreply, State};
-handle_event(#wx{event = #wxClose{}}, #state{log=LogOn} = State) ->
- LogOn andalso rpc:block_call(State#state.node, rb, stop, []),
- {stop, normal, State};
+handle_event(#wx{event = #wxClose{}}, State) ->
+ stop_servers(State),
+ {noreply, State};
-handle_event(#wx{id = ?wxID_EXIT, event = #wxCommand{type = command_menu_selected}},
- #state{log=LogOn} = State) ->
- LogOn andalso rpc:block_call(State#state.node, rb, stop, []),
- {stop, normal, State};
+handle_event(#wx{id = ?wxID_EXIT, event = #wxCommand{type = command_menu_selected}}, State) ->
+ stop_servers(State),
+ {noreply, State};
handle_event(#wx{id = ?wxID_HELP, event = #wxCommand{type = command_menu_selected}}, State) ->
External = "http://www.erlang.org/doc/apps/observer/index.html",
@@ -379,9 +379,9 @@ handle_call({get_attrib, Attrib}, _From, State) ->
handle_call(get_tracer, _From, State=#state{trace_panel=TraceP}) ->
{reply, TraceP, State};
-handle_call(stop, _, State = #state{frame = Frame}) ->
- wxFrame:destroy(Frame),
- {stop, normal, ok, State};
+handle_call(stop, From, State) ->
+ stop_servers(State),
+ {noreply, State#state{reply_to=From}};
handle_call(log_status, _From, State) ->
{reply, State#state.log, State};
@@ -426,17 +426,45 @@ handle_info({get_debug_info, From}, State = #state{notebook=Notebook, active_tab
From ! {observer_debug, wx:get_env(), Notebook, Pid},
{noreply, State};
-handle_info({'EXIT', Pid, _Reason}, State) ->
- io:format("Child (~s) crashed exiting: ~p ~p~n",
- [pid2panel(Pid, State), Pid,_Reason]),
+handle_info({'EXIT', Pid, Reason}, State) ->
+ case Reason of
+ normal ->
+ {noreply, State};
+ _ ->
+ io:format("Observer: Child (~s) crashed exiting: ~p ~p~n",
+ [pid2panel(Pid, State), Pid, Reason]),
+ {stop, normal, State}
+ end;
+
+handle_info({stop, Me}, State) when Me =:= self() ->
{stop, normal, State};
handle_info(_Info, State) ->
{noreply, State}.
-terminate(_Reason, #state{frame = Frame}) ->
+stop_servers(#state{node=Node, log=LogOn, sys_panel=Sys, pro_panel=Procs, tv_panel=TVs,
+ trace_panel=Trace, app_panel=Apps, perf_panel=Perfs,
+ allc_panel=Alloc} = _State) ->
+ LogOn andalso rpc:block_call(Node, rb, stop, []),
+ Me = self(),
+ Tabs = [Sys, Procs, TVs, Trace, Apps, Perfs, Alloc],
+ Stop = fun() ->
+ try
+ _ = [wx_object:stop(Panel) || Panel <- Tabs],
+ ok
+ catch _:_ -> ok
+ end,
+ Me ! {stop, Me}
+ end,
+ spawn(Stop).
+
+terminate(_Reason, #state{frame = Frame, reply_to=From}) ->
wxFrame:destroy(Frame),
wx:destroy(),
+ case From of
+ false -> ignore;
+ _ -> gen_server:reply(From, ok)
+ end,
ok.
code_change(_, _, State) ->