From 66a4e405e05b87a7e90bb6ed1adf66ec44d87c23 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Sun, 21 May 2017 14:24:57 +0300 Subject: [PATCH] Improve mod_metrics * Do not spawn a process per event * Avoid UDP socket creation on every event * Get rid of calls to str.erl module * Add options 'ip' and 'port' --- src/mod_metrics.erl | 54 +++++++++++++++++++++++++++++++++------------ 1 file changed, 40 insertions(+), 14 deletions(-) diff --git a/src/mod_metrics.erl b/src/mod_metrics.erl index ecae7cd1b..450fe4141 100644 --- a/src/mod_metrics.erl +++ b/src/mod_metrics.erl @@ -32,8 +32,7 @@ -include("logger.hrl"). -include("xmpp.hrl"). --export([start/2, stop/1, send_metrics/4, mod_opt_type/1, - depends/2, reload/3]). +-export([start/2, stop/1, mod_opt_type/1, depends/2, reload/3]). -export([offline_message_hook/1, sm_register_connection_hook/3, sm_remove_connection_hook/3, @@ -41,6 +40,8 @@ s2s_send_packet/1, s2s_receive_packet/1, remove_user/2, register_user/2]). +-define(SOCKET_NAME, mod_metrics_udp_socket). + %%==================================================================== %% API %%==================================================================== @@ -125,20 +126,20 @@ register_user(_User, Server) -> %%==================================================================== push(Host, Probe) -> - spawn(?MODULE, send_metrics, [Host, Probe, {127,0,0,1}, 11111]). + IP = gen_mod:get_module_opt(Host, ?MODULE, ip, {127,0,0,1}), + Port = gen_mod:get_module_opt(Host, ?MODULE, port, 11111), + send_metrics(Host, Probe, IP, Port). send_metrics(Host, Probe, Peer, Port) -> % our default metrics handler is https://github.com/processone/grapherl % grapherl metrics are named first with service domain, then nodename % and name of the data itself, followed by type timestamp and value % example => process-one.net/xmpp-1.user_receive_packet:c/1441784958:1 - [_, NodeId] = str:tokens(misc:atom_to_binary(node()), <<"@">>), - [Node | _] = str:tokens(NodeId, <<".">>), + [_, FQDN] = binary:split(misc:atom_to_binary(node()), <<"@">>), + [Node|_] = binary:split(FQDN, <<".">>), BaseId = <>, - DateTime = erlang:universaltime(), - UnixTime = calendar:datetime_to_gregorian_seconds(DateTime) - 62167219200, - TS = integer_to_binary(UnixTime), - case gen_udp:open(0) of + TS = integer_to_binary(p1_time_compat:system_time(seconds)), + case get_socket() of {ok, Socket} -> case Probe of {Key, Val} -> @@ -150,11 +151,36 @@ send_metrics(Host, Probe, Peer, Port) -> Data = <>, gen_udp:send(Socket, Peer, Port, Data) - end, - gen_udp:close(Socket); - Error -> - ?WARNING_MSG("can not open udp socket to grapherl: ~p", [Error]) + end; + Err -> + Err end. +get_socket() -> + case whereis(?SOCKET_NAME) of + undefined -> + case gen_udp:open(0) of + {ok, Socket} -> + try register(?SOCKET_NAME, Socket) of + true -> {ok, Socket} + catch _:badarg -> + {ok, Socket} + end; + {error, Reason} = Err -> + ?ERROR_MSG("can not open udp socket to grapherl: ~s", + [inet:format_error(Reason)]), + Err + end; + Socket -> + {ok, Socket} + end. + +mod_opt_type(ip) -> + fun(S) -> + {ok, IP} = inet:parse_ipv4_address(iolist_to_binary(S)), + IP + end; +mod_opt_type(port) -> + fun(I) when is_integer(I), I>0, I<65536 -> I end; mod_opt_type(_) -> - []. + [ip, port].