Przeglądaj źródła

ft: Def Rotator模块修改

master
SisMaker 4 lat temu
rodzic
commit
11906550ac
6 zmienionych plików z 83 dodań i 95 usunięć
  1. +4
    -4
      README.md
  2. +8
    -8
      src/backend/rumBackendFile.erl
  3. +3
    -3
      src/crashLog/rumCrashLog.erl
  4. +3
    -3
      src/rotator/rumRotatorExm.erl
  5. +52
    -59
      src/rotator/rumRotatorIns.erl
  6. +13
    -18
      src/utils/rumUtil.erl

+ 4
- 4
README.md Wyświetl plik

@ -374,20 +374,20 @@ The module should provide the following callbacks as `lager_rotator_behaviour`
```erlang
%% @doc Create a log file
-callback(create_logfile(Name :: list(), Buffer :: {integer(), integer()} | any()) ->
-callback(createLogfile(Name :: list(), Buffer :: {integer(), integer()} | any()) ->
{ok, {FD :: file:io_device(), Inode :: integer(), Size :: integer()}} | {error, any()}).
%% @doc Open a log file
-callback(open_logfile(Name :: list(), Buffer :: {integer(), integer()} | any()) ->
-callback(openLogfile(Name :: list(), Buffer :: {integer(), integer()} | any()) ->
{ok, {FD :: file:io_device(), Inode :: integer(), Size :: integer()}} | {error, any()}).
%% @doc Ensure reference to current target, could be rotated
-callback(ensure_logfile(Name :: list(), FD :: file:io_device(), Inode :: integer(),
-callback(ensureLogfile(Name :: list(), FD :: file:io_device(), Inode :: integer(),
Buffer :: {integer(), integer()} | any()) ->
{ok, {FD :: file:io_device(), Inode :: integer(), Size :: integer()}} | {error, any()}).
%% @doc Rotate the log file
-callback(rotate_logfile(Name :: list(), Count :: integer()) ->
-callback(rotateLogfile(Name :: list(), Count :: integer()) ->
ok).
```

+ 8
- 8
src/backend/rumBackendFile.erl Wyświetl plik

@ -104,7 +104,7 @@ init(LogFileConfig) when is_list(LogFileConfig) ->
State0 = #state{name = Name, level = Level, size = Size, date = Date, count = Count, rotator = Rotator,
shaper = Shaper, formatter = Formatter, formatter_config = FormatterConfig,
sync_on = SyncOn, sync_interval = SyncInterval, sync_size = SyncSize, check_interval = CheckInterval},
State = case Rotator:create_logfile(Name, {SyncSize, SyncInterval}) of
State = case Rotator:createLogfile(Name, {SyncSize, SyncInterval}) of
{ok, {FD, Inode, Ctime, _Size}} ->
State0#state{fd = FD, inode = Inode, ctime = Ctime};
{error, Reason} ->
@ -173,7 +173,7 @@ handle_event(_Event, State) ->
%% @private
handle_info({rotate, File}, #state{name = File, count = Count, date = Date, rotator = Rotator} = State0) ->
State1 = close_file(State0),
_ = Rotator:rotate_logfile(File, Count),
_ = Rotator:rotateLogfile(File, Count),
schedule_rotation(File, Date),
{ok, State1};
handle_info({shaper_expired, Name}, #state{shaper = Shaper, name = Name, formatter = Formatter, formatter_config = FormatConfig} = State) ->
@ -227,12 +227,12 @@ write(#state{name = Name, fd = FD,
true ->
%% need to check for rotation
Buffer = {State0#state.sync_size, State0#state.sync_interval},
case Rotator:ensure_logfile(Name, FD, Inode, Ctime, Buffer) of
case Rotator:ensureLogfile(Name, FD, Inode, Ctime, Buffer) of
{ok, {_FD, _Inode, _Ctime, Size}} when RotSize > 0, Size > RotSize ->
State1 = close_file(State0),
case Rotator:rotate_logfile(Name, Count) of
case Rotator:rotateLogfile(Name, Count) of
ok ->
%% go around the loop again, we'll do another rotation check and hit the next clause of ensure_logfile
%% go around the loop again, we'll do another rotation check and hit the next clause of ensureLogfile
write(State1, Timestamp, Level, Msg);
{error, Reason} ->
case Flap of
@ -271,7 +271,7 @@ write_should_check(#state{last_check = LastCheck0, check_interval = CheckInterva
_ ->
% We need to know if the file has changed "out from under lager" so we don't
% write to an invalid FD
{Result, _FInfo} = rumUtil:has_file_changed(Name, Inode0, Ctime0),
{Result, _FInfo} = rumUtil:isFileChanged(Name, Inode0, Ctime0),
Result
end.
@ -501,7 +501,7 @@ rotation_test_() ->
% while a process has an open file handle referencing it
ok;
_ ->
{ok, {FD, Inode, Ctime, _Size}} = Rotator:open_logfile(TestLog, {SyncSize, SyncInterval}),
{ok, {FD, Inode, Ctime, _Size}} = Rotator:openLogfile(TestLog, {SyncSize, SyncInterval}),
State0 = DefaultState#state{fd = FD, inode = Inode, ctime = Ctime},
State1 = write(State0, os:timestamp(), ?DEBUG, "hello world"),
?assertMatch(#state{name = TestLog, level = ?DEBUG, fd = FD, inode = Inode, ctime = Ctime}, State1),
@ -528,7 +528,7 @@ rotation_test_() ->
RotationSize = 15,
PreviousCheck = os:timestamp(),
{ok, {FD, Inode, Ctime, _Size}} = Rotator:open_logfile(TestLog, {SyncSize, SyncInterval}),
{ok, {FD, Inode, Ctime, _Size}} = Rotator:openLogfile(TestLog, {SyncSize, SyncInterval}),
State0 = DefaultState#state{
fd = FD, inode = Inode, ctime = Ctime, size = RotationSize,
check_interval = CheckInterval, last_check = PreviousCheck},

+ 3
- 3
src/crashLog/rumCrashLog.erl Wyświetl plik

@ -80,7 +80,7 @@ handleCast(_Msg, _State) ->
kpS.
handleInfo(rotate, #state{fileName = Name, count = Count, date = Date, rotator = Rotator}) ->
_ = Rotator:rotate_logfile(Name, Count),
_ = Rotator:rotateLogfile(Name, Count),
schedule_rotation(Date),
kpS;
handleInfo(_Msg, _State) ->
@ -184,9 +184,9 @@ do_log({log, Event}, #state{fileName = Name, fd = FD, inode = Inode, ctime = Cti
if ReportStr == ignore ->
{ok, State};
true ->
case Rotator:ensure_logfile(Name, FD, Inode, Ctime, false) of
case Rotator:ensureLogfile(Name, FD, Inode, Ctime, false) of
{ok, {_FD, _Inode, _Ctime, Size}} when RotSize /= 0, Size > RotSize ->
_ = Rotator:rotate_logfile(Name, Count),
_ = Rotator:rotateLogfile(Name, Count),
handle_cast({log, Event}, State);
{ok, {NewFD, NewInode, NewCtime, _Size}} ->
TimeBinStr = rumUtil:msToBinStr(),

+ 3
- 3
src/rotator/rumRotatorExm.erl Wyświetl plik

@ -2,17 +2,17 @@
%% Create a log file
-callback createLogFile(Name :: list(), Buffer :: {integer(), integer()} | any()) ->
{ok, {file:io_device(), integer(), file:date_time(), integer()}} |
{ok, Fd :: file:io_device(), Inode :: integer(), DateTime :: file:date_time(), FileSize :: integer()} |
{error, any()}.
%% Open a log file
-callback openLogFile(Name :: list(), Buffer :: {integer(), integer()} | any()) ->
{ok, {file:io_device(), integer(), file:date_time(), integer()}} |
{ok, Fd :: file:io_device(), Inode :: integer(), DateTime :: file:date_time(), FileSize :: integer()} |
{error, any()}.
%% Ensure reference to current target, could be rotated
-callback ensureLogFile(Name :: list(), FD :: file:io_device(), Inode :: integer(), CTime :: file:date_time(), Buffer :: {integer(), integer()} | any()) ->
{ok, {file:io_device(), integer(), file:date_time(), integer()}} |
{ok, Fd :: file:io_device(), Inode :: integer(), DateTime :: file:date_time(), FileSize :: integer()} |
{error, any()}.
%% Rotate the log file

+ 52
- 59
src/rotator/rumRotatorIns.erl Wyświetl plik

@ -15,66 +15,62 @@
-include_lib("eunit/include/eunit.hrl").
-endif.
createLogFile(Name, Buffer) ->
openLogFile(Name, Buffer).
createLogFile(FileName, Buffer) ->
openLogFile(FileName, Buffer).
openLogFile(Name, Buffer) ->
case filelib:ensure_dir(Name) of
openLogFile(FileName, Buffer) ->
case filelib:ensure_dir(FileName) of
ok ->
Options = [append, raw] ++
Options =
case Buffer of
{Size0, Interval} when is_integer(Interval), Interval >= 0, is_integer(Size0), Size0 >= 0 ->
[{delayed_write, Size0, Interval}];
_ -> []
{Size, Interval} ->
[append, raw, {delayed_write, Size, Interval}];
_ ->
[append, raw]
end,
case file:open(Name, Options) of
{ok, FD} ->
case file:read_file_info(Name, [raw]) of
{ok, FInfo0} ->
Inode = FInfo0#file_info.inode,
{ok, CTime} = maybe_update_ctime(Name, FInfo0),
Size1 = FInfo0#file_info.size,
{ok, {FD, Inode, CTime, Size1}};
X -> X
case file:open(FileName, Options) of
{ok, Fd} ->
case file:read_file_info(FileName, [raw]) of
{ok, FileInfo} ->
#file_info{size = FileSize, inode = Inode} = FileInfo,
CTime = tryUpdateCTime(FileName, FileInfo),
{ok, Fd, Inode, CTime, FileSize};
RfiErr -> RfiErr
end;
Y -> Y
OpErr -> OpErr
end;
Z -> Z
EnDirErr -> EnDirErr
end.
ensureLogFile(Name, undefined, _Inode, _CTime, Buffer) ->
openLogFile(Name, Buffer);
ensureLogFile(Name, FD, Inode0, CTime0, Buffer) ->
case rumUtil:has_file_changed(Name, Inode0, CTime0) of
{true, _FInfo} ->
reopen_logfile(Name, FD, Buffer);
{_, FInfo} ->
{ok, {FD, Inode0, CTime0, FInfo#file_info.size}}
ensureLogFile(FileName, Fd, Inode, CTime, Buffer) ->
case Fd of
undefined ->
openLogFile(FileName, Buffer);
_ ->
case rumUtil:isFileChanged(FileName, Inode, CTime) of
{true, _FInfo} ->
reopenLogfile(FileName, Fd, Buffer);
{_, FInfo} ->
{ok, Fd, Inode, CTime, FInfo#file_info.size}
end
end.
reopen_logfile(Name, FD0, Buffer) ->
%% Flush and close any file handles.
%% delayed write can cause file:close not to do a close
_ = file:datasync(FD0),
_ = file:close(FD0),
_ = file:close(FD0),
case openLogFile(Name, Buffer) of
{ok, {_FD1, _Inode, _Size, _CTime} = FileInfo} ->
%% inode changed, file was probably moved and
%% recreated
{ok, FileInfo};
Error ->
Error
end.
reopenLogfile(FileName, Fd, Buffer) ->
%% Flush and close any file handles. delayed write can cause file:close not to do a close
_ = file:datasync(Fd),
_ = file:close(Fd),
_ = file:close(Fd),
openLogFile(FileName, Buffer).
%% renames failing are OK
%% IMY-TODO
rotateLogFile(File, 0) ->
%% open the file in write-only mode to truncate/create it
case file:open(File, [write]) of
{ok, FD} ->
_ = file:close(FD),
_ = file:close(FD),
{ok, _CTime} = maybe_update_ctime(File),
tryUpdateCTime(File),
ok;
Error ->
Error
@ -89,28 +85,25 @@ rotateLogFile(File0, Count) ->
_ = file:rename(File1, File2),
rotateLogFile(File0, Count - 1).
maybe_update_ctime(Name) ->
tryUpdateCTime(Name) ->
case file:read_file_info(Name, [raw]) of
{ok, FInfo} ->
maybe_update_ctime(Name, FInfo);
tryUpdateCTime(Name, FInfo);
_ ->
{ok, calendar:local_time()}
erlang:localtime()
end.
maybe_update_ctime(Name, FInfo) ->
{OsType, _} = os:type(),
do_update_ctime(OsType, Name, FInfo).
do_update_ctime(win32, Name, FInfo0) ->
% Note: we force the creation time to be the current time.
% On win32 this may prevent the ctime from being updated:
% https://stackoverflow.com/q/8804342/1466825
NewCtime = calendar:local_time(),
FInfo1 = FInfo0#file_info{ctime = NewCtime},
ok = file:write_file_info(Name, FInfo1, [raw]),
{ok, NewCtime};
do_update_ctime(_, _Name, FInfo) ->
{ok, FInfo#file_info.ctime}.
tryUpdateCTime(Name, FileInfo) ->
case os:type() of
{win32, _} ->
%win32上ctime的更新https://stackoverflow.com/q/8804342/1466825
NewCtime = erlang:localtime(),
NewFileInfo = FileInfo#file_info{ctime = NewCtime},
ok = file:write_file_info(Name, NewFileInfo, [raw]),
NewCtime;
_ ->
element(#file_info.ctime, FileInfo)
end.
-ifdef(TEST).

+ 13
- 18
src/utils/rumUtil.erl Wyświetl plik

@ -28,7 +28,7 @@
, makeInnerSinkName/1
, otp_version/0
, maybe_flush/2
, has_file_changed/3
, isFileChanged/3
, get_env/2
]).
@ -616,23 +616,18 @@ maybe_flush(undefined, #rumShaper{} = S) ->
maybe_flush(Flag, #rumShaper{} = S) when is_boolean(Flag) ->
S#rumShaper{flushQueue = Flag}.
-spec has_file_changed(Name :: file:name_all(),
Inode0 :: pos_integer(),
Ctime0 :: file:date_time()) -> {boolean(), file:file_info() | undefined}.
has_file_changed(Name, Inode0, Ctime0) ->
{OsType, _} = os:type(),
F = file:read_file_info(Name, [raw]),
case {OsType, F} of
{win32, {ok, #file_info{ctime = Ctime1} = FInfo}} ->
% Note: on win32, Inode is always zero
% So check the file's ctime to see if it
% needs to be re-opened
Changed = Ctime0 =/= Ctime1,
{Changed, FInfo};
{_, {ok, #file_info{inode = Inode1} = FInfo}} ->
Changed = Inode0 =/= Inode1,
{Changed, FInfo};
{_, _} ->
-spec isFileChanged(FileName :: file:name_all(), Inode :: pos_integer(), Ctime :: file:date_time()) -> {boolean(), file:file_info() | undefined}.
isFileChanged(FileName, Inode, Ctime) ->
case file:read_file_info(FileName, [raw]) of
{ok, FileInfo} ->
case os:type() of
{win32, _} ->
% Note: on win32, Inode is always zero So check the file's ctime to see if it needs to be re-opened
{Ctime =/= FileInfo#file_info.ctime, FileInfo};
_ ->
{Inode =/= FileInfo#file_info.inode, FileInfo}
end;
_ ->
{true, undefined}
end.

Ładowanie…
Anuluj
Zapisz