From 32effd632ce18d47d48209b634c91e7b9a0ea97a Mon Sep 17 00:00:00 2001 From: Rory Z Date: Fri, 17 Jul 2020 16:08:00 +0800 Subject: [PATCH] Auto-pull-request-on-2020-07-17 (#3599) * chore: update app.src.script * chore(alarms): Add timestamp for alarm * perf(emqx_vm): make emqx_vm:get_memory/0 more efficiency --- src/emqx.app.src.script | 19 +++++++++---------- src/emqx_alarm_handler.erl | 18 ++++++++++-------- src/emqx_vm.erl | 38 +++++++++++++++++++++++++++----------- 3 files changed, 46 insertions(+), 29 deletions(-) diff --git a/src/emqx.app.src.script b/src/emqx.app.src.script index b76a11720..6f8cc6a14 100644 --- a/src/emqx.app.src.script +++ b/src/emqx.app.src.script @@ -12,16 +12,15 @@ Config = case os:getenv("EMQX_DESC") of end, RemoveLeadingV = - fun(Tag) -> - case re:run(Tag, "v\[0-9\]+\.\[0-9\]+\.*") of - nomatch -> - Tag; - {match, _} -> - %% if it is a version number prefixed by 'v' then remove the 'v' - "v" ++ Vsn = Tag, - Vsn - end - end, + fun(Tag) -> + case re:run(Tag, "^[v|e]?[0-9]\.[0-9]\.([0-9]|(rc|beta|alpha)\.[0-9])", [{capture, none}]) of + nomatch -> + Tag; + {match, _} -> + %% if it is a version number prefixed by 'v' or 'e', then remove it + re:replace(Tag, "[v|e]", "", [{return ,list}]) + end + end, case os:getenv("EMQX_DEPS_DEFAULT_VSN") of false -> Config; % env var not defined diff --git a/src/emqx_alarm_handler.erl b/src/emqx_alarm_handler.erl index 990f8a76e..c1dc1091a 100644 --- a/src/emqx_alarm_handler.erl +++ b/src/emqx_alarm_handler.erl @@ -105,7 +105,7 @@ init(_) -> {ok, []}. handle_event({set_alarm, {AlarmId, AlarmDesc = #alarm{timestamp = undefined}}}, State) -> - handle_event({set_alarm, {AlarmId, AlarmDesc#alarm{timestamp = erlang:system_time(millisecond)}}}, State); + handle_event({set_alarm, {AlarmId, AlarmDesc#alarm{timestamp = erlang:system_time(second)}}}, State); handle_event({set_alarm, Alarm = {AlarmId, AlarmDesc}}, State) -> ?LOG(warning, "New Alarm: ~p, Alarm Info: ~p", [AlarmId, AlarmDesc]), case encode_alarm(Alarm) of @@ -114,7 +114,7 @@ handle_event({set_alarm, Alarm = {AlarmId, AlarmDesc}}, State) -> {error, Reason} -> ?LOG(error, "Failed to encode alarm: ~p", [Reason]) end, - set_alarm_(AlarmId, AlarmDesc), + set_alarm_(AlarmId, AlarmDesc, erlang:system_time(second)), {ok, State}; handle_event({clear_alarm, AlarmId}, State) -> ?LOG(info, "Clear Alarm: ~p", [AlarmId]), @@ -164,10 +164,12 @@ encode_alarm({AlarmId, #alarm{severity = Severity, }); encode_alarm({AlarmId, undefined}) -> - emqx_json:safe_encode(#{id => maybe_to_binary(AlarmId)}); + emqx_json:safe_encode(#{id => maybe_to_binary(AlarmId), + desc => #{timestamp => erlang:system_time(second)}}); encode_alarm({AlarmId, AlarmDesc}) -> emqx_json:safe_encode(#{id => maybe_to_binary(AlarmId), - desc => maybe_to_binary(AlarmDesc) + desc => #{summary => maybe_to_binary(AlarmDesc), + timestamp => erlang:system_time(second)} }). alarm_msg(Topic, Payload) -> @@ -185,8 +187,8 @@ maybe_to_binary(Data) when is_binary(Data) -> maybe_to_binary(Data) -> iolist_to_binary(io_lib:format("~p", [Data])). -set_alarm_(Id, Desc) -> - mnesia:dirty_write(?ALARM_TAB, #common_alarm{id = Id, desc = Desc}). +set_alarm_(Id, Desc, Ts) -> + mnesia:dirty_write(?ALARM_TAB, #common_alarm{id = Id, desc = {Desc, Ts}}). clear_alarm_(Id) -> case mnesia:dirty_read(?ALARM_TAB, Id) of @@ -199,5 +201,5 @@ clear_alarm_(Id) -> set_alarm_history(Id, Desc) -> His = #alarm_history{id = Id, desc = Desc, - clear_at = erlang:system_time(millisecond)}, - mnesia:dirty_write(?ALARM_HISTORY_TAB, His). + clear_at = erlang:system_time(second)}, + mnesia:dirty_write(?ALARM_HISTORY_TAB, His). \ No newline at end of file diff --git a/src/emqx_vm.erl b/src/emqx_vm.erl index b4a36f410..52f3a8e37 100644 --- a/src/emqx_vm.erl +++ b/src/emqx_vm.erl @@ -22,6 +22,7 @@ , get_system_info/0 , get_system_info/1 , get_memory/0 + , get_memory/2 , mem_info/0 , loads/0 ]). @@ -241,32 +242,47 @@ scheduler_usage_diff(First, Last) -> end, lists:zip(lists:sort(First), lists:sort(Last))). get_memory()-> - [{Key, get_memory(Key, current)} || Key <- [used, allocated, unused, usage]] ++ erlang:memory(). + get_memory_once(current) ++ erlang:memory(). + +get_memory(Ks, Keyword) when is_list(Ks) -> + Ms = get_memory_once(Keyword) ++ erlang:memory(), + [M || M = {K, _} <- Ms, lists:member(K, Ks)]; get_memory(used, Keyword) -> lists:sum(lists:map(fun({_, Prop}) -> container_size(Prop, Keyword, blocks_size) end, util_alloc())); + get_memory(allocated, Keyword) -> - lists:sum(lists:map(fun({_, Prop})-> + lists:sum(lists:map(fun({_, Prop}) -> container_size(Prop, Keyword, carriers_size) end, util_alloc())); + get_memory(unused, Keyword) -> - get_memory(allocated, Keyword) - get_memory(used, Keyword); + Ms = get_memory_once(Keyword), + proplists:get_value(allocated, Ms) - proplists:get_value(used, Ms); + get_memory(usage, Keyword) -> - get_memory(used, Keyword) / get_memory(allocated, Keyword). + Ms = get_memory_once(Keyword), + proplists:get_value(used, Ms) / proplists:get_value(allocated, Ms). + +%% @private A more quickly function to calculate memory +get_memory_once(Keyword) -> + Calc = fun({_, Prop}, {N1, N2}) -> + {N1 + container_size(Prop, Keyword, blocks_size), + N2 + container_size(Prop, Keyword, carriers_size)} + end, + {Used, Allocated} = lists:foldl(Calc, {0, 0}, util_alloc()), + [{used, Used}, + {allocated, Allocated}, + {unused, Allocated - Used}, + {usage, Used / Allocated}]. util_alloc()-> alloc(?UTIL_ALLOCATORS). -alloc()-> - {_Mem, Allocs} = snapshot_int(), - Allocs. alloc(Type) -> - [{{T, Instance}, Props} || {{T, Instance}, Props} <- alloc(), lists:member(T, Type)]. - -snapshot_int() -> - {erlang:memory(), allocators()}. + [{{T, Instance}, Props} || {{T, Instance}, Props} <- allocators(), lists:member(T, Type)]. allocators() -> UtilAllocators = erlang:system_info(alloc_util_allocators),