aboutsummaryrefslogtreecommitdiffstats
path: root/lib/observer/src/observer_procinfo.erl
diff options
context:
space:
mode:
authorcrownedgrouse <[email protected]>2013-10-27 02:36:49 +0100
committerDan Gudmundsson <[email protected]>2015-02-19 13:25:19 +0100
commit6fe02e14d95e849d55d37d5449e835bcb8753da2 (patch)
tree2a8c5b24257fcc25c6a52c4420c72b58a77ae534 /lib/observer/src/observer_procinfo.erl
parentef029376067280869683776fc616f8514a2ff81a (diff)
downloadotp-6fe02e14d95e849d55d37d5449e835bcb8753da2.tar.gz
otp-6fe02e14d95e849d55d37d5449e835bcb8753da2.tar.bz2
otp-6fe02e14d95e849d55d37d5449e835bcb8753da2.zip
observer: Add SASL log view for processes
Add a new menu to toggle log view. Disabled by default. Disabled if rb_server already started on observed node, in order not to interfere with somebody else. If enabled, add a tab in process view where log entries related to pid process are shown. Need an observed node with at least a version R16B2, due to the use of newly capability to rb to write into a file descriptor (on the observing node).
Diffstat (limited to 'lib/observer/src/observer_procinfo.erl')
-rw-r--r--lib/observer/src/observer_procinfo.erl80
1 files changed, 79 insertions, 1 deletions
diff --git a/lib/observer/src/observer_procinfo.erl b/lib/observer/src/observer_procinfo.erl
index 8e8a37fc93..a8512894f9 100644
--- a/lib/observer/src/observer_procinfo.erl
+++ b/lib/observer/src/observer_procinfo.erl
@@ -43,6 +43,8 @@
-record(worker, {panel, callback}).
+-record(io, {rdata=""}).
+
start(Process, ParentFrame, Parent) ->
wx_object:start_link(?MODULE, [Process, ParentFrame, Parent], []).
@@ -69,6 +71,10 @@ init([Pid, ParentFrame, Parent]) ->
DictPage = init_panel(Notebook, "Dictionary", [Pid,Table], fun init_dict_page/3),
StackPage = init_panel(Notebook, "Stack Trace", [Pid], fun init_stack_page/2),
StatePage = init_panel(Notebook, "State", [Pid,Table], fun init_state_page/3),
+ Ps = case gen_server:call(observer, log_status) of
+ true -> [init_panel(Notebook, "Log", [Pid,Table], fun init_log_page/3)];
+ false -> []
+ end,
wxFrame:connect(Frame, close_window),
wxMenu:connect(Frame, command_menu_selected),
@@ -78,7 +84,7 @@ init([Pid, ParentFrame, Parent]) ->
pid=Pid,
frame=Frame,
notebook=Notebook,
- pages=[ProcessPage,MessagePage,DictPage,StackPage,StatePage],
+ pages=[ProcessPage,MessagePage,DictPage,StackPage,StatePage|Ps],
expand_table=Table
}}
catch error:{badrpc, _} ->
@@ -327,6 +333,26 @@ fetch_state_info2(Pid, M) ->
{badrpc,{'EXIT',{timeout, _}}} -> []
end.
+init_log_page(Parent, Pid, Table) ->
+ Win = observer_lib:html_window(Parent),
+ Update = fun() ->
+ Fd = spawn_link(fun() -> io_server() end),
+ rpc:call(node(Pid), rb, rescan, [[{start_log, Fd}]]),
+ rpc:call(node(Pid), rb , grep, [local_pid_str(Pid)]),
+ Logs = io_get_data(Fd),
+ %% Replace remote local pid notation to global notation
+ Pref = global_pid_node_pref(Pid),
+ ExpPid = re:replace(Logs,"<0\.","<" ++ Pref ++ ".",[global, {return, list}]),
+ %% Try to keep same look by removing blanks at right of rewritten PID
+ NbBlanks = length(Pref) - 1,
+ Re = "(<" ++ Pref ++ "\.[^>]{1,}>)[ ]{"++ integer_to_list(NbBlanks) ++ "}",
+ Look = re:replace(ExpPid, Re, "\\1", [global, {return, list}]),
+ Html = observer_html_lib:expandable_term("SaslLog", Look, Table),
+ wxHtmlWindow:setPage(Win, Html)
+ end,
+ Update(),
+ {Win, Update}.
+
create_menus(MenuBar) ->
Menus = [{"File", [#create_menu{id=?wxID_CLOSE, text="Close"}]},
{"View", [#create_menu{id=?REFRESH, text="Refresh\tCtrl-R"}]}],
@@ -409,3 +435,55 @@ filter_monitor_info() ->
Ms = proplists:get_value(monitors, Data),
[Pid || {process, Pid} <- Ms]
end.
+
+local_pid_str(Pid) ->
+ %% observer can observe remote nodes
+ %% There is no function to get the local
+ %% pid from the remote pid ...
+ %% So grep will fail to find remote pid in remote local log.
+ %% i.e. <4589.42.1> will not be found, but <0.42.1> will
+ %% Let's replace first integer by zero
+ "<0" ++ re:replace(pid_to_list(Pid),"\<([0-9]{1,})","",[{return, list}]).
+
+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},
+ receive
+ {Pid, data, Data} -> lists:flatten(Data)
+ end.
+
+io_server() ->
+ io_server(#io{}).
+
+io_server(State) ->
+ receive
+ {io_request, From, ReplyAs, Request} ->
+ case io_request(Request,State) of
+ {Tag, Reply, NewState} when Tag =:= ok; Tag =:= error ->
+ From ! {io_reply, ReplyAs, Reply},
+ io_server(NewState);
+ {stop, Reply, _NewState} ->
+ From ! {io_reply, ReplyAs, Reply},
+ exit(Reply)
+ end;
+ {Pid, get_data_and_close} ->
+ Pid ! {self(), data, lists:reverse(State#io.rdata)},
+ normal;
+ _Unknown ->
+ io:format("~p: Unknown msg: ~p ~n",[?LINE, _Unknown]),
+ io_server(State)
+ end.
+
+io_request({put_chars, _Encoding, Chars}, State = #io{rdata=Data}) ->
+ {ok, ok, State#io{rdata=[Chars|Data]}};
+io_request({put_chars, Encoding, Module, Function, Args}, State) ->
+ try io_request({put_chars, Encoding, apply(Module, Function, Args)}, State)
+ catch _:_ -> {error, {error,Function}, State}
+ end;
+io_request(Req, State) ->
+ io:format("~p: Unknown req: ~p ~n",[?LINE, Req]),
+ State.