./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 => instrument_handler_already_attached,
44 event => EventName, labels => Labels,
45 new_handlers => HandlerFuns, new_config => Config})
46 end.
47
48 -spec tear_down(event_name(), labels()) -> ok.
49 tear_down(EventName, Labels) ->
50
:-(
mongoose_instrument_registry:detach(EventName, Labels).
51
52 -spec span(event_name(), labels(), fun(() -> Result), measure_fun(Result)) -> Result.
53 span(Event, Labels, F, MeasureF) ->
54
:-(
span(Event, Labels, F, [], MeasureF).
55
56 -spec span(event_name(), labels(), fun((...) -> Result), list(), measure_fun(Result)) -> Result.
57 span(Event, Labels, F, Args, MeasureF) ->
58
:-(
Handlers = get_handlers(Event, Labels),
59
:-(
{Time, Result} = timer:tc(F, Args),
60
:-(
handle_event(Event, Labels, MeasureF(Time, Result), Handlers),
61
:-(
Result.
62
63 -spec execute(event_name(), labels(), measurements()) -> ok.
64 execute(Event, Labels, Measurements) ->
65
:-(
Handlers = get_handlers(Event, Labels),
66
:-(
handle_event(Event, Labels, Measurements, Handlers).
67
68 -spec get_handlers(event_name(), labels()) -> handlers().
69 get_handlers(Event, Labels) ->
70
:-(
case mongoose_instrument_registry:lookup(Event, Labels) of
71 {ok, Handlers} ->
72
:-(
Handlers;
73 {error, not_found} ->
74
:-(
error(#{what => instrument_handler_not_attached, event_name => Event, labels => Labels})
75 end.
76
77 -spec handle_event(event_name(), labels(), measurements(), handlers()) -> ok.
78 handle_event(Event, Labels, Measurements, {EventHandlers, Config}) ->
79
:-(
lists:foreach(fun(Handler) -> Handler(Event, Labels, Config, Measurements) end, EventHandlers).
80
81 -spec handler_modules() -> [module()].
82 handler_modules() ->
83
:-(
[list_to_existing_atom("mongoose_instrument_" ++ atom_to_list(Key))
84
:-(
|| Key <- maps:keys(mongoose_config:get_opt(instrumentation))].
Line Hits Source