From f47a8be9a695857584513a530617196cb63034ba Mon Sep 17 00:00:00 2001 From: Luke Bakken Date: Wed, 7 Aug 2019 13:23:15 -0700 Subject: [PATCH 1/2] Add t to string formatting to accept unicode file and dir names --- src/lager.erl | 2 +- src/lager_crash_log.erl | 6 +++--- src/lager_file_backend.erl | 12 ++++++------ 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/lager.erl b/src/lager.erl index 2ad888b..d36de0b 100644 --- a/src/lager.erl +++ b/src/lager.erl @@ -392,7 +392,7 @@ status() -> Level = get_loglevel(Sink, Handler), case Handler of {lager_file_backend, File} -> - io_lib:format("File ~s (~s) at level ~p\n", [File, Sink, Level]); + io_lib:format("File ~ts (~s) at level ~p\n", [File, Sink, Level]); lager_console_backend -> io_lib:format("Console (~s) at level ~p\n", [Sink, Level]); _ -> diff --git a/src/lager_crash_log.erl b/src/lager_crash_log.erl index 5a48238..b3377f6 100644 --- a/src/lager_crash_log.erl +++ b/src/lager_crash_log.erl @@ -80,7 +80,7 @@ init([RelFilename, MaxBytes, Size, Date, Count, Rotator]) -> fmtmaxbytes=MaxBytes, size=Size, count=Count, date=Date, rotator=Rotator}}; {error, Reason} -> - ?INT_LOG(error, "Failed to open crash log file ~s with error: ~s", + ?INT_LOG(error, "Failed to open crash log file ~ts with error: ~s", [Filename, file:format_error(Reason)]), {ok, #state{name=Filename, fmtmaxbytes=MaxBytes, flap=true, size=Size, count=Count, date=Date, rotator=Rotator}} @@ -216,7 +216,7 @@ do_log({log, Event}, #state{name=Name, fd=FD, inode=Inode, flap=Flap, Msg = io_lib:format("~s~s~s", [Time, MsgStr, NodeSuffix]), case file:write(NewFD, unicode:characters_to_binary(Msg)) of {error, Reason} when Flap == false -> - ?INT_LOG(error, "Failed to write log message to file ~s: ~s", + ?INT_LOG(error, "Failed to write log message to file ~ts: ~s", [Name, file:format_error(Reason)]), {ok, State#state{fd=NewFD, inode=NewInode, flap=true}}; ok -> @@ -229,7 +229,7 @@ do_log({log, Event}, #state{name=Name, fd=FD, inode=Inode, flap=Flap, true -> {ok, State}; _ -> - ?INT_LOG(error, "Failed to reopen crash log ~s with error: ~s", + ?INT_LOG(error, "Failed to reopen crash log ~ts with error: ~s", [Name, file:format_error(Reason)]), {ok, State#state{flap=true}} end diff --git a/src/lager_file_backend.erl b/src/lager_file_backend.erl index e725312..1e9caab 100644 --- a/src/lager_file_backend.erl +++ b/src/lager_file_backend.erl @@ -126,7 +126,7 @@ init(LogFileConfig) when is_list(LogFileConfig) -> {ok, {FD, Inode, _}} -> State0#state{fd=FD, inode=Inode}; {error, Reason} -> - ?INT_LOG(error, "Failed to open log file ~s with error ~s", [Name, file:format_error(Reason)]), + ?INT_LOG(error, "Failed to open log file ~ts with error ~s", [Name, file:format_error(Reason)]), State0#state{flap=true} end, {ok, State} @@ -149,7 +149,7 @@ handle_call({set_loghwm, Hwm}, #state{shaper=Shaper, name=Name} = State) -> {ok, {error, bad_log_hwm}, State}; _ -> NewShaper = Shaper#lager_shaper{hwm=Hwm}, - ?INT_LOG(notice, "Changed loghwm of ~s to ~p", [Name, Hwm]), + ?INT_LOG(notice, "Changed loghwm of ~ts to ~p", [Name, Hwm]), {ok, {last_loghwm, Shaper#lager_shaper.hwm}, State#state{shaper=NewShaper}} end; handle_call(rotate, State = #state{name=File}) -> @@ -255,7 +255,7 @@ write(#state{name=Name, fd=FD, inode=Inode, flap=Flap, size=RotSize, true -> State; _ -> - ?INT_LOG(error, "Failed to rotate log file ~s with error ~s", [Name, file:format_error(Reason)]), + ?INT_LOG(error, "Failed to rotate log file ~ts with error ~s", [Name, file:format_error(Reason)]), State#state{flap=true} end end; @@ -267,7 +267,7 @@ write(#state{name=Name, fd=FD, inode=Inode, flap=Flap, size=RotSize, true -> State; _ -> - ?INT_LOG(error, "Failed to reopen log file ~s with error ~s", [Name, file:format_error(Reason)]), + ?INT_LOG(error, "Failed to reopen log file ~ts with error ~s", [Name, file:format_error(Reason)]), State#state{flap=true} end end; @@ -284,7 +284,7 @@ do_write(#state{fd=FD, name=Name, flap=Flap} = State, Level, Msg) -> %% force a sync on any message that matches the 'sync_on' bitmask Flap2 = case file:datasync(FD) of {error, Reason2} when Flap == false -> - ?INT_LOG(error, "Failed to write log message to file ~s: ~s", + ?INT_LOG(error, "Failed to write log message to file ~ts: ~s", [Name, file:format_error(Reason2)]), true; ok -> @@ -327,7 +327,7 @@ validate_logfile_proplist(List) -> end catch {bad_config, Msg, Value} -> - ?INT_LOG(error, "~s ~p for file ~p", + ?INT_LOG(error, "~s ~p for file ~tp", [Msg, Value, proplists:get_value(file, List)]), false end. From c88d5d5666301b7abeca6aacc93251394c364f40 Mon Sep 17 00:00:00 2001 From: Luke Bakken Date: Fri, 9 Aug 2019 12:44:21 -0700 Subject: [PATCH 2/2] Add tests that show ~t format modifier is necessary for unicode file paths --- src/lager.erl | 73 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 49 insertions(+), 24 deletions(-) diff --git a/src/lager.erl b/src/lager.erl index d36de0b..275bebc 100644 --- a/src/lager.erl +++ b/src/lager.erl @@ -24,6 +24,10 @@ -define(TRACE_SINK, '__trace_sink'). -define(ROTATE_TIMEOUT, 100000). +-ifdef(TEST). +-include_lib("eunit/include/eunit.hrl"). +-endif. + %% API -export([start/0, log/3, log/4, log/5, @@ -389,32 +393,25 @@ status() -> end, Status = ["Lager status:\n", [begin - Level = get_loglevel(Sink, Handler), - case Handler of - {lager_file_backend, File} -> - io_lib:format("File ~ts (~s) at level ~p\n", [File, Sink, Level]); - lager_console_backend -> - io_lib:format("Console (~s) at level ~p\n", [Sink, Level]); - _ -> - [] - end - end || {Handler, _Watcher, Sink} <- lists:sort(fun({_, _, S1}, - {_, _, S2}) -> S1 =< S2 end, - Handlers)], + Level = get_loglevel(Sink, Handler), + get_sink_handler_status(Sink, Handler, Level) + end || {Handler, _Watcher, Sink} <- lists:sort(fun({_, _, S1}, + {_, _, S2}) -> S1 =< S2 end, + Handlers)], "Active Traces:\n", [begin - LevelName = case Level of - {mask, Mask} -> - case lager_util:mask_to_levels(Mask) of - [] -> none; - Levels -> hd(Levels) - end; - Num -> - lager_util:num_to_level(Num) - end, - io_lib:format("Tracing messages matching ~p (sink ~s) at level ~p to ~p\n", - [Filter, Sink, LevelName, Destination]) - end || {Sink, {Filter, Level, Destination}} <- Traces], + LevelName = case Level of + {mask, Mask} -> + case lager_util:mask_to_levels(Mask) of + [] -> none; + Levels -> hd(Levels) + end; + Num -> + lager_util:num_to_level(Num) + end, + io_lib:format("Tracing messages matching ~p (sink ~s) at level ~p to ~p\n", + [Filter, Sink, LevelName, Destination]) + end || {Sink, {Filter, Level, Destination}} <- Traces], [ "Tracing Reductions:\n", case ?DEFAULT_TRACER:info('query') of @@ -432,6 +429,15 @@ status() -> ]], io:put_chars(Status). +get_sink_handler_status(Sink, Handler, Level) -> + case Handler of + {lager_file_backend, File} -> + io_lib:format("File ~ts (~s) at level ~p\n", [File, Sink, Level]); + lager_console_backend -> + io_lib:format("Console (~s) at level ~p\n", [Sink, Level]); + _ -> + [] + end. %% @doc Set the loglevel for a particular backend. set_loglevel(Handler, Level) when is_atom(Level) -> @@ -719,3 +725,22 @@ check_timeout(#trace_func_state_v1{timeout=Timeout, started=Started} = FuncState false -> FuncState end. + +-ifdef(TEST). +get_sink_handler_status_ascii_test() -> + File = "C:\\ProgramData\\Directory With Spaces\\lager.log", + validate_status(File). + +get_sink_handler_status_latin_test() -> + File = "C:\\ProgramData\\Tést Directory\\lager.log", + validate_status(File). + +get_sink_handler_status_unicode_test() -> + File = "C:\\ProgramData\\찦차를 타고 온 펲시맨과 쑛다리 똠방각하 (Korean)\\lager.log", + validate_status(File). + +validate_status(File) -> + Handler = {lager_file_backend, File}, + Status = get_sink_handler_status(?DEFAULT_SINK, Handler, debug), + ?assertNotEqual(nomatch, string:find(Status, File)). +-endif.