|
|
@ -30,6 +30,7 @@ |
|
|
|
|
|
|
|
-record(state, { |
|
|
|
fileName :: string(), |
|
|
|
fBName :: string(), |
|
|
|
level :: lgMaskLevel(), |
|
|
|
fd :: file:io_device() | undefined, |
|
|
|
inode :: integer() | undefined, |
|
|
@ -53,7 +54,7 @@ |
|
|
|
-spec init([lgFileOpt(), ...]) -> {ok, #state{}} | {error, atom()}. |
|
|
|
init(Opts) -> |
|
|
|
true = checkOpts(Opts, false), |
|
|
|
RelName = lgUtil:get_opt(file, Opts, undefined), |
|
|
|
FBName = lgUtil:get_opt(file, Opts, undefined), |
|
|
|
CfgLevel = lgUtil:get_opt(level, Opts, ?LgDefLogLevel), |
|
|
|
CfgDate = lgUtil:get_opt(date, Opts, ?LgDefRotateDate), |
|
|
|
Size = lgUtil:get_opt(size, Opts, ?LgDefRotateSize), |
|
|
@ -74,20 +75,22 @@ init(Opts) -> |
|
|
|
SyncOn = lgUtil:configToMask(CfgSyncOn), |
|
|
|
CheckInt = ?IIF(CfgCheckInt == always, 0, CfgCheckInt), |
|
|
|
{ok, Date} = lgUtil:parseRotateSpec(CfgDate), |
|
|
|
FileName = lgUtil:parsePath(RelName), |
|
|
|
scheduleRotation(Date, FileName), |
|
|
|
FileName = lgUtil:parsePath(FBName), |
|
|
|
scheduleRotation(Date, FBName), |
|
|
|
FmtCfg = ?IIF(CfgFmtCfg =/= [], CfgFmtCfg, begin MdWhitelist = lgUtil:get_env(mdWhitelist, []), lgFmtTer:fmtCfg(MdWhitelist) end), |
|
|
|
|
|
|
|
Shaper = #lgShaper{hwm = Hwm, flushQueue = FlushQueue, flushThr = FlushThr, id = FileName}, |
|
|
|
Shaper = #lgShaper{hwm = Hwm, flushQueue = FlushQueue, flushThr = FlushThr, id = FBName}, |
|
|
|
TemState = #state{ |
|
|
|
fileName = FileName, level = Level, size = Size, date = Date |
|
|
|
fileName = FileName, fBName = FBName, level = Level, size = Size, date = Date |
|
|
|
, count = Count, rotator = Rotator, shaper = Shaper |
|
|
|
, fmtTer = FmtTer, fmtCfg = FmtCfg |
|
|
|
, syncOn = SyncOn, syncInt = SyncInt |
|
|
|
, syncSize = SyncSize, checkInt = CheckInt |
|
|
|
}, |
|
|
|
|
|
|
|
case Rotator:createLogFile(FileName, {SyncSize, SyncInt}) of |
|
|
|
{ok, Fd, Inode, CTime, _Size} -> |
|
|
|
?INT_LOG(?error, "Failed to open log file ~ts 1111", [FileName]), |
|
|
|
{ok, TemState#state{fd = Fd, inode = Inode, cTime = CTime}}; |
|
|
|
{error, Reason} -> |
|
|
|
?INT_LOG(?error, "Failed to open log file ~ts with error ~s", [FileName, file:format_error(Reason)]), |
|
|
@ -96,33 +99,33 @@ init(Opts) -> |
|
|
|
|
|
|
|
handleCall(mGetLogLevel, #state{level = Level} = State) -> |
|
|
|
{reply, Level, State}; |
|
|
|
handleCall({mSetLogLevel, Level}, #state{fileName = FileName} = State) -> |
|
|
|
handleCall({mSetLogLevel, Level}, #state{fBName = FBName} = State) -> |
|
|
|
case lgUtil:validateLogLevel(Level) of |
|
|
|
false -> |
|
|
|
{reply, {error, bad_loglevel}, State}; |
|
|
|
LevelMask -> |
|
|
|
?INT_LOG(?notice, "Changed loglevel of ~s to ~p", [FileName, Level]), |
|
|
|
?INT_LOG(?notice, "Changed loglevel of ~s to ~p", [FBName, Level]), |
|
|
|
{reply, ok, State#state{level = LevelMask}} |
|
|
|
end; |
|
|
|
|
|
|
|
handleCall({mSetLogHwm, Hwm}, #state{shaper = Shaper, fileName = FileName} = State) -> |
|
|
|
handleCall({mSetLogHwm, Hwm}, #state{shaper = Shaper, fBName = FBName} = State) -> |
|
|
|
case checkOpts([{hwm, Hwm}], true) of |
|
|
|
false -> |
|
|
|
{reply, {error, badHwm}, State}; |
|
|
|
_ -> |
|
|
|
NewShaper = Shaper#lgShaper{hwm = Hwm}, |
|
|
|
?INT_LOG(?notice, "Changed loghwm of ~ts to ~p", [FileName, Hwm]), |
|
|
|
?INT_LOG(?notice, "Changed loghwm of ~ts to ~p", [FBName, Hwm]), |
|
|
|
{reply, {lastHwm, Shaper#lgShaper.hwm}, State#state{shaper = NewShaper}} |
|
|
|
end; |
|
|
|
handleCall(mRotate, State = #state{fileName = File}) -> |
|
|
|
{ok, NewState} = handleInfo({mRotate, File}, State), |
|
|
|
handleCall(mRotate, State = #state{fBName = FBName}) -> |
|
|
|
{ok, NewState} = handleInfo({mRotate, FBName}, State), |
|
|
|
{reply, ok, NewState}; |
|
|
|
handleCall(_Msg, State) -> |
|
|
|
?ERR("~p call receive unexpect msg ~p ~n ", [?MODULE, _Msg]), |
|
|
|
{reply, ok, State}. |
|
|
|
|
|
|
|
handleEvent({mWriteLog, Message}, #state{fileName = FileName, level = Level, shaper = Shaper, fmtTer = FmtTer, fmtCfg = FmtCfg} = State) -> |
|
|
|
case lgUtil:isLoggAble(Message, Level, {lgBkdFile, FileName}) of |
|
|
|
handleEvent({mWriteLog, Message}, #state{fBName = FBName, level = Level, shaper = Shaper, fmtTer = FmtTer, fmtCfg = FmtCfg} = State) -> |
|
|
|
case lgUtil:isLoggAble(Message, Level, {lgBkdFile, FBName}) of |
|
|
|
true -> |
|
|
|
#lgMsg{timestamp = Timestamp, severity = Severity} = Message, |
|
|
|
case lgUtil:checkHwm(Shaper) of |
|
|
@ -151,12 +154,11 @@ handleEvent(_Msg, _State) -> |
|
|
|
?ERR("~p event receive unexpect msg ~p ~n ", [?MODULE, _Msg]), |
|
|
|
kpS. |
|
|
|
|
|
|
|
handleInfo({mRotate, File}, #state{fileName = File, count = Count, date = Date, rotator = Rotator} = State) -> |
|
|
|
handleInfo({mRotate, FBName}, #state{fBName = FBName, date = Date} = State) -> |
|
|
|
NewState = closeFile(State), |
|
|
|
_ = Rotator:rotateLogFile(File, Count), |
|
|
|
scheduleRotation(File, Date), |
|
|
|
scheduleRotation(Date, FBName), |
|
|
|
{ok, NewState}; |
|
|
|
handleInfo({mShaperExpired, Name}, #state{shaper = Shaper, fileName = Name, fmtTer = FmtTer, fmtCfg = FmtCfg} = State) -> |
|
|
|
handleInfo({mShaperExpired, FBName}, #state{shaper = Shaper, fBName = FBName, fmtTer = FmtTer, fmtCfg = FmtCfg} = State) -> |
|
|
|
case Shaper#lgShaper.dropped of |
|
|
|
0 -> |
|
|
|
ignore; |
|
|
@ -180,7 +182,7 @@ terminate(_Reason, State) -> |
|
|
|
code_change(_OldVsn, State, _Extra) -> |
|
|
|
{ok, State}. |
|
|
|
|
|
|
|
writeLog(#state{fileName = FileName, fd = Fd, inode = Inode, cTime = CTime, flap = Flap, size = RotSize, count = Count, rotator = Rotator, lastCheck = LastCheck, checkInt = CheckInt, syncSize = SyncSize, syncInt = SyncInt} = State, Timestamp, Level, Msg) -> |
|
|
|
writeLog(#state{fileName = FileName, fd = Fd, inode = Inode, cTime = CTime, flap = Flap, size = RotSize, rotator = Rotator, lastCheck = LastCheck, checkInt = CheckInt, syncSize = SyncSize, syncInt = SyncInt} = State, Timestamp, Level, Msg) -> |
|
|
|
case isWriteCheck(Fd, LastCheck, CheckInt, FileName, Inode, CTime, Timestamp) of |
|
|
|
true -> |
|
|
|
%% need to check for rotation |
|
|
@ -188,18 +190,13 @@ writeLog(#state{fileName = FileName, fd = Fd, inode = Inode, cTime = CTime, flap |
|
|
|
{ok, NewFD, NewInode, NewCTime, FileSize} -> |
|
|
|
case RotSize > 0 andalso FileSize > RotSize of |
|
|
|
true -> |
|
|
|
TemState = closeFile(State), |
|
|
|
case Rotator:rotateLogFile(FileName, Count) of |
|
|
|
ok -> |
|
|
|
%% go around the loop again, we'll do another rotation check and hit the next clause of ensureLogFile |
|
|
|
writeLog(TemState, Timestamp, Level, Msg); |
|
|
|
{error, Reason} -> |
|
|
|
?IIF(Flap, State, begin ?INT_LOG(?error, "Failed to rotate log file ~ts with error ~s", [FileName, file:format_error(Reason)]), State#state{flap = true} end) |
|
|
|
end; |
|
|
|
NewState = closeFile(State), |
|
|
|
%% go around the loop again, we'll do another rotation check and hit the next clause of ensureLogFile |
|
|
|
writeLog(NewState, Timestamp, Level, Msg); |
|
|
|
_ -> |
|
|
|
%% update our last check and try again |
|
|
|
TemState = State#state{lastCheck = Timestamp, fd = NewFD, inode = NewInode, cTime = NewCTime}, |
|
|
|
writeFile(TemState, Level, Msg) |
|
|
|
NewState = State#state{lastCheck = Timestamp, fd = NewFD, inode = NewInode, cTime = NewCTime}, |
|
|
|
writeFile(NewState, Level, Msg) |
|
|
|
end; |
|
|
|
{error, Reason} -> |
|
|
|
?IIF(Flap, State, begin ?INT_LOG(?error, "Failed to reopen log file ~ts with error ~s", [FileName, file:format_error(Reason)]), State#state{flap = true} end) |
|
|
@ -291,13 +288,13 @@ checkOpts([{id, _} | Tail], IsFile) -> |
|
|
|
checkOpts([Other | _Tail], _IsFile) -> |
|
|
|
{error, {invalid_opt, Other}}. |
|
|
|
|
|
|
|
scheduleRotation(undefined, _FileName) -> |
|
|
|
scheduleRotation(undefined, _FBName) -> |
|
|
|
ok; |
|
|
|
scheduleRotation(Date, Name) -> |
|
|
|
erlang:send_after(lgUtil:calcNextRotateMs(Date), self(), {mRotate, Name}), |
|
|
|
scheduleRotation(Date, FBName) -> |
|
|
|
erlang:send_after(lgUtil:calcNextRotateMs(Date), self(), {mRotate, FBName}), |
|
|
|
ok. |
|
|
|
|
|
|
|
closeFile(#state{fd = Fd} = State) -> |
|
|
|
closeFile(#state{fBName = FBName, fd = Fd} = State) -> |
|
|
|
case Fd of |
|
|
|
undefined -> State; |
|
|
|
_ -> |
|
|
@ -306,5 +303,6 @@ closeFile(#state{fd = Fd} = State) -> |
|
|
|
_ = file:datasync(Fd), |
|
|
|
_ = file:close(Fd), |
|
|
|
_ = file:close(Fd), |
|
|
|
State#state{fd = undefined} |
|
|
|
NewFileName = lgUtil:parsePath(FBName), |
|
|
|
State#state{fileName = NewFileName, fd = undefined} |
|
|
|
end. |