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'
This commit is contained in:
Evgeniy Khramtsov 2017-05-21 14:24:57 +03:00
parent 0a77b9f43e
commit 66a4e405e0
1 changed files with 40 additions and 14 deletions

View File

@ -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 = <<Host/binary, "/", Node/binary, ".">>,
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 = <<BaseId/binary, (misc:atom_to_binary(Key))/binary,
":c/", TS/binary, ":1">>,
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].