diff options
-rw-r--r-- | lib/observer/src/observer_lib.erl | 19 | ||||
-rw-r--r-- | lib/observer/src/observer_procinfo.erl | 8 | ||||
-rw-r--r-- | lib/observer/src/observer_sys_wx.erl | 98 | ||||
-rw-r--r-- | lib/observer/src/observer_wx.erl | 58 | ||||
-rw-r--r-- | lib/observer/test/observer_SUITE.erl | 2 |
5 files changed, 117 insertions, 68 deletions
diff --git a/lib/observer/src/observer_lib.erl b/lib/observer/src/observer_lib.erl index c6a1c73c83..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 -> @@ -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_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) -> diff --git a/lib/observer/test/observer_SUITE.erl b/lib/observer/test/observer_SUITE.erl index 3dc3e4772b..ae8111dcd6 100644 --- a/lib/observer/test/observer_SUITE.erl +++ b/lib/observer/test/observer_SUITE.erl @@ -38,7 +38,7 @@ ]). %% Default timetrap timeout (set in init_per_testcase) --define(default_timeout, ?t:minutes(1)). +-define(default_timeout, ?t:minutes(2)). suite() -> [{ct_hooks,[ts_install_cth]}]. |