diff --git a/src/emqx_trace_handler.erl b/src/emqx_trace_handler.erl index ffe581300..49f3157cc 100644 --- a/src/emqx_trace_handler.erl +++ b/src/emqx_trace_handler.erl @@ -59,6 +59,22 @@ }} ). +-define(CLIENT_FORMAT, + {logger_formatter, #{ + template => [ + time, " [", level, "] ", + {clientid, + [{peername, [clientid, "@", peername, " "], [clientid, " "]}], + [{peername, [peername, " "], []}] + }, + msg, "\n" + ], + single_line => false, + max_size => unlimited, + depth => unlimited + }} +). + -define(CONFIG(_LogFile_), #{ type => halt, file => _LogFile_, @@ -160,7 +176,7 @@ filter_ip_address(_Log, _ExpectId) -> ignore. install_handler(Who = #{name := Name, type := Type}, Level, LogFile) -> HandlerId = handler_id(Name, Type), Config = #{ level => Level, - formatter => ?FORMAT, + formatter => formatter(Who), filter_default => stop, filters => filters(Who), config => ?CONFIG(LogFile) @@ -176,6 +192,31 @@ filters(#{type := topic, filter := Filter, name := Name}) -> filters(#{type := ip_address, filter := Filter, name := Name}) -> [{ip_address, {fun ?MODULE:filter_ip_address/2, {ensure_list(Filter), Name}}}]. +formatter(#{type := Type}) -> + {logger_formatter, + #{ + template => template(Type), + single_line => false, + max_size => unlimited, + depth => unlimited + } + }. + +%% Don't log clientid since clientid only supports exact match, all client ids are the same. +%% if clientid is not latin characters. the logger_formatter restricts the output must be `~tp` +%% (actually should use `~ts`), the utf8 characters clientid will become very difficult to read. +template(clientid) -> + [time, " [", level, "] ", {peername, [peername, " "], []}, msg, "\n"]; +%% TODO better format when clientid is utf8. +template(_) -> + [ time, " [", level, "] ", + {clientid, + [{peername, [clientid, "@", peername, " "], [clientid, " "]}], + [{peername, [peername, " "], []}] + }, + msg, "\n" + ]. + filter_traces(#{id := Id, level := Level, dst := Dst, filters := Filters}, Acc) -> Init = #{id => Id, level => Level, dst => Dst}, case Filters of @@ -209,7 +250,7 @@ do_handler_id(Name, Type) -> ensure_bin(List) when is_list(List) -> iolist_to_binary(List); ensure_bin(Bin) when is_binary(Bin) -> Bin. -ensure_list(Bin) when is_binary(Bin) -> binary_to_list(Bin); +ensure_list(Bin) when is_binary(Bin) -> unicode:characters_to_list(Bin, utf8); ensure_list(List) when is_list(List) -> List. show_prompts(ok, Who, Msg) -> diff --git a/test/emqx_trace_handler_SUITE.erl b/test/emqx_trace_handler_SUITE.erl index cbf455d2d..d46c18a70 100644 --- a/test/emqx_trace_handler_SUITE.erl +++ b/test/emqx_trace_handler_SUITE.erl @@ -28,7 +28,7 @@ {password, <<"pass">>} ]). -all() -> [t_trace_clientid, t_trace_topic, t_trace_ip_address]. +all() -> [t_trace_clientid, t_trace_topic, t_trace_ip_address, t_trace_clientid_utf8]. init_per_suite(Config) -> emqx_ct_helpers:boot_modules(all), @@ -105,6 +105,22 @@ t_trace_clientid(_Config) -> emqtt:disconnect(T), ?assertEqual([], emqx_trace_handler:running()). +t_trace_clientid_utf8(_) -> + emqx_logger:set_log_level(debug), + + Utf8Id = <<"client 漢字編碼"/utf8>>, + ok = emqx_trace_handler:install(clientid, Utf8Id, debug, "tmp/client-utf8.log"), + {ok, T} = emqtt:start_link([{clientid, Utf8Id}]), + emqtt:connect(T), + [begin emqtt:publish(T, <<"a/b/c">>, <<"hi">>) end|| _ <- lists:seq(1, 10)], + emqtt:ping(T), + + ok = filesync(Utf8Id, clientid), + ok = emqx_trace_handler:uninstall(clientid, Utf8Id), + emqtt:disconnect(T), + ?assertEqual([], emqx_trace_handler:running()), + ok. + t_trace_topic(_Config) -> {ok, T} = emqtt:start_link(?CLIENT), emqtt:connect(T),