./ct_report/coverage/mod_event_pusher_http.COVER.html

1 %%%----------------------------------------------------------------------
2 %%% File : mod_event_pusher_http.erl
3 %%% Author : Baibossynv Valery <baibossynov.valery@gmail.com>
4 %%% Purpose : Message passing via http
5 %%% Created : 16 Dec 2015 by Baibossynv Valery <baibossynov.valery@gmail.com>
6 %%%----------------------------------------------------------------------
7
8 -module(mod_event_pusher_http).
9 -author("baibossynov.valery@gmail.com").
10
11 -ignore_xref([behaviour_info/1]).
12
13 -behaviour(gen_mod).
14 -behaviour(mod_event_pusher).
15 -behaviour(mongoose_module_metrics).
16
17 -callback should_make_req(Acc :: mongoose_acc:t(),
18 Dir :: in | out,
19 Packet :: exml:element(),
20 From :: jid:jid(),
21 To :: jid:jid(),
22 Opts :: [{atom(), term()}]) -> boolean().
23 -callback prepare_headers(Acc :: mongoose_acc:t(),
24 Dir :: in | out,
25 Host :: jid:lserver(),
26 Message :: binary(),
27 Sender :: jid:luser(),
28 Receiver :: jid:luser(),
29 Opts :: [{atom(), term()}]) -> [{binary(), binary()}].
30 -callback prepare_body(Acc :: mongoose_acc:t(),
31 Dir :: in | out,
32 Host :: jid:lserver(),
33 Message :: binary(),
34 Sender :: jid:luser(),
35 Receiver :: jid:luser(),
36 Opts :: [{atom(), term()}]) -> binary().
37
38 -include("mod_event_pusher_events.hrl").
39 -include("jlib.hrl").
40
41 %% API
42 -export([start/2, stop/1, config_spec/0, push_event/3]).
43
44 -include("mongoose.hrl").
45 -include("jlib.hrl").
46 -include("mongoose_config_spec.hrl").
47
48 -define(DEFAULT_POOL_NAME, http_pool).
49 -define(DEFAULT_PATH, "").
50
51 -define(SENT_METRIC, [mod_event_pusher_http, sent]).
52 -define(FAILED_METRIC, [mod_event_pusher_http, failed]).
53 -define(RESPONSE_METRIC, [mod_event_pusher_http, response_time]).
54
55 start(Host, _Opts) ->
56 5 ensure_metrics(Host),
57 5 ok.
58
59 stop(_Host) ->
60 5 ok.
61
62 config_spec() ->
63 164 #section{
64 items = #{<<"pool_name">> => #option{type = atom,
65 validate = pool_name},
66 <<"path">> => #option{type = string},
67 <<"callback_module">> => #option{type = atom,
68 validate = module}
69 }
70 }.
71
72 push_event(Acc, _Host, #chat_event{direction = Dir, from = From, to = To, packet = Packet}) ->
73 63 lists:map(fun(Opts) -> push_event(Acc, Dir, From, To, Packet, Opts) end,
74 gen_mod:get_module_opt(From#jid.lserver, ?MODULE, configs, [])),
75 63 Acc;
76 push_event(Acc, _Host, _Event) ->
77 44 Acc.
78
79 push_event(Acc, Dir, From, To, Packet, Opts) ->
80 69 Body = exml_query:path(Packet, [{element, <<"body">>}, cdata], <<>>),
81 69 Mod = get_callback_module(Opts),
82 69 case Mod:should_make_req(Acc, Dir, Packet, From, To, Opts) of
83 true ->
84 19 make_req(Acc, Dir, From#jid.lserver, From#jid.luser, To#jid.luser, Body, Opts);
85 _ ->
86 50 ok
87 end,
88 69 Acc.
89
90 %%%===================================================================
91 %%% Internal functions
92 %%%===================================================================
93
94 get_callback_module(Opts) ->
95 88 proplists:get_value(callback_module, Opts, mod_event_pusher_http_defaults).
96
97 make_req(Acc, Dir, Host, Sender, Receiver, Message, Opts) ->
98 19 Path = fix_path(list_to_binary(proplists:get_value(path, Opts, ?DEFAULT_PATH))),
99 19 PoolName = proplists:get_value(pool_name, Opts, ?DEFAULT_POOL_NAME),
100 19 Mod = get_callback_module(Opts),
101 19 Body = Mod:prepare_body(Acc, Dir, Host, Message, Sender, Receiver, Opts),
102 19 Headers = Mod:prepare_headers(Acc, Dir, Host, Message, Sender, Receiver, Opts),
103 19 LogMeta = #{what => event_pusher_http_req,
104 text => <<"mod_event_pusher_http makes an external HTTP call">>,
105 path => Path, body => Body, headers => Headers,
106 sender => Sender, receiver => Receiver, direction => Dir,
107 server => Host, pool_name => PoolName, acc => Acc},
108 19 ?LOG_INFO(LogMeta),
109 19 T0 = os:timestamp(),
110 19 {Res, Elapsed} = case mongoose_http_client:post(Host, PoolName, Path, Headers, Body) of
111 {ok, _} ->
112 17 {ok, timer:now_diff(os:timestamp(), T0)};
113 {error, Reason} ->
114 2 {{error, Reason}, 0}
115 end,
116 19 record_result(Host, Res, Elapsed, LogMeta),
117 19 ok.
118
119 ensure_metrics(Host) ->
120 5 mongoose_metrics:ensure_metric(Host, ?SENT_METRIC, spiral),
121 5 mongoose_metrics:ensure_metric(Host, ?FAILED_METRIC, spiral),
122 5 mongoose_metrics:ensure_metric(Host, ?RESPONSE_METRIC, histogram),
123 5 ok.
124
125 record_result(Host, ok, Elapsed, _LogMeta) ->
126 17 mongoose_metrics:update(Host, ?SENT_METRIC, 1),
127 17 mongoose_metrics:update(Host, ?RESPONSE_METRIC, Elapsed),
128 17 ok;
129 record_result(Host, {error, Reason}, _, LogMeta) ->
130 2 mongoose_metrics:update(Host, ?FAILED_METRIC, 1),
131 2 ?LOG_WARNING(LogMeta#{what => event_pusher_http_req_failed,
132 text => <<"mod_event_pusher_http HTTP call failed">>,
133 reason => Reason
134
:-(
}),
135 2 ok.
136
137 %% @doc Strip initial slash (it is added by mongoose_http_client)
138 fix_path(<<"/", R/binary>>) ->
139 15 R;
140 fix_path(R) ->
141 4 R.
Line Hits Source