Skip to content

Commit

Permalink
Added TLoggerProFileByFolderAppender - by an idea and first implement…
Browse files Browse the repository at this point in the history
…ation of Mark Lobanov <[email protected]>
  • Loading branch information
danieleteti committed May 29, 2024
1 parent 4d54155 commit 59be284
Show file tree
Hide file tree
Showing 2 changed files with 165 additions and 0 deletions.
164 changes: 164 additions & 0 deletions lib/loggerpro/LoggerPro.FileAppender.pas
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ TLoggerProFileAppenderBase = class(TLoggerProAppenderBase)
}
DEFAULT_FILENAME_FORMAT = '{module}.{number}.{tag}.log';
DEFAULT_FILENAME_FORMAT_WITH_PID = '{module}.{number}.{pid}.{tag}.log';
DEFAULT_FILENAME_FORMAT_WITHOUT_TAG = '{module}.{number}.log';
{ @abstract(Defines number of log file set to maintain during logs rotation) }
DEFAULT_MAX_BACKUP_FILE_COUNT = 5;
{ @abstract(Defines the max size of each log file)
Expand Down Expand Up @@ -158,6 +159,36 @@ TLoggerProSimpleFileAppender = class(TLoggerProFileAppenderBase)
end;


TMakeFileNameProc = reference to procedure(out AFileName: string);

{ by an idea of Mark Lobanov <[email protected]> }
TLoggerProFileByFolderAppender = class(TLoggerProFileAppender)
private
fFileWriter: TStreamWriter;
fCurrentDate: TDateTime;
function GetLogFolder: string;
function GetFileFormat: string;
procedure RotateLog;
procedure ChangeLogFolder;
procedure RefreshCurrentDate;
procedure InternalRotateLog(aMakeFileNameProc: TMakeFileNameProc);
protected
function GetLogFileName(const aTag: string; const aFileNumber: Integer): string; override;
procedure CheckLogFileNameFormat(const aLogFileNameFormat: string); override;
public
constructor Create(
aMaxBackupFileCount: Integer = TLoggerProFileAppenderBase.DEFAULT_MAX_BACKUP_FILE_COUNT;
aMaxFileSizeInKiloByte: Integer = TLoggerProFileAppenderBase.DEFAULT_MAX_FILE_SIZE_KB;
const aLogsFolder: string = '';
const aLogItemRenderer: ILogItemRenderer = nil;
const aEncoding: TEncoding = nil); reintroduce;

procedure WriteLog(const ALogItem: TLogItem); override;
procedure Setup; override;
procedure TearDown; override;
end;


implementation

uses
Expand Down Expand Up @@ -537,5 +568,138 @@ procedure TLoggerProSimpleFileAppender.WriteLog(const aLogItem: TLogItem);
end;
end;

{ TLoggerProFileByFolderAppender }

constructor TLoggerProFileByFolderAppender.Create(
aMaxBackupFileCount, aMaxFileSizeInKiloByte: Integer;
const aLogsFolder: string;
const aLogItemRenderer: ILogItemRenderer;
const aEncoding: TEncoding);
var
lEncoding: TEncoding;
begin
if AEncoding = nil then
LEncoding := TEncoding.UTF8
else
LEncoding := AEncoding;

inherited Create(aMaxBackupFileCount, aMaxFileSizeInKiloByte,
aLogsFolder, GetFileFormat, aLogItemRenderer, LEncoding);
RefreshCurrentDate;
end;

procedure TLoggerProFileByFolderAppender.CheckLogFileNameFormat(const ALogFileNameFormat: string);
begin
//do nothing, user cannot change filename format in this appender
end;

function TLoggerProFileByFolderAppender.GetLogFolder: string;
const
LOG_DIR = 'Logs';
begin
if fLogsFolder.IsEmpty then
fLogsFolder := TPath.Combine(TPath.GetDirectoryName({ParamStr(0)} GetModuleName(HInstance)), LOG_DIR)
else
if not EndsText(LOG_DIR, fLogsFolder) then
fLogsFolder := TPath.Combine(FLogsFolder, LOG_DIR);
if not TDirectory.Exists(fLogsFolder) then
TDirectory.CreateDirectory(fLogsFolder);

Result := TPath.Combine(fLogsFolder, FormatDateTime('yyyymmdd', Now));
if not TDirectory.Exists(Result) then
TDirectory.CreateDirectory(Result);
end;


procedure TLoggerProFileByFolderAppender.InternalRotateLog(aMakeFileNameProc: TMakeFileNameProc);
var
lLogFileName: string;
begin
EmitEndRotateLogItem(fFileWriter);
FreeAndNil(fFileWriter);
aMakeFileNameProc(lLogFileName);
fFileWriter := CreateWriter(lLogFileName, 16 * 1024);
EmitStartRotateLogItem(fFileWriter);
end;

procedure TLoggerProFileByFolderAppender.ChangeLogFolder;
begin
InternalRotateLog(
procedure(out AFileName: string)
begin
AFileName := GetLogFileName(EmptyStr, 0);
end
);
end;

procedure TLoggerProFileByFolderAppender.RotateLog;
begin
InternalRotateLog(
procedure(out AFileName: string)
begin
RotateFile(EmptyStr, AFileName);
end
);
end;

function TLoggerProFileByFolderAppender.GetFileFormat: string;
begin
Result := TLoggerProFileAppenderBase.DEFAULT_FILENAME_FORMAT_WITHOUT_TAG;
end;

function TLoggerProFileByFolderAppender.GetLogFileName(const ATag: string; const AFileNumber: Integer): string;
var
lOnlyFileName: String;
begin
lOnlyFileName := TPath.GetFileName(inherited);
Result := TPath.Combine(GetLogFolder, lOnlyFileName);
end;


procedure TLoggerProFileByFolderAppender.RefreshCurrentDate;
begin
fCurrentDate := Date;
end;

procedure TLoggerProFileByFolderAppender.Setup;
begin
inherited;
fFileWriter := CreateWriter(GetLogFileName(EmptyStr, 0));
RefreshCurrentDate;
end;

procedure TLoggerProFileByFolderAppender.TearDown;
begin
fFileWriter.Free;
inherited;
end;

procedure TLoggerProFileByFolderAppender.WriteLog(const ALogItem: TLogItem);
var
lLogRow: string;
begin
if not SameDate(fCurrentDate, Date) then
begin
ChangeLogFolder;
RefreshCurrentDate;
end;

if Assigned(OnLogRow) then
begin
OnLogRow(ALogItem, lLogRow);
end
else
begin
lLogRow := LogItemRenderer.RenderLogItem(ALogItem);
end;

WriteToStream(fFileWriter, lLogRow);

if fFileWriter.BaseStream.Size > fMaxFileSizeInKiloByte * 1024 then
begin
RotateLog;
end;
end;

end.

1 change: 1 addition & 0 deletions lib/loggerpro/LoggerPro.pas
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,7 @@ TLoggerProAppenderBase = class abstract(TInterfacedObject, ILogAppender)
FFormatSettings: TFormatSettings;
protected
property FormatSettings: TFormatSettings read FFormatSettings;
property LogItemRenderer: ILogItemRenderer read FLogItemRenderer;
public
constructor Create(ALogItemRenderer: ILogItemRenderer = nil); virtual;
procedure Setup; virtual;
Expand Down

0 comments on commit 59be284

Please sign in to comment.