appmon_web.erl
来自「OTP是开放电信平台的简称」· ERL 代码 · 共 1,037 行 · 第 1/3 页
ERL
1,037 行
%% ``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 via the world wide web 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.%% %% The Initial Developer of the Original Code is Ericsson Utvecklings AB.%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings%% AB. All Rights Reserved.''%% %% $Id$%%%%%---------------------------------------------------------------------%%% File : webappmon.erl%%% Author : Martin G. <marting@erix.ericsson.se>%%% Purpose : Frontend to the webbased version of appmon.%%% Created : 24 Apr 2001 by Martin G. <marting@erix.ericsson.se>%%%----------------------------------------------------------------------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>" ++
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?