1
0
mirror of synced 2024-11-14 00:19:16 +00:00
x2log/X2Log.Observer.LogFile.pas

182 lines
4.9 KiB
ObjectPascal
Raw Normal View History

2014-05-18 18:09:07 +00:00
unit X2Log.Observer.LogFile;
interface
uses
System.Classes,
System.Generics.Collections,
System.SyncObjs,
X2Log.Intf,
X2Log.Observer.Custom,
X2Log.Observer.CustomThreaded;
type
TX2LogFileObserver = class(TX2LogCustomThreadedObserver)
private
FFileName: string;
protected
function CreateWorkerThread: TX2LogObserverWorkerThread; override;
public
constructor Create(const AFileName: string; ALogLevels: TX2LogLevels = X2LogLevelsDefault);
constructor CreateInProgramData(const AFileName: string; ALogLevels: TX2LogLevels = X2LogLevelsDefault);
constructor CreateInUserAppData(const AFileName: string; ALogLevels: TX2LogLevels = X2LogLevelsDefault);
end;
implementation
uses
System.IOUtils,
System.SysUtils,
System.Win.ComObj,
Winapi.SHFolder,
Winapi.Windows,
X2Log.Constants;
type
TX2LogFileWorkerThread = class(TX2LogObserverWorkerThread)
private
FFileName: string;
protected
procedure ProcessEntry(AEntry: TX2LogQueueEntry); override;
property FileName: string read FFileName;
public
constructor Create(const AFileName: string);
end;
{ TX2LogFileObserver }
constructor TX2LogFileObserver.Create(const AFileName: string; ALogLevels: TX2LogLevels);
begin
FFileName := AFileName;
inherited Create(ALogLevels);
end;
constructor TX2LogFileObserver.CreateInProgramData(const AFileName: string; ALogLevels: TX2LogLevels);
var
path: PWideChar;
begin
GetMem(path, MAX_PATH);
try
OleCheck(SHGetFolderPath(0, CSIDL_COMMON_APPDATA, 0, SHGFP_TYPE_CURRENT, path));
Create(IncludeTrailingPathDelimiter(path) + AFileName, ALogLevels);
finally
FreeMem(path);
end;
end;
constructor TX2LogFileObserver.CreateInUserAppData(const AFileName: string; ALogLevels: TX2LogLevels);
var
path: PWideChar;
begin
GetMem(path, MAX_PATH);
try
OleCheck(SHGetFolderPath(0, CSIDL_APPDATA, 0, SHGFP_TYPE_CURRENT, path));
Create(IncludeTrailingPathDelimiter(path) + AFileName, ALogLevels);
finally
FreeMem(path);
end;
end;
function TX2LogFileObserver.CreateWorkerThread: TX2LogObserverWorkerThread;
begin
Result := TX2LogFileWorkerThread.Create(FFileName);
end;
{ TX2LogFileWorkerThread }
constructor TX2LogFileWorkerThread.Create(const AFileName: string);
begin
FFileName := AFileName;
inherited Create;
end;
procedure TX2LogFileWorkerThread.ProcessEntry(AEntry: TX2LogQueueEntry);
var
baseReportFileName: string;
errorMsg: string;
detailsExtension: string;
detailsFile: THandle;
detailsFileStream: THandleStream;
detailsWriter: TStreamWriter;
detailsFileName: string;
detailsNumber: Integer;
writer: TStreamWriter;
logDetailsStreamable: IX2LogDetailsStreamable;
2014-05-18 18:09:07 +00:00
begin
ForceDirectories(ExtractFilePath(FileName));
errorMsg := AEntry.Message;
if Supports(AEntry.Details, IX2LogDetailsStreamable, logDetailsStreamable) then
2014-05-18 18:09:07 +00:00
begin
detailsExtension := ExtractFileExt(FileName);
baseReportFileName := ChangeFileExt(FileName, '_' + FormatDateTime(GetLogResourceString(@LogFileNameDateFormat), Now));
detailsFileName := baseReportFileName + detailsExtension;
detailsNumber := 0;
if ForceDirectories(ExtractFilePath(detailsFileName)) then
begin
repeat
{ TFileStream lacks the ability to create a file only when it does not exist }
detailsFile := CreateFile(PChar(detailsFileName), GENERIC_READ or GENERIC_WRITE,
FILE_SHARE_READ or FILE_SHARE_WRITE, nil, CREATE_NEW,
FILE_ATTRIBUTE_NORMAL, 0);
if detailsFile = INVALID_HANDLE_VALUE then
begin
if GetLastError = ERROR_FILE_EXISTS then
begin
{ Generate a new file name }
Inc(detailsNumber);
detailsFileName := Format('%s_%d%s', [baseReportFileName, detailsNumber,
detailsExtension]);
end else
break;
end else
begin
{ Details file succesfully generated }
try
detailsFileStream := THandleStream.Create(detailsFile);
try
logDetailsStreamable.SaveToStream(detailsFileStream);
2014-05-18 18:09:07 +00:00
finally
FreeAndNil(detailsFileStream);
end;
finally
CloseHandle(detailsFile);
end;
// ErrorLogs.Add(reportFileName);
errorMsg := errorMsg + Format(GetLogResourceString(@LogFileLineDetails), [ExtractFileName(detailsFileName)]);
break;
end;
until False;
end;
end;
{ Append line to log file }
writer := TFile.AppendText(FileName);
try
writer.WriteLine('[' + FormatDateTime(GetLogResourceString(@LogFileLineDateFormat), Now) + '] ' +
GetLogLevelText(AEntry.Level) + ': ' + errorMsg);
finally
FreeAndNil(writer);
end;
end;
end.