et_contents_viewer.erl
来自「OTP是开放电信平台的简称」· ERL 代码 · 共 591 行 · 第 1/2 页
ERL
591 行
First = et_collector:make_key(S#state.event_order, E), Mode = {search_actors, forward, First, [From, To]}, send_viewer_event(S, {mode, Mode}), {noreply, S}; 'r' -> E = S#state.filtered_event, From = E#event.from, To = E#event.to, First = et_collector:make_key(S#state.event_order, E), Mode = {search_actors, reverse, First, [From, To]}, send_viewer_event(S, {mode, Mode}), {noreply, S}; 'a' -> send_viewer_event(S, {mode, all}), {noreply, S}; 0 -> case lists:keysearch(collector, #filter.name, S#state.filters) of {value, F} when record(F, filter) -> ChildState= S#state{active_filter = F#filter.name}, case gen_server:start_link(?MODULE, [ChildState], []) of {ok, Pid} when S#state.parent_pid /= self() -> unlink(Pid); _ -> ignore end; false -> ignore end, {noreply, S}; Int when integer(Int), Int > 0, Int =< 9 -> case catch lists:nth(Int, S#state.filters) of F when record(F, filter) -> ChildState= S#state{active_filter = F#filter.name}, case gen_server:start_link(?MODULE, [ChildState], []) of {ok, Pid} when S#state.parent_pid /= self() -> unlink(Pid); _ -> ignore end; {'EXIT', _} -> ignore end, {noreply, S}; 'Shift_L' -> {noreply, S}; 'Shift_R' -> {noreply, S}; 'Caps_Lock' -> {noreply, S}; _ -> io:format("~p: ignored: ~p~n", [?MODULE, KeySym]), {noreply, S} end;handle_info({gs, _Obj, configure, [], [W, H | _]}, S) -> gs:config(S#state.packer, [{width, W},{height, H}]), S2 = S#state{width = W, height = H}, {noreply, S2};handle_info({'EXIT', Pid, Reason}, S) -> if Pid == S#state.parent_pid -> unlink(Pid), {stop, Reason, S}; true -> {noreply, S} end;handle_info(Info, S) -> ok = error_logger:format("~p(~p): handle_info(~p, ~p)~n", [?MODULE, self(), Info, S]), {noreply, S}.%%----------------------------------------------------------------------%% Func: terminate/2%% Purpose: Shutdown the server%% Returns: any (ignored by gen_server)%%----------------------------------------------------------------------terminate(_Reason, _S) -> ignore.%%----------------------------------------------------------------------%% Func: code_change/3%% Purpose: Convert process state when code is changed%% Returns: {ok, NewState}%%----------------------------------------------------------------------code_change(_OldVsn, S, _Extra) -> {ok, S}.%%%----------------------------------------------------------------------%%% Handle graphics%%%----------------------------------------------------------------------create_window(S) -> H = S#state.height, W = S#state.width, Name = S#state.active_filter, Title = lists:concat([?MODULE, " (filter: ", Name, ")"]), WinOpt = [{title, Title}, {configure, true}, {width, W}, {height, H}], GS = gs:start(), Win = gs:window(GS, WinOpt), Bar = gs:menubar(Win, []), create_file_menu(Bar), PackerOpt = [{packer_x, [{stretch, 1}]}, {packer_y, [{stretch, 1}, {fixed, 25}]}, {x, 0}, {y, 25}], Packer = gs:frame(Win, PackerOpt), EditorOpt = [{pack_xy, {1, 1}}, {vscroll, right}, {hscroll, bottom}, {wrap, none}, {bg, lightblue}, {font, {courier, 12}}], Editor = gs:editor(Packer, EditorOpt), FilteredEvent = config_editor(Editor, S), S2 = S#state{win = Win, packer = Packer, filtered_event = FilteredEvent}, create_hide_menu(Bar, S2), create_search_menu(Bar, S2), create_filter_menu(Bar, S#state.filters), gs:config(Packer, [{width, W}, {height, H}]), gs:config(Win, [{map,true}, {keypress, true}]), S2.create_file_menu(Bar) -> Button = gs:menubutton(Bar, [{label, {text, "File"}}]), Menu = gs:menu(Button, []), gs:menuitem(close, Menu, [{label, {text,"Close (c)"}}]), gs:menuitem(save, Menu, [{label, {text,"Save"}}]).create_filter_menu(Bar, Filters) -> Button = gs:menubutton(Bar, [{label, {text, "Filters"}}]), Menu = gs:menu(Button, []), gs:menuitem(Menu, [{label, {text, "Select Filter"}}, {bg, lightblue}, {enable, false}]), gs:menuitem(Menu, [{itemtype, separator}]), Item = fun(F, N) when F#filter.name == collector-> Label = lists:concat([pad_string(F#filter.name, 20), "(0)"]), gs:menuitem(Menu, [{label, {text, Label}}, {data, F}]), N + 1; (F, N) -> Name = F#filter.name, Label = lists:concat([pad_string(Name, 20), "(", N, ")"]), gs:menuitem(Menu, [{label, {text, Label}}, {data, F}]), N + 1 end, Filters2 = lists:keysort(#filter.name, Filters), lists:foldl(Item, 1, Filters2), Menu.create_hide_menu(Bar, S) -> Button = gs:menubutton(Bar, [{label, {text, "Hide"}}]), Menu = gs:menu(Button, []), E = S#state.filtered_event, From = E#event.from, To = E#event.to, if S#state.viewer_pid == undefined -> ignore; From == To -> gs:menuitem(Menu, [{label, {text, "Hide actor in Viewer "}}, {bg, lightblue}, {enable, false}]), gs:menuitem(Menu, [{itemtype, separator}]), gs:menuitem({hide, [From]}, Menu, [{label, {text,"From=To (f|t|b)"}}]), gs:menuitem(Menu, [{itemtype, separator}]), gs:menuitem(Menu, [{label, {text, "Show actor in Viewer "}}, {bg, lightblue}, {enable, false}]), gs:menuitem(Menu, [{itemtype, separator}]), gs:menuitem({show, [From]}, Menu, [{label, {text,"From=To (F|T|B)"}}]); true -> gs:menuitem(Menu, [{label, {text, "Hide actor in Viewer "}}, {bg, lightblue}, {enable, false}]), gs:menuitem(Menu, [{itemtype, separator}]), gs:menuitem({hide, [From]}, Menu, [{label, {text,"From (f)"}}]), gs:menuitem({hide, [To]}, Menu, [{label, {text,"To (t)"}}]), gs:menuitem({hide, [From, To]}, Menu, [{label, {text,"Both (b)"}}]), gs:menuitem(Menu, [{itemtype, separator}]), gs:menuitem(Menu, [{label, {text, "Show actor in Viewer "}}, {bg, lightblue}, {enable, false}]), gs:menuitem(Menu, [{itemtype, separator}]), gs:menuitem({show, [From]}, Menu, [{label, {text,"From (F)"}}]), gs:menuitem({show, [To]}, Menu, [{label, {text,"To (T)"}}]), gs:menuitem({show, [From, To]}, Menu, [{label, {text,"Both (B)"}}]) end.create_search_menu(Bar, S) -> Button = gs:menubutton(Bar, [{label, {text, "Search"}}]), Menu = gs:menu(Button, []), E = S#state.filtered_event, From = E#event.from, To = E#event.to, gs:menuitem(Menu, [{label, {text, "Search in Viewer "}}, {bg, lightblue}, {enable, false}]), gs:menuitem(Menu, [{itemtype, separator}]), if S#state.viewer_pid == undefined -> S; From == To -> Key = et_collector:make_key(S#state.event_order, E), ModeS = {search_actors, forward, Key, [From]}, ModeR = {search_actors, reverse, Key, [From]}, gs:menuitem({mode, ModeS}, Menu, [{label, {text,"Forward from this event (s)"}}]), gs:menuitem({mode, ModeR}, Menu, [{label, {text,"Reverse from this event (r)"}}]); true -> Key = et_collector:make_key(S#state.event_order, E), ModeS = {search_actors, forward, Key, [From, To]}, ModeR = {search_actors, reverse, Key, [From, To]}, gs:menuitem({mode, ModeS}, Menu, [{label, {text,"Forward from this event (s)"}}]), gs:menuitem({mode, ModeR}, Menu, [{label, {text,"Reverse from this event (r)"}}]) end, gs:menuitem({mode, all}, Menu, [{label, {text,"Abort search. Display all (a)"}}]).config_editor(Editor, S) -> Event = S#state.event, Name = S#state.active_filter, {value, F} = lists:keysearch(Name, #filter.name, S#state.filters), FilterFun = F#filter.function, case catch FilterFun(Event) of true -> do_config_editor(Editor, Event, lightblue, S#state.event_order); {true, Event2} when record(Event2, event) -> do_config_editor(Editor, Event2, lightblue, S#state.event_order); false -> do_config_editor(Editor, Event, red, S#state.event_order); Bad -> Contents = {bad_filter, Name, Bad}, BadEvent = Event#event{contents = Contents}, do_config_editor(Editor, BadEvent, red, S#state.event_order) end.do_config_editor(Editor, Event, Colour, TsKey) -> String = event_to_string(Event, TsKey), gs:config(Editor, {insert, {'end', String}}), gs:config(Editor, {enable, false}), gs:config(Editor, {bg, Colour}), Event.%%%----------------------------------------------------------------------%%% String handling%%%----------------------------------------------------------------------term_to_string(Term) -> case catch io_lib:format("~s", [Term]) of {'EXIT', _} -> io_lib:format("~p", [Term]); GoodString -> GoodString end.now_to_string({Mega, Sec, Micro} = Now) when integer(Mega), integer(Sec), integer(Micro) -> {{Y, Mo, D}, {H, Mi, S}} = calendar:now_to_universal_time(Now), lists:concat([Y, "-", Mo, "-", D, " ", H, ".", Mi, ".", S, ".", Micro]);now_to_string(Other) -> term_to_string(Other).event_to_string(Event, TsKey) -> ReportedTs = Event#event.trace_ts, ParsedTs = Event#event.event_ts, Deep = ["DETAIL LEVEL: ", term_to_string(Event#event.detail_level), "\nLABEL: ", term_to_string(Event#event.label), case Event#event.from == Event#event.to of true -> ["\nACTOR: ", term_to_string(Event#event.from)]; false -> ["\nFROM: ", term_to_string(Event#event.from), "\nTO: ", term_to_string(Event#event.to)] end, case ReportedTs == ParsedTs of true -> ["\nPARSED: ", now_to_string(ParsedTs)]; false -> case TsKey of trace_ts -> ["\nTRACE_TS: ", now_to_string(ReportedTs), "\nEVENT_TS: ", now_to_string(ParsedTs)]; event_ts -> ["\nEVENT_TS: ", now_to_string(ParsedTs), "\nTRACE_TS: ", now_to_string(ReportedTs)] end end, "\nCONTENTS:\n\n", term_to_string(Event#event.contents)], lists:flatten(Deep).pad_string(Atom, MinLen) when atom(Atom) -> pad_string(atom_to_list(Atom), MinLen);pad_string(String, MinLen) when integer(MinLen), MinLen >= 0 -> Len = length(String), case Len >= MinLen of true -> String; false -> String ++ lists:duplicate(MinLen - Len, $ ) end.send_viewer_event(S, Event) -> case S#state.viewer_pid of ViewerPid when pid(ViewerPid) -> ViewerPid ! {et, Event}; undefined -> ignore end.
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?