Merge pull request #6379 from JimMoen/v4.3/fix-vm-mem-info
fix(vm): memory info calc and display
This commit is contained in:
commit
72a7f353c6
|
@ -1,6 +1,6 @@
|
||||||
{application, emqx_management,
|
{application, emqx_management,
|
||||||
[{description, "EMQ X Management API and CLI"},
|
[{description, "EMQ X Management API and CLI"},
|
||||||
{vsn, "4.3.8"}, % strict semver, bump manually!
|
{vsn, "4.3.9"}, % strict semver, bump manually!
|
||||||
{modules, []},
|
{modules, []},
|
||||||
{registered, [emqx_management_sup]},
|
{registered, [emqx_management_sup]},
|
||||||
{applications, [kernel,stdlib,minirest]},
|
{applications, [kernel,stdlib,minirest]},
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
%% -*- mode: erlang -*-
|
%% -*- mode: erlang -*-
|
||||||
{VSN,
|
{VSN,
|
||||||
[ {<<"4\\.3\\.[0-7]+">>,
|
[ {<<"4\\.3\\.[0-8]+">>,
|
||||||
[ {apply,{minirest,stop_http,['http:management']}},
|
[ {apply,{minirest,stop_http,['http:management']}},
|
||||||
{apply,{minirest,stop_http,['https:management']}},
|
{apply,{minirest,stop_http,['https:management']}},
|
||||||
{restart_application, emqx_management}
|
{restart_application, emqx_management}
|
||||||
]},
|
]},
|
||||||
{<<".*">>, []}
|
{<<".*">>, []}
|
||||||
],
|
],
|
||||||
[ {<<"4\\.3\\.[0-7]+">>,
|
[ {<<"4\\.3\\.[0-8]+">>,
|
||||||
[ {apply,{minirest,stop_http,['http:management']}},
|
[ {apply,{minirest,stop_http,['http:management']}},
|
||||||
{apply,{minirest,stop_http,['https:management']}},
|
{apply,{minirest,stop_http,['https:management']}},
|
||||||
{restart_application, emqx_management}
|
{restart_application, emqx_management}
|
||||||
|
|
|
@ -120,6 +120,7 @@
|
||||||
|
|
||||||
-define(APP, emqx_management).
|
-define(APP, emqx_management).
|
||||||
|
|
||||||
|
-elvis([{elvis_style, god_modules, disable}]).
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
%% Node Info
|
%% Node Info
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
|
@ -139,10 +140,12 @@ node_info(Node) when Node =:= node() ->
|
||||||
Info#{node => node(),
|
Info#{node => node(),
|
||||||
otp_release => iolist_to_binary(otp_rel()),
|
otp_release => iolist_to_binary(otp_rel()),
|
||||||
memory_total => proplists:get_value(allocated, Memory),
|
memory_total => proplists:get_value(allocated, Memory),
|
||||||
memory_used => proplists:get_value(total, Memory),
|
memory_used => proplists:get_value(used, Memory),
|
||||||
process_available => erlang:system_info(process_limit),
|
process_available => erlang:system_info(process_limit),
|
||||||
process_used => erlang:system_info(process_count),
|
process_used => erlang:system_info(process_count),
|
||||||
max_fds => proplists:get_value(max_fds, lists:usort(lists:flatten(erlang:system_info(check_io)))),
|
max_fds =>
|
||||||
|
proplists:get_value( max_fds
|
||||||
|
, lists:usort(lists:flatten(erlang:system_info(check_io)))),
|
||||||
connections => ets:info(emqx_channel, size),
|
connections => ets:info(emqx_channel, size),
|
||||||
node_status => 'Running',
|
node_status => 'Running',
|
||||||
uptime => iolist_to_binary(proplists:get_value(uptime, BrokerInfo)),
|
uptime => iolist_to_binary(proplists:get_value(uptime, BrokerInfo)),
|
||||||
|
@ -196,10 +199,12 @@ get_stats(Node) ->
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
|
|
||||||
lookup_client({clientid, ClientId}, FormatFun) ->
|
lookup_client({clientid, ClientId}, FormatFun) ->
|
||||||
lists:append([lookup_client(Node, {clientid, ClientId}, FormatFun) || Node <- ekka_mnesia:running_nodes()]);
|
lists:append([lookup_client(Node, {clientid, ClientId}, FormatFun)
|
||||||
|
|| Node <- ekka_mnesia:running_nodes()]);
|
||||||
|
|
||||||
lookup_client({username, Username}, FormatFun) ->
|
lookup_client({username, Username}, FormatFun) ->
|
||||||
lists:append([lookup_client(Node, {username, Username}, FormatFun) || Node <- ekka_mnesia:running_nodes()]).
|
lists:append([lookup_client(Node, {username, Username}, FormatFun)
|
||||||
|
|| Node <- ekka_mnesia:running_nodes()]).
|
||||||
|
|
||||||
lookup_client(Node, {clientid, ClientId}, {M,F}) when Node =:= node() ->
|
lookup_client(Node, {clientid, ClientId}, {M,F}) when Node =:= node() ->
|
||||||
lists:append(lists:map(
|
lists:append(lists:map(
|
||||||
|
@ -222,10 +227,7 @@ lookup_client(Node, {username, Username}, FormatFun) ->
|
||||||
|
|
||||||
kickout_client(ClientId) ->
|
kickout_client(ClientId) ->
|
||||||
Results = [kickout_client(Node, ClientId) || Node <- ekka_mnesia:running_nodes()],
|
Results = [kickout_client(Node, ClientId) || Node <- ekka_mnesia:running_nodes()],
|
||||||
case lists:any(fun(Item) -> Item =:= ok end, Results) of
|
check_every_ok(Results).
|
||||||
true -> ok;
|
|
||||||
false -> lists:last(Results)
|
|
||||||
end.
|
|
||||||
|
|
||||||
kickout_client(Node, ClientId) when Node =:= node() ->
|
kickout_client(Node, ClientId) when Node =:= node() ->
|
||||||
emqx_cm:kick_session(ClientId);
|
emqx_cm:kick_session(ClientId);
|
||||||
|
@ -238,10 +240,7 @@ list_acl_cache(ClientId) ->
|
||||||
|
|
||||||
clean_acl_cache(ClientId) ->
|
clean_acl_cache(ClientId) ->
|
||||||
Results = [clean_acl_cache(Node, ClientId) || Node <- ekka_mnesia:running_nodes()],
|
Results = [clean_acl_cache(Node, ClientId) || Node <- ekka_mnesia:running_nodes()],
|
||||||
case lists:any(fun(Item) -> Item =:= ok end, Results) of
|
check_every_ok(Results).
|
||||||
true -> ok;
|
|
||||||
false -> lists:last(Results)
|
|
||||||
end.
|
|
||||||
|
|
||||||
clean_acl_cache(Node, ClientId) when Node =:= node() ->
|
clean_acl_cache(Node, ClientId) when Node =:= node() ->
|
||||||
case emqx_cm:lookup_channels(ClientId) of
|
case emqx_cm:lookup_channels(ClientId) of
|
||||||
|
@ -281,7 +280,7 @@ call_client(ClientId, Req) ->
|
||||||
end, Results),
|
end, Results),
|
||||||
case Expected of
|
case Expected of
|
||||||
[] -> {error, not_found};
|
[] -> {error, not_found};
|
||||||
[Result|_] -> Result
|
[Result | _] -> Result
|
||||||
end.
|
end.
|
||||||
|
|
||||||
%% @private
|
%% @private
|
||||||
|
@ -292,7 +291,7 @@ call_client(Node, ClientId, Req) when Node =:= node() ->
|
||||||
Pid = lists:last(Pids),
|
Pid = lists:last(Pids),
|
||||||
case emqx_cm:get_chan_info(ClientId, Pid) of
|
case emqx_cm:get_chan_info(ClientId, Pid) of
|
||||||
#{conninfo := #{conn_mod := ConnMod}} ->
|
#{conninfo := #{conn_mod := ConnMod}} ->
|
||||||
ConnMod:call(Pid, Req);
|
erlang:apply(ConnMod, call, [Pid, Req]);
|
||||||
undefined -> {error, not_found}
|
undefined -> {error, not_found}
|
||||||
end
|
end
|
||||||
end;
|
end;
|
||||||
|
@ -313,11 +312,12 @@ list_subscriptions(Node) ->
|
||||||
rpc_call(Node, list_subscriptions, [Node]).
|
rpc_call(Node, list_subscriptions, [Node]).
|
||||||
|
|
||||||
list_subscriptions_via_topic(Topic, FormatFun) ->
|
list_subscriptions_via_topic(Topic, FormatFun) ->
|
||||||
lists:append([list_subscriptions_via_topic(Node, Topic, FormatFun) || Node <- ekka_mnesia:running_nodes()]).
|
lists:append([list_subscriptions_via_topic(Node, Topic, FormatFun)
|
||||||
|
|| Node <- ekka_mnesia:running_nodes()]).
|
||||||
|
|
||||||
list_subscriptions_via_topic(Node, Topic, {M,F}) when Node =:= node() ->
|
list_subscriptions_via_topic(Node, Topic, {M,F}) when Node =:= node() ->
|
||||||
MatchSpec = [{{{'_', '$1'}, '_'}, [{'=:=','$1', Topic}], ['$_']}],
|
MatchSpec = [{{{'_', '$1'}, '_'}, [{'=:=','$1', Topic}], ['$_']}],
|
||||||
M:F(ets:select(emqx_suboption, MatchSpec));
|
erlang:apply(M, F, [ets:select(emqx_suboption, MatchSpec)]);
|
||||||
|
|
||||||
list_subscriptions_via_topic(Node, Topic, FormatFun) ->
|
list_subscriptions_via_topic(Node, Topic, FormatFun) ->
|
||||||
rpc_call(Node, list_subscriptions_via_topic, [Node, Topic, FormatFun]).
|
rpc_call(Node, list_subscriptions_via_topic, [Node, Topic, FormatFun]).
|
||||||
|
@ -436,7 +436,8 @@ list_listeners(Node) when Node =:= node() ->
|
||||||
Http = lists:map(fun({Protocol, Opts}) ->
|
Http = lists:map(fun({Protocol, Opts}) ->
|
||||||
#{protocol => Protocol,
|
#{protocol => Protocol,
|
||||||
listen_on => proplists:get_value(port, Opts),
|
listen_on => proplists:get_value(port, Opts),
|
||||||
acceptors => maps:get(num_acceptors, proplists:get_value(transport_options, Opts, #{}), 0),
|
acceptors => maps:get( num_acceptors
|
||||||
|
, proplists:get_value(transport_options, Opts, #{}), 0),
|
||||||
max_conns => proplists:get_value(max_connections, Opts),
|
max_conns => proplists:get_value(max_connections, Opts),
|
||||||
current_conns => proplists:get_value(all_connections, Opts),
|
current_conns => proplists:get_value(all_connections, Opts),
|
||||||
shutdown_count => []}
|
shutdown_count => []}
|
||||||
|
@ -483,9 +484,12 @@ add_duration_field(Alarms) ->
|
||||||
|
|
||||||
add_duration_field([], _Now, Acc) ->
|
add_duration_field([], _Now, Acc) ->
|
||||||
Acc;
|
Acc;
|
||||||
add_duration_field([Alarm = #{activated := true, activate_at := ActivateAt}| Rest], Now, Acc) ->
|
add_duration_field([Alarm = #{activated := true, activate_at := ActivateAt} | Rest], Now, Acc) ->
|
||||||
add_duration_field(Rest, Now, [Alarm#{duration => Now - ActivateAt} | Acc]);
|
add_duration_field(Rest, Now, [Alarm#{duration => Now - ActivateAt} | Acc]);
|
||||||
add_duration_field([Alarm = #{activated := false, activate_at := ActivateAt, deactivate_at := DeactivateAt}| Rest], Now, Acc) ->
|
add_duration_field([Alarm = #{ activated := false
|
||||||
|
, activate_at := ActivateAt
|
||||||
|
, deactivate_at := DeactivateAt}
|
||||||
|
| Rest], Now, Acc) ->
|
||||||
add_duration_field(Rest, Now, [Alarm#{duration => DeactivateAt - ActivateAt} | Acc]).
|
add_duration_field(Rest, Now, [Alarm#{duration => DeactivateAt - ActivateAt} | Acc]).
|
||||||
|
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
|
@ -560,15 +564,19 @@ check_row_limit(Tables) ->
|
||||||
|
|
||||||
check_row_limit([], _Limit) ->
|
check_row_limit([], _Limit) ->
|
||||||
ok;
|
ok;
|
||||||
check_row_limit([Tab|Tables], Limit) ->
|
check_row_limit([Tab | Tables], Limit) ->
|
||||||
case table_size(Tab) > Limit of
|
case table_size(Tab) > Limit of
|
||||||
true -> false;
|
true -> false;
|
||||||
false -> check_row_limit(Tables, Limit)
|
false -> check_row_limit(Tables, Limit)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
check_every_ok(Results) ->
|
||||||
|
case lists:any(fun(Item) -> Item =:= ok end, Results) of
|
||||||
|
true -> ok;
|
||||||
|
false -> lists:last(Results)
|
||||||
|
end.
|
||||||
|
|
||||||
max_row_limit() ->
|
max_row_limit() ->
|
||||||
application:get_env(?APP, max_row_limit, ?MAX_ROW_LIMIT).
|
application:get_env(?APP, max_row_limit, ?MAX_ROW_LIMIT).
|
||||||
|
|
||||||
table_size(Tab) -> ets:info(Tab, size).
|
table_size(Tab) -> ets:info(Tab, size).
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,7 @@
|
||||||
sl_alloc,
|
sl_alloc,
|
||||||
ll_alloc,
|
ll_alloc,
|
||||||
fix_alloc,
|
fix_alloc,
|
||||||
|
literal_alloc,
|
||||||
std_alloc
|
std_alloc
|
||||||
]).
|
]).
|
||||||
|
|
||||||
|
@ -317,7 +318,8 @@ get_process_gc_info(Pid) when is_pid(Pid) ->
|
||||||
process_info(Pid, ?PROCESS_GC_KEYS).
|
process_info(Pid, ?PROCESS_GC_KEYS).
|
||||||
|
|
||||||
get_process_group_leader_info(LeaderPid) when is_pid(LeaderPid) ->
|
get_process_group_leader_info(LeaderPid) when is_pid(LeaderPid) ->
|
||||||
[{Key, Value}|| {Key, Value} <- process_info(LeaderPid), lists:member(Key, ?PROCESS_INFO_KEYS)].
|
[{Key, Value}
|
||||||
|
|| {Key, Value} <- process_info(LeaderPid), lists:member(Key, ?PROCESS_INFO_KEYS)].
|
||||||
|
|
||||||
get_process_limit() ->
|
get_process_limit() ->
|
||||||
erlang:system_info(process_limit).
|
erlang:system_info(process_limit).
|
||||||
|
@ -339,12 +341,12 @@ get_ets_info(Tab) ->
|
||||||
mapping(Entries) ->
|
mapping(Entries) ->
|
||||||
mapping(Entries, []).
|
mapping(Entries, []).
|
||||||
mapping([], Acc) -> Acc;
|
mapping([], Acc) -> Acc;
|
||||||
mapping([{owner, V}|Entries], Acc) when is_pid(V) ->
|
mapping([{owner, V} | Entries], Acc) when is_pid(V) ->
|
||||||
OwnerInfo = process_info(V),
|
OwnerInfo = process_info(V),
|
||||||
Owner = proplists:get_value(registered_name, OwnerInfo, undefined),
|
Owner = proplists:get_value(registered_name, OwnerInfo, undefined),
|
||||||
mapping(Entries, [{owner, Owner}|Acc]);
|
mapping(Entries, [{owner, Owner} | Acc]);
|
||||||
mapping([{Key, Value}|Entries], Acc) ->
|
mapping([{Key, Value} | Entries], Acc) ->
|
||||||
mapping(Entries, [{Key, Value}|Acc]).
|
mapping(Entries, [{Key, Value} | Acc]).
|
||||||
|
|
||||||
avg1() ->
|
avg1() ->
|
||||||
compat_windows(fun cpu_sup:avg1/0).
|
compat_windows(fun cpu_sup:avg1/0).
|
||||||
|
|
Loading…
Reference in New Issue