./ct_report/coverage/mongoose_instrument.COVER.html

1 -module(mongoose_instrument).
2
3 -export([set_up/1, set_up/3,
4 tear_down/1, tear_down/2,
5 span/4, span/5,
6 execute/3]).
7
8 -ignore_xref([set_up/3, tear_down/2, span/4, span/5, execute/3]).
9
10 -type event_name() :: atom().
11 -type labels() :: #{host_type => mongooseim:host_type()}. % to be extended
12 -type metrics() :: #{atom() => spiral | histogram}. % to be extended
13 -type measurements() :: #{atom() => integer() | atom() | binary()}.
14 -type spec() :: {event_name(), labels(), config()}.
15 -type config() :: #{metrics => metrics()}. % to be extended
16 -type handler_fun() :: fun((event_name(), labels(), config(), measurements()) -> any()).
17 -type handlers() :: {[handler_fun()], config()}.
18 -type execution_time() :: integer().
19 -type measure_fun(Result) :: fun((execution_time(), Result) -> measurements()).
20
21 -callback set_up(event_name(), labels(), config()) -> boolean().
22 -callback handle_event(event_name(), labels(), config(), measurements()) -> any().
23
24 -export_type([event_name/0, labels/0, config/0, measurements/0, spec/0, handlers/0]).
25
26 -spec set_up([spec()]) -> ok.
27 set_up(Specs) ->
28
:-(
lists:foreach(fun({EventName, Labels, Config}) -> set_up(EventName, Labels, Config) end, Specs).
29
30 -spec tear_down([spec()]) -> ok.
31 tear_down(Specs) ->
32
:-(
lists:foreach(fun({EventName, Labels, _Config}) -> tear_down(EventName, Labels) end, Specs).
33
34 -spec set_up(event_name(), labels(), config()) -> ok.
35 set_up(EventName, Labels, Config) ->
36
:-(
AllModules = handler_modules(),
37
:-(
UsedModules = lists:filter(fun(Mod) -> Mod:set_up(EventName, Labels, Config) end, AllModules),
38
:-(
HandlerFuns = [fun Mod:handle_event/4 || Mod <- UsedModules],
39
:-(
case mongoose_instrument_registry:attach(EventName, Labels, {HandlerFuns, Config}) of
40 ok ->
41
:-(
ok;
42 {error, already_attached} ->
43
:-(
error(#{what => event_already_registered, event_name => EventName, labels => Labels})
44 end.
45
46 -spec tear_down(event_name(), labels()) -> ok.
47 tear_down(EventName, Labels) ->
48
:-(
mongoose_instrument_registry:detach(EventName, Labels).
49
50 -spec span(event_name(), labels(), fun(() -> Result), measure_fun(Result)) -> Result.
51 span(Event, Labels, F, MeasureF) ->
52
:-(
span(Event, Labels, F, [], MeasureF).
53
54 -spec span(event_name(), labels(), fun((...) -> Result), list(), measure_fun(Result)) -> Result.
55 span(Event, Labels, F, Args, MeasureF) ->
56
:-(
Handlers = get_handlers(Event, Labels),
57
:-(
{Time, Result} = timer:tc(F, Args),
58
:-(
handle_event(Event, Labels, MeasureF(Time, Result), Handlers),
59
:-(
Result.
60
61 -spec execute(event_name(), labels(), measurements()) -> ok.
62 execute(Event, Labels, Measurements) ->
63
:-(
Handlers = get_handlers(Event, Labels),
64
:-(
handle_event(Event, Labels, Measurements, Handlers).
65
66 -spec get_handlers(event_name(), labels()) -> handlers().
67 get_handlers(EventName, Labels) ->
68
:-(
case mongoose_instrument_registry:lookup(EventName, Labels) of
69 {ok, Handlers} ->
70
:-(
Handlers;
71 {error, not_found} ->
72
:-(
error(#{what => event_not_registered, event_name => EventName, labels => Labels})
73 end.
74
75 -spec handle_event(event_name(), labels(), measurements(), handlers()) -> ok.
76 handle_event(Event, Labels, Measurements, {EventHandlers, Config}) ->
77
:-(
lists:foreach(fun(Handler) -> Handler(Event, Labels, Config, Measurements) end, EventHandlers).
78
79 -spec handler_modules() -> [module()].
80 handler_modules() ->
81
:-(
[list_to_existing_atom("mongoose_instrument_" ++ atom_to_list(Key))
82
:-(
|| Key <- maps:keys(mongoose_config:get_opt(instrumentation))].
Line Hits Source