FS#17 - Log export ability
Fixed: DateTime is now passed around everywhere (to accomodate the Export functionality)
This commit is contained in:
parent
fabf621dc0
commit
ca47ad3f4e
@ -11,7 +11,6 @@ uses
|
|||||||
|
|
||||||
var
|
var
|
||||||
client: IX2LogObservable;
|
client: IX2LogObservable;
|
||||||
observerForm: TX2LogObserverMonitorForm;
|
|
||||||
|
|
||||||
begin
|
begin
|
||||||
ReportMemoryLeaksOnShutdown := True;
|
ReportMemoryLeaksOnShutdown := True;
|
||||||
@ -22,8 +21,12 @@ begin
|
|||||||
|
|
||||||
client := TX2LogNamedPipeClient.Create('X2LogTest');
|
client := TX2LogNamedPipeClient.Create('X2LogTest');
|
||||||
try
|
try
|
||||||
observerForm := TX2LogObserverMonitorForm.Instance(client);
|
with TX2LogObserverMonitorForm.Create(nil, client) do
|
||||||
observerForm.ShowModal;
|
try
|
||||||
|
ShowModal;
|
||||||
|
finally
|
||||||
|
Free;
|
||||||
|
end;
|
||||||
finally
|
finally
|
||||||
client := nil;
|
client := nil;
|
||||||
end;
|
end;
|
||||||
|
@ -87,7 +87,7 @@ type
|
|||||||
FFileObserver: IX2LogObserver;
|
FFileObserver: IX2LogObserver;
|
||||||
FNamedPipeObserver: IX2LogObserver;
|
FNamedPipeObserver: IX2LogObserver;
|
||||||
protected
|
protected
|
||||||
procedure DoLog(Sender: TObject; Level: TX2LogLevel; const Msg: string; Details: IX2LogDetails);
|
procedure DoLog(Sender: TObject; Level: TX2LogLevel; DateTime: TDateTime; const Msg: string; Details: IX2LogDetails);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -149,7 +149,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure TMainForm.DoLog(Sender: TObject; Level: TX2LogLevel; const Msg: string; Details: IX2LogDetails);
|
procedure TMainForm.DoLog(Sender: TObject; Level: TX2LogLevel; DateTime: TDateTime; const Msg: string; Details: IX2LogDetails);
|
||||||
var
|
var
|
||||||
text: string;
|
text: string;
|
||||||
logDetailsText: IX2LogDetailsText;
|
logDetailsText: IX2LogDetailsText;
|
||||||
|
@ -19,8 +19,8 @@ type
|
|||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
|
|
||||||
{ IX2LogBase }
|
{ IX2LogBase }
|
||||||
procedure Log(ALevel: TX2LogLevel; const AMessage: string; ADetails: IX2LogDetails = nil); virtual;
|
procedure Log(ALevel: TX2LogLevel; const AMessage: string; ADetails: IX2LogDetails = nil); overload; virtual;
|
||||||
|
procedure Log(ALevel: TX2LogLevel; ADateTime: TDateTime; const AMessage: string; ADetails: IX2LogDetails = nil); overload; virtual;
|
||||||
|
|
||||||
{ IX2LogObservable }
|
{ IX2LogObservable }
|
||||||
procedure Attach(AObserver: IX2LogObserver);
|
procedure Attach(AObserver: IX2LogObserver);
|
||||||
@ -73,5 +73,15 @@ begin
|
|||||||
observer.Log(ALevel, AMessage, ADetails);
|
observer.Log(ALevel, AMessage, ADetails);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure TX2LogBaseClient.Log(ALevel: TX2LogLevel; ADateTime: TDateTime; const AMessage: string; ADetails: IX2LogDetails);
|
||||||
|
var
|
||||||
|
observer: IX2LogObserver;
|
||||||
|
|
||||||
|
begin
|
||||||
|
for observer in Observers do
|
||||||
|
observer.Log(ALevel, ADateTime, AMessage, ADetails);
|
||||||
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ type
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
TX2LogNamedPipeClient = class(TX2LogBaseClient, IX2LogBase)
|
TX2LogNamedPipeClient = class(TX2LogBaseClient)
|
||||||
private
|
private
|
||||||
FWorkerThread: TThread;
|
FWorkerThread: TThread;
|
||||||
protected
|
protected
|
||||||
@ -393,7 +393,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
Client.Log(header.Level, msg, details);
|
Client.Log(header.Level, header.DateTime, msg, details);
|
||||||
except
|
except
|
||||||
on E:EReadError do
|
on E:EReadError do
|
||||||
ClosePipe;
|
ClosePipe;
|
||||||
|
@ -43,15 +43,29 @@ resourcestring
|
|||||||
LogMonitorFormButtonPause = 'Pause';
|
LogMonitorFormButtonPause = 'Pause';
|
||||||
LogMonitorFormButtonCopyDetails = 'Copy';
|
LogMonitorFormButtonCopyDetails = 'Copy';
|
||||||
LogMonitorFormButtonSaveDetails = 'Save';
|
LogMonitorFormButtonSaveDetails = 'Save';
|
||||||
|
LogMonitorFormButtonWordWrapDetails = 'Word wrap';
|
||||||
|
|
||||||
LogMonitorFormButtonFilter = 'Filter:';
|
LogMonitorFormButtonFilter = 'Filter:';
|
||||||
|
|
||||||
|
{ Caption of the menu items which are not on the toolbar }
|
||||||
|
LogMonitorFormMenuFile = 'File';
|
||||||
|
LogMonitorFormMenuFileSaveAs = 'Save as...';
|
||||||
|
LogMonitorFormMenuFileClose = 'Close';
|
||||||
|
LogMonitorFormMenuLog = 'Log';
|
||||||
|
LogMonitorFormMenuDetails = 'Details';
|
||||||
|
LogMonitorFormMenuWindow = 'Window';
|
||||||
|
LogMonitorFormMenuWindowAlwaysOnTop = 'Always on top';
|
||||||
|
|
||||||
|
|
||||||
{ Status messages }
|
{ Status messages }
|
||||||
LogMonitorFormStatusPaused = 'Paused: %d log message(s) skipped';
|
LogMonitorFormStatusPaused = 'Paused: %d log message(s) skipped';
|
||||||
|
|
||||||
{ Filter for Save details buttons }
|
{ Filter for Save details buttons }
|
||||||
LogMonitorFormSaveDetailsFilter = 'All files (*.*)|*.*';
|
LogMonitorFormSaveDetailsFilter = 'All files (*.*)|*.*';
|
||||||
|
|
||||||
|
{ Filter for Save as menu item }
|
||||||
|
LogMonitorFormSaveDetailsSaveAs = 'Log files (*.log)|*.log|All files (*.*)|*.*';
|
||||||
|
|
||||||
|
|
||||||
function GetLogLevelText(ALogLevel: TX2LogLevel): string;
|
function GetLogLevelText(ALogLevel: TX2LogLevel): string;
|
||||||
|
|
||||||
|
@ -24,7 +24,8 @@ type
|
|||||||
class procedure SetExceptionStrategy(AStrategy: IX2LogExceptionStrategy);
|
class procedure SetExceptionStrategy(AStrategy: IX2LogExceptionStrategy);
|
||||||
|
|
||||||
{ Facade for IX2LogBase }
|
{ Facade for IX2LogBase }
|
||||||
class procedure Log(ALevel: TX2LogLevel; const AMessage: string; ADetails: IX2LogDetails);
|
class procedure Log(ALevel: TX2LogLevel; const AMessage: string; ADetails: IX2LogDetails); overload;
|
||||||
|
class procedure Log(ALevel: TX2LogLevel; ADateTime: TDateTime; const AMessage: string; ADetails: IX2LogDetails); overload;
|
||||||
|
|
||||||
class procedure Verbose(const AMessage: string; const ADetails: string = '');
|
class procedure Verbose(const AMessage: string; const ADetails: string = '');
|
||||||
class procedure VerboseEx(const AMessage: string; ADetails: IX2LogDetails = nil);
|
class procedure VerboseEx(const AMessage: string; ADetails: IX2LogDetails = nil);
|
||||||
@ -87,6 +88,12 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
class procedure TX2GlobalLog.Log(ALevel: TX2LogLevel; ADateTime: TDateTime; const AMessage: string; ADetails: IX2LogDetails);
|
||||||
|
begin
|
||||||
|
Instance.Log(ALevel, ADateTime, AMessage, ADetails);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
class procedure TX2GlobalLog.Verbose(const AMessage, ADetails: string);
|
class procedure TX2GlobalLog.Verbose(const AMessage, ADetails: string);
|
||||||
begin
|
begin
|
||||||
Instance.Verbose(AMessage, ADetails);
|
Instance.Verbose(AMessage, ADetails);
|
||||||
|
@ -49,6 +49,7 @@ type
|
|||||||
IX2LogBase = interface
|
IX2LogBase = interface
|
||||||
['{1949E8DC-6DC5-43DC-B678-55CF8274E79D}']
|
['{1949E8DC-6DC5-43DC-B678-55CF8274E79D}']
|
||||||
procedure Log(ALevel: TX2LogLevel; const AMessage: string; ADetails: IX2LogDetails = nil); overload;
|
procedure Log(ALevel: TX2LogLevel; const AMessage: string; ADetails: IX2LogDetails = nil); overload;
|
||||||
|
procedure Log(ALevel: TX2LogLevel; ADateTime: TDateTime; const AMessage: string; ADetails: IX2LogDetails = nil); overload;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -95,6 +96,7 @@ type
|
|||||||
ID: Word;
|
ID: Word;
|
||||||
Version: Byte;
|
Version: Byte;
|
||||||
Size: Word;
|
Size: Word;
|
||||||
|
DateTime: TDateTime;
|
||||||
Level: TX2LogLevel;
|
Level: TX2LogLevel;
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -15,14 +15,15 @@ type
|
|||||||
private
|
private
|
||||||
FLogLevels: TX2LogLevels;
|
FLogLevels: TX2LogLevels;
|
||||||
protected
|
protected
|
||||||
procedure DoLog(ALevel: TX2LogLevel; const AMessage: string; ADetails: IX2LogDetails); virtual; abstract;
|
procedure DoLog(ALevel: TX2LogLevel; ADateTime: TDateTime; const AMessage: string; ADetails: IX2LogDetails); virtual; abstract;
|
||||||
|
|
||||||
property LogLevels: TX2LogLevels read FLogLevels;
|
property LogLevels: TX2LogLevels read FLogLevels;
|
||||||
public
|
public
|
||||||
constructor Create(ALogLevels: TX2LogLevels = X2LogLevelsDefault);
|
constructor Create(ALogLevels: TX2LogLevels = X2LogLevelsDefault);
|
||||||
|
|
||||||
{ IX2LogBase }
|
{ IX2LogBase }
|
||||||
procedure Log(ALevel: TX2LogLevel; const AMessage: string; ADetails: IX2LogDetails = nil);
|
procedure Log(ALevel: TX2LogLevel; const AMessage: string; ADetails: IX2LogDetails = nil); overload;
|
||||||
|
procedure Log(ALevel: TX2LogLevel; ADateTime: TDateTime; const AMessage: string; ADetails: IX2LogDetails = nil); overload;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -39,9 +40,15 @@ end;
|
|||||||
|
|
||||||
|
|
||||||
procedure TX2LogCustomObserver.Log(ALevel: TX2LogLevel; const AMessage: string; ADetails: IX2LogDetails);
|
procedure TX2LogCustomObserver.Log(ALevel: TX2LogLevel; const AMessage: string; ADetails: IX2LogDetails);
|
||||||
|
begin
|
||||||
|
Log(ALevel, Now, AMessage, ADetails);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure TX2LogCustomObserver.Log(ALevel: TX2LogLevel; ADateTime: TDateTime; const AMessage: string; ADetails: IX2LogDetails);
|
||||||
begin
|
begin
|
||||||
if ALevel in LogLevels then
|
if ALevel in LogLevels then
|
||||||
DoLog(ALevel, AMessage, ADetails);
|
DoLog(ALevel, ADateTime, AMessage, ADetails);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
@ -20,7 +20,7 @@ type
|
|||||||
protected
|
protected
|
||||||
function CreateWorkerThread: TX2LogObserverWorkerThread; virtual; abstract;
|
function CreateWorkerThread: TX2LogObserverWorkerThread; virtual; abstract;
|
||||||
|
|
||||||
procedure DoLog(ALevel: TX2LogLevel; const AMessage: string; ADetails: IX2LogDetails); override;
|
procedure DoLog(ALevel: TX2LogLevel; ADateTime: TDateTime; const AMessage: string; ADetails: IX2LogDetails); override;
|
||||||
|
|
||||||
property WorkerThread: TX2LogObserverWorkerThread read FWorkerThread;
|
property WorkerThread: TX2LogObserverWorkerThread read FWorkerThread;
|
||||||
public
|
public
|
||||||
@ -33,13 +33,15 @@ type
|
|||||||
private
|
private
|
||||||
FDetails: IX2LogDetails;
|
FDetails: IX2LogDetails;
|
||||||
FLevel: TX2LogLevel;
|
FLevel: TX2LogLevel;
|
||||||
|
FDateTime: TDateTime;
|
||||||
FMessage: string;
|
FMessage: string;
|
||||||
public
|
public
|
||||||
constructor Create(ALevel: TX2LogLevel; const AMessage: string; ADetails: IX2LogDetails); overload;
|
constructor Create(ALevel: TX2LogLevel; ADateTime: TDateTime; const AMessage: string; ADetails: IX2LogDetails); overload;
|
||||||
constructor Create(AEntry: TX2LogQueueEntry); overload;
|
constructor Create(AEntry: TX2LogQueueEntry); overload;
|
||||||
|
|
||||||
procedure Assign(Source: TPersistent); override;
|
procedure Assign(Source: TPersistent); override;
|
||||||
|
|
||||||
|
property DateTime: TDateTime read FDateTime;
|
||||||
property Details: IX2LogDetails read FDetails;
|
property Details: IX2LogDetails read FDetails;
|
||||||
property Level: TX2LogLevel read FLevel;
|
property Level: TX2LogLevel read FLevel;
|
||||||
property Message: string read FMessage;
|
property Message: string read FMessage;
|
||||||
@ -51,6 +53,7 @@ type
|
|||||||
FFileName: string;
|
FFileName: string;
|
||||||
FLogQueue: TObjectQueue<TX2LogQueueEntry>;
|
FLogQueue: TObjectQueue<TX2LogQueueEntry>;
|
||||||
FLogQueueSignal: TEvent;
|
FLogQueueSignal: TEvent;
|
||||||
|
FThreadStartSignal: TEvent;
|
||||||
protected
|
protected
|
||||||
procedure Execute; override;
|
procedure Execute; override;
|
||||||
procedure TerminatedSet; override;
|
procedure TerminatedSet; override;
|
||||||
@ -68,7 +71,7 @@ type
|
|||||||
constructor Create;
|
constructor Create;
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
|
|
||||||
procedure Log(ALevel: TX2LogLevel; const AMessage: string; ADetails: IX2LogDetails);
|
procedure Log(ALevel: TX2LogLevel; ADateTime: TDateTime; const AMessage: string; ADetails: IX2LogDetails);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -94,19 +97,20 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure TX2LogCustomThreadedObserver.DoLog(ALevel: TX2LogLevel; const AMessage: string; ADetails: IX2LogDetails);
|
procedure TX2LogCustomThreadedObserver.DoLog(ALevel: TX2LogLevel; ADateTime: TDateTime; const AMessage: string; ADetails: IX2LogDetails);
|
||||||
begin
|
begin
|
||||||
WorkerThread.Log(ALevel, AMessage, ADetails);
|
WorkerThread.Log(ALevel, ADateTime, AMessage, ADetails);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{ TX2LogQueueEntry }
|
{ TX2LogQueueEntry }
|
||||||
constructor TX2LogQueueEntry.Create(ALevel: TX2LogLevel; const AMessage: string; ADetails: IX2LogDetails);
|
constructor TX2LogQueueEntry.Create(ALevel: TX2LogLevel; ADateTime: TDateTime; const AMessage: string; ADetails: IX2LogDetails);
|
||||||
begin
|
begin
|
||||||
inherited Create;
|
inherited Create;
|
||||||
|
|
||||||
FLevel := ALevel;
|
FLevel := ALevel;
|
||||||
|
FDateTime := ADateTime;
|
||||||
FMessage := AMessage;
|
FMessage := AMessage;
|
||||||
FDetails := ADetails;
|
FDetails := ADetails;
|
||||||
end;
|
end;
|
||||||
@ -130,6 +134,7 @@ begin
|
|||||||
entrySource := TX2LogQueueEntry(Source);
|
entrySource := TX2LogQueueEntry(Source);
|
||||||
|
|
||||||
FLevel := entrySource.Level;
|
FLevel := entrySource.Level;
|
||||||
|
FDateTime := entrySource.DateTime;
|
||||||
FMessage := entrySource.Message;
|
FMessage := entrySource.Message;
|
||||||
FDetails := entrySource.Details;
|
FDetails := entrySource.Details;
|
||||||
end else
|
end else
|
||||||
@ -140,6 +145,7 @@ end;
|
|||||||
{ TX2LogObserverWorkerThread }
|
{ TX2LogObserverWorkerThread }
|
||||||
constructor TX2LogObserverWorkerThread.Create;
|
constructor TX2LogObserverWorkerThread.Create;
|
||||||
begin
|
begin
|
||||||
|
FThreadStartSignal := TEvent.Create(nil, True, False, '');
|
||||||
FLogQueueSignal := TEvent.Create(nil, False, False, '');
|
FLogQueueSignal := TEvent.Create(nil, False, False, '');
|
||||||
FLogQueue := TObjectQueue<TX2LogQueueEntry>.Create(True);
|
FLogQueue := TObjectQueue<TX2LogQueueEntry>.Create(True);
|
||||||
|
|
||||||
@ -149,18 +155,24 @@ end;
|
|||||||
|
|
||||||
destructor TX2LogObserverWorkerThread.Destroy;
|
destructor TX2LogObserverWorkerThread.Destroy;
|
||||||
begin
|
begin
|
||||||
|
{ For very short-lived observers (for example, the "Save as" functionality
|
||||||
|
of the observer form) the WorkerThread can be destroyed before the thread
|
||||||
|
has a chance to properly start and clear out it's queue. }
|
||||||
|
FThreadStartSignal.WaitFor(INFINITE);
|
||||||
|
|
||||||
inherited Destroy;
|
inherited Destroy;
|
||||||
|
|
||||||
FreeAndNil(FLogQueue);
|
FreeAndNil(FLogQueue);
|
||||||
FreeAndNil(FLogQueueSignal);
|
FreeAndNil(FLogQueueSignal);
|
||||||
|
FreeAndNil(FThreadStartSignal);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure TX2LogObserverWorkerThread.Log(ALevel: TX2LogLevel; const AMessage: string; ADetails: IX2LogDetails);
|
procedure TX2LogObserverWorkerThread.Log(ALevel: TX2LogLevel; ADateTime: TDateTime; const AMessage: string; ADetails: IX2LogDetails);
|
||||||
begin
|
begin
|
||||||
TMonitor.Enter(LogQueue);
|
TMonitor.Enter(LogQueue);
|
||||||
try
|
try
|
||||||
LogQueue.Enqueue(TX2LogQueueEntry.Create(ALevel, AMessage, ADetails));
|
LogQueue.Enqueue(TX2LogQueueEntry.Create(ALevel, ADateTime, AMessage, ADetails));
|
||||||
finally
|
finally
|
||||||
TMonitor.Exit(LogQueue);
|
TMonitor.Exit(LogQueue);
|
||||||
end;
|
end;
|
||||||
@ -174,17 +186,17 @@ var
|
|||||||
entry: TX2LogQueueEntry;
|
entry: TX2LogQueueEntry;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
FThreadStartSignal.SetEvent;
|
||||||
NameThreadForDebugging('TX2LogObserverWorkerThread');
|
NameThreadForDebugging('TX2LogObserverWorkerThread');
|
||||||
|
|
||||||
Setup;
|
Setup;
|
||||||
try
|
try
|
||||||
while not Terminated do
|
while True do
|
||||||
begin
|
begin
|
||||||
|
{ When Terminated, flush the queue }
|
||||||
|
if not Terminated then
|
||||||
WaitForEntry;
|
WaitForEntry;
|
||||||
|
|
||||||
if Terminated then
|
|
||||||
break;
|
|
||||||
|
|
||||||
entry := nil;
|
entry := nil;
|
||||||
TMonitor.Enter(LogQueue);
|
TMonitor.Enter(LogQueue);
|
||||||
try
|
try
|
||||||
@ -199,7 +211,8 @@ begin
|
|||||||
ProcessEntry(entry);
|
ProcessEntry(entry);
|
||||||
finally
|
finally
|
||||||
FreeAndNil(entry);
|
FreeAndNil(entry);
|
||||||
end;
|
end else if Terminated then
|
||||||
|
break;
|
||||||
end;
|
end;
|
||||||
finally
|
finally
|
||||||
Cleanup;
|
Cleanup;
|
||||||
|
@ -7,7 +7,7 @@ uses
|
|||||||
|
|
||||||
|
|
||||||
type
|
type
|
||||||
TX2LogEvent = procedure(Sender: TObject; Level: TX2LogLevel; const Msg: string; Details: IX2LogDetails) of object;
|
TX2LogEvent = procedure(Sender: TObject; Level: TX2LogLevel; DateTime: TDateTime; const Msg: string; Details: IX2LogDetails) of object;
|
||||||
|
|
||||||
|
|
||||||
TX2LogEventObserver = class(TX2LogCustomObserver)
|
TX2LogEventObserver = class(TX2LogCustomObserver)
|
||||||
@ -15,7 +15,7 @@ type
|
|||||||
FOnLog: TX2LogEvent;
|
FOnLog: TX2LogEvent;
|
||||||
FRunInMainThread: Boolean;
|
FRunInMainThread: Boolean;
|
||||||
protected
|
protected
|
||||||
procedure DoLog(ALevel: TX2LogLevel; const AMessage: string; ADetails: IX2LogDetails); override;
|
procedure DoLog(ALevel: TX2LogLevel; ADateTime: TDateTime; const AMessage: string; ADetails: IX2LogDetails); override;
|
||||||
public
|
public
|
||||||
constructor Create(ALogLevels: TX2LogLevels = X2LogLevelsDefault); overload;
|
constructor Create(ALogLevels: TX2LogLevels = X2LogLevelsDefault); overload;
|
||||||
constructor Create(AOnLog: TX2LogEvent; ALogLevels: TX2LogLevels = X2LogLevelsDefault); overload;
|
constructor Create(AOnLog: TX2LogEvent; ALogLevels: TX2LogLevels = X2LogLevelsDefault); overload;
|
||||||
@ -48,7 +48,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure TX2LogEventObserver.DoLog(ALevel: TX2LogLevel; const AMessage: string; ADetails: IX2LogDetails);
|
procedure TX2LogEventObserver.DoLog(ALevel: TX2LogLevel; ADateTime: TDateTime; const AMessage: string; ADetails: IX2LogDetails);
|
||||||
begin
|
begin
|
||||||
if Assigned(FOnLog) then
|
if Assigned(FOnLog) then
|
||||||
begin
|
begin
|
||||||
@ -58,10 +58,10 @@ begin
|
|||||||
procedure
|
procedure
|
||||||
begin
|
begin
|
||||||
if Assigned(FOnLog) then
|
if Assigned(FOnLog) then
|
||||||
FOnLog(Self, ALevel, AMessage, ADetails);
|
FOnLog(Self, ALevel, ADateTime, AMessage, ADetails);
|
||||||
end);
|
end);
|
||||||
end else
|
end else
|
||||||
FOnLog(Self, ALevel, AMessage, ADetails);
|
FOnLog(Self, ALevel, ADateTime, AMessage, ADetails);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ begin
|
|||||||
if Supports(AEntry.Details, IX2LogDetailsStreamable, logDetailsStreamable) then
|
if Supports(AEntry.Details, IX2LogDetailsStreamable, logDetailsStreamable) then
|
||||||
begin
|
begin
|
||||||
detailsExtension := ExtractFileExt(FileName);
|
detailsExtension := ExtractFileExt(FileName);
|
||||||
baseReportFileName := ChangeFileExt(FileName, '_' + FormatDateTime(GetLogResourceString(@LogFileNameDateFormat), Now));
|
baseReportFileName := ChangeFileExt(FileName, '_' + FormatDateTime(GetLogResourceString(@LogFileNameDateFormat), AEntry.DateTime));
|
||||||
detailsFileName := baseReportFileName + detailsExtension;
|
detailsFileName := baseReportFileName + detailsExtension;
|
||||||
detailsNumber := 0;
|
detailsNumber := 0;
|
||||||
|
|
||||||
@ -170,7 +170,7 @@ begin
|
|||||||
{ Append line to log file }
|
{ Append line to log file }
|
||||||
writer := TFile.AppendText(FileName);
|
writer := TFile.AppendText(FileName);
|
||||||
try
|
try
|
||||||
writer.WriteLine('[' + FormatDateTime(GetLogResourceString(@LogFileLineDateFormat), Now) + '] ' +
|
writer.WriteLine('[' + FormatDateTime(GetLogResourceString(@LogFileLineDateFormat), AEntry.DateTime) + '] ' +
|
||||||
GetLogLevelText(AEntry.Level) + ': ' + errorMsg);
|
GetLogLevelText(AEntry.Level) + ': ' + errorMsg);
|
||||||
finally
|
finally
|
||||||
FreeAndNil(writer);
|
FreeAndNil(writer);
|
||||||
|
@ -10,6 +10,7 @@ object X2LogObserverMonitorForm: TX2LogObserverMonitorForm
|
|||||||
Font.Height = -11
|
Font.Height = -11
|
||||||
Font.Name = 'Tahoma'
|
Font.Name = 'Tahoma'
|
||||||
Font.Style = []
|
Font.Style = []
|
||||||
|
Menu = mmMain
|
||||||
OldCreateOrder = False
|
OldCreateOrder = False
|
||||||
Position = poScreenCenter
|
Position = poScreenCenter
|
||||||
ShowHint = True
|
ShowHint = True
|
||||||
@ -181,7 +182,7 @@ object X2LogObserverMonitorForm: TX2LogObserverMonitorForm
|
|||||||
end
|
end
|
||||||
item
|
item
|
||||||
Position = 2
|
Position = 2
|
||||||
Width = 424
|
Width = 428
|
||||||
WideText = 'Message'
|
WideText = 'Message'
|
||||||
end>
|
end>
|
||||||
end
|
end
|
||||||
@ -198,24 +199,24 @@ object X2LogObserverMonitorForm: TX2LogObserverMonitorForm
|
|||||||
ShowCaptions = True
|
ShowCaptions = True
|
||||||
TabOrder = 1
|
TabOrder = 1
|
||||||
OnCustomDraw = ToolbarCustomDraw
|
OnCustomDraw = ToolbarCustomDraw
|
||||||
object tbClear: TToolButton
|
|
||||||
Left = 0
|
|
||||||
Top = 0
|
|
||||||
Action = actClear
|
|
||||||
AutoSize = True
|
|
||||||
end
|
|
||||||
object tbPause: TToolButton
|
object tbPause: TToolButton
|
||||||
Left = 56
|
Left = 0
|
||||||
Top = 0
|
Top = 0
|
||||||
Action = actPause
|
Action = actPause
|
||||||
AutoSize = True
|
AutoSize = True
|
||||||
Style = tbsCheck
|
Style = tbsCheck
|
||||||
end
|
end
|
||||||
|
object tbClear: TToolButton
|
||||||
|
Left = 60
|
||||||
|
Top = 0
|
||||||
|
Action = actClear
|
||||||
|
AutoSize = True
|
||||||
|
end
|
||||||
object lblFilter: TLabel
|
object lblFilter: TLabel
|
||||||
Left = 116
|
Left = 116
|
||||||
Top = 0
|
Top = 0
|
||||||
Width = 46
|
Width = 46
|
||||||
Height = 22
|
Height = 13
|
||||||
Caption = ' Filter: '
|
Caption = ' Filter: '
|
||||||
Layout = tlCenter
|
Layout = tlCenter
|
||||||
end
|
end
|
||||||
@ -266,7 +267,7 @@ object X2LogObserverMonitorForm: TX2LogObserverMonitorForm
|
|||||||
Left = 448
|
Left = 448
|
||||||
Top = 48
|
Top = 48
|
||||||
Bitmap = {
|
Bitmap = {
|
||||||
494C01010A004000D00010001000FFFFFFFFFF10FFFFFFFFFFFFFFFF424D3600
|
494C01010A004000EC0010001000FFFFFFFFFF10FFFFFFFFFFFFFFFF424D3600
|
||||||
0000000000003600000028000000400000003000000001002000000000000030
|
0000000000003600000028000000400000003000000001002000000000000030
|
||||||
0000000000000000000000000000000000000000000000000000000000000000
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
0000000000000000000000000000000000000000000000000000000000000000
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
@ -722,15 +723,97 @@ object X2LogObserverMonitorForm: TX2LogObserverMonitorForm
|
|||||||
end
|
end
|
||||||
object actWordWrap: TAction
|
object actWordWrap: TAction
|
||||||
AutoCheck = True
|
AutoCheck = True
|
||||||
Caption = '&Word wrap'
|
Caption = 'Word wrap'
|
||||||
Enabled = False
|
Enabled = False
|
||||||
ImageIndex = 9
|
ImageIndex = 9
|
||||||
OnExecute = actWordWrapExecute
|
OnExecute = actWordWrapExecute
|
||||||
end
|
end
|
||||||
|
object actClose: TAction
|
||||||
|
Caption = '&Close'
|
||||||
|
OnExecute = actCloseExecute
|
||||||
|
end
|
||||||
|
object actAlwaysOnTop: TAction
|
||||||
|
Caption = 'Always on top'
|
||||||
|
OnExecute = actAlwaysOnTopExecute
|
||||||
|
end
|
||||||
|
object actSaveAs: TAction
|
||||||
|
Caption = '&Save as...'
|
||||||
|
ImageIndex = 5
|
||||||
|
OnExecute = actSaveAsExecute
|
||||||
|
end
|
||||||
end
|
end
|
||||||
object sdDetails: TSaveDialog
|
object sdDetails: TSaveDialog
|
||||||
Options = [ofOverwritePrompt, ofHideReadOnly, ofEnableSizing]
|
Options = [ofOverwritePrompt, ofHideReadOnly, ofEnableSizing]
|
||||||
Left = 512
|
Left = 512
|
||||||
Top = 112
|
Top = 112
|
||||||
end
|
end
|
||||||
|
object mmMain: TMainMenu
|
||||||
|
Images = ilsLog
|
||||||
|
Left = 448
|
||||||
|
Top = 112
|
||||||
|
object mmMainFile: TMenuItem
|
||||||
|
Caption = 'File'
|
||||||
|
object mmMainFileSaveAs: TMenuItem
|
||||||
|
Action = actSaveAs
|
||||||
|
end
|
||||||
|
object mmMainFileSep1: TMenuItem
|
||||||
|
Caption = '-'
|
||||||
|
end
|
||||||
|
object mmMainFileClose: TMenuItem
|
||||||
|
Action = actClose
|
||||||
|
end
|
||||||
|
end
|
||||||
|
object mmMainLog: TMenuItem
|
||||||
|
Caption = 'Log'
|
||||||
|
object mmMainLogPause: TMenuItem
|
||||||
|
Action = actPause
|
||||||
|
AutoCheck = True
|
||||||
|
end
|
||||||
|
object mmMainLogClear: TMenuItem
|
||||||
|
Action = actClear
|
||||||
|
end
|
||||||
|
object mmMainLogSep1: TMenuItem
|
||||||
|
Caption = '-'
|
||||||
|
end
|
||||||
|
object mmMainLogVerbose: TMenuItem
|
||||||
|
Action = actShowVerbose
|
||||||
|
end
|
||||||
|
object mmMainLogInfo: TMenuItem
|
||||||
|
Action = actShowInfo
|
||||||
|
end
|
||||||
|
object mmMainLogWarning: TMenuItem
|
||||||
|
Action = actShowWarning
|
||||||
|
end
|
||||||
|
object mmMainLogError: TMenuItem
|
||||||
|
Action = actShowError
|
||||||
|
end
|
||||||
|
end
|
||||||
|
object mmMainDetails: TMenuItem
|
||||||
|
Caption = 'Details'
|
||||||
|
object mmMainDetailsCopy: TMenuItem
|
||||||
|
Action = actCopyDetails
|
||||||
|
end
|
||||||
|
object mmMainDetailsSave: TMenuItem
|
||||||
|
Action = actSaveDetails
|
||||||
|
end
|
||||||
|
object mmMainDetailsSep1: TMenuItem
|
||||||
|
Caption = '-'
|
||||||
|
end
|
||||||
|
object mmMainDetailsWordWrap: TMenuItem
|
||||||
|
Action = actWordWrap
|
||||||
|
AutoCheck = True
|
||||||
|
end
|
||||||
|
end
|
||||||
|
object mmMainWindow: TMenuItem
|
||||||
|
Caption = 'Window'
|
||||||
|
object mmMainWindowAlwaysOnTop: TMenuItem
|
||||||
|
Action = actAlwaysOnTop
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
object sdSaveAs: TSaveDialog
|
||||||
|
Options = [ofOverwritePrompt, ofHideReadOnly, ofEnableSizing]
|
||||||
|
Left = 512
|
||||||
|
Top = 176
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -18,7 +18,7 @@ uses
|
|||||||
Winapi.Messages,
|
Winapi.Messages,
|
||||||
|
|
||||||
X2Log.Details.Intf,
|
X2Log.Details.Intf,
|
||||||
X2Log.Intf;
|
X2Log.Intf, Vcl.Menus;
|
||||||
|
|
||||||
|
|
||||||
const
|
const
|
||||||
@ -70,6 +70,30 @@ type
|
|||||||
tbWordWrap: TToolButton;
|
tbWordWrap: TToolButton;
|
||||||
tbDetailsSep1: TToolButton;
|
tbDetailsSep1: TToolButton;
|
||||||
actWordWrap: TAction;
|
actWordWrap: TAction;
|
||||||
|
mmMain: TMainMenu;
|
||||||
|
mmMainFile: TMenuItem;
|
||||||
|
mmMainLog: TMenuItem;
|
||||||
|
mmMainDetails: TMenuItem;
|
||||||
|
mmMainWindow: TMenuItem;
|
||||||
|
actClose: TAction;
|
||||||
|
mmMainFileClose: TMenuItem;
|
||||||
|
mmMainLogClear: TMenuItem;
|
||||||
|
mmMainLogPause: TMenuItem;
|
||||||
|
mmMainLogSep1: TMenuItem;
|
||||||
|
mmMainLogVerbose: TMenuItem;
|
||||||
|
mmMainLogInfo: TMenuItem;
|
||||||
|
mmMainLogWarning: TMenuItem;
|
||||||
|
mmMainLogError: TMenuItem;
|
||||||
|
mmMainDetailsCopy: TMenuItem;
|
||||||
|
mmMainDetailsSave: TMenuItem;
|
||||||
|
mmMainDetailsWordWrap: TMenuItem;
|
||||||
|
mmMainDetailsSep1: TMenuItem;
|
||||||
|
actAlwaysOnTop: TAction;
|
||||||
|
mmMainWindowAlwaysOnTop: TMenuItem;
|
||||||
|
actSaveAs: TAction;
|
||||||
|
mmMainFileSep1: TMenuItem;
|
||||||
|
mmMainFileSaveAs: TMenuItem;
|
||||||
|
sdSaveAs: TSaveDialog;
|
||||||
|
|
||||||
procedure FormShow(Sender: TObject);
|
procedure FormShow(Sender: TObject);
|
||||||
procedure FormClose(Sender: TObject; var Action: TCloseAction);
|
procedure FormClose(Sender: TObject; var Action: TCloseAction);
|
||||||
@ -78,6 +102,7 @@ type
|
|||||||
procedure vstLogGetHint(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; var LineBreakStyle: TVTTooltipLineBreakStyle; var HintText: string);
|
procedure vstLogGetHint(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; var LineBreakStyle: TVTTooltipLineBreakStyle; var HintText: string);
|
||||||
procedure vstLogGetImageIndex(Sender: TBaseVirtualTree; Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex; var Ghosted: Boolean; var ImageIndex: Integer);
|
procedure vstLogGetImageIndex(Sender: TBaseVirtualTree; Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex; var Ghosted: Boolean; var ImageIndex: Integer);
|
||||||
procedure vstLogFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex);
|
procedure vstLogFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex);
|
||||||
|
procedure actCloseExecute(Sender: TObject);
|
||||||
procedure actClearExecute(Sender: TObject);
|
procedure actClearExecute(Sender: TObject);
|
||||||
procedure actCopyDetailsExecute(Sender: TObject);
|
procedure actCopyDetailsExecute(Sender: TObject);
|
||||||
procedure actSaveDetailsExecute(Sender: TObject);
|
procedure actSaveDetailsExecute(Sender: TObject);
|
||||||
@ -88,6 +113,8 @@ type
|
|||||||
procedure actShowWarningExecute(Sender: TObject);
|
procedure actShowWarningExecute(Sender: TObject);
|
||||||
procedure actShowErrorExecute(Sender: TObject);
|
procedure actShowErrorExecute(Sender: TObject);
|
||||||
procedure actWordWrapExecute(Sender: TObject);
|
procedure actWordWrapExecute(Sender: TObject);
|
||||||
|
procedure actAlwaysOnTopExecute(Sender: TObject);
|
||||||
|
procedure actSaveAsExecute(Sender: TObject);
|
||||||
private class var
|
private class var
|
||||||
FInstances: TMonitorFormDictionary;
|
FInstances: TMonitorFormDictionary;
|
||||||
private
|
private
|
||||||
@ -128,6 +155,8 @@ type
|
|||||||
procedure SetVisibleDetails(AControl: TControl);
|
procedure SetVisibleDetails(AControl: TControl);
|
||||||
procedure SetWordWrap(AValue: Boolean);
|
procedure SetWordWrap(AValue: Boolean);
|
||||||
|
|
||||||
|
procedure ExportLog(ALog: IX2LogBase);
|
||||||
|
|
||||||
property Closed: Boolean read FClosed;
|
property Closed: Boolean read FClosed;
|
||||||
property Details: IX2LogDetails read FDetails;
|
property Details: IX2LogDetails read FDetails;
|
||||||
property LockCount: Integer read FLockCount;
|
property LockCount: Integer read FLockCount;
|
||||||
@ -154,7 +183,8 @@ type
|
|||||||
procedure Unlock;
|
procedure Unlock;
|
||||||
|
|
||||||
{ IX2LogObserver }
|
{ IX2LogObserver }
|
||||||
procedure Log(ALevel: TX2LogLevel; const AMessage: string; ADetails: IX2LogDetails);
|
procedure Log(ALevel: TX2LogLevel; const AMessage: string; ADetails: IX2LogDetails); overload;
|
||||||
|
procedure Log(ALevel: TX2LogLevel; ADateTime: TDateTime; const AMessage: string; ADetails: IX2LogDetails); overload;
|
||||||
|
|
||||||
property FreeOnClose: Boolean read FFreeOnClose write FFreeOnClose;
|
property FreeOnClose: Boolean read FFreeOnClose write FFreeOnClose;
|
||||||
property MaxEntries: Cardinal read FMaxEntries write FMaxEntries;
|
property MaxEntries: Cardinal read FMaxEntries write FMaxEntries;
|
||||||
@ -170,7 +200,8 @@ uses
|
|||||||
Vcl.Themes,
|
Vcl.Themes,
|
||||||
Winapi.Windows,
|
Winapi.Windows,
|
||||||
|
|
||||||
X2Log.Constants;
|
X2Log.Constants,
|
||||||
|
X2Log.Observer.LogFile;
|
||||||
|
|
||||||
|
|
||||||
{$R *.dfm}
|
{$R *.dfm}
|
||||||
@ -184,7 +215,7 @@ type
|
|||||||
Message: string;
|
Message: string;
|
||||||
Details: IX2LogDetails;
|
Details: IX2LogDetails;
|
||||||
|
|
||||||
procedure Initialize(APaused: Boolean; ALevel: TX2LogLevel; const AMessage: string; ADetails: IX2LogDetails);
|
procedure Initialize(APaused: Boolean; ALevel: TX2LogLevel; ADateTime: TDateTime; const AMessage: string; ADetails: IX2LogDetails);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
PLogEntryNodeData = ^TLogEntryNodeData;
|
PLogEntryNodeData = ^TLogEntryNodeData;
|
||||||
@ -199,9 +230,9 @@ const
|
|||||||
|
|
||||||
|
|
||||||
{ TLogEntryNode }
|
{ TLogEntryNode }
|
||||||
procedure TLogEntryNodeData.Initialize(APaused: Boolean; ALevel: TX2LogLevel; const AMessage: string; ADetails: IX2LogDetails);
|
procedure TLogEntryNodeData.Initialize(APaused: Boolean; ALevel: TX2LogLevel; ADateTime: TDateTime; const AMessage: string; ADetails: IX2LogDetails);
|
||||||
begin
|
begin
|
||||||
Self.Time := Now;
|
Self.Time := ADateTime;
|
||||||
Self.Paused := APaused;
|
Self.Paused := APaused;
|
||||||
Self.Level := ALevel;
|
Self.Level := ALevel;
|
||||||
Self.Message := AMessage;
|
Self.Message := AMessage;
|
||||||
@ -316,12 +347,21 @@ begin
|
|||||||
vstLog.Header.Columns[ColumnTime].Text := GetLogResourceString(@LogMonitorFormColumnTime);
|
vstLog.Header.Columns[ColumnTime].Text := GetLogResourceString(@LogMonitorFormColumnTime);
|
||||||
vstLog.Header.Columns[ColumnMessage].Text := GetLogResourceString(@LogMonitorFormColumnMessage);
|
vstLog.Header.Columns[ColumnMessage].Text := GetLogResourceString(@LogMonitorFormColumnMessage);
|
||||||
|
|
||||||
|
mmMainFile.Caption := GetLogResourceString(@LogMonitorFormMenuFile);
|
||||||
|
mmMainLog.Caption := GetLogResourceString(@LogMonitorFormMenuLog);
|
||||||
|
mmMainDetails.Caption := GetLogResourceString(@LogMonitorFormMenuDetails);
|
||||||
|
mmMainWindow.Caption := GetLogResourceString(@LogMonitorFormMenuWindow);
|
||||||
|
|
||||||
|
actSaveAs.Caption := GetLogResourceString(@LogMonitorFormMenuFileSaveAs);
|
||||||
|
actClose.Caption := GetLogResourceString(@LogMonitorFormMenuFileClose);
|
||||||
actClear.Caption := GetLogResourceString(@LogMonitorFormButtonClear);
|
actClear.Caption := GetLogResourceString(@LogMonitorFormButtonClear);
|
||||||
actPause.Caption := GetLogResourceString(@LogMonitorFormButtonPause);
|
actPause.Caption := GetLogResourceString(@LogMonitorFormButtonPause);
|
||||||
actCopyDetails.Caption := GetLogResourceString(@LogMonitorFormButtonCopyDetails);
|
actCopyDetails.Caption := GetLogResourceString(@LogMonitorFormButtonCopyDetails);
|
||||||
actSaveDetails.Caption := GetLogResourceString(@LogMonitorFormButtonSaveDetails);
|
actSaveDetails.Caption := GetLogResourceString(@LogMonitorFormButtonSaveDetails);
|
||||||
|
actAlwaysOnTop.Caption := GetLogResourceString(@LogMonitorFormMenuWindowAlwaysOnTop);
|
||||||
|
|
||||||
sdDetails.Filter := GetLogResourceString(@LogMonitorFormSaveDetailsFilter);
|
sdDetails.Filter := GetLogResourceString(@LogMonitorFormSaveDetailsFilter);
|
||||||
|
sdSaveAs.Filter := GetLogResourceString(@LogMonitorFormSaveDetailsSaveAs);
|
||||||
|
|
||||||
lblFilter.Caption := ' ' + GetLogResourceString(@LogMonitorFormButtonFilter) + ' ';
|
lblFilter.Caption := ' ' + GetLogResourceString(@LogMonitorFormButtonFilter) + ' ';
|
||||||
actShowVerbose.Caption := GetLogLevelText(TX2LogLevel.Verbose);
|
actShowVerbose.Caption := GetLogLevelText(TX2LogLevel.Verbose);
|
||||||
@ -417,6 +457,12 @@ end;
|
|||||||
|
|
||||||
|
|
||||||
procedure TX2LogObserverMonitorForm.Log(ALevel: TX2LogLevel; const AMessage: string; ADetails: IX2LogDetails);
|
procedure TX2LogObserverMonitorForm.Log(ALevel: TX2LogLevel; const AMessage: string; ADetails: IX2LogDetails);
|
||||||
|
begin
|
||||||
|
Log(ALevel, Now, AMessage, ADetails);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure TX2LogObserverMonitorForm.Log(ALevel: TX2LogLevel; ADateTime: TDateTime; const AMessage: string; ADetails: IX2LogDetails);
|
||||||
var
|
var
|
||||||
node: PVirtualNode;
|
node: PVirtualNode;
|
||||||
nodeData: PLogEntryNodeData;
|
nodeData: PLogEntryNodeData;
|
||||||
@ -440,7 +486,7 @@ begin
|
|||||||
{ BeginUpdate causes OnInitNode to be triggered on-demand,
|
{ BeginUpdate causes OnInitNode to be triggered on-demand,
|
||||||
moved Initialize call here }
|
moved Initialize call here }
|
||||||
Initialize(nodeData^);
|
Initialize(nodeData^);
|
||||||
nodeData^.Initialize(Paused, ALevel, AMessage, ADetails);
|
nodeData^.Initialize(Paused, ALevel, ADateTime, AMessage, ADetails);
|
||||||
|
|
||||||
vstLog.IsVisible[node] := (not Paused) and (ALevel in VisibleLevels);
|
vstLog.IsVisible[node] := (not Paused) and (ALevel in VisibleLevels);
|
||||||
|
|
||||||
@ -484,6 +530,7 @@ end;
|
|||||||
procedure TX2LogObserverMonitorForm.UpdateUI;
|
procedure TX2LogObserverMonitorForm.UpdateUI;
|
||||||
begin
|
begin
|
||||||
actClear.Enabled := (vstLog.RootNodeCount > 0);
|
actClear.Enabled := (vstLog.RootNodeCount > 0);
|
||||||
|
actSaveAs.Enabled := (vstLog.RootNodeCount > 0);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -706,6 +753,20 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure TX2LogObserverMonitorForm.ExportLog(ALog: IX2LogBase);
|
||||||
|
var
|
||||||
|
node: PVirtualNode;
|
||||||
|
nodeData: PLogEntryNodeData;
|
||||||
|
|
||||||
|
begin
|
||||||
|
for node in vstLog.Nodes do
|
||||||
|
begin
|
||||||
|
nodeData := vstLog.GetNodeData(node);
|
||||||
|
ALog.Log(nodeData^.Level, nodeData^.Time, nodeData^.Message, nodeData^.Details);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure TX2LogObserverMonitorForm.vstLogFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode);
|
procedure TX2LogObserverMonitorForm.vstLogFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode);
|
||||||
var
|
var
|
||||||
nodeData: PLogEntryNodeData;
|
nodeData: PLogEntryNodeData;
|
||||||
@ -787,6 +848,12 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure TX2LogObserverMonitorForm.actCloseExecute(Sender: TObject);
|
||||||
|
begin
|
||||||
|
Close;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure TX2LogObserverMonitorForm.actClearExecute(Sender: TObject);
|
procedure TX2LogObserverMonitorForm.actClearExecute(Sender: TObject);
|
||||||
begin
|
begin
|
||||||
vstLog.Clear;
|
vstLog.Clear;
|
||||||
@ -889,6 +956,33 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure TX2LogObserverMonitorForm.actAlwaysOnTopExecute(Sender: TObject);
|
||||||
|
begin
|
||||||
|
actAlwaysOnTop.Checked := not actAlwaysOnTop.Checked;
|
||||||
|
|
||||||
|
if actAlwaysOnTop.Checked then
|
||||||
|
SetWindowPos(Self.Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE or SWP_NOMOVE or SWP_NOACTIVATE)
|
||||||
|
else
|
||||||
|
SetWindowPos(Self.Handle, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE or SWP_NOMOVE or SWP_NOACTIVATE);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure TX2LogObserverMonitorForm.actSaveAsExecute(Sender: TObject);
|
||||||
|
var
|
||||||
|
logFile: IX2LogBase;
|
||||||
|
|
||||||
|
begin
|
||||||
|
if sdSaveAs.Execute then
|
||||||
|
begin
|
||||||
|
{ Default behaviour of the LogFile observer is to append }
|
||||||
|
System.SysUtils.DeleteFile(sdSaveAs.FileName);
|
||||||
|
|
||||||
|
logFile := TX2LogFileObserver.Create(sdSaveAs.FileName, X2LogLevelsAll);
|
||||||
|
ExportLog(logFile);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure TX2LogObserverMonitorForm.ToolbarCustomDraw(Sender: TToolBar; const ARect: TRect; var DefaultDraw: Boolean);
|
procedure TX2LogObserverMonitorForm.ToolbarCustomDraw(Sender: TToolBar; const ARect: TRect; var DefaultDraw: Boolean);
|
||||||
var
|
var
|
||||||
element: TThemedElementDetails;
|
element: TThemedElementDetails;
|
||||||
|
@ -216,6 +216,7 @@ begin
|
|||||||
header.Version := X2LogMessageVersion;
|
header.Version := X2LogMessageVersion;
|
||||||
header.Size := SizeOf(header);
|
header.Size := SizeOf(header);
|
||||||
header.Level := AEntry.Level;
|
header.Level := AEntry.Level;
|
||||||
|
header.DateTime := AEntry.DateTime;
|
||||||
|
|
||||||
WriteBuffer.WriteBuffer(header, SizeOf(header));
|
WriteBuffer.WriteBuffer(header, SizeOf(header));
|
||||||
|
|
||||||
|
@ -25,9 +25,22 @@ begin
|
|||||||
SetLogResourceString(@LogMonitorFormButtonPause, 'Pauzeren');
|
SetLogResourceString(@LogMonitorFormButtonPause, 'Pauzeren');
|
||||||
SetLogResourceString(@LogMonitorFormButtonCopyDetails, 'Kopiëren');
|
SetLogResourceString(@LogMonitorFormButtonCopyDetails, 'Kopiëren');
|
||||||
SetLogResourceString(@LogMonitorFormButtonSaveDetails, 'Opslaan');
|
SetLogResourceString(@LogMonitorFormButtonSaveDetails, 'Opslaan');
|
||||||
|
SetLogResourceString(@LogMonitorFormButtonWordWrapDetails, 'Terugloop');
|
||||||
|
|
||||||
|
SetLogResourceString(@LogMonitorFormButtonFilter, 'Filter:');
|
||||||
|
|
||||||
|
SetLogResourceString(@LogMonitorFormMenuFile, 'Bestand');
|
||||||
|
SetLogResourceString(@LogMonitorFormMenuFileSaveAs, 'Opslaan als...');
|
||||||
|
SetLogResourceString(@LogMonitorFormMenuFileClose, 'Sluiten');
|
||||||
|
SetLogResourceString(@LogMonitorFormMenuLog, 'Log');
|
||||||
|
SetLogResourceString(@LogMonitorFormMenuDetails, 'Details');
|
||||||
|
SetLogResourceString(@LogMonitorFormMenuWindow, 'Venster');
|
||||||
|
SetLogResourceString(@LogMonitorFormMenuWindowAlwaysOnTop, 'Altijd op voorgrond');
|
||||||
|
|
||||||
SetLogResourceString(@LogMonitorFormStatusPaused, 'Gepauzeerd: %d melding(en) overgeslagen');
|
SetLogResourceString(@LogMonitorFormStatusPaused, 'Gepauzeerd: %d melding(en) overgeslagen');
|
||||||
|
|
||||||
SetLogResourceString(@LogMonitorFormSaveDetailsFilter, 'Alle bestanden (*.*)|*.*');
|
SetLogResourceString(@LogMonitorFormSaveDetailsFilter, 'Alle bestanden (*.*)|*.*');
|
||||||
|
SetLogResourceString(@LogMonitorFormSaveDetailsSaveAs, 'Log bestanden (*.log)|*.log|Alle bestanden (*.*)|*.*');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user