%%% @author zhongwen -module(observer_cli_application). -include("observer_cli.hrl"). %% API -export([start/1]). -define(INTERVAL, 2000). %% @doc List application info -spec start(ViewOpts) -> no_return when ViewOpts :: view_opts(). start(#view_opts{} = ViewOpts) -> Pid = spawn(fun() -> ?output(?CLEAR), render_worker(?INTERVAL) end), manager(Pid, ViewOpts). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% Private %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% manager(Pid, ViewOpts) -> case observer_cli_lib:parse_cmd(ViewOpts, [Pid]) of quit -> erlang:send(Pid, quit); _ -> manager(Pid, ViewOpts) end. render_worker(Interval) -> Text = "Interval: " ++ integer_to_list(Interval) ++ "ms", Menu = observer_cli_lib:render_menu(app, Text), Info = render_application_info(), LastLine = observer_cli_lib:render_last_line("q(quit)"), ?output([?CURSOR_TOP, Menu, Info, LastLine]), erlang:send_after(Interval, self(), redraw), receive quit -> quit; redraw -> render_worker(Interval) end. render_application_info() -> [ {loaded, LoadedApps}, {loading, LoadingApps}, {started, StartedApps}, {start_p_false, StartPFlase}, {running, RunningApps}, {starting, StartingApps} ] = application_controller:info(), {LoadedNotRunning, RunView} = render_running_apps(RunningApps, StartedApps, LoadedApps), LoadedView = draw_loaded_apps(LoadedNotRunning), StartingView = render_starting_apps(StartingApps), SPFView = render_start_p_false(StartPFlase), LoadingView = render_loading_apps(LoadingApps), [RunView, LoadedView, StartingView, SPFView, LoadingView]. render_running_apps(RunningApps, StartedApps, LoadedApps) -> Title = ?render([?UNDERLINE, ?GRAY_BG, ?W("Status", 7), ?W("Application", 16), ?W("Vsn", 8), ?W("Type", 10), ?W("Application", 16), ?W("Vsn", 8), ?W("Type", 10), ?W("Application", 16), ?W("Vsn", 8), ?W("Type", 10) ]), draw_running_apps_1(RunningApps, StartedApps, LoadedApps, Title). draw_running_apps_1([], _StartedApps, LoadedApps, Render) -> {LoadedApps, Render}; draw_running_apps_1([{RunningApp, _}], StartedApps, LoadedApps, Acc) -> {_, Type} = lists:keyfind(RunningApp, 1, StartedApps), {value, {_, _Desc, Vsn}, NewLoadedApps} = lists:keytake(RunningApp, 1, LoadedApps), {NewLoadedApps, Acc ++ [?render([?W("Running", 7), ?W2(?GREEN, RunningApp, 17), ?W(Vsn, 10), ?W(Type, 95)])]}; draw_running_apps_1([{App1, _}, {App2, _}], StartedApps, LoadedApps, Acc) -> {_, Type1} = lists:keyfind(App1, 1, StartedApps), {_, Type2} = lists:keyfind(App2, 1, StartedApps), {value, {_, _Desc1, Vsn1}, LoadedApps1} = lists:keytake(App1, 1, LoadedApps), {value, {_, _Desc2, Vsn2}, LoadedApps2} = lists:keytake(App2, 1, LoadedApps1), {LoadedApps2, Acc ++ [?render([?W("Running", 7), ?W2(?GREEN, App1, 17), ?W(Vsn1, 9), ?W(Type1, 10), ?W2(?GREEN, App2, 17), ?W(Vsn2, 9), ?W(Type2, 53)])] }; draw_running_apps_1([{App1, _}, {App2, _}, {App3, _} | Rest], StartedApps, LoadedApps, Acc) -> {_, Type1} = lists:keyfind(App1, 1, StartedApps), {_, Type2} = lists:keyfind(App2, 1, StartedApps), {_, Type3} = lists:keyfind(App3, 1, StartedApps), {value, {_, _Desc1, Vsn1}, LoadedApps1} = lists:keytake(App1, 1, LoadedApps), {value, {_, _Desc2, Vsn2}, LoadedApps2} = lists:keytake(App2, 1, LoadedApps1), {value, {_, _Desc3, Vsn3}, LoadedApps3} = lists:keytake(App3, 1, LoadedApps2), NewAcc = Acc ++ [?render([?W("Running", 7), ?W2(?GREEN, App1, 17), ?W(Vsn1, 9), ?W(Type1, 10), ?W2(?GREEN, App2, 17), ?W(Vsn2, 9), ?W(Type2, 10), ?W2(?GREEN, App3, 17), ?W(Vsn3, 9), ?W(Type3, 10)])], draw_running_apps_1(Rest, StartedApps, LoadedApps3, NewAcc). draw_loaded_apps([]) -> []; draw_loaded_apps(Apps) -> Title = ?render([?UNDERLINE, ?GRAY_BG, ?W("Status", 7), ?W("Application", 16), ?W("Vsn", 8), ?W("Type", 10), ?W("Application", 16), ?W("Vsn", 8), ?W("Type", 10), ?W("Application", 16), ?W("Vsn", 8), ?W("Type", 10) ]), draw_loaded_apps_1(Apps, Title). draw_loaded_apps_1([], Acc) -> Acc; draw_loaded_apps_1([{App, _Desc, Vsn}], Acc) -> Acc ++ [?render([?W("Loaded", 7), ?W2(?YELLOW, App, 17), ?W(Vsn, 10), ?W("******", 96)])]; draw_loaded_apps_1([{App1, _Desc1, Vsn1}, {App2, _Desc2, Vsn2}], Acc) -> Acc ++ [?render([?W("Loaded", 7), ?W2(?YELLOW, App1, 17), ?W(Vsn1, 9), ?W("******", 10), ?W2(?YELLOW, App2, 17), ?W(Vsn2, 9), ?W("******", 53)])]; draw_loaded_apps_1([{App1, _Desc1, Vsn1}, {App2, _Desc2, Vsn2}, {App3, _Desc3, Vsn3} | Apps], Acc) -> NewAcc = Acc ++ [?render([?W("Loaded", 7), ?W2(?YELLOW, App1, 17), ?W(Vsn1, 9), ?W("******", 10), ?W2(?YELLOW, App2, 17), ?W(Vsn2, 9), ?W("******", 10), ?W2(?YELLOW, App3, 17), ?W(Vsn3, 9), ?W("******", 10)])], draw_loaded_apps_1(Apps, NewAcc). render_starting_apps([]) -> []; render_starting_apps(Apps) -> Title = ?render([?UNDERLINE, ?GRAY_BG, ?W("Status", 7), ?W("Application", 18), ?W("RestartType", 11), ?W("Type", 11), ?W("From", 13), ?W("Application", 18), ?W("RestartType", 11), ?W("Type", 11), ?W("From", 12) ]), draw_starting_apps_1(Apps, Title). draw_starting_apps_1([], Acc) -> Acc; draw_starting_apps_1([{App, RestartType, Type, From}], Acc) -> Acc ++ [?render([?W("Starting", 7), ?W2(?L_GREEN, App, 19), ?W(RestartType, 12), ?W(Type, 11), ?W(From, 77)])]; draw_starting_apps_1([{App1, RestartType1, Type1, From1}, {App2, RestartType2, Type2, From2} | Apps], Acc) -> NewAcc = Acc ++ [?render([?W("Starting", 7), ?W2(?L_GREEN, App1, 19), ?W(RestartType1, 12), ?W(Type1, 11), ?W(From1, 13), ?W2(?L_GREEN, App2, 19), ?W(RestartType2, 12), ?W(Type2, 11), ?W(From2, 12)])], draw_starting_apps_1(Apps, NewAcc). render_start_p_false([]) -> []; render_start_p_false(Apps) -> draw_start_p_false_1(Apps, []). draw_start_p_false_1([], Acc) -> Acc; draw_start_p_false_1([{App, RestartType, Type, From}], Acc) -> Acc ++ [?render([?W("SPFalse", 7), ?W2(?L_GREEN, App, 19), ?W(RestartType, 12), ?W(Type, 11), ?W(From, 77)])]; draw_start_p_false_1([{App1, RestartType1, Type1, From1}, {App2, RestartType2, Type2, From2} | Apps], Acc) -> NewAcc = Acc ++ [?render([?W("SPFalse", 7), ?W2(?L_GREEN, App1, 19), ?W(RestartType1, 12), ?W(Type1, 11), ?W(From1, 13), ?W2(?L_GREEN, App2, 19), ?W(RestartType2, 12), ?W(Type2, 11), ?W(From2, 12)])], draw_start_p_false_1(Apps, NewAcc). render_loading_apps([]) -> []; render_loading_apps(Apps) -> Title = ?render([?UNDERLINE, ?GRAY_BG, ?W("Status", 7), ?W("Application", 16), ?W("From", 11), ?W("Application", 16), ?W("From", 10), ?W("Application", 16), ?W("From", 11), ?W("Application", 16), ?W("From", 9) ]), draw_loading_apps_1(Apps, Title). draw_loading_apps_1([], Acc) -> Acc; draw_loading_apps_1([{App1, From1}], Acc) -> Acc ++ [?render([?W("Loading", 7), ?W2(?L_GREEN, App1, 17), ?W(From1, 108)])]; draw_loading_apps_1([{App1, From1}, {App2, From2}], Acc) -> Acc ++ [?render([?W("Loading", 7), ?W2(?L_GREEN, App1, 17), ?W(From1, 12), ?W2(?L_GREEN, App2, 17), ?W(From2, 75)])]; draw_loading_apps_1([{App1, From1}, {App2, From2}, {App3, From3}], Acc) -> Acc ++ [?render([?W("Loading", 7), ?W2(?L_GREEN, App1, 17), ?W(From1, 12), ?W2(?L_GREEN, App2, 17), ?W(From2, 11), ?W2(?L_GREEN, App3, 17), ?W(From3, 43)])]; draw_loading_apps_1([{App1, From1}, {App2, From2}, {App3, From3}, {App4, From4} | Apps], Acc) -> NewAcc = Acc ++ [?render([?W("Loading", 7), ?W2(?L_GREEN, App1, 17), ?W(From1, 12), ?W2(?L_GREEN, App2, 17), ?W(From2, 11), ?W2(?L_GREEN, App3, 17), ?W(From3, 11), ?W2(?L_GREEN, App4, 17), ?W(From4, 11)])], draw_loading_apps_1(Apps, NewAcc).