diff --git a/apps/emqx/src/config/emqx_config_logger.erl b/apps/emqx/src/config/emqx_config_logger.erl
index bc284732b..fca6ebc43 100644
--- a/apps/emqx/src/config/emqx_config_logger.erl
+++ b/apps/emqx/src/config/emqx_config_logger.erl
@@ -31,14 +31,12 @@ remove_handler() ->
ok = emqx_config_handler:remove_handler(?LOG),
ok.
-post_config_update(?LOG, _Req, NewConf, _OldConf, _AppEnvs) ->
- NewLog = #{log => NewConf},
- [{"logger_level", LevelFunc}, {"logger", LoggerFunc}] =
- emqx_conf_schema:translation("kernel"),
- NewHandlers = LoggerFunc(NewLog),
- Level = LevelFunc(NewLog),
+post_config_update(?LOG, _Req, _NewConf, _OldConf, AppEnvs) ->
+ Kernel = proplists:get_value(kernel, AppEnvs),
+ NewHandlers = proplists:get_value(logger, Kernel, []),
+ Level = proplists:get_value(logger_level, Kernel, warning),
ok = update_log_handlers(NewHandlers),
- ok = logger:set_primary_config(level, Level),
+ ok = emqx_logger:set_primary_log_level(Level),
application:set_env(kernel, logger_level, Level),
ok;
post_config_update(_ConfPath, _Req, _NewConf, _OldConf, _AppEnvs) ->
diff --git a/apps/emqx/src/emqx_config_handler.erl b/apps/emqx/src/emqx_config_handler.erl
index 750f89dd2..0282e5f8e 100644
--- a/apps/emqx/src/emqx_config_handler.erl
+++ b/apps/emqx/src/emqx_config_handler.erl
@@ -396,14 +396,29 @@ assert_callback_function(Mod) ->
end,
ok.
+-spec schema(module(), emqx_map_lib:config_key_path()) -> hocon_schema:schema().
schema(SchemaModule, [RootKey | _]) ->
Roots = hocon_schema:roots(SchemaModule),
- Field =
+ {Field, Translations} =
case lists:keyfind(bin(RootKey), 1, Roots) of
{_, {Ref, ?REF(Ref)}} -> {Ref, ?R_REF(SchemaModule, Ref)};
- {_, Field0} -> Field0
+ {_, {Name, Field0}} ->
+ case maps:take(translate_to, Field0) of
+ {TRs, Field1} ->
+ {
+ {Name, Field1},
+ lists:foldl(fun(T, Acc) ->
+ Acc#{T => hocon_schema:translation(SchemaModule, T)}
+ end, #{}, TRs)
+ };
+ error -> {{Name, Field0}, #{}}
+ end
end,
- #{roots => [Field]}.
+ #{
+ roots => [Field],
+ translations => Translations,
+ validations => hocon_schema:validations(SchemaModule)
+ }.
load_prev_handlers() ->
Handlers = application:get_env(emqx, ?MODULE, #{}),
diff --git a/apps/emqx/src/emqx_flapping.erl b/apps/emqx/src/emqx_flapping.erl
index f4b05b7ff..c69208c22 100644
--- a/apps/emqx/src/emqx_flapping.erl
+++ b/apps/emqx/src/emqx_flapping.erl
@@ -149,7 +149,7 @@ handle_info({timeout, _TRef, {garbage_collect, Zone}}, State) ->
- maps:get(window_time, get_policy(Zone)),
MatchSpec = [{{'_', '_', '_', '$1', '_'},[{'<', '$1', Timestamp}], [true]}],
ets:select_delete(?FLAPPING_TAB, MatchSpec),
- start_timer(Zone),
+ _ = start_timer(Zone),
{noreply, State, hibernate};
handle_info(Info, State) ->
diff --git a/apps/emqx/src/emqx_vm_mon.erl b/apps/emqx/src/emqx_vm_mon.erl
index 18005dce5..e763c7bfb 100644
--- a/apps/emqx/src/emqx_vm_mon.erl
+++ b/apps/emqx/src/emqx_vm_mon.erl
@@ -45,7 +45,7 @@ start_link() ->
%%--------------------------------------------------------------------
init([]) ->
- start_check_timer(),
+ _ = start_check_timer(),
{ok, #{}}.
handle_call(Req, _From, State) ->
@@ -82,7 +82,7 @@ handle_info({timeout, _Timer, check}, State) ->
_Precent ->
ok
end,
- start_check_timer(),
+ _ = start_check_timer(),
{noreply, State};
handle_info(Info, State) ->
diff --git a/apps/emqx_conf/src/emqx_conf_schema.erl b/apps/emqx_conf/src/emqx_conf_schema.erl
index e9cca65a5..b0d467e34 100644
--- a/apps/emqx_conf/src/emqx_conf_schema.erl
+++ b/apps/emqx_conf/src/emqx_conf_schema.erl
@@ -75,17 +75,20 @@ roots() ->
sc(ref("node"),
#{ desc => "Node name, cookie, config & data directories "
"and the Erlang virtual machine (BEAM) boot parameters."
+ , translate_to => ["emqx"]
})}
, {"cluster",
sc(ref("cluster"),
#{ desc => "EMQX nodes can form a cluster to scale up the total capacity.
"
"Here holds the configs to instruct how individual nodes "
"can discover each other."
+ , translate_to => ["ekka"]
})}
, {"log",
sc(ref("log"),
#{ desc => "Configure logging backends (to console or to file), "
"and logging level for each logger backend."
+ , translate_to => ["kernel"]
})}
, {"rpc",
sc(ref("rpc"),
@@ -93,6 +96,7 @@ roots() ->
"inter-broker communication.
Most of the time the default config "
"should work, but in case you need to do performance "
"fine-turning or experiment a bit, this is where to look."
+ , translate_to => ["gen_rpc"]
})}
, {"db",
sc(ref("db"),
@@ -737,6 +741,7 @@ tr_cluster_discovery(Conf) ->
Strategy = conf_get("cluster.discovery_strategy", Conf),
{Strategy, filter(options(Strategy, Conf))}.
+-spec tr_logger_level(hocon:config()) -> logger:level().
tr_logger_level(Conf) ->
ConsoleLevel = conf_get("log.console_handler.level", Conf, undefined),
FileLevels = [conf_get("level", SubConf) || {_, SubConf}
diff --git a/apps/emqx_management/test/emqx_mgmt_api_configs_SUITE.erl b/apps/emqx_management/test/emqx_mgmt_api_configs_SUITE.erl
index dc944c9e7..77fae29be 100644
--- a/apps/emqx_management/test/emqx_mgmt_api_configs_SUITE.erl
+++ b/apps/emqx_management/test/emqx_mgmt_api_configs_SUITE.erl
@@ -71,11 +71,30 @@ t_update(_Config) ->
t_log(_Config) ->
{ok, Log} = get_config("log"),
File = "log/emqx-test.log",
+ %% update handler
Log1 = emqx_map_lib:deep_put([<<"file_handlers">>, <<"default">>, <<"enable">>], Log, true),
Log2 = emqx_map_lib:deep_put([<<"file_handlers">>, <<"default">>, <<"file">>], Log1, File),
{ok, #{}} = update_config(<<"log">>, Log2),
{ok, Log3} = logger:get_handler_config(default),
?assertMatch(#{config := #{file := File}}, Log3),
+ ErrLog1 = emqx_map_lib:deep_put([<<"file_handlers">>, <<"default">>, <<"enable">>], Log, 1),
+ ?assertMatch({error, {"HTTP/1.1", 400, _}}, update_config(<<"log">>, ErrLog1)),
+ ErrLog2 = emqx_map_lib:deep_put([<<"file_handlers">>, <<"default">>, <<"enabfe">>], Log, true),
+ ?assertMatch({error, {"HTTP/1.1", 400, _}}, update_config(<<"log">>, ErrLog2)),
+
+ %% add new handler
+ File1 = "log/emqx-test1.log",
+ Handler = emqx_map_lib:deep_get([<<"file_handlers">>, <<"default">>], Log2),
+ NewLog1 = emqx_map_lib:deep_put([<<"file_handlers">>, <<"new">>], Log2, Handler),
+ NewLog2 = emqx_map_lib:deep_put([<<"file_handlers">>, <<"new">>, <<"file">>], NewLog1, File1),
+ {ok, #{}} = update_config(<<"log">>, NewLog2),
+ {ok, Log4} = logger:get_handler_config(new),
+ ?assertMatch(#{config := #{file := File1}}, Log4),
+
+ %% disable new handler
+ Disable = emqx_map_lib:deep_put([<<"file_handlers">>, <<"new">>, <<"enable">>], NewLog2, false),
+ {ok, #{}} = update_config(<<"log">>, Disable),
+ ?assertEqual({error, {not_found, new}}, logger:get_handler_config(new)),
ok.
t_zones(_Config) ->
diff --git a/apps/emqx_plugin_libs/src/emqx_plugin_libs_ssl.erl b/apps/emqx_plugin_libs/src/emqx_plugin_libs_ssl.erl
index 8da9198db..770c05045 100644
--- a/apps/emqx_plugin_libs/src/emqx_plugin_libs_ssl.erl
+++ b/apps/emqx_plugin_libs/src/emqx_plugin_libs_ssl.erl
@@ -78,7 +78,8 @@ save_files_return_opts(Options, Dir) ->
Versions = emqx_tls_lib:integral_versions(Get(versions)),
Ciphers = emqx_tls_lib:integral_ciphers(Versions, Get(ciphers)),
filter([{keyfile, Key}, {certfile, Cert}, {cacertfile, CA},
- {verify, Verify}, {server_name_indication, SNI}, {versions, Versions}, {ciphers, Ciphers}]).
+ {verify, Verify}, {server_name_indication, SNI},
+ {versions, Versions}, {ciphers, Ciphers}]).
%% @doc Save a key or certificate file in data dir,
%% and return path of the saved file.