summaryrefslogtreecommitdiff
path: root/lib/observer
diff options
context:
space:
mode:
Diffstat (limited to 'lib/observer')
-rw-r--r--lib/observer/src/observer_lib.erl82
-rw-r--r--lib/observer/src/observer_sock_wx.erl101
-rw-r--r--lib/observer/src/observer_wx.erl42
3 files changed, 129 insertions, 96 deletions
diff --git a/lib/observer/src/observer_lib.erl b/lib/observer/src/observer_lib.erl
index 57a9a741a5..c2cc61af86 100644
--- a/lib/observer/src/observer_lib.erl
+++ b/lib/observer/src/observer_lib.erl
@@ -26,7 +26,9 @@
wait_for_progress/0, report_progress/1,
user_term/3, user_term_multiline/3,
interval_dialog/4, start_timer/1, start_timer/2, stop_timer/1, timer_config/1,
- display_info/2, display_info/3, fill_info/2, update_info/2, to_str/1,
+ display_info/2, display_info/3,
+ fill_info/2, fill_info/3, update_info/2,
+ to_str/1,
create_menus/3, create_menu_item/3,
is_darkmode/1, colors/1, create_attrs/1,
set_listctrl_col_size/2, mix/3,
@@ -171,51 +173,65 @@ display_info(Panel, Sizer, Info) ->
end,
[Add(I) || I <- Info].
-fill_info([{dynamic, Key}|Rest], Data)
+fill_info(Fields, Data) ->
+ fill_info(Fields, Data, undefined).
+
+fill_info([{dynamic, Key}|Rest], Data, Default)
when is_atom(Key); is_function(Key) ->
%% Special case used by crashdump_viewer when the value decides
%% which header to use
- case get_value(Key, Data) of
- undefined -> [undefined | fill_info(Rest, Data)];
- {Str,Value} -> [{Str, Value} | fill_info(Rest, Data)]
+ case get_value(Key, Data, Default) of
+ undefined -> [undefined | fill_info(Rest, Data, Default)];
+ {Str,Value} -> [{Str, Value} | fill_info(Rest, Data, Default)]
end;
-fill_info([{Str, Key}|Rest], Data) when is_atom(Key); is_function(Key) ->
- case get_value(Key, Data) of
- undefined -> [undefined | fill_info(Rest, Data)];
- Value -> [{Str, Value} | fill_info(Rest, Data)]
+fill_info([{Str, Key}|Rest], Data, Default)
+ when is_atom(Key); is_function(Key) ->
+ case get_value(Key, Data, Default) of
+ undefined ->
+ [undefined | fill_info(Rest, Data, Default)];
+ Value ->
+ [{Str, Value} | fill_info(Rest, Data, Default)]
end;
-fill_info([{Str,Attrib,Key}|Rest], Data) when is_atom(Key); is_function(Key) ->
- case get_value(Key, Data) of
- undefined -> [undefined | fill_info(Rest, Data)];
- Value -> [{Str,Attrib,Value} | fill_info(Rest, Data)]
+fill_info([{Str, Attrib, Key}|Rest], Data, Default)
+ when is_atom(Key); is_function(Key) ->
+ case get_value(Key, Data, Default) of
+ undefined ->
+ [undefined | fill_info(Rest, Data, Default)];
+ Value ->
+ [{Str,Attrib,Value} | fill_info(Rest, Data, Default)]
end;
-fill_info([{Str, {Format, Key}}|Rest], Data)
+fill_info([{Str, {Format, Key}}|Rest], Data, Default)
when is_atom(Key); is_function(Key) ->
- case get_value(Key, Data) of
- undefined -> [undefined | fill_info(Rest, Data)];
- Value -> [{Str, {Format, Value}} | fill_info(Rest, Data)]
+ case get_value(Key, Data, Default) of
+ undefined -> [undefined | fill_info(Rest, Data, Default)];
+ Value -> [{Str, {Format, Value}} | fill_info(Rest, Data, Default)]
end;
-fill_info([{Str, Attrib, {Format, Key}}|Rest], Data)
+fill_info([{Str, Attrib, {Format, Key}}|Rest], Data, Default)
when is_atom(Key); is_function(Key) ->
- case get_value(Key, Data) of
- undefined -> [undefined | fill_info(Rest, Data)];
- Value -> [{Str, Attrib, {Format, Value}} | fill_info(Rest, Data)]
+ case get_value(Key, Data, Default) of
+ undefined -> [undefined | fill_info(Rest, Data, Default)];
+ Value -> [{Str, Attrib, {Format, Value}} |
+ fill_info(Rest, Data, Default)]
end;
-fill_info([{Str,SubStructure}|Rest], Data) when is_list(SubStructure) ->
- [{Str, fill_info(SubStructure, Data)}|fill_info(Rest,Data)];
-fill_info([{Str,Attrib,SubStructure}|Rest], Data) ->
- [{Str, Attrib, fill_info(SubStructure, Data)}|fill_info(Rest,Data)];
-fill_info([{Str, Key = {K,N}}|Rest], Data) when is_atom(K), is_integer(N) ->
- case get_value(Key, Data) of
- undefined -> [undefined | fill_info(Rest, Data)];
- Value -> [{Str, Value} | fill_info(Rest, Data)]
+fill_info([{Str,SubStructure}|Rest], Data, Default)
+ when is_list(SubStructure) ->
+ [{Str, fill_info(SubStructure, Data, Default)}|
+ fill_info(Rest, Data, Default)];
+fill_info([{Str,Attrib,SubStructure}|Rest], Data, Default) ->
+ [{Str, Attrib, fill_info(SubStructure, Data, Default)}|
+ fill_info(Rest, Data, Default)];
+fill_info([{Str, Key = {K,N}}|Rest], Data, Default)
+ when is_atom(K), is_integer(N) ->
+ case get_value(Key, Data, Default) of
+ undefined -> [undefined | fill_info(Rest, Data, Default)];
+ Value -> [{Str, Value} | fill_info(Rest, Data, Default)]
end;
-fill_info([], _) -> [].
+fill_info([], _, _Default) -> [].
-get_value(Fun, Data) when is_function(Fun) ->
+get_value(Fun, Data, _Default) when is_function(Fun) ->
Fun(Data);
-get_value(Key, Data) ->
- proplists:get_value(Key,Data).
+get_value(Key, Data, Default) ->
+ proplists:get_value(Key, Data, Default).
update_info([Fields|Fs], [{_Header, SubStructure}| Rest]) ->
update_info2(Fields, SubStructure),
diff --git a/lib/observer/src/observer_sock_wx.erl b/lib/observer/src/observer_sock_wx.erl
index dc91d0f050..c1cb161a8a 100644
--- a/lib/observer/src/observer_sock_wx.erl
+++ b/lib/observer/src/observer_sock_wx.erl
@@ -75,7 +75,7 @@
panel,
sizer,
fields,
- node = {node(),true},
+ node = {node(), true},
opt = #opt{},
right_clicked_socket,
sockets,
@@ -111,7 +111,9 @@ update_gen_socket_info(#state{node = {Node, true},
case rpc:call(Node, observer_backend, socket_info, []) of
Info when is_list(Info) ->
Gen = info_fields(),
- observer_lib:update_info(Fields, observer_lib:fill_info(Gen, Info)),
+ observer_lib:update_info(Fields,
+ observer_lib:fill_info(Gen, Info,
+ "Not Supported")),
wxSizer:layout(Sizer);
_ ->
ignore
@@ -129,17 +131,35 @@ init([Notebook, Parent, Config]) ->
"~n Notebook: ~p"
"~n Parent: ~p"
"~n Config: ~p", [Notebook, Parent, Config]),
- Info = observer_backend:socket_info(),
+ try
+ begin
+ do_init(Notebook, Parent, Config, observer_backend:socket_info())
+ end
+ catch
+ C:E:S ->
+ %% Current node does not support socket (windows?)
+ d("init -> catched: "
+ "~n C: ~p"
+ "~n E: ~p"
+ "~n S: ~p", [C, E, S]),
+ do_init(Notebook, Parent, Config, [])
+ end.
+
+do_init(Notebook, Parent, Config, Info) ->
Gen = info_fields(),
Panel = wxPanel:new(Notebook),
Sizer = wxBoxSizer:new(?wxVERTICAL),
GenSizer = wxBoxSizer:new(?wxHORIZONTAL),
{GenPanel, _GenSizer, GenFields} =
- observer_lib:display_info(Panel, observer_lib:fill_info(Gen, Info)),
- wxSizer:add(GenSizer, GenPanel, [{flag, ?wxEXPAND}, {proportion, 1}]),
+ observer_lib:display_info(Panel,
+ observer_lib:fill_info(Gen, Info,
+ "Not Supported")),
+ wxSizer:add(GenSizer, GenPanel,
+ [{flag, ?wxEXPAND}, {proportion, 1}]),
BorderFlags = ?wxLEFT bor ?wxRIGHT,
- wxSizer:add(Sizer, GenSizer, [{flag, ?wxEXPAND bor BorderFlags bor ?wxTOP},
- {proportion, 0}, {border, 5}]),
+ wxSizer:add(Sizer, GenSizer,
+ [{flag, ?wxEXPAND bor BorderFlags bor ?wxTOP},
+ {proportion, 0}, {border, 5}]),
Style = ?wxLC_REPORT bor ?wxLC_HRULES,
Grid = wxListCtrl:new(Panel, [{winid, ?GRID}, {style, Style}]),
wxSizer:add(Sizer, Grid, [{flag, ?wxEXPAND bor ?wxALL},
@@ -371,43 +391,6 @@ handle_call(Event, From, _State) ->
handle_cast(Event, _State) ->
error({unhandled_cast, Event}).
-%% handle_info({socketinfo_open, IdStr},
-%% State = #state{node = {ActiveNodeName, ActiveAvailable},
-%% grid = Grid,
-%% opt = Opt,
-%% open_wins = Opened}) ->
-%% NodeName = node(list_to_port(PortIdStr)), % How do we do this for sockets?
-%% Available =
-%% case NodeName of
-%% ActiveNodeName ->
-%% ActiveAvailable;
-%% _ ->
-%% portinfo_available(NodeName)
-%% end,
-%% if Available ->
-%% Sockets0 = get_sockets(NodeName, Available),
-%% Sockets = lists:keyfind(SockIdStr, #socket.id_str, Sockets),
-%% NewOpened =
-%% case Port of
-%% false ->
-%% self() ! {error,"No such socket: " ++ SockIdStr},
-%% Opened;
-%% _ ->
-%% display_socket_info(Grid, Port, Opened)
-%% end,
-%% Ports =
-%% case NodeName of
-%% ActiveNodeName ->
-%% update_grid(Grid, sel(State), Opt, Ports0);
-%% _ ->
-%% State#state.ports
-%% end,
-%% {noreply, State#state{ports=Ports, open_wins=NewOpened}};
-%% true ->
-%% popup_unavailable_info(NodeName),
-%% {noreply, State}
-%% end;
-
handle_info(refresh_interval, State = #state{node = Node,
grid = Grid,
opt = Opt,
@@ -425,12 +408,13 @@ handle_info(refresh_interval, State = #state{node = Node,
{noreply, State#state{sockets = Sockets}}
end;
-handle_info({active, NodeName},
+handle_info({active, NodeName},
#state{parent = Parent,
grid = Grid,
opt = Opt,
timer = Timer0} = State0) ->
- Available = portinfo_available(NodeName),
+ d("handle_info({active, ~p}) -> entry", [NodeName]),
+ Available = socketinfo_available(NodeName),
Available orelse popup_unavailable_info(NodeName),
State1 = State0#state{node = {NodeName, Available}},
_ = update_gen_socket_info(State1),
@@ -446,15 +430,18 @@ handle_info(not_active, State = #state{timer = Timer0}) ->
Timer = observer_lib:stop_timer(Timer0),
{noreply, State#state{timer=Timer}};
-handle_info({info, {port_info_not_available,NodeName}},
+handle_info({info, {socket_info_not_available, NodeName}},
State = #state{panel=Panel}) ->
- Str = io_lib:format("Can not fetch port info from ~p.~n"
- "Too old OTP version.",[NodeName]),
+ Str = io_lib:format("Can not fetch socket info from ~p.~n"
+ "Too old OTP version.", [NodeName]),
observer_lib:display_info_dialog(Panel, Str),
{noreply, State};
handle_info({error, Error}, #state{panel=Panel} = State) ->
- Str = io_lib:format("ERROR: ~ts~n",[Error]),
+ ErrorStr = if is_list(Error) -> Error;
+ true -> f("~p", [Error])
+ end,
+ Str = io_lib:format("ERROR: ~ts~n", [ErrorStr]),
observer_lib:display_info_dialog(Panel, Str),
{noreply, State};
@@ -492,9 +479,17 @@ get_sockets(NodeName) when is_atom(NodeName) ->
case rpc:call(NodeName, observer_backend, get_socket_list, []) of
SocketInfoMaps when is_list(SocketInfoMaps) ->
[infomap_to_rec(SockInfo) || SockInfo <- SocketInfoMaps];
+ {badrpc,
+ {'EXIT', {undef, [{observer_backend, get_socket_list, [], []}]}}} ->
+ d("get_sockets -> No Backend"),
+ {error, "No socket backend support"};
{badrpc, Error} ->
+ d("get_sockets -> badrpc: "
+ "~n ~p", [Error]),
{error, Error};
{error, _} = ERROR ->
+ d("get_sockets -> error:"
+ "~n ~p", [ERROR]),
ERROR
end.
@@ -792,16 +787,16 @@ get_indecies(Rest = [_|_], I, [_|T]) ->
get_indecies(_, _, _) ->
[].
-portinfo_available(NodeName) ->
+socketinfo_available(NodeName) ->
_ = rpc:call(NodeName, code, ensure_loaded, [observer_backend]),
case rpc:call(NodeName, erlang, function_exported,
- [observer_backend, get_port_list, 0]) of
+ [observer_backend, get_socket_list, 0]) of
true -> true;
false -> false
end.
popup_unavailable_info(NodeName) ->
- self() ! {info, {port_info_not_available, NodeName}},
+ self() ! {info, {socket_info_not_available, NodeName}},
ok.
f(F, A) ->
diff --git a/lib/observer/src/observer_wx.erl b/lib/observer/src/observer_wx.erl
index 04f725cb4e..b61532f5b0 100644
--- a/lib/observer/src/observer_wx.erl
+++ b/lib/observer/src/observer_wx.erl
@@ -200,8 +200,26 @@ setup(#state{frame = Frame} = State) ->
wxNotebook:addPage(Notebook, PortPanel, "Ports", []),
%% Socket Panel
+ %% Note that this panel should *only* be added if we have support for socket
+ %% Also, if we run on/with an "old" node (without this support),
+ %% we should also not include this!
+ %% SockPanel =
+ %% try socket:supports() of
+ %% _ ->
+ %% d("setup -> create socket panel"),
+ %% SP = observer_sock_wx:start_link(Notebook,
+ %% self(),
+ %% Cnf(sock_panel)),
+ %% wxNotebook:addPage(Notebook, SP, "Sockets", []),
+ %% SP
+ %% catch
+ %% _:_:_ ->
+ %% undefined
+ %% end,
d("setup -> create socket panel"),
- SockPanel = observer_sock_wx:start_link(Notebook, self(), Cnf(sock_panel)),
+ SockPanel = observer_sock_wx:start_link(Notebook,
+ self(),
+ Cnf(sock_panel)),
wxNotebook:addPage(Notebook, SockPanel, "Sockets", []),
%% Table Viewer Panel
@@ -226,15 +244,19 @@ setup(#state{frame = Frame} = State) ->
SysPid = wx_object:get_pid(SysPanel),
SysPid ! {active, node()},
- Panels = [{sys_panel, SysPanel, "System"}, %% In order
- {perf_panel, PerfPanel, "Load Charts"},
- {allc_panel, AllcPanel, ?ALLOC_STR},
- {app_panel, AppPanel, "Applications"},
- {pro_panel, ProPanel, "Processes"},
- {port_panel, PortPanel, "Ports"},
- {sock_panel, SockPanel, "Sockets"},
- {tv_panel, TVPanel, "Table Viewer"},
- {trace_panel, TracePanel, ?TRACE_STR}],
+ Panels =
+ [{sys_panel, SysPanel, "System"}, %% In order
+ {perf_panel, PerfPanel, "Load Charts"},
+ {allc_panel, AllcPanel, ?ALLOC_STR},
+ {app_panel, AppPanel, "Applications"},
+ {pro_panel, ProPanel, "Processes"},
+ {port_panel, PortPanel, "Ports"}] ++
+ if (SockPanel =:= undefined) -> [];
+ true ->
+ [{sock_panel, SockPanel, "Sockets"}]
+ end ++
+ [{tv_panel, TVPanel, "Table Viewer"},
+ {trace_panel, TracePanel, ?TRACE_STR}],
UpdState = State#state{main_panel = Panel,
notebook = Notebook,