164 lines
3.1 KiB
ObjectPascal
164 lines
3.1 KiB
ObjectPascal
unit uLogManagerThread;
|
|
|
|
interface
|
|
|
|
uses
|
|
System.Classes, System.SysUtils, System.Generics.Collections,
|
|
System.SyncObjs;
|
|
|
|
type
|
|
TRollingType = (rtDaily, rtHourly);
|
|
|
|
procedure InitLogger(const Folder, FilePrefix: string; RollType: TRollingType);
|
|
procedure AddLog_Thread(const Msg: string);
|
|
procedure StopLogger;
|
|
|
|
implementation
|
|
|
|
var
|
|
LogQueue: TThreadedQueue<string>;
|
|
LogThread: TThread;
|
|
|
|
LogFolder : string;
|
|
LogFilePrefix: string;
|
|
RollingType : TRollingType;
|
|
|
|
StopFlag: Boolean = False;
|
|
|
|
type
|
|
TLogThread = class(TThread)
|
|
private
|
|
FCurrentFileName: string;
|
|
function GetLogFileName: string;
|
|
procedure WriteToFile(const S: string);
|
|
protected
|
|
procedure Execute; override;
|
|
end;
|
|
|
|
procedure InitLogger(const Folder, FilePrefix: string; RollType: TRollingType);
|
|
begin
|
|
LogFolder := IncludeTrailingPathDelimiter(Folder);
|
|
if not DirectoryExists(LogFolder) then
|
|
ForceDirectories(LogFolder);
|
|
|
|
LogFilePrefix := FilePrefix;
|
|
RollingType := RollType;
|
|
|
|
LogQueue := TThreadedQueue<string>.Create(1000, 1000, 1000);
|
|
|
|
StopFlag := False;
|
|
LogThread := TLogThread.Create(False);
|
|
end;
|
|
|
|
procedure StopLogger;
|
|
begin
|
|
StopFlag := True;
|
|
|
|
if Assigned(LogThread) then
|
|
begin
|
|
LogThread.WaitFor;
|
|
LogThread.Free;
|
|
LogThread := nil;
|
|
end;
|
|
|
|
if Assigned(LogQueue) then
|
|
begin
|
|
LogQueue.Free;
|
|
LogQueue := nil;
|
|
end;
|
|
end;
|
|
|
|
procedure AddLog_Thread(const Msg: string);
|
|
begin
|
|
if Assigned(LogQueue) then
|
|
LogQueue.PushItem(FormatDateTime('yyyy-mm-dd hh:nn:ss.zzz', Now) + ' ' + Msg);
|
|
end;
|
|
|
|
{ TLogThread }
|
|
|
|
function TLogThread.GetLogFileName: string;
|
|
var
|
|
S: string;
|
|
begin
|
|
case RollingType of
|
|
rtDaily: S := FormatDateTime('yyyy-mm-dd', Now);
|
|
rtHourly: S := FormatDateTime('yyyy-mm-dd_hh', Now);
|
|
end;
|
|
|
|
Result := LogFolder + LogFilePrefix + '_' + S + '.txt';
|
|
end;
|
|
|
|
procedure TLogThread.WriteToFile(const S: string);
|
|
var
|
|
FS: TFileStream;
|
|
SW: TStreamWriter;
|
|
begin
|
|
if FCurrentFileName <> GetLogFileName then
|
|
FCurrentFileName := GetLogFileName;
|
|
|
|
// Append ¸ðµå·Î ¿±â
|
|
if FileExists(FCurrentFileName) then
|
|
FS := TFileStream.Create(FCurrentFileName, fmOpenWrite or fmShareDenyNone)
|
|
else
|
|
FS := TFileStream.Create(FCurrentFileName, fmCreate or fmShareDenyNone);
|
|
|
|
try
|
|
FS.Seek(0, soEnd);
|
|
|
|
// UTF-8 + BOM (ÆÄÀÏ ÃÖÃÊ »ý¼º ½Ã ÀÚµ¿)
|
|
SW := TStreamWriter.Create(FS, TEncoding.UTF8);
|
|
try
|
|
SW.WriteLine(S);
|
|
SW.Flush;
|
|
finally
|
|
SW.Free;
|
|
end;
|
|
finally
|
|
FS.Free;
|
|
end;
|
|
end;
|
|
{
|
|
procedure TLogThread.WriteToFile(const S: string);
|
|
var
|
|
F: TextFile;
|
|
begin
|
|
if FCurrentFileName <> GetLogFileName then
|
|
FCurrentFileName := GetLogFileName;
|
|
|
|
AssignFile(F, FCurrentFileName);
|
|
|
|
if FileExists(FCurrentFileName) then
|
|
Append(F)
|
|
else
|
|
Rewrite(F);
|
|
|
|
try
|
|
Writeln(F, S);
|
|
finally
|
|
CloseFile(F);
|
|
end;
|
|
end;
|
|
}
|
|
procedure TLogThread.Execute;
|
|
var
|
|
LogItem: string;
|
|
WR: TWaitResult;
|
|
begin
|
|
FCurrentFileName := GetLogFileName;
|
|
|
|
while not StopFlag do
|
|
begin
|
|
WR := LogQueue.PopItem(LogItem); // Delphi 10.4¿¡¼ À¯ÀÏÇÏ°Ô Á¸ÀçÇÏ´Â PopItem
|
|
|
|
if WR = wrSignaled then
|
|
begin
|
|
WriteToFile(LogItem);
|
|
end
|
|
else
|
|
Sleep(10); // Å¥°¡ ºñ¾úÀ¸¸é Àá½Ã ½¬¾ú´Ù°¡ ´Ù½Ã È®ÀÎ
|
|
end;
|
|
end;
|
|
|
|
end.
|
|
|