diff options
Diffstat (limited to 'lib/appmon/src/appmon_web.erl')
-rw-r--r-- | lib/appmon/src/appmon_web.erl | 1037 |
1 files changed, 1037 insertions, 0 deletions
diff --git a/lib/appmon/src/appmon_web.erl b/lib/appmon/src/appmon_web.erl new file mode 100644 index 0000000000..e8a8422a80 --- /dev/null +++ b/lib/appmon/src/appmon_web.erl @@ -0,0 +1,1037 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2001-2009. 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 +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%%%--------------------------------------------------------------------- +%%% File : webappmon.erl +%%% Author : Martin G. <[email protected]> +%%% Purpose : Frontend to the webbased version of appmon. +%%% Created : 24 Apr 2001 by Martin G. <[email protected]> +%%%--------------------------------------------------------------------- + +-module(appmon_web). + +%% The functions that the user can call to interact with the genserver +-export([init/1,handle_call/3,handle_cast/2,handle_info/2]). +-export([terminate/2,code_change/3]). + +-export([node_info/2,application_info/2,application_env/2]). +-export([proc_info/2,trace/2]). +-export([start/0,stop/0,start_link/0]). + +%% Export the function that returns the configuration data needed by +%% webtool +-export([configData/0]). + + +%% The following directive caters for (significantly) faster native +%% code compilation of one function in this file by the HiPE compiler +%% on register-poor architectures like the x86. +-compile([{hipe,[{regalloc,graph_color}]}]). + +-behaviour(gen_server). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Start the genserver % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +start_link()-> + gen_server:start_link({local,webappmon_server},appmon_web,[],[]). +start()-> + gen_server:start({local,webappmon_server},appmon_web,[],[]). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Stop the genserver % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +stop()-> + gen_server:call(webappmon_server,stop,1000). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Get the page that shows the nodes and the apps on the sel node % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +node_info(Env,Input)-> + gen_server:call(webappmon_server,{node_data,Env,Input}). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Get the application process tree % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +application_info(Env,Input)-> + gen_server:call(webappmon_server,{app_data,Env,Input}). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Get the page that shows the data about the process % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +proc_info(Env,Input)-> + gen_server:call(webappmon_server,{proc_data,Env,Input}). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Get the spec on the app % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +application_env(Env,Input)-> + gen_server:call(webappmon_server,{app_env,Env,Input}). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Toggle the trace flag for the selected process % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +trace(Env,Input)-> + gen_server:call(webappmon_server,{trace,Env,Input}). + +configData()-> + {appmon,[{web_data,{"WebAppmon","/appmon/main_frame.html"}}, + {alias,{"/appmon",code:priv_dir(appmon)}}, + {alias,{erl_alias,"/erl",[appmon_web]}}, + {start,{child,{backend,{process_info,start_link,[]}, + permanent,100,worker,[process_info]}}}, + {start,{child,{{local,webappmon_server}, + {appmon_web,start_link,[]}, + permanent,100,worker,[appmon_web]}}} + ]}. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% Callback functions for the genserver % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +init(_Arg)-> + {ok,[]}. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Create the different pages % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +handle_call({node_data,_Env,Input},_From,State)-> + {reply,app_and_node_sel_page(Input),State}; + +handle_call({app_data,_Env,Input},_From,State)-> + {reply,process_tree_page(Input),State}; + +handle_call({proc_data,_Env,Input},_From,State)-> + {reply,process_specifickation_page(Input),State}; + +handle_call({app_env,_Env,Input},_From,State)-> + {reply,application_specifickation_page(Input),State}; + +handle_call({trace,_Env,Input},_From,State)-> + {reply,toggle_trace(Input),State}. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Shutdown the genserver % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +terminate(_,_State)-> + ok. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Callback function currently not used ... % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +handle_cast(_,State)-> + {noreply,State}. + +handle_info(_,State)-> + {noreply,State}. + +code_change(_OldVsn,State,_Extra)-> + {ok,State}. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% %% +%% Private functions to create the part of the sides that is common %% +%% to all sides %% +%% %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Create the Header for the page If we now the mimetype use that type%% +%% otherwise use text %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +header() -> + header("text/html"). +header(MimeType) -> + "Content-type: " ++ MimeType ++ "\r\n\r\n". + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Create the Htmlheader sett the title of the side to nothing if %% +%% we dont know the name of the side %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +html_header()-> + html_header(""). + +html_header(Part) -> + "<HTML BGCOLOR=\"#FFFFFF\">\n" ++ + "<HEAD>\n" ++ + "<TITLE>Appmon " ++ Part ++ "</TITLE>\n" ++ + "</HEAD>\n". + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Close the Html tag and if neccessay add some clean upp %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +html_end()-> + "</HTML>". + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% %% +%% The functions that creates the whole pages by collecting %% +%% the necessary data %% +%% %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Returns the page where the user see's which nodes and apps that %% +%% are availible for monitoring %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +app_and_node_sel_page(Input)-> + [header(), + html_header(), + node_body(httpd:parse_query(Input)), + html_end()]. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Returns the process tree for the application whose name is %% +%% the first value in the Inputs key/value list %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +process_tree_page(Input)-> + [header(), + html_header(), + application_javascript(httpd:parse_query(Input)), + application_body(httpd:parse_query(Input)), + html_end()]. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Send trace on or off to the process thats pid is the third arg of %% +%% the inputs key/val list. Then it returns the process tree for the %% +%% the application that is the first key/val pair of input %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +toggle_trace(Input)-> + send_trace(httpd:parse_query(Input)), + [header(), + html_header(), + application_javascript(httpd:parse_query(Input)), + application_body(httpd:parse_query(Input)), + html_end()]. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Creates the page that shows all information about the process that %% +%% that is the first arg of th input key/val pairs %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +process_specifickation_page(Input)-> + [header(), + html_header(), + process_body(httpd:parse_query(Input)), + html_end()]. + +application_specifickation_page(Input)-> + [header(), + html_header(), + application_env_body(httpd:parse_query(Input)), + html_end()]. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% The Private functions that do the job %% +%% To build the the page that shows the applications %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Build the body of the side that shows the node name and %% +%% the application list %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +node_body([{"node",Node}|_Rest])-> + case process_info:is_node(Node) of + {true,Controlled_node,Name} -> + "<BODY BGCOLOR=\"#FFFFFF\">" ++ + node_selections_javascripts() ++ + node_selection(Controlled_node) ++ + node_title() ++ + application_tree(Controlled_node,Name) ++ + "</BODY>"; + + {false,Server_node,Name} -> + "<BODY BGCOLOR=\"#FFFFFF\">" ++ + node_selections_javascripts() ++ + node_selection(Server_node) ++ + node_title() ++ + application_tree(Server_node,Name) ++ + "</BODY>" + end; + +node_body(_Whatever)-> + node_body([{atom_to_list(node),atom_to_list(node())}]). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Returns the javascript that sets a new node to monitor %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +node_selections_javascripts()-> + "<SCRIPT> + function node_selected() + { + parent.frames.base_frames.location=\"../../appmon/start_info.html\" + window.location =\"./node_info?node=\" + " ++ + "document.node_selection.nodes[document.node_selection.nodes.selectedIndex].value; + } + </SCRIPT>". + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Insert the html code that shows the combobox where the user can %% +%% select another node to monitor %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +node_selection(Node)-> + " <FORM ACTION=\"./node_info\" NAME=node_selection>\n + <TABLE WIDTH=\"100%\" BORDER=\"0\">\n + <TR><TD ALIGN=\"center\">\n + <SELECT NAME=nodes onChange=\"node_selected()\">\n" ++ + print_nodes(order_nodes(Node,process_info:get_nodes())) ++ + "</SELECT>\n + </TD></TR>\n + </TABLE>\n + </FORM>". + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Add the node we are working with in the beginning of the list and %% +%% remove it from other places so its always the first in the listbox %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +order_nodes(Node,Node_list)-> + [Node|lists:delete(Node,Node_list)]. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Take the list of nodes and make it to a list of options to the %% +%% the combobox %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +print_nodes([])-> + []; +print_nodes([Node|Rest])-> + "<OPTION value=\"" ++ + atom_to_list(Node) ++ + "\">" ++ + atom_to_list(Node) ++ + "\n" ++ + print_nodes(Rest). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Create the header of the node info page i.e. the name of the node %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +node_title()-> + " <TABLE WIDTH=\"100%\" BORDER=\"0\"> + <TR><TD ALIGN=\"center\"><FONT SIZE=5>Applications</FONT></TD></TR> + </TABLE>\n". + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Build the body of the side that shows the node i.e the application %% +%% list %% +%% Node and Node_name are the same just different types %% +%% Node are the atom Node_name the string of the node name %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +application_tree(Node,Node_name)-> + Fun=fun(Name)-> + Name_str =atom_to_list(Name), + "<LI><A HREF=\"./application_info?name=" ++ Name_str ++ + "&mode=all&node=" ++ Node_name ++ + "\" TARGET=main><B>" ++ Name_str ++ + "</B></A>" ++ print_space(15-length(Name_str),[]) ++ + "<A HREF=\"./application_env?name=" ++ Name_str ++ + "&node=" ++ Node_name ++ + "\" TARGET=\"main\"><FONT SIZE=2>spec</FONT></A></LI>\n" + end, + "<UL>" ++ + lists:map(Fun, (process_info:get_applications(Node))) ++ + "</UL>" ++ + "<FORM Name=reload>" ++ + "<INPUT TYPE=\"button\" onClick=\"node_selected()\" + VALUE=\"Reload\">\n" ++ + "</FORM>" ++ + "<!--<A HREF=\"../../appmon/application_help.html\" TARGET=main>Help</A>-->". + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Print spaces between the application name and the spec link %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +print_space(N,Space)when N >0 -> + print_space(N-1," " ++ Space); +print_space(_N,Space)-> + Space. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% The Private functions that do the job %% +%% To build the the page that shows process in an application %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%Generates the javascript that govern the look of the page that %% +%%the processes of an application %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%Args is the list whit input args should be App Mode, Node +application_javascript(Args)when length(Args)>=3 -> + Vars= + "<SCRIPT> + var proc; + var app=\"" ++ element(2,lists:nth(1,Args)) ++ "\"; + var node=\"" ++ element(2,lists:nth(3,Args)) ++ "\";", + CommonFuncs= + " function reload_bottom_frame() + {parent.proc_data.location.href=\"/appmon/blank.html\";} + + function show_process_info() + { + if(proc.indexOf(\"#Port\")== -1) + { + if(proc.charAt(0)==\'<\') + window.location=\"./proc_info?name=\" + proc + \"&node=\" + node + else + { + start=proc.indexOf(\"<\"); + endpoint=proc.lastIndexOf(\">\"); + window.location=\"./proc_info?name=\" + proc.slice(start,endpoint+1) + \"&node=\" + node ; + } + } + } + + function trace() + { + if(proc.charAt(0)==\'<\') + window.location=\"./trace?name=\" + app + \"&mode=\" + get_mode() + \"&node=\" + node + \"&proc=\" + proc; + else + { + start=proc.indexOf(\"<\"); + endpoint=proc.lastIndexOf(\">\"); + window.location=\"./trace?name=\" + app + \"&mode=\" + get_mode() + \"&node=\" + node + \"&proc=\" + + proc.slice(start,endpoint+1) ; + } + + } + + function reload_page()\n + { + window.location=\"./application_info?name=\" + app + \"&mode=\" + get_mode() + \"&node=\" + node ; + } + function get_mode() + { + for (i= 0; i < document.reload_form.mode.length; i++) + { + if (document.reload_form.mode[i].checked) + return(document.reload_form.mode[i].value); + } + return(\"all\"); + }", + Vars++CommonFuncs++"</SCRIPT>"; +application_javascript(_)-> + "<SCRIPT></SCRIPT>". + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Create the body i.e the process tree for the applications whose %% +%% name is the second arg in the first tuple %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%args is the list [{_,Appname},{_,Mode},{_Node}] +application_body(Args) when is_list(Args),length(Args) >= 3 -> + App=element(2,lists:nth(1,Args)), + Mode=element(2,lists:nth(2,Args)), + Node=element(2,lists:nth(3,Args)), + "<BODY BGCOLOR=\"FFFFFF\" onLoad=reload_bottom_frame() >" + ++ mode_selection(Mode) ++ + selected_app_header(App,Node) ++ process_tree(App,Mode,Node)++ + "</BODY>"; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% If the pattern above ain't match then something is wrong %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +application_body(_Whatever)-> + "Please use the links to the left". + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Create the part of the process tree page side where the user can %% +%% select the mode the view the tree in. %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +mode_selection(Mode)-> + "<FORM NAME=\"reload_form\">\n" ++ + "<TABLE>" ++ + "<TR>\n" ++ + "<!--<TD><INPUT TYPE=\"button\" NAME=\"refresh_but\" VALUE=\"Reload\" onClick=\"reload_page()\"> + </TD>\n-->" ++ + print_radio_buttons([{"all","All processes"},{"sup_child","Supervised processes"}, + {"sup","Only supervisors"}],Mode) ++ + "</TR>\n </TABLE>\n" ++ + "</FORM>". + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Print the radiobuttons. if the mode is the one the current %% +%% radiobutton represent set the one checked %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +print_radio_buttons([],_)-> + []; +print_radio_buttons([{Mode,Name}|Rest],Mode)-> + "<TD><INPUT TYPE=\"radio\" NAME=\"mode\" CHECKED=\"true\" VALUE=\""++ + Mode ++"\" onClick=\"reload_page()\"> " ++Name ++ + "</TD>\n" ++ print_radio_buttons(Rest,Mode); +print_radio_buttons([{Mode1,Name}|Rest],Mode)-> + "<TD><INPUT TYPE=\"radio\" NAME=\"mode\" VALUE=\""++ Mode1 ++ + "\" onClick=\"reload_page()\"> " ++ Name ++ + "</TD>\n" ++ + print_radio_buttons(Rest,Mode). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% The part that shows the name of the application that the process %% +%% tree represent %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +selected_app_header(App,Node)-> + {Year,Mon,Day}=date(), + "<TABLE> + <TR> + <TD>Node:</TD> + <TD>" ++Node ++"</TD> + </TR> + <TR> + <TD>Application:</TD> + <TD>" ++App ++"</TD> + </TR> + <TR> + <TD>Date:</TD> + <TD>" ++ integer_to_list(Day) ++ "/" ++ + integer_to_list(Mon) ++" - "++ + integer_to_list(Year) ++ + "</TD> + </TR> + </TABLE> + <TABLE WIDTH=100%> + <TR> + <TD> + <HR WIDTH=\"80%\"> + <!--<FONT SIZE=4>Process tree</FONT> + <HR ALIGN=\"center\" WIDTH=\"80%\">--> + </TD> + </TR> + </TABLE>". + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%get the process tree from process_info and build the nested %% +%% unordered list that represent the applications process tree %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +process_tree(App,Mode,Node)-> + case process_info:get_processes(list_to_atom(App), + list_to_atom(Mode), + list_to_atom(Node)) of + unknown-> + "Unknown application please update application tree"; + {Tree,Traced_dict} -> + "<UL>" ++ + htmlify_tree(Tree,Traced_dict,1,Node,Mode,App) ++ + "</UL>" + end. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Build each node in the tree and then build its children %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +htmlify_tree({Pid,Childs,Childs2},Proc_tab,N,Node,Mode,App)-> + case ets:lookup(Proc_tab,Pid) of + [] when N<3-> + print_pid(Pid,Node,Mode,App,notrace)++ + htmlify_prim_child(Childs,Proc_tab,N+1,Node,Mode,App) ++ + htmlify_sec_child(Childs2); + [_Traced]-> + print_pid(Pid,Node,Mode,App,"<FONT SIZE=2 COLOR=\"firebrick\">Stop Trace</FONT>")++ + htmlify_prim_child(Childs,Proc_tab,N+1,Node,Mode,App) ++ + htmlify_sec_child(Childs2); + []-> + print_pid(Pid,Node,Mode,App,"<FONT SIZE=2>Start Trace</FONT>")++ + htmlify_prim_child(Childs,Proc_tab,N+1,Node,Mode,App) ++ + htmlify_sec_child(Childs2) + end. + +print_pid(Pid,Node,_Mode,_App,notrace)-> + "<LI><A TARGET=\"proc_data\" STYLE=\"text-decoration:none; color:blue\" HREF=\"./proc_info?name=" ++ urlify_pid(Pid) ++ + "&node="++ Node ++" \" >"++ htmlify_pid(Pid,[]) ++ + "</A>"; + +print_pid([$P,$o,$r,$t|Rest],_Node,_Mode,_App,_TrMode)-> + "<LI>" ++ htmlify_pid([$P,$o,$r,$t|Rest],[]); + +print_pid(Pid,Node,Mode,App,TrMode)-> + "<LI><A TARGET=\"proc_data\" STYLE=\"text-decoration:none; color:blue\" HREF=\"./proc_info?name=" ++ + urlify_pid(Pid) ++ "&node="++ Node ++" \" >"++ + htmlify_pid(Pid,[]) ++ "</A>"++ + "   + <A HREF=\"./trace?app="++App++"&mode="++Mode++ + "&node="++Node++"&proc="++urlify_pid(Pid)++"\"> + "++TrMode++"</A>". + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Change the '<' sign and the '>' sign to the html representation %% +%% of the sign %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +htmlify_pid([60|Pid],New)-> + htmlify_pid(Pid,";tl&"++New); +htmlify_pid([139|Pid],New)-> + htmlify_pid(Pid,";tl&"++New); + +htmlify_pid([62|Pid],New)-> + htmlify_pid(Pid,";tg&"++New); +htmlify_pid([155|Pid],New)-> + htmlify_pid(Pid,";tg&"++New); +htmlify_pid([Chr|Pid],New)-> + htmlify_pid(Pid,[Chr|New]); +htmlify_pid([],New)-> + lists:reverse(New). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Change the < and > sign to the representation of the signs in %% +%% the HTTP protocol %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +urlify_pid(Pid) -> + case regexp:first_match(Pid,"[<].*[>]") of + {match,Start,Len}-> + "%3C"++string:substr(Pid,Start+1,Len-2)++"%3E"; + _-> + Pid + end. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Change the < and > sign from the representation of the signs in %% +%% the HTTP protocol %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +unurlify_pid(Pid)-> + unurlify_pid(Pid,[]). + +unurlify_pid([$%,$3,$C|Rest],New)-> + unurlify_pid(Rest,[60|New]); + +unurlify_pid([$%,$3,$E|Rest],New)-> + unurlify_pid(Rest,[62|New]); +unurlify_pid([Chr|Rest],New)-> + unurlify_pid(Rest,[Chr|New]); + +unurlify_pid([],New)-> + lists:reverse(New). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Make html of the list of primary childs %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +htmlify_prim_child([],_Proc_tab,_N,_Node,_Mode,_App)-> + []; + +htmlify_prim_child(Childs,Proc_tab,N,Node,Mode,App)-> + Fun=fun(Child)-> + htmlify_tree(Child,Proc_tab,N,Node,Mode,App) + end, + "<UL>\n" ++ lists:map(Fun,Childs) ++ "</UL>\n". + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Make html of hte list whit sedondary childs, they has no childs %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +htmlify_sec_child([])-> + []; + +htmlify_sec_child(Sec_child_list)-> + Htmlify_child=fun(Pid1)-> + "<LI><FONT COLOR=\"#FF2222\">" ++ Pid1 ++ + "</FONT></LI>\n" + end, + "<UL>" ++ lists:map(Htmlify_child,Sec_child_list) ++ "</UL>\n". + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% The Private functions that do the job %% +%% To build the the page that shows process data %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% The function that creates the collects the various part of %% +%% the side that shows information about a specific process, %% +%% Pid_name should be the list representation of a pid %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +process_body(Args) when length(Args)==2-> + Pid=element(2,lists:nth(1,Args)), + Node=element(2,lists:nth(2,Args)), + "<BODY BGCOLOR=\"#FFFFFF\">" ++ + process_information_table(Pid,Node) ++ "</BODY>"; + +process_body(_)-> + "<BODY BGCOLOR=\"#FFFFFF\">Please dont call this side manually</BODY>". + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Create the table that shows the name of the pid to show extended %% +%% info about %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Get the table that shows the extended info about a process %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +process_information_table(Pid_name,Node)-> + PidID=unurlify_pid(Pid_name), + case catch list_to_pid(PidID) of + Pid when is_pid(Pid) -> + get_process_table(Pid,Node); + _Other -> + io_lib:format("Not a process id ~s",[PidID]) + end. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Create the table that shoows the extended info about processes %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +get_process_table(Pid,Node_name) when is_list(Node_name)-> + Node=list_to_atom(Node_name), + get_process_table(Pid,Node); + +get_process_table(Pid,Node) when is_atom(Node)-> + case lists:member(Node,[node()|nodes()]) of + true-> + Proc_data=process_info:get_process_data(Pid,Node), + "<TABLE BORDER=1 > + <TR BGCOLOR=\"#8899AA\"><TD COLSPAN=6 ALIGN=\"center\" > + <FONT size=4> Process" ++ + htmlify_pid(pid_to_list(Pid),[]) ++ "</FONT> + </TD></TR>" ++ + start_process_proc_data(Proc_data) ++ + "</TABLE><BR><BR>"; + _ -> + "Please try again the Node dont exists" + end. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% The process information is quite messy tidi it up by creating a %% +%% table that looks like key val %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +start_process_proc_data(Proc_data)-> + %%Pic out the special cases the links and the process dict + {Special,Usual}=split_proc_data(Proc_data), + Usual2=append_empty(Usual), + UsualProcData=process_proc_data(Usual2,0), + SpecProcData=process_proc_data(Special), + UsualProcData++SpecProcData. + +append_empty(List) when length(List) rem 2 == 0 -> + List; +append_empty(List)-> + append_empty(lists:append(List,[empty])). + +split_proc_data(Proc_data)-> + Spec=lists:map(fun(Key)-> + case lists:keysearch(Key,1,Proc_data) of + {value,Data}-> + Data; + _ -> + not_included + end + end,[links,dictionary,messages]), + Spec2=clear(Spec,[]), + Usual=lists:filter(fun({Key,_Val})-> + case Key of + messages -> + false; + links -> + false; + dictionary -> + false; + _ -> + true + end + end,Proc_data), + {Spec2,Usual}. + +clear([],New)-> + New; +clear([not_included|Spec],New)-> + clear(Spec,New); +clear([Other|Spec],New)-> + clear(Spec,[Other|New]). + +process_proc_data(Data,3)-> + "</TR>"++process_proc_data(Data,0); +process_proc_data([],_N)-> + []; +process_proc_data(Data,0)-> + "<TR>"++process_proc_data(Data,1); + +process_proc_data([empty|Data],N)-> + "<TD> </TD><TD> </TD> "++process_proc_data(Data,N+1); + +process_proc_data([{current_function,MFA}|Rest],N)-> + "<TD NOWRAP=true><FONT SIZE=3><B>Current function:</B></TD><TD><FONT SIZE=3>"++ + io_lib:format("~p",[MFA]) ++"</TD>\n " ++ + process_proc_data(Rest,N+1); + +process_proc_data([{error_handler,Mod}|Rest],N)-> + "<TD NOWRAP=\"true\"><B><FONT SIZE=3>Error handler:</B></TD><TD><FONT SIZE=3>" + ++ atom_to_list(Mod) ++ "</TD>\n" ++ + process_proc_data(Rest,N+1); + +process_proc_data([{group_leader,Grp}|Rest],N)-> + "<TD NOWRAP=\"true\"><FONT SIZE=3><B>Group leader:</B></TD><TD><FONT SIZE=3>" ++ + htmlify_pid(pid_to_list(Grp),[]) ++ "</TD>\n " ++ + process_proc_data(Rest,N+1); + +process_proc_data([{heap_size,Size}|Rest],N)-> + "<TD NOWRAP=\"true\"><FONT SIZE=3><B>Heap size:</B></TD><TD><FONT SIZE=3>" + ++ integer_to_list(Size) ++ "</TD>\n " ++ + process_proc_data(Rest,N+1); + +process_proc_data([{initial_call,MFA}|Rest],N)-> + "<TD NOWRAP=\"true\"><FONT SIZE=3><B>Initial call:</B></TD><TD><FONT SIZE=3>"++ + io_lib:format("~p",[MFA]) ++"</TD>\n " ++ + process_proc_data(Rest,N+1); + +process_proc_data([{message_queue_len,Size}|Rest],N)-> + "<TD NOWRAP=\"true\"><FONT SIZE=3><B>Message queue length:</B></TD><TD><FONT SIZE=3>" ++ + integer_to_list(Size) ++ "</TD>\n " ++ + process_proc_data(Rest,N+1); + +process_proc_data([{priority,Level}|Rest],N)-> + "<TD><FONT SIZE=3><B>Process priority:</B></TD><TD><FONT SIZE=3>" ++ + atom_to_list(Level) ++ "</TD>\n " ++ + process_proc_data(Rest,N+1); + +process_proc_data([{reductions,Number}|Rest],N)-> + "<TD ><FONT SIZE=3><B>Number of executed reductions:</B></TD> + <TD><FONT SIZE=3>" ++ integer_to_list(Number) ++ "</TD>\n " ++ + process_proc_data(Rest,N+1); + +process_proc_data([{registered_name,Name}|Rest],N)-> + "<TD NOWRAP=\"true\"><FONT SIZE=3><B>Process Name:</B></TD><TD><FONT SIZE=3>" + ++ atom_to_list(Name) ++ "</TD>\n" ++ + process_proc_data(Rest,N+1); + +process_proc_data([{stack_size,Size}|Rest],N)-> + "<TD NOWRAP=\"true\"><FONT SIZE=3><B>Stack size:</B></TD><TD><FONT SIZE=3>" + ++ integer_to_list(Size) ++ "</TD>\n " ++ + process_proc_data(Rest,N+1); + +process_proc_data([{status,Status}|Rest],N)-> + "<TD NOWRAP=\"true\"><FONT SIZE=3><B>Process status:</B></TD><TD><FONT SIZE=3>" + ++ atom_to_list(Status) ++ "</TD>\n " ++ + process_proc_data(Rest,N+1); + +process_proc_data([{trap_exit,Boolean}|Rest],N)-> + "<TD NOWRAP=\"true\" ><FONT SIZE=3><B>Trap Exit:</B></TD><TD><FONT SIZE=3>" + ++ atom_to_list(Boolean) ++ "</TD>\n " ++ + process_proc_data(Rest,N+1); + +process_proc_data([{Key,Val}|Rest],N)-> + "<TD NOWRAP=\"true\" ><FONT SIZE=3><B>" ++ io_lib:write(Key) ++ + "</B></TD><TD><FONT SIZE=3>" ++ io_lib:write(Val) ++ + "</TD>\n " ++ + process_proc_data(Rest,N). + +process_proc_data([])-> + []; +process_proc_data([{links,List_of_pids}|Rest])-> + "<TR><TD NOWRAP=\"true\"><FONT SIZE=3><B>Links:</B></TD><TD COLSPAN=5><FONT SIZE=3>"++ print_links(List_of_pids) ++"</TD></TR>\n " ++ + process_proc_data(Rest); + +process_proc_data([{messages,Queue}|Rest])-> + "<TR><TD NOWRAP=\"true\"><FONT SIZE=3><B>Message Queue:</B></TD><TD COLSPAN=5><FONT SIZE=3>" ++ io_lib:write(Queue) ++ "</TD></TR>\n " ++ + process_proc_data(Rest); + +process_proc_data([{dictionary,Dict}|Rest])-> + "<TR><TD NOWRAP=\"true\"><FONT SIZE=3><B>Process dictionary:</B></TD><TD COLSPAN=5><FONT SIZE=3> </TD></TR>\n " ++ + get_dictionary_data(Dict) ++ + process_proc_data(Rest). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% In the process info there are the links to other processes print %% +%% this pid %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +print_links(Pids)-> + print_links(Pids,[]). + +print_links([],Links)-> + htmlify_pid(Links,[]); + +print_links([Pid],Links) when is_pid(Pid) -> + print_links([],Links ++ pid_to_list(Pid)); + +print_links([Pid],Links) when is_port(Pid) -> + print_links([],Links ++ erlang:port_to_list(Pid)); + +print_links([Pid|Rest],Links) when is_pid(Pid) -> + print_links(Rest,Links ++ pid_to_list(Pid) ++ ", "); + +print_links([Pid|Rest],Links) when is_port(Pid) -> + print_links(Rest,Links ++ erlang:port_to_list(Pid) ++ ", "). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Fix the data in the process dictionary %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +get_dictionary_data([])-> + []; + +get_dictionary_data([{Key,Val}|Dict])-> + FormatedVal=add_space(htmlify_pid(lists:flatten(fix_type(Val)),[])), + "<TR><TD><FONT SIZE=3>" ++ + htmlify_pid(lists:flatten(fix_type(Key)),[]) ++ + "</TD><TD COLSPAN=5><FONT SIZE=3>" ++ + FormatedVal++ "</TD></TR>\n" ++ + get_dictionary_data(Dict). + +add_space(List)-> + add_space(List,0,[]). +add_space([],_Len,New) -> + lists:reverse(New); +add_space([Char|Rest],Len,New)when Len<50 -> + add_space(Rest,Len+1,[Char|New]); + +add_space([$\,|Rest],_Len,New) -> + add_space(Rest,0,[$\ ,$,|New]); + +add_space([Char|Rest],Len,New) -> + add_space(Rest,Len+1,[Char|New]). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Interpret the type of the data and make it to a list %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +fix_type(Val) when is_atom(Val) -> + atom_to_list(Val); +fix_type(Val) when is_float(Val) -> + float_to_list(Val); +fix_type(Val) when is_integer(Val) -> + integer_to_list(Val); +fix_type(Val) when is_list(Val) -> + case io_lib:printable_list(Val) of + true-> + case Val of + []-> + io_lib:write(Val); + _-> + Val + end; + _-> + io_lib:write(Val) + end; +fix_type(Val) when is_pid(Val) -> + pid_to_list(Val); +fix_type(Val) when is_port(Val) -> + erlang:port_to_list(Val); +fix_type(Val) when is_tuple(Val) -> + io_lib:write(Val); +fix_type(_Val) -> + []. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% The Private functions that send the trace signal to the process %% +%% thats the 4 member of the Arg list %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +send_trace(Args)when length(Args)>=4-> + {_,Proc}=lists:nth(4,Args), + Pid2=unurlify_pid(Proc), + process_info:send_trace(Pid2); + +send_trace(_Args)-> + arg_error. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Private functions that prints the application environment %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +application_env_body(Args)when length(Args)>=2 -> + App=element(2,lists:nth(1,Args)), + Node=element(2,lists:nth(2,Args)), + "<SCRIPT> + function reload_bottom_frame() + {parent.proc_data.location.href=\"/appmon/blank.html\";} + </SCRIPT> + <BODY BGCOLOR=\"#FFFFFF\" onLoad=reload_bottom_frame()>" + ++ application_env_table(App,Node) ++ "</BODY>"; + +application_env_body(_)-> + "<BODY BGCOLOR=\"#FFFFFF\">Please dont call this side manually</BODY>". + +application_env_table(App,Node)-> + case process_info:get_application_keys(list_to_atom(App), + list_to_atom(Node)) of + {ok,List}-> + "<TABLE BORDER=1>" ++ application_env_head(App,Node) ++ + print_key_list(List,[]) ++ "</TABLE>"; + _ -> + "Please try again,something went wrong" + end. + +application_env_head(App,Node)-> + "<TR BGCOLOR=\"#8899AA\"><TD ALIGN=\"center\" COLSPAN=3> + <FONT SIZE=6>" ++ App ++ "@" ++ Node ++ "</FONT>\n + </TD></TR> + <TR><TD COLSPAN=3> </TD></TR> + <TR BGCOLOR=\"#8899AA\"> + <TD><B>Key</B></TD><TD><B>Val/Sec. key</B></TD><TD><B>Sec. Val</B></TD> + </TR>". + +print_key_list([],Result)-> + Result; + +print_key_list([{application,Name}|Rest],Result)-> + print_key_list(Rest,Result ++ print_key("Application name :",Name)); + +print_key_list([{description,Desc}|Rest],Result)-> + print_key_list(Rest,Result ++ print_key("Description :",Desc)); + +print_key_list([{vsn,Ver}|Rest],Result)-> + print_key_list(Rest,Result ++ print_key("Version :",Ver)); + +print_key_list([{id,Id}|Rest],Result)-> + print_key_list(Rest,Result ++ print_key("ID:",fix_type(Id))); + +print_key_list([{modules,Mods}|Rest],Result)-> + print_key_list(Rest,Result ++ print_key("Modules:"," ") ++ + print_secondary_list(Mods,[])); + +print_key_list([{maxP,Max}|Rest],Result)-> + print_key_list(Rest,Result ++ + print_key("Max nr of processes",fix_type(Max))); + +print_key_list([{maxT,Max}|Rest],Result)-> + print_key_list(Rest,Result ++ + print_key("Max running sec:",fix_type(Max))); + +print_key_list([{registered,Names}|Rest],Result)-> + print_key_list(Rest,Result ++ + print_key("Registered names:"," ") ++ + print_secondary_list(Names,[])); + +print_key_list([{applications,Apps}|Rest],Result)-> + print_key_list(Rest,Result ++ print_key("Depends on:"," ") ++ + print_secondary_list(Apps,[])); + +print_key_list([{included_applications,Inc_apps}|Rest],Result)-> + print_key_list(Rest,Result ++ + print_key("Included applications:", + fix_type(Inc_apps))); + +print_key_list([{env,Env}|Rest],Result)-> + print_key_list(Rest,Result ++ + print_key("Environment:",fix_type(Env))); + +print_key_list([{mod,Mod}|Rest],Result)-> + print_key_list(Rest,Result ++ + print_key("Application callback mod:", + fix_type(Mod))); + +print_key_list([{start_phases,Phase_arg}|Rest],Result)-> + print_key_list(Rest,Result ++ + print_key("Application callback mod:", + fix_type(Phase_arg))); + +print_key_list([_|Rest],Result)-> + print_key_list(Rest,Result). + +print_key(Label,Val)-> + "<TR> + <TD><B>" ++ Label ++ "</B></TD><TD>" ++ Val ++ + "</TD><TD> </TD> + </TR>". + +print_key2(Label,Val)-> + "<TR> + <TD> </TD><TD>" ++ Label ++ "</TD><TD>" ++ Val ++ "</TD> + </TR>". + +print_secondary_list([],Result)-> + Result; +print_secondary_list([{Mod,Ver}|Rest],Result) -> + print_secondary_list(Rest,Result ++ + print_key2(fix_type(Mod),fix_type(Ver))); + +print_secondary_list([Mod|Rest],Result) -> + print_secondary_list(Rest,Result ++ + print_key2(fix_type(Mod)," ")). |