1 |
|
%%============================================================================== |
2 |
|
%% Copyright 2019 Erlang Solutions Ltd. |
3 |
|
%% |
4 |
|
%% Licensed under the Apache License, Version 2.0 (the "License"); |
5 |
|
%% you may not use this file except in compliance with the License. |
6 |
|
%% You may obtain a copy of the License at |
7 |
|
%% |
8 |
|
%% http://www.apache.org/licenses/LICENSE-2.0 |
9 |
|
%% |
10 |
|
%% Unless required by applicable law or agreed to in writing, software |
11 |
|
%% distributed under the License is distributed on an "AS IS" BASIS, |
12 |
|
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 |
|
%% See the License for the specific language governing permissions and |
14 |
|
%% limitations under the License. |
15 |
|
%%============================================================================== |
16 |
|
-module(mongoose_metrics_probe). |
17 |
|
-behaviour(exometer_probe). |
18 |
|
|
19 |
|
-include("mongoose_logger.hrl"). |
20 |
|
|
21 |
|
%% exometer_entry callbacks |
22 |
|
%% exometer_probe callbacks |
23 |
|
-export([ |
24 |
|
behaviour/0, |
25 |
|
probe_init/3, |
26 |
|
probe_terminate/1, |
27 |
|
probe_get_value/2, |
28 |
|
probe_get_datapoints/1, |
29 |
|
probe_update/2, |
30 |
|
probe_reset/1, |
31 |
|
probe_sample/1, |
32 |
|
probe_setopts/3, |
33 |
|
probe_handle_msg/2, |
34 |
|
probe_code_change/3 |
35 |
|
]). |
36 |
|
|
37 |
|
-ignore_xref([behaviour_info/1]). |
38 |
|
|
39 |
|
-type datapoint() :: atom(). |
40 |
|
-callback datapoints() -> [datapoint()]. |
41 |
|
-callback sample() -> #{datapoint() => integer()}. |
42 |
|
|
43 |
|
-record(state, { |
44 |
|
callback_module :: atom(), |
45 |
|
data = #{} :: #{datapoint() => integer()}, |
46 |
|
ref :: reference() | undefined |
47 |
|
}). |
48 |
|
|
49 |
|
-spec behaviour() -> exometer:behaviour(). |
50 |
|
behaviour() -> |
51 |
216 |
probe. |
52 |
|
|
53 |
|
probe_init(_Name, _Type, Opts) -> |
54 |
216 |
Mod = case proplists:get_value(callback_module, Opts) of |
55 |
216 |
M when is_atom(M) -> M; |
56 |
:-( |
M -> error({invalid_callback_module, M}) |
57 |
|
end, |
58 |
216 |
{ok, #state{callback_module = Mod, |
59 |
|
data = #{}}}. |
60 |
|
|
61 |
212 |
probe_terminate(_) -> ok. |
62 |
|
|
63 |
|
probe_get_value(DPs, #state{data = Data} = S) -> |
64 |
708 |
{ok, maps:to_list(maps:with(DPs, Data)), S}. |
65 |
|
|
66 |
|
probe_get_datapoints(#state{callback_module = Mod}) -> |
67 |
708 |
{ok, Mod:datapoints()}. |
68 |
|
|
69 |
|
probe_update(_, _) -> |
70 |
:-( |
{error, not_supported}. |
71 |
|
|
72 |
|
probe_reset(S) -> |
73 |
:-( |
{ok, S#state{data = #{}}}. |
74 |
|
|
75 |
|
|
76 |
|
probe_sample(#state{callback_module = Mod, ref = undefined} = S) -> |
77 |
509 |
{_Pid, Ref} = |
78 |
|
spawn_monitor( |
79 |
|
fun() -> |
80 |
509 |
exit({sample, Mod:sample()}) |
81 |
|
end), |
82 |
509 |
{ok, S#state{ref = Ref}}; |
83 |
|
probe_sample(#state{} = S) -> |
84 |
:-( |
{ok, S}. |
85 |
|
|
86 |
|
probe_setopts(_Entry, _Opts, _S) -> |
87 |
:-( |
{error, not_supported}. |
88 |
|
|
89 |
|
probe_handle_msg({'DOWN', Ref, _, _, {sample, Data}}, #state{ref = Ref} = S) -> |
90 |
509 |
{ok, S#state{ref = undefined, data = Data}}; |
91 |
|
probe_handle_msg({'DOWN', Ref, _, _, Reason}, #state{callback_module = Mod, ref = Ref} = S) -> |
92 |
:-( |
?LOG_WARNING(#{what => probe_callback_module_died, callback_module => Mod, |
93 |
:-( |
reason => Reason}), |
94 |
:-( |
{ok, S#state{ref = undefined}}; |
95 |
|
probe_handle_msg(_, S) -> |
96 |
:-( |
{ok, S}. |
97 |
|
|
98 |
:-( |
probe_code_change(_, S, _) -> {ok, S}. |