diff options
Diffstat (limited to 'src/mod_stats.erl')
-rw-r--r-- | src/mod_stats.erl | 364 |
1 files changed, 189 insertions, 175 deletions
diff --git a/src/mod_stats.erl b/src/mod_stats.erl index 7c62e1e83..f988626fd 100644 --- a/src/mod_stats.erl +++ b/src/mod_stats.erl @@ -25,227 +25,241 @@ %%%---------------------------------------------------------------------- -module(mod_stats). + -author('alexey@process-one.net'). -behaviour(gen_mod). --export([start/2, - stop/1, - process_local_iq/3]). +-export([start/2, stop/1, process_local_iq/3]). +-include("ejabberd.hrl"). -include("jlib.hrl"). start(Host, Opts) -> - IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue), - gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_STATS, - ?MODULE, process_local_iq, IQDisc). + IQDisc = gen_mod:get_opt(iqdisc, Opts, fun gen_iq_handler:check_type/1, + one_queue), + gen_iq_handler:add_iq_handler(ejabberd_local, Host, + ?NS_STATS, ?MODULE, process_local_iq, IQDisc). stop(Host) -> - gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_STATS). - + gen_iq_handler:remove_iq_handler(ejabberd_local, Host, + ?NS_STATS). -process_local_iq(_From, To, #iq{id = _ID, type = Type, - xmlns = XMLNS, sub_el = SubEl} = IQ) -> - %%Lang = xml:get_tag_attr_s("xml:lang", SubEl), +process_local_iq(_From, To, + #iq{id = _ID, type = Type, xmlns = XMLNS, + sub_el = SubEl} = + IQ) -> case Type of - set -> - IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}; - get -> - {xmlelement, _, _Attrs, Els} = SubEl, - Node = string:tokens(xml:get_tag_attr_s("node", SubEl), "/"), - Names = get_names(Els, []), - - case get_local_stats(To#jid.server, Node, Names) of - {result, Res} -> - IQ#iq{type = result, - sub_el = [{xmlelement, "query", - [{"xmlns", XMLNS}], - Res}]}; - {error, Error} -> - IQ#iq{type = error, sub_el = [SubEl, Error]} - end + set -> + IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}; + get -> + #xmlel{children = Els} = SubEl, + Node = str:tokens(xml:get_tag_attr_s(<<"node">>, SubEl), + <<"/">>), + Names = get_names(Els, []), + case get_local_stats(To#jid.server, Node, Names) of + {result, Res} -> + IQ#iq{type = result, + sub_el = + [#xmlel{name = <<"query">>, + attrs = [{<<"xmlns">>, XMLNS}], + children = Res}]}; + {error, Error} -> + IQ#iq{type = error, sub_el = [SubEl, Error]} + end end. - -get_names([], Res) -> - Res; -get_names([{xmlelement, "stat", Attrs, _} | Els], Res) -> - Name = xml:get_attr_s("name", Attrs), +get_names([], Res) -> Res; +get_names([#xmlel{name = <<"stat">>, attrs = Attrs} + | Els], + Res) -> + Name = xml:get_attr_s(<<"name">>, Attrs), case Name of - "" -> - get_names(Els, Res); - _ -> - get_names(Els, [Name | Res]) + <<"">> -> get_names(Els, Res); + _ -> get_names(Els, [Name | Res]) end; -get_names([_ | Els], Res) -> - get_names(Els, Res). - +get_names([_ | Els], Res) -> get_names(Els, Res). --define(STAT(Name), {xmlelement, "stat", [{"name", Name}], []}). +-define(STAT(Name), + #xmlel{name = <<"stat">>, attrs = [{<<"name">>, Name}], + children = []}). get_local_stats(_Server, [], []) -> {result, - [?STAT("users/online"), - ?STAT("users/total"), - ?STAT("users/all-hosts/online"), - ?STAT("users/all-hosts/total") - ]}; - + [?STAT(<<"users/online">>), ?STAT(<<"users/total">>), + ?STAT(<<"users/all-hosts/online">>), + ?STAT(<<"users/all-hosts/total">>)]}; get_local_stats(Server, [], Names) -> - {result, lists:map(fun(Name) -> - get_local_stat(Server, [], Name) - end, Names)}; - -get_local_stats(_Server, ["running nodes", _], []) -> {result, - [?STAT("time/uptime"), - ?STAT("time/cputime"), - ?STAT("users/online"), - ?STAT("transactions/committed"), - ?STAT("transactions/aborted"), - ?STAT("transactions/restarted"), - ?STAT("transactions/logged") - ]}; - -get_local_stats(_Server, ["running nodes", ENode], Names) -> + lists:map(fun (Name) -> get_local_stat(Server, [], Name) + end, + Names)}; +get_local_stats(_Server, [<<"running nodes">>, _], + []) -> + {result, + [?STAT(<<"time/uptime">>), ?STAT(<<"time/cputime">>), + ?STAT(<<"users/online">>), + ?STAT(<<"transactions/committed">>), + ?STAT(<<"transactions/aborted">>), + ?STAT(<<"transactions/restarted">>), + ?STAT(<<"transactions/logged">>)]}; +get_local_stats(_Server, [<<"running nodes">>, ENode], + Names) -> case search_running_node(ENode) of - false -> - {error, ?ERR_ITEM_NOT_FOUND}; - Node -> - {result, - lists:map(fun(Name) -> get_node_stat(Node, Name) end, Names)} + false -> {error, ?ERR_ITEM_NOT_FOUND}; + Node -> + {result, + lists:map(fun (Name) -> get_node_stat(Node, Name) end, + Names)} end; - get_local_stats(_Server, _, _) -> {error, ?ERR_FEATURE_NOT_IMPLEMENTED}. - - -define(STATVAL(Val, Unit), - {xmlelement, "stat", - [{"name", Name}, - {"units", Unit}, - {"value", Val} - ], []}). + #xmlel{name = <<"stat">>, + attrs = + [{<<"name">>, Name}, {<<"units">>, Unit}, + {<<"value">>, Val}], + children = []}). -define(STATERR(Code, Desc), - {xmlelement, "stat", - [{"name", Name}], - [{xmlelement, "error", - [{"code", Code}], - [{xmlcdata, Desc}]}]}). - - -get_local_stat(Server, [], Name) when Name == "users/online" -> + #xmlel{name = <<"stat">>, attrs = [{<<"name">>, Name}], + children = + [#xmlel{name = <<"error">>, + attrs = [{<<"code">>, Code}], + children = [{xmlcdata, Desc}]}]}). + +get_local_stat(Server, [], Name) + when Name == <<"users/online">> -> case catch ejabberd_sm:get_vh_session_list(Server) of - {'EXIT', _Reason} -> - ?STATERR("500", "Internal Server Error"); - Users -> - ?STATVAL(integer_to_list(length(Users)), "users") + {'EXIT', _Reason} -> + ?STATERR(<<"500">>, <<"Internal Server Error">>); + Users -> + ?STATVAL((iolist_to_binary(integer_to_list(length(Users)))), + <<"users">>) end; - -get_local_stat(Server, [], Name) when Name == "users/total" -> - %%LServer = jlib:nameprep(Server), - case catch ejabberd_auth:get_vh_registered_users_number(Server) of - {'EXIT', _Reason} -> - ?STATERR("500", "Internal Server Error"); - NUsers -> - ?STATVAL(integer_to_list(NUsers), "users") +get_local_stat(Server, [], Name) + when Name == <<"users/total">> -> + case catch + ejabberd_auth:get_vh_registered_users_number(Server) + of + {'EXIT', _Reason} -> + ?STATERR(<<"500">>, <<"Internal Server Error">>); + NUsers -> + ?STATVAL((iolist_to_binary(integer_to_list(NUsers))), + <<"users">>) end; - -get_local_stat(_Server, [], Name) when Name == "users/all-hosts/online" -> +get_local_stat(_Server, [], Name) + when Name == <<"users/all-hosts/online">> -> case catch mnesia:table_info(session, size) of - {'EXIT', _Reason} -> - ?STATERR("500", "Internal Server Error"); - Users -> - ?STATVAL(integer_to_list(Users), "users") + {'EXIT', _Reason} -> + ?STATERR(<<"500">>, <<"Internal Server Error">>); + Users -> + ?STATVAL((iolist_to_binary(integer_to_list(Users))), + <<"users">>) end; - -get_local_stat(_Server, [], Name) when Name == "users/all-hosts/total" -> - NumUsers = lists:foldl( - fun(Host, Total) -> - ejabberd_auth:get_vh_registered_users_number(Host) - + Total - end, 0, ejabberd_config:get_global_option(hosts)), - ?STATVAL(integer_to_list(NumUsers), "users"); - +get_local_stat(_Server, [], Name) + when Name == <<"users/all-hosts/total">> -> + NumUsers = lists:foldl(fun (Host, Total) -> + ejabberd_auth:get_vh_registered_users_number(Host) + + Total + end, + 0, ?MYHOSTS), + ?STATVAL((iolist_to_binary(integer_to_list(NumUsers))), + <<"users">>); get_local_stat(_Server, _, Name) -> - ?STATERR("404", "Not Found"). - - - -get_node_stat(Node, Name) when Name == "time/uptime" -> - case catch rpc:call(Node, erlang, statistics, [wall_clock]) of - {badrpc, _Reason} -> - ?STATERR("500", "Internal Server Error"); - CPUTime -> - ?STATVAL( - io_lib:format("~.3f", [element(1, CPUTime)/1000]), "seconds") + ?STATERR(<<"404">>, <<"Not Found">>). + +get_node_stat(Node, Name) + when Name == <<"time/uptime">> -> + case catch rpc:call(Node, erlang, statistics, + [wall_clock]) + of + {badrpc, _Reason} -> + ?STATERR(<<"500">>, <<"Internal Server Error">>); + CPUTime -> + ?STATVAL(list_to_binary( + io_lib:format("~.3f", + [element(1, CPUTime) / 1000])), + <<"seconds">>) end; - -get_node_stat(Node, Name) when Name == "time/cputime" -> - case catch rpc:call(Node, erlang, statistics, [runtime]) of - {badrpc, _Reason} -> - ?STATERR("500", "Internal Server Error"); - RunTime -> - ?STATVAL( - io_lib:format("~.3f", [element(1, RunTime)/1000]), "seconds") +get_node_stat(Node, Name) + when Name == <<"time/cputime">> -> + case catch rpc:call(Node, erlang, statistics, [runtime]) + of + {badrpc, _Reason} -> + ?STATERR(<<"500">>, <<"Internal Server Error">>); + RunTime -> + ?STATVAL(list_to_binary( + io_lib:format("~.3f", + [element(1, RunTime) / 1000])), + <<"seconds">>) end; - -get_node_stat(Node, Name) when Name == "users/online" -> - case catch rpc:call(Node, ejabberd_sm, dirty_get_my_sessions_list, []) of - {badrpc, _Reason} -> - ?STATERR("500", "Internal Server Error"); - Users -> - ?STATVAL(integer_to_list(length(Users)), "users") +get_node_stat(Node, Name) + when Name == <<"users/online">> -> + case catch rpc:call(Node, ejabberd_sm, + dirty_get_my_sessions_list, []) + of + {badrpc, _Reason} -> + ?STATERR(<<"500">>, <<"Internal Server Error">>); + Users -> + ?STATVAL((iolist_to_binary(integer_to_list(length(Users)))), + <<"users">>) end; - -get_node_stat(Node, Name) when Name == "transactions/committed" -> - case catch rpc:call(Node, mnesia, system_info, [transaction_commits]) of - {badrpc, _Reason} -> - ?STATERR("500", "Internal Server Error"); - Transactions -> - ?STATVAL(integer_to_list(Transactions), "transactions") +get_node_stat(Node, Name) + when Name == <<"transactions/committed">> -> + case catch rpc:call(Node, mnesia, system_info, + [transaction_commits]) + of + {badrpc, _Reason} -> + ?STATERR(<<"500">>, <<"Internal Server Error">>); + Transactions -> + ?STATVAL((iolist_to_binary(integer_to_list(Transactions))), + <<"transactions">>) end; - -get_node_stat(Node, Name) when Name == "transactions/aborted" -> - case catch rpc:call(Node, mnesia, system_info, [transaction_failures]) of - {badrpc, _Reason} -> - ?STATERR("500", "Internal Server Error"); - Transactions -> - ?STATVAL(integer_to_list(Transactions), "transactions") +get_node_stat(Node, Name) + when Name == <<"transactions/aborted">> -> + case catch rpc:call(Node, mnesia, system_info, + [transaction_failures]) + of + {badrpc, _Reason} -> + ?STATERR(<<"500">>, <<"Internal Server Error">>); + Transactions -> + ?STATVAL((iolist_to_binary(integer_to_list(Transactions))), + <<"transactions">>) end; - -get_node_stat(Node, Name) when Name == "transactions/restarted" -> - case catch rpc:call(Node, mnesia, system_info, [transaction_restarts]) of - {badrpc, _Reason} -> - ?STATERR("500", "Internal Server Error"); - Transactions -> - ?STATVAL(integer_to_list(Transactions), "transactions") +get_node_stat(Node, Name) + when Name == <<"transactions/restarted">> -> + case catch rpc:call(Node, mnesia, system_info, + [transaction_restarts]) + of + {badrpc, _Reason} -> + ?STATERR(<<"500">>, <<"Internal Server Error">>); + Transactions -> + ?STATVAL((iolist_to_binary(integer_to_list(Transactions))), + <<"transactions">>) end; - -get_node_stat(Node, Name) when Name == "transactions/logged" -> - case catch rpc:call(Node, mnesia, system_info, [transaction_log_writes]) of - {badrpc, _Reason} -> - ?STATERR("500", "Internal Server Error"); - Transactions -> - ?STATVAL(integer_to_list(Transactions), "transactions") +get_node_stat(Node, Name) + when Name == <<"transactions/logged">> -> + case catch rpc:call(Node, mnesia, system_info, + [transaction_log_writes]) + of + {badrpc, _Reason} -> + ?STATERR(<<"500">>, <<"Internal Server Error">>); + Transactions -> + ?STATVAL((iolist_to_binary(integer_to_list(Transactions))), + <<"transactions">>) end; - get_node_stat(_, Name) -> - ?STATERR("404", "Not Found"). - + ?STATERR(<<"404">>, <<"Not Found">>). search_running_node(SNode) -> - search_running_node(SNode, mnesia:system_info(running_db_nodes)). + search_running_node(SNode, + mnesia:system_info(running_db_nodes)). -search_running_node(_, []) -> - false; +search_running_node(_, []) -> false; search_running_node(SNode, [Node | Nodes]) -> - case atom_to_list(Node) of - SNode -> - Node; - _ -> - search_running_node(SNode, Nodes) + case iolist_to_binary(atom_to_list(Node)) of + SNode -> Node; + _ -> search_running_node(SNode, Nodes) end. - |