• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

emqx / emqx / 8644497754

11 Apr 2024 09:24AM UTC coverage: 62.388% (-0.05%) from 62.44%
8644497754

push

github

web-flow
Merge pull request #12858 from zmstone/0410-fix-variform-number-handling

fix(variform): allow numbers to be numbers

2 of 3 new or added lines in 1 file covered. (66.67%)

67 existing lines in 12 files now uncovered.

34873 of 55897 relevant lines covered (62.39%)

6476.85 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.24
/apps/emqx/src/emqx_os_mon.erl
1
%%--------------------------------------------------------------------
2
%% Copyright (c) 2019-2024 EMQ Technologies Co., Ltd. All Rights Reserved.
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

17
-module(emqx_os_mon).
18

19
-behaviour(gen_server).
20

21
-include("emqx.hrl").
22
-include("logger.hrl").
23

24
-export([start_link/0]).
25

26
-export([
27
    get_sysmem_high_watermark/0,
28
    set_sysmem_high_watermark/1,
29
    get_procmem_high_watermark/0,
30
    set_procmem_high_watermark/1
31
]).
32

33
-export([
34
    current_sysmem_percent/0
35
]).
36

37
-export([update/1]).
38

39
%% gen_server callbacks
40
-export([
41
    init/1,
42
    handle_continue/2,
43
    handle_call/3,
44
    handle_cast/2,
45
    handle_info/2,
46
    terminate/2,
47
    code_change/3
48
]).
49
-export([is_os_check_supported/0]).
50

51
-define(OS_MON, ?MODULE).
52

53
start_link() ->
54
    gen_server:start_link({local, ?OS_MON}, ?MODULE, [], []).
501✔
55

56
update(OS) ->
57
    gen_server:cast(?MODULE, {monitor_conf_update, OS}).
3✔
58

59
%%--------------------------------------------------------------------
60
%% API
61
%%--------------------------------------------------------------------
62

63
get_sysmem_high_watermark() ->
64
    gen_server:call(?OS_MON, ?FUNCTION_NAME, infinity).
2✔
65

66
set_sysmem_high_watermark(Float) ->
67
    gen_server:call(?OS_MON, {?FUNCTION_NAME, Float}, infinity).
1✔
68

69
get_procmem_high_watermark() ->
70
    memsup:get_procmem_high_watermark().
2✔
71

72
set_procmem_high_watermark(Float) ->
73
    memsup:set_procmem_high_watermark(Float).
505✔
74

75
current_sysmem_percent() ->
76
    Ratio = load_ctl:get_memory_usage(),
571✔
77
    erlang:floor(Ratio * 10000) / 100.
571✔
78

79
%%--------------------------------------------------------------------
80
%% gen_server callbacks
81
%%--------------------------------------------------------------------
82

83
init([]) ->
84
    {ok, undefined, {continue, setup}}.
501✔
85

86
handle_continue(setup, undefined) ->
87
    %% start os_mon temporarily
88
    {ok, _} = application:ensure_all_started(os_mon),
501✔
89
    %% memsup is not reliable, ignore
90
    memsup:set_sysmem_high_watermark(1.0),
501✔
91
    SysHW = init_os_monitor(),
501✔
92
    MemRef = start_mem_check_timer(),
501✔
93
    CpuRef = start_cpu_check_timer(),
501✔
94
    %% the value of the first call should be regarded as garbage.
95
    _Val = cpu_sup:util(),
501✔
96
    {noreply, #{sysmem_high_watermark => SysHW, mem_time_ref => MemRef, cpu_time_ref => CpuRef}}.
501✔
97

98
init_os_monitor() ->
99
    init_os_monitor(emqx:get_config([sysmon, os])).
501✔
100

101
init_os_monitor(OS) ->
102
    #{
504✔
103
        sysmem_high_watermark := SysHW,
104
        procmem_high_watermark := PHW
105
    } = OS,
106
    set_procmem_high_watermark(PHW),
504✔
107
    ok = update_mem_alarm_status(SysHW),
504✔
108
    SysHW.
504✔
109

110
handle_call(get_sysmem_high_watermark, _From, #{sysmem_high_watermark := HWM} = State) ->
111
    {reply, HWM, State};
2✔
112
handle_call({set_sysmem_high_watermark, New}, _From, #{sysmem_high_watermark := _Old} = State) ->
113
    ok = update_mem_alarm_status(New),
1✔
114
    {reply, ok, State#{sysmem_high_watermark := New}};
1✔
115
handle_call(Req, _From, State) ->
116
    {reply, {error, {unexpected_call, Req}}, State}.
1✔
117

118
handle_cast({monitor_conf_update, OS}, State) ->
119
    cancel_outdated_timer(State),
3✔
120
    SysHW = init_os_monitor(OS),
3✔
121
    MemRef = start_mem_check_timer(),
3✔
122
    CpuRef = start_cpu_check_timer(),
3✔
123
    {noreply, #{sysmem_high_watermark => SysHW, mem_time_ref => MemRef, cpu_time_ref => CpuRef}};
3✔
124
handle_cast(Msg, State) ->
125
    ?SLOG(error, #{msg => "unexpected_cast", cast => Msg}),
1✔
126
    {noreply, State}.
1✔
127

128
handle_info({timeout, _Timer, mem_check}, #{sysmem_high_watermark := HWM} = State) ->
129
    ok = update_mem_alarm_status(HWM),
66✔
130
    Ref = start_mem_check_timer(),
66✔
131
    {noreply, State#{mem_time_ref => Ref}};
66✔
132
handle_info({timeout, _Timer, cpu_check}, State) ->
133
    CPUHighWatermark = emqx:get_config([sysmon, os, cpu_high_watermark]) * 100,
76✔
134
    CPULowWatermark = emqx:get_config([sysmon, os, cpu_low_watermark]) * 100,
76✔
135
    CPUVal = cpu_sup:util(),
76✔
136
    case CPUVal of
76✔
137
        %% 0 or 0.0
138
        Busy when Busy == 0 ->
UNCOV
139
            ok;
×
140
        Busy when Busy > CPUHighWatermark ->
141
            _ = emqx_alarm:activate(
5✔
142
                high_cpu_usage,
143
                #{
144
                    usage => Busy,
145
                    high_watermark => CPUHighWatermark,
146
                    low_watermark => CPULowWatermark
147
                },
148
                usage_msg(Busy, cpu)
149
            );
150
        Busy when Busy < CPULowWatermark ->
151
            ok = emqx_alarm:ensure_deactivated(
64✔
152
                high_cpu_usage,
153
                #{
154
                    usage => Busy,
155
                    high_watermark => CPUHighWatermark,
156
                    low_watermark => CPULowWatermark
157
                },
158
                usage_msg(Busy, cpu)
159
            );
160
        _Busy ->
161
            ok
7✔
162
    end,
163
    Ref = start_cpu_check_timer(),
76✔
164
    {noreply, State#{cpu_time_ref => Ref}};
76✔
165
handle_info(Info, State) ->
166
    ?SLOG(error, #{msg => "unexpected_info", info => Info}),
1✔
167
    {noreply, State}.
1✔
168

169
terminate(_Reason, _State) ->
170
    ok.
1✔
171

172
code_change(_OldVsn, State, _Extra) ->
173
    {ok, State}.
×
174

175
%%--------------------------------------------------------------------
176
%% Internal functions
177
%%--------------------------------------------------------------------
178
cancel_outdated_timer(#{mem_time_ref := MemRef, cpu_time_ref := CpuRef}) ->
179
    emqx_utils:cancel_timer(MemRef),
3✔
180
    emqx_utils:cancel_timer(CpuRef),
3✔
181
    ok.
3✔
182

183
start_cpu_check_timer() ->
184
    Interval = emqx:get_config([sysmon, os, cpu_check_interval]),
580✔
185
    case erlang:system_info(system_architecture) of
580✔
186
        "x86_64-pc-linux-musl" -> undefined;
×
187
        _ -> start_timer(Interval, cpu_check)
580✔
188
    end.
189

190
is_os_check_supported() ->
191
    {unix, linux} =:= os:type().
3,501✔
192

193
start_mem_check_timer() ->
194
    Interval = emqx:get_config([sysmon, os, mem_check_interval]),
570✔
195
    case is_integer(Interval) andalso is_os_check_supported() of
570✔
196
        true ->
197
            start_timer(Interval, mem_check);
569✔
198
        false ->
199
            undefined
1✔
200
    end.
201

202
start_timer(Interval, Msg) ->
203
    emqx_utils:start_timer(Interval, Msg).
1,149✔
204

205
update_mem_alarm_status(HWM) when HWM > 1.0 orelse HWM < 0.0 ->
206
    ?SLOG(warning, #{msg => "discarded_out_of_range_mem_alarm_threshold", value => HWM}),
×
207
    ok = emqx_alarm:ensure_deactivated(
×
208
        high_system_memory_usage,
209
        #{},
210
        <<"Deactivated mem usage alarm due to out of range threshold">>
211
    );
212
update_mem_alarm_status(HWM) ->
213
    is_os_check_supported() andalso
571✔
214
        do_update_mem_alarm_status(HWM),
571✔
215
    ok.
571✔
216

217
do_update_mem_alarm_status(HWM0) ->
218
    HWM = HWM0 * 100,
571✔
219
    Usage = current_sysmem_percent(),
571✔
220
    case Usage > HWM of
571✔
221
        true ->
222
            _ = emqx_alarm:activate(
35✔
223
                high_system_memory_usage,
224
                #{
225
                    usage => Usage,
226
                    high_watermark => HWM
227
                },
228
                usage_msg(Usage, mem)
229
            );
230
        false ->
231
            ok = emqx_alarm:ensure_deactivated(
536✔
232
                high_system_memory_usage,
233
                #{
234
                    usage => Usage,
235
                    high_watermark => HWM
236
                },
237
                usage_msg(Usage, mem)
238
            )
239
    end,
240
    ok.
571✔
241

242
usage_msg(Usage, What) ->
243
    %% divide by 1.0 to ensure float point number
244
    iolist_to_binary(io_lib:format("~.2f% ~p usage", [Usage / 1.0, What])).
640✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc