./ct_report/coverage/mongoose_system_metrics_collector.COVER.html

1 -module(mongoose_system_metrics_collector).
2
3 -include("mongoose.hrl").
4
5 -type report_struct() ::
6 #{
7 name := term(),
8 params := #{term() := term()}
9 }.
10
11 -export_type([report_struct/0]).
12
13 -export([collect/1]).
14
15 collect(PrevReport) ->
16
:-(
ReportResults = [ get_reports(RGetter) || RGetter <- report_getters()],
17
:-(
StanzasCount = get_xmpp_stanzas_count(PrevReport),
18
:-(
lists:flatten(ReportResults ++ StanzasCount).
19
20 -spec get_reports(fun(() -> [report_struct()])) -> [report_struct()].
21 get_reports(Fun) ->
22
:-(
Fun().
23
24 -spec report_getters() -> [fun(() -> [report_struct()])].
25 report_getters() ->
26
:-(
[
27 fun get_hosts_count/0,
28 fun get_domains_count/0,
29 fun get_modules/0,
30 fun get_number_of_custom_modules/0,
31 fun get_cluster_data/0,
32 fun get_api/0,
33 fun get_transport_mechanisms/0,
34 fun get_tls_options/0,
35 fun get_outgoing_pools/0
36 ].
37
38 get_cluster_data() ->
39
:-(
Steps = [
40 fun get_uptime/0,
41 fun get_version/0,
42 fun get_components/0,
43 fun get_cluster_size/0,
44 fun get_config_type/0
45 ],
46
:-(
Params = lists:foldl(fun(Step, Acc) ->
47
:-(
maps:merge(Acc, Step())
48 end, #{}, Steps),
49
:-(
[#{name => cluster, params => Params}].
50
51 get_hosts_count() ->
52
:-(
HostTypes = ?ALL_HOST_TYPES,
53
:-(
NumberOfHosts = length(HostTypes),
54
:-(
[#{name => host_count, params => #{value => NumberOfHosts}}].
55
56 get_domains_count() ->
57
:-(
DomainsCount = mongoose_domain_core:domains_count(),
58
:-(
[#{name => domain_count, params => #{value => DomainsCount}}].
59
60 get_modules() ->
61
:-(
HostTypes = ?ALL_HOST_TYPES,
62
:-(
AllModules = lists:flatten([gen_mod:loaded_modules(H) || H <- HostTypes]),
63
:-(
ModulesToReport = filter_behaviour_implementations(lists:usort(AllModules),
64 mongoose_module_metrics),
65
:-(
ModsWithOpts = [get_modules_metrics(Host, ModulesToReport) || Host <- HostTypes],
66
:-(
[report_module_with_opts(Mod, Opt) || {Mod, Opt} <- lists:flatten(ModsWithOpts)].
67
68 filter_behaviour_implementations(Modules, Behaviour) ->
69
:-(
lists:filter(
70 fun(M) ->
71
:-(
try lists:keyfind([Behaviour], 2, M:module_info(attributes)) of
72
:-(
{behavior, _} -> true;
73
:-(
{behaviour, _} -> true;
74
:-(
_ -> false
75 catch
76
:-(
_:_ -> false
77 end
78 end, Modules).
79
80 get_modules_metrics(Host, Modules) ->
81
:-(
lists:map(
82 fun(M) ->
83
:-(
case erlang:function_exported(M, config_metrics, 1) of
84
:-(
true -> {M, M:config_metrics(Host)};
85
:-(
false -> {M, [{none, none}]}
86 end
87 end, Modules).
88
89 report_module_with_opts(Module, Opts) ->
90
:-(
#{name => module_with_opt, params =>
91 lists:foldl(
92 fun
93 ({none, _}, Acc) ->
94
:-(
Acc;
95 ({OptKey, OptValue}, Acc) ->
96
:-(
maps:put(OptKey, OptValue, Acc)
97 end, #{module => Module}, Opts)
98 }.
99
100 get_number_of_custom_modules() ->
101
:-(
HostTypes = ?ALL_HOST_TYPES,
102
:-(
AllModules = lists:flatten(
103 lists:map(fun gen_mod:loaded_modules/1, HostTypes)),
104
:-(
GenMods = filter_behaviour_implementations(AllModules, gen_mod),
105
:-(
GenModsSet = sets:from_list(GenMods),
106
:-(
MetricsModule = filter_behaviour_implementations(AllModules,
107 mongoose_module_metrics),
108
:-(
MetricsModuleSet = sets:from_list(MetricsModule),
109
:-(
CountCustomMods= sets:size(sets:subtract(GenModsSet, MetricsModuleSet)),
110
:-(
[#{name => custom_module_count, params => #{value => CountCustomMods}}].
111
112 get_uptime() ->
113
:-(
{Uptime, _} = statistics(wall_clock),
114
:-(
UptimeSeconds = Uptime div 1000,
115
:-(
{D, {H, M, S}} = calendar:seconds_to_daystime(UptimeSeconds),
116
:-(
Formatted = io_lib:format("~4..0B-~2..0B:~2..0B:~2..0B", [D,H,M,S]),
117
:-(
#{uptime => list_to_binary(Formatted)}.
118
119 get_cluster_size() ->
120
:-(
NodesNo = length(nodes()) + 1,
121
:-(
#{node_number => NodesNo}.
122
123 get_version() ->
124
:-(
case lists:keyfind(mongooseim, 1, application:which_applications()) of
125 {_, _, Version} ->
126
:-(
#{version => list_to_binary(Version)};
127 _ ->
128
:-(
[]
129 end.
130
131 get_components() ->
132
:-(
Domains = mongoose_router:get_all_domains() ++ mongoose_component:dirty_get_all_components(all),
133
:-(
Components = [mongoose_component:lookup_component(D, node()) || D <- Domains],
134
:-(
LenComponents = length(lists:flatten(Components)),
135
:-(
#{component => LenComponents}.
136
137 get_api() ->
138
:-(
ApiList = filter_unknown_api(get_http_handler_modules()),
139
:-(
[#{name => http_api,
140 params => lists:foldl(fun(Element, Acc) ->
141
:-(
maps:put(Element, enabled, Acc)
142 end, #{}, ApiList)}].
143
144 filter_unknown_api(ApiList) ->
145
:-(
AllowedToReport = [mongoose_client_api, mongoose_admin_api, mod_bosh, mod_websockets],
146
:-(
[Api || Api <- ApiList, lists:member(Api, AllowedToReport)].
147
148 get_transport_mechanisms() ->
149
:-(
HTTP = [Mod || Mod <- get_http_handler_modules(),
150
:-(
Mod =:= mod_bosh orelse Mod =:= mod_websockets],
151
:-(
TCP = lists:usort([tcp || #{proto := tcp} <- get_listeners(mongoose_c2s_listener)]),
152
:-(
[#{name => transport_mechanism,
153 params => lists:foldl(fun(Element, Acc) ->
154
:-(
maps:put(Element, enabled, Acc)
155 end, #{}, HTTP ++ TCP)}].
156
157 get_http_handler_modules() ->
158
:-(
Listeners = get_listeners(ejabberd_cowboy),
159
:-(
lists:usort(lists:flatmap(fun get_http_handler_modules/1, Listeners)).
160
161 get_listeners(Module) ->
162
:-(
Listeners = mongoose_config:get_opt(listen),
163
:-(
lists:filter(fun(#{module := Mod}) -> Mod =:= Module end, Listeners).
164
165 get_http_handler_modules(#{handlers := Handlers}) ->
166
:-(
[Module || #{module := Module} <- Handlers].
167
168 get_tls_options() ->
169
:-(
TLSOptions = lists:flatmap(fun extract_tls_options/1, get_listeners(mongoose_c2s_listener)),
170
:-(
lists:foldl(fun({Mode, Module}, Acc) ->
171
:-(
[#{name => tls_option, params => #{mode => Mode, module => Module}}] ++ Acc
172 end, [], lists:usort(TLSOptions)).
173
174 extract_tls_options(#{tls := #{mode := TLSMode, module := TLSModule}}) ->
175
:-(
[{TLSMode, TLSModule}];
176
:-(
extract_tls_options(_) -> [].
177
178 get_outgoing_pools() ->
179
:-(
OutgoingPools = mongoose_config:get_opt(outgoing_pools),
180
:-(
[#{name => outgoing_pool,
181
:-(
params => #{value => Type}} || #{type := Type} <- OutgoingPools].
182
183 get_xmpp_stanzas_count(PrevReport) ->
184
:-(
StanzaTypes = [xmppMessageSent, xmppMessageReceived, xmppIqSent,
185 xmppIqReceived, xmppPresenceSent, xmppPresenceReceived],
186
:-(
NewCount = [count_stanzas(StanzaType) || StanzaType <- StanzaTypes],
187
:-(
StanzasCount = calculate_stanza_rate(PrevReport, NewCount),
188
:-(
[#{name => xmpp_stanza_count,
189 params => #{
190 stanza_type => StanzaType,
191 total => Total,
192 increment => Increment
193
:-(
}} || {StanzaType, Total, Increment} <- StanzasCount].
194
195 count_stanzas(StanzaType) ->
196
:-(
ExometerResults = exometer:get_values(['_', StanzaType]),
197
:-(
StanzaCount = lists:foldl(fun({ _, [{count,Count}, {one, _}]}, Sum) ->
198
:-(
Count + Sum end, 0, ExometerResults),
199
:-(
{StanzaType, StanzaCount}.
200
201 calculate_stanza_rate([], NewCount) ->
202
:-(
[{Type, Count, Count} || {Type, Count} <- NewCount];
203 calculate_stanza_rate(PrevReport, NewCount) ->
204
:-(
ReportProplist = [{Name, Key} ||
205 #{name := xmpp_stanza_count,
206
:-(
params := #{stanza_type := Name, total := Key}} <- PrevReport],
207
:-(
[{Type, Count,
208 case proplists:get_value(Type, ReportProplist) of
209
:-(
undefined -> Count;
210
:-(
Total -> Count-Total
211
:-(
end} || {Type, Count} <- NewCount].
212
213 get_config_type() ->
214
:-(
ConfigPath = mongoose_config:get_config_path(),
215
:-(
ConfigType = case filename:extension(ConfigPath) of
216
:-(
".toml" -> toml;
217
:-(
".cfg" -> cfg;
218
:-(
_ -> unknown_config_type
219 end,
220
:-(
#{config_type => ConfigType}.
Line Hits Source