From cf20035dc7a4fbab47ce17b99b674e4db5eb7a07 Mon Sep 17 00:00:00 2001 From: Dan Gudmundsson Date: Thu, 14 Nov 2013 15:34:55 +0100 Subject: observer: Fix memory and scheduler info and handle missing fields Fix app viewer crash --- lib/observer/src/observer_app_wx.erl | 15 ++++++++++----- lib/observer/src/observer_lib.erl | 31 +++++++++++++++++++++---------- lib/observer/src/observer_perf_wx.erl | 29 ++++++++++++++++------------- lib/observer/src/observer_sys_wx.erl | 9 ++++++--- 4 files changed, 53 insertions(+), 31 deletions(-) (limited to 'lib/observer/src') diff --git a/lib/observer/src/observer_app_wx.erl b/lib/observer/src/observer_app_wx.erl index 82395fbe08..a710bd0a69 100644 --- a/lib/observer/src/observer_app_wx.erl +++ b/lib/observer/src/observer_app_wx.erl @@ -178,11 +178,16 @@ handle_event(#wx{id=Id, event=_Sz=#wxSize{size=Size}}, {noreply, State}; handle_event(#wx{event=#wxMouse{type=Type, x=X0, y=Y0}}, - S0=#state{app=#app{ptree=Tree}, app_w=AppWin}) -> - {X,Y} = wxScrolledWindow:calcUnscrolledPosition(AppWin, X0, Y0), - Hit = locate_node(X,Y, [Tree]), - State = handle_mouse_click(Hit, Type, S0), - {noreply, State}; + S0=#state{app=App, app_w=AppWin}) -> + case App of + #app{ptree=Tree} -> + {X,Y} = wxScrolledWindow:calcUnscrolledPosition(AppWin, X0, Y0), + Hit = locate_node(X,Y, [Tree]), + State = handle_mouse_click(Hit, Type, S0), + {noreply, State}; + _ -> + {noreply, S0} + end; handle_event(#wx{event=#wxCommand{type=command_menu_selected}}, State = #state{sel=undefined}) -> diff --git a/lib/observer/src/observer_lib.erl b/lib/observer/src/observer_lib.erl index f11ccfb752..6288dd3a45 100644 --- a/lib/observer/src/observer_lib.erl +++ b/lib/observer/src/observer_lib.erl @@ -144,29 +144,29 @@ fill_info([{dynamic, Key}|Rest], Data) %% Special case used by crashdump_viewer when the value decides %% which header to use case get_value(Key, Data) of - undefined -> fill_info(Rest, Data); + undefined -> [undefined | fill_info(Rest, Data)]; {Str,Value} -> [{Str, Value} | fill_info(Rest, Data)] end; fill_info([{Str, Key}|Rest], Data) when is_atom(Key); is_function(Key) -> case get_value(Key, Data) of - undefined -> fill_info(Rest, Data); + undefined -> [undefined | fill_info(Rest, Data)]; Value -> [{Str, Value} | fill_info(Rest, Data)] end; fill_info([{Str,Attrib,Key}|Rest], Data) when is_atom(Key); is_function(Key) -> case get_value(Key, Data) of - undefined -> fill_info(Rest, Data); + undefined -> [undefined | fill_info(Rest, Data)]; Value -> [{Str,Attrib,Value} | fill_info(Rest, Data)] end; fill_info([{Str, {Format, Key}}|Rest], Data) when is_atom(Key); is_function(Key), is_atom(Format) -> case get_value(Key, Data) of - undefined -> fill_info(Rest, Data); + undefined -> [undefined | fill_info(Rest, Data)]; Value -> [{Str, {Format, Value}} | fill_info(Rest, Data)] end; fill_info([{Str, Attrib, {Format, Key}}|Rest], Data) when is_atom(Key); is_function(Key), is_atom(Format) -> case get_value(Key, Data) of - undefined -> fill_info(Rest, Data); + undefined -> [undefined | fill_info(Rest, Data)]; Value -> [{Str, Attrib, {Format, Value}} | fill_info(Rest, Data)] end; fill_info([{Str,SubStructure}|Rest], Data) when is_list(SubStructure) -> @@ -189,6 +189,8 @@ update_info([Fields|Fs], [{_Header, _Attrib, SubStructure}| Rest]) -> update_info([], []) -> ok. +update_info2([undefined|Fs], [_|Rest]) -> + update_info2(Fs, Rest); update_info2([Scroll = {_, _, _}|Fs], [{_, NewInfo}|Rest]) -> update_scroll_boxes(Scroll, NewInfo), update_info2(Fs, Rest); @@ -198,6 +200,9 @@ update_info2([Field|Fs], [{_Str, {click, Value}}|Rest]) -> update_info2([Field|Fs], [{_Str, Value}|Rest]) -> wxTextCtrl:setValue(Field, to_str(Value)), update_info2(Fs, Rest); +update_info2([Field|Fs], [undefined|Rest]) -> + wxTextCtrl:setValue(Field, ""), + update_info2(Fs, Rest); update_info2([], []) -> ok. update_scroll_boxes({_, _, 0}, {_, []}) -> ok; @@ -223,10 +228,10 @@ to_str({bytes, B}) -> MB = KB div 1024, GB = MB div 1024, if - GB > 10 -> integer_to_list(GB) ++ " gB"; - MB > 10 -> integer_to_list(MB) ++ " mB"; + GB > 10 -> integer_to_list(GB) ++ " GB"; + MB > 10 -> integer_to_list(MB) ++ " MB"; KB > 0 -> integer_to_list(KB) ++ " kB"; - true -> integer_to_list(B) ++ " B " + true -> integer_to_list(B) ++ " B" end; to_str({time_ms, MS}) -> S = MS div 1000, @@ -396,7 +401,9 @@ create_box(Panel, {scroll_boxes,Data}) -> AddBox = fun({Title,Proportion,Format = {_,_}}) -> add_box(Panel, OuterBox, Cursor, Title, Proportion, Format); ({Title, Format = {_,_}}) -> - add_box(Panel, OuterBox, Cursor, Title, 1, Format) + add_box(Panel, OuterBox, Cursor, Title, 1, Format); + (undefined) -> + undefined end, Boxes = [AddBox(Entry) || Entry <- Data], wxCursor:destroy(Cursor), @@ -457,7 +464,9 @@ create_box(Panel, Data) -> wxTextCtrl:setMinSize(Field,{0,H}), wxSizer:add(Box, Line, [{proportion,0},{flag,?wxEXPAND}]), - Field + Field; + (undefined) -> + undefined end, InfoFields = [AddRow(Entry) || Entry <- Info], {Box, InfoFields}. @@ -512,6 +521,8 @@ get_max_size(Txt,[{Desc,_}|Info],MaxX,MaxY) -> true -> get_max_size(Txt,Info,MaxX,MaxY) end; +get_max_size(Txt,[undefined|Info],MaxX,MaxY) -> + get_max_size(Txt,Info,MaxX,MaxY); get_max_size(_,[],X,Y) -> {X+2,Y}. diff --git a/lib/observer/src/observer_perf_wx.erl b/lib/observer/src/observer_perf_wx.erl index 54c98f3ba3..8173349ed7 100644 --- a/lib/observer/src/observer_perf_wx.erl +++ b/lib/observer/src/observer_perf_wx.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2012. All Rights Reserved. +%% Copyright Ericsson AB 2012-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -283,7 +283,12 @@ mem_types() -> lmax([]) -> 0; lmax(List) -> - lists:max([lists:max(tuple_to_list(T)) || T <- List]). + Max = [lists:max(tuple_to_list(T)) || T <- List, + tuple_size(T) > 0], + case Max of + [] -> 0; + _ -> lists:max(Max) + end. calc_delta([{Id, WN, TN}|Ss], [{Id, WP, TP}|Ps]) -> [100*(WN-WP) div (TN-TP)|calc_delta(Ss, Ps)]; @@ -301,25 +306,23 @@ draw(Offset, Id, DC, Panel, Paint=#paint{pens=Pens, small=Small}, Data, Active) {X0,Y0,WS,HS} = draw_borders(Id, NoGraphs, DC, Size, Max, Paint), Last = 60*WS+X0-1, Start = max(61-Len, 0)*WS+X0 - Offset*WS, - case Hs of - [] -> ignore; - [_] -> ignore; - _ -> + Samples = length(Hs), + case Active andalso Samples > 1 andalso NoGraphs > 0 of + true -> Draw = fun(N) -> Lines = make_lines(Hs, Start, N, {X0,Max*HS,Last}, Y0, WS, HS), setPen(DC, element(1+ ((N-1) rem tuple_size(Pens)), Pens)), strokeLines(DC, Lines), N+1 end, - [Draw(I) || I <- lists:seq(NoGraphs, 1, -1)] - end, - case Active of + [Draw(I) || I <- lists:seq(NoGraphs, 1, -1)]; false -> - NotActive = "Service not available", + Info = case Active andalso Samples =< 1 of + true -> "Waiting on data"; + false -> "Information not available" + end, setFont(DC, Small, {0,0,0}), - drawText(DC, NotActive, X0 + 100, element(2,Size) div 2); - true -> - ignore + drawText(DC, Info, X0 + 100, element(2,Size) div 2) end, ok. diff --git a/lib/observer/src/observer_sys_wx.erl b/lib/observer/src/observer_sys_wx.erl index 31800cf12a..8321d6eefe 100644 --- a/lib/observer/src/observer_sys_wx.erl +++ b/lib/observer/src/observer_sys_wx.erl @@ -167,9 +167,12 @@ info_fields() -> {"Async thread pool size", thread_pool_size} ]}, {"CPU's and Threads", - [{"System Logical CPU's", logical_processors}, - {"Erlang Logical CPU's", logical_processors_online}, - {"Used Logical CPU's", logical_processors_available} + [{"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, -- cgit v1.2.3