feat(gateway): export basic gateway info for telemetry

This commit is contained in:
Thales Macedo Garitezi 2022-03-30 17:53:28 -03:00
parent b1902cff27
commit 7d807ce6bb
No known key found for this signature in database
GPG Key ID: DD279F8152A9B6DD
8 changed files with 232 additions and 5 deletions

View File

@ -30,6 +30,9 @@
list/0 list/0
]). ]).
%% APIs For `emqx_telemetry'
-export([get_basic_usage_info/0]).
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% APIs %% APIs
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
@ -81,6 +84,66 @@ start(Name) ->
stop(Name) -> stop(Name) ->
emqx_gateway_sup:stop_gateway_insta(Name). emqx_gateway_sup:stop_gateway_insta(Name).
%% @doc Expose basic info for `emqx_telemetry'.
-spec get_basic_usage_info() ->
#{
authn => Authn,
num_clients => non_neg_integer(),
listeners => [
#{
type => atom(),
authn => Authn
}
]
}
when
Authn :: binary().
get_basic_usage_info() ->
lists:foldl(
fun(GatewayInfo, Acc) ->
Config = maps:get(config, GatewayInfo, #{}),
GatewayType = maps:get(name, GatewayInfo),
GatewayAuthn = get_authn_type(Config),
Listeners = get_listeners(Config),
TabName = emqx_gateway_cm:tabname(chan, GatewayType),
NumClients = ets:info(TabName, size),
Acc#{
GatewayType => #{
authn => GatewayAuthn,
listeners => Listeners,
num_clients => NumClients
}
}
end,
#{},
list()
).
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% Internal funcs %% Internal funcs
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
get_authn_type(#{authentication := #{mechanism := Mechanism, backend := Backend}}) when
is_atom(Mechanism), is_atom(Backend)
->
MechanismBin = atom_to_binary(Mechanism),
BackendBin = atom_to_binary(Backend),
<<MechanismBin/binary, ":", BackendBin/binary>>;
get_authn_type(_) ->
<<"undefined">>.
get_listeners(#{listeners := Listeners0}) when is_map(Listeners0) ->
Listeners = [
{ListenerType, Config}
|| {ListenerType, Listeners1} <- maps:to_list(Listeners0),
{_Name, Config} <- maps:to_list(Listeners1)
],
lists:map(
fun({ListenerType, ListenerConfig}) ->
ListenerAuthn = get_authn_type(ListenerConfig),
#{type => ListenerType, authn => ListenerAuthn}
end,
Listeners
);
get_listeners(_) ->
[].

View File

@ -17,6 +17,7 @@
-module(emqx_gateway_SUITE). -module(emqx_gateway_SUITE).
-include_lib("eunit/include/eunit.hrl"). -include_lib("eunit/include/eunit.hrl").
-include_lib("common_test/include/ct.hrl").
-compile(export_all). -compile(export_all).
-compile(nowarn_export_all). -compile(nowarn_export_all).
@ -37,7 +38,26 @@ init_per_suite(Conf) ->
Conf. Conf.
end_per_suite(_Conf) -> end_per_suite(_Conf) ->
emqx_common_test_helpers:stop_apps([emqx_gateway]). emqx_common_test_helpers:stop_apps([emqx_gateway, emqx_authn]),
emqx_config:delete_override_conf_files(),
ok.
init_per_testcase(t_get_basic_usage_info_2, Config) ->
DataDir = ?config(data_dir, Config),
emqx_common_test_helpers:stop_apps([emqx_gateway]),
ok = setup_fake_usage_data(DataDir),
Config;
init_per_testcase(_TestCase, Config) ->
Config.
end_per_testcase(t_get_basic_usage_info_2, _Config) ->
emqx_gateway_cm:unregister_channel(lwm2m, <<"client_id">>),
emqx_config:put([gateway], #{}),
emqx_common_test_helpers:stop_apps([emqx_gateway]),
emqx_common_test_helpers:start_apps([emqx_gateway]),
ok;
end_per_testcase(_TestCase, _Config) ->
ok.
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% cases %% cases
@ -114,3 +134,64 @@ t_start_stop_update(_) ->
{error, already_started} = emqx_gateway:start(?GWNAME), {error, already_started} = emqx_gateway:start(?GWNAME),
ok. ok.
t_get_basic_usage_info_empty(_Config) ->
?assertEqual(
#{},
emqx_gateway:get_basic_usage_info()
).
t_get_basic_usage_info_1(_Config) ->
{ok, _} = emqx_gateway:load(?GWNAME, #{idle_timeout => 1000}),
?assertEqual(
#{
mqttsn =>
#{
authn => <<"undefined">>,
listeners => [],
num_clients => 0
}
},
emqx_gateway:get_basic_usage_info()
).
t_get_basic_usage_info_2(_Config) ->
?assertEqual(
#{
lwm2m =>
#{
authn => <<"password_based:redis">>,
listeners =>
[
#{
authn =>
<<"password_based:built_in_database">>,
type => udp
}
],
num_clients => 1
}
},
emqx_gateway:get_basic_usage_info()
).
%%--------------------------------------------------------------------
%% helper functions
%%--------------------------------------------------------------------
read_lwm2m_conf(DataDir) ->
ConfPath = filename:join([DataDir, "lwm2m.conf"]),
{ok, Conf} = file:read_file(ConfPath),
Conf.
setup_fake_usage_data(Lwm2mDataDir) ->
XmlDir = emqx_common_test_helpers:deps_path(emqx_gateway, "src/lwm2m/lwm2m_xml"),
Lwm2mConf = read_lwm2m_conf(Lwm2mDataDir),
ok = emqx_common_test_helpers:load_config(emqx_gateway_schema, Lwm2mConf),
emqx_config:put([gateway, lwm2m, xml_dir], XmlDir),
{ok, _} = application:ensure_all_started(emqx_gateway),
%% to simulate a connection
FakeConnInfo = #{conn_mod => fake_conn_mod},
FakeChanPid = self(),
ok = emqx_gateway_cm:register_channel(lwm2m, <<"client_id">>, FakeChanPid, FakeConnInfo),
ok.

View File

@ -0,0 +1,76 @@
gateway.lwm2m {
## How long time the connection will be disconnected if the
## connection is established but no bytes received
idle_timeout = 30s
## To control whether write statistics data into ETS table
## for dashboard to read.
enable_stats = true
## When publishing or subscribing, prefix all topics with a mountpoint string.
mountpoint = "lwm2m/${username}"
xml_dir = "etc/lwm2m_xml"
##
##
lifetime_min = 1s
lifetime_max = 86400s
qmode_time_window = 22s
auto_observe = false
## always | contains_object_list
update_msg_publish_condition = contains_object_list
translators {
command {
topic = "/dn/#"
qos = 0
}
response {
topic = "/up/resp"
qos = 0
}
notify {
topic = "/up/notify"
qos = 0
}
register {
topic = "/up/resp"
qos = 0
}
update {
topic = "/up/resp"
qos = 0
}
}
listeners.udp.default {
bind = 5783
authentication: {
mechanism: password_based,
backend: built_in_database
}
}
authentication {
mechanism: password_based,
backend: redis,
redis_type: single,
server: "localhost:6379",
cmd: "HMGET mqtt_user:${username} password_hash salt is_superuser",
password_hash_algorithm: {
name: plain,
salt_position: suffix
}
}
}

View File

@ -42,6 +42,8 @@
all() -> emqx_common_test_helpers:all(?MODULE). all() -> emqx_common_test_helpers:all(?MODULE).
init_per_suite(Conf) -> init_per_suite(Conf) ->
application:load(emqx),
emqx_config:delete_override_conf_files(),
emqx_config:erase(gateway), emqx_config:erase(gateway),
emqx_common_test_helpers:load_config(emqx_gateway_schema, ?CONF_DEFAULT), emqx_common_test_helpers:load_config(emqx_gateway_schema, ?CONF_DEFAULT),
emqx_mgmt_api_test_util:init_suite([emqx_conf, emqx_authn, emqx_gateway]), emqx_mgmt_api_test_util:init_suite([emqx_conf, emqx_authn, emqx_gateway]),

View File

@ -43,7 +43,8 @@ init_per_suite(Conf) ->
end_per_suite(_Conf) -> end_per_suite(_Conf) ->
meck:unload(emqx_gateway_metrics), meck:unload(emqx_gateway_metrics),
emqx_common_test_helpers:stop_apps([]). emqx_common_test_helpers:stop_apps([]),
emqx_config:delete_override_conf_files().
init_per_testcase(_TestCase, Conf) -> init_per_testcase(_TestCase, Conf) ->
process_flag(trap_exit, true), process_flag(trap_exit, true),

View File

@ -39,7 +39,8 @@ init_per_suite(Conf) ->
Conf. Conf.
end_per_suite(_Conf) -> end_per_suite(_Conf) ->
emqx_common_test_helpers:stop_apps([]). emqx_common_test_helpers:stop_apps([]),
emqx_config:delete_override_conf_files().
init_per_testcase(_TestCase, Conf) -> init_per_testcase(_TestCase, Conf) ->
{ok, Pid} = emqx_gateway_cm_registry:start_link(?GWNAME), {ok, Pid} = emqx_gateway_cm_registry:start_link(?GWNAME),

View File

@ -42,7 +42,8 @@ init_per_suite(Conf) ->
Conf. Conf.
end_per_suite(_Conf) -> end_per_suite(_Conf) ->
emqx_common_test_helpers:stop_apps([emqx_gateway, emqx_authn, emqx_conf]). emqx_common_test_helpers:stop_apps([emqx_gateway, emqx_authn, emqx_conf]),
emqx_config:delete_override_conf_files().
init_per_testcase(_CaseName, Conf) -> init_per_testcase(_CaseName, Conf) ->
_ = emqx_gateway_conf:unload_gateway(stomp), _ = emqx_gateway_conf:unload_gateway(stomp),

View File

@ -34,7 +34,9 @@ end_suite() ->
end_suite(Apps) -> end_suite(Apps) ->
application:unload(emqx_management), application:unload(emqx_management),
emqx_common_test_helpers:stop_apps(Apps ++ [emqx_dashboard]). emqx_common_test_helpers:stop_apps(Apps ++ [emqx_dashboard]),
emqx_config:delete_override_conf_files(),
ok.
set_special_configs(emqx_dashboard) -> set_special_configs(emqx_dashboard) ->
Config = #{ Config = #{