1
0
mirror of synced 2024-11-12 15:49:16 +00:00
x2log/X2Log.Observer.LogFile.pas

201 lines
6.0 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
FOutputFileName: string;
FLogDetails: Boolean;
2014-05-18 18:09:07 +00:00
protected
function CreateWorkerThread: TX2LogObserverWorkerThread; override;
2015-03-06 11:51:59 +00:00
property OutputFileName: string read FOutputFileName;
property LogDetails: Boolean read FLogDetails;
2014-05-18 18:09:07 +00:00
public
constructor Create(const AOutputFileName: string; ALogLevels: TX2LogLevels = X2LogLevelsDefault; ALogDetails: Boolean = True);
constructor CreateInProgramData(const AOutputFileName: string; ALogLevels: TX2LogLevels = X2LogLevelsDefault; ALogDetails: Boolean = True);
constructor CreateInUserAppData(const AOutputFileName: string; ALogLevels: TX2LogLevels = X2LogLevelsDefault; ALogDetails: Boolean = True);
2014-05-18 18:09:07 +00:00
end;
TX2LogFileWorkerThread = class(TX2LogObserverWorkerThread)
private
FOutputFileName: string;
FLogDetails: Boolean;
2014-05-18 18:09:07 +00:00
protected
function GetFileName(AEntry: TX2LogQueueEntry): string; virtual;
2014-05-18 18:09:07 +00:00
procedure ProcessEntry(AEntry: TX2LogQueueEntry); override;
property OutputFileName: string read FOutputFileName;
property LogDetails: Boolean read FLogDetails;
2014-05-18 18:09:07 +00:00
public
constructor Create(const AOutputFileName: string; ALogDetails: Boolean = True);
2014-05-18 18:09:07 +00:00
end;
2015-03-06 11:51:59 +00:00
implementation
uses
System.IOUtils,
System.SysUtils,
System.Win.ComObj,
Winapi.SHFolder,
Winapi.Windows,
X2Log.Constants;
2014-05-18 18:09:07 +00:00
{ TX2LogFileObserver }
constructor TX2LogFileObserver.Create(const AOutputFileName: string; ALogLevels: TX2LogLevels; ALogDetails: Boolean);
2014-05-18 18:09:07 +00:00
begin
FOutputFileName := AOutputFileName;
FLogDetails := ALogDetails;
2014-05-18 18:09:07 +00:00
inherited Create(ALogLevels);
end;
constructor TX2LogFileObserver.CreateInProgramData(const AOutputFileName: string; ALogLevels: TX2LogLevels; ALogDetails: Boolean);
2014-05-18 18:09:07 +00:00
var
path: PWideChar;
begin
GetMem(path, MAX_PATH);
try
OleCheck(SHGetFolderPath(0, CSIDL_COMMON_APPDATA, 0, SHGFP_TYPE_CURRENT, path));
Create(IncludeTrailingPathDelimiter(path) + AOutputFileName, ALogLevels, ALogDetails);
2014-05-18 18:09:07 +00:00
finally
FreeMem(path);
end;
end;
constructor TX2LogFileObserver.CreateInUserAppData(const AOutputFileName: string; ALogLevels: TX2LogLevels; ALogDetails: Boolean);
2014-05-18 18:09:07 +00:00
var
path: PWideChar;
begin
GetMem(path, MAX_PATH);
try
OleCheck(SHGetFolderPath(0, CSIDL_APPDATA, 0, SHGFP_TYPE_CURRENT, path));
Create(IncludeTrailingPathDelimiter(path) + AOutputFileName, ALogLevels, ALogDetails);
2014-05-18 18:09:07 +00:00
finally
FreeMem(path);
end;
end;
function TX2LogFileObserver.CreateWorkerThread: TX2LogObserverWorkerThread;
begin
Result := TX2LogFileWorkerThread.Create(OutputFileName, LogDetails);
2014-05-18 18:09:07 +00:00
end;
{ TX2LogFileWorkerThread }
constructor TX2LogFileWorkerThread.Create(const AOutputFileName: string; ALogDetails: Boolean);
2014-05-18 18:09:07 +00:00
begin
FOutputFileName := AOutputFileName;
FLogDetails := ALogDetails;
2014-05-18 18:09:07 +00:00
inherited Create;
end;
procedure TX2LogFileWorkerThread.ProcessEntry(AEntry: TX2LogQueueEntry);
var
fileName: string;
2014-05-18 18:09:07 +00:00
baseReportFileName: string;
errorMsg: string;
detailsExtension: string;
detailsFile: THandle;
detailsFileStream: THandleStream;
detailsFileName: string;
detailsNumber: Integer;
writer: TStreamWriter;
logDetailsStreamable: IX2LogDetailsStreamable;
2014-05-18 18:09:07 +00:00
begin
fileName := GetFileName(AEntry);
ForceDirectories(ExtractFilePath(fileName));
if Length(AEntry.Category) > 0 then
errorMsg := Format(GetLogResourceString(@LogFileLineCategory), [AEntry.Message, AEntry.Category])
else
errorMsg := Format(GetLogResourceString(@LogFileLineNoCategory), [AEntry.Message]);
2014-05-18 18:09:07 +00:00
if LogDetails and Supports(AEntry.Details, IX2LogDetailsStreamable, logDetailsStreamable) then
2014-05-18 18:09:07 +00:00
begin
detailsExtension := ExtractFileExt(fileName);
baseReportFileName := ChangeFileExt(fileName, '_' + FormatDateTime(GetLogResourceString(@LogFileNameDateFormat), AEntry.DateTime));
2014-05-18 18:09:07 +00:00
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 := Format(GetLogResourceString(@LogFileLineDetails), [errorMsg, ExtractFileName(detailsFileName)]);
2014-05-18 18:09:07 +00:00
break;
end;
until False;
end;
end;
{ Append line to log file }
writer := TFile.AppendText(fileName);
2014-05-18 18:09:07 +00:00
try
writer.WriteLine('[' + FormatDateTime(GetLogResourceString(@LogFileLineDateFormat), AEntry.DateTime) + '] ' +
2014-05-18 18:09:07 +00:00
GetLogLevelText(AEntry.Level) + ': ' + errorMsg);
finally
FreeAndNil(writer);
end;
end;
2015-03-06 11:51:59 +00:00
function TX2LogFileWorkerThread.GetFileName(AEntry: TX2LogQueueEntry): string;
2015-03-06 11:51:59 +00:00
begin
Result := FOutputFileName;
2015-03-06 11:51:59 +00:00
end;
2014-05-18 18:09:07 +00:00
end.