Initial commit - Delphi MES client project
This commit is contained in:
@@ -0,0 +1,662 @@
|
||||
unit uLogManager;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
SysUtils, Classes, System.JSON, System.Threading, System.Generics.Collections,
|
||||
FMX.Forms, FMX.Controls, System.DateUtils;
|
||||
|
||||
type
|
||||
TLogCategory = (lcSystem, lcNetwork, lcDatabase, lcBusiness, lcDevice, lcUI, lcSecurity, lcPerformance);
|
||||
|
||||
TLogCategories = set of TLogCategory;
|
||||
|
||||
TLogLevel = (llTrace, llDebug, llInfo, llWarn, llError, llFatal);
|
||||
|
||||
TLogEntry = record
|
||||
Timestamp: TDateTime;
|
||||
Level: TLogLevel;
|
||||
Category: TLogCategory;
|
||||
Message: string;
|
||||
Tag: string;
|
||||
UserID: string;
|
||||
ThreadID: Cardinal;
|
||||
procedure Clear;
|
||||
end;
|
||||
|
||||
TOnLogEvent = reference to procedure(const LogEntry: TLogEntry);
|
||||
|
||||
TLogManager = class
|
||||
private
|
||||
FLogs: TList<TLogEntry>;
|
||||
FMaxLogCount: Integer;
|
||||
FEnabled: Boolean;
|
||||
FCategories: TLogCategories;
|
||||
FMinLevel: TLogLevel;
|
||||
FOnLog: TOnLogEvent;
|
||||
FLock: TObject;
|
||||
FLogFileDir: string;
|
||||
procedure AddLogInternal(const Entry: TLogEntry);
|
||||
function GetLevelString(Level: TLogLevel): string;
|
||||
function GetCategoryString(Category: TLogCategory): string;
|
||||
public
|
||||
constructor Create; virtual;
|
||||
destructor Destroy; override;
|
||||
procedure Log(Level: TLogLevel; Category: TLogCategory; const Message: string; const Args: array of const); overload;
|
||||
procedure Log(Level: TLogLevel; Category: TLogCategory; const Message: string); overload;
|
||||
procedure Trace(const Message: string; const Args: array of const); overload;
|
||||
procedure Trace(const Message: string); overload;
|
||||
procedure Debug(const Message: string; const Args: array of const); overload;
|
||||
procedure Debug(const Message: string); overload;
|
||||
procedure Info(const Message: string; const Args: array of const); overload;
|
||||
procedure Info(const Message: string); overload;
|
||||
procedure Warn(const Message: string; const Args: array of const); overload;
|
||||
procedure Warn(const Message: string); overload;
|
||||
procedure Error(const Message: string; const Args: array of const); overload;
|
||||
procedure Error(const Message: string); overload;
|
||||
procedure Fatal(const Message: string; const Args: array of const); overload;
|
||||
procedure Fatal(const Message: string); overload;
|
||||
procedure TraceCategory(Category: TLogCategory; const Message: string; const Args: array of const); overload;
|
||||
procedure TraceCategory(Category: TLogCategory; const Message: string); overload;
|
||||
procedure DebugCategory(Category: TLogCategory; const Message: string; const Args: array of const); overload;
|
||||
procedure DebugCategory(Category: TLogCategory; const Message: string); overload;
|
||||
procedure InfoCategory(Category: TLogCategory; const Message: string; const Args: array of const); overload;
|
||||
procedure InfoCategory(Category: TLogCategory; const Message: string); overload;
|
||||
procedure WarnCategory(Category: TLogCategory; const Message: string; const Args: array of const); overload;
|
||||
procedure WarnCategory(Category: TLogCategory; const Message: string); overload;
|
||||
procedure ErrorCategory(Category: TLogCategory; const Message: string; const Args: array of const); overload;
|
||||
procedure ErrorCategory(Category: TLogCategory; const Message: string); overload;
|
||||
procedure FatalCategory(Category: TLogCategory; const Message: string; const Args: array of const); overload;
|
||||
procedure FatalCategory(Category: TLogCategory; const Message: string); overload;
|
||||
procedure LogException(E: Exception; Category: TLogCategory; const AdditionalInfo: string = ''); overload;
|
||||
procedure LogException(E: Exception; const AdditionalInfo: string = ''); overload;
|
||||
procedure LogPerformance(const OperationName: string; const ElapsedMS: Int64);
|
||||
procedure ClearLogs;
|
||||
function GetLogs(Level: TLogLevel; Category: TLogCategory): TArray<TLogEntry>; overload;
|
||||
function GetLogs(Level: TLogLevel; Categories: TLogCategories): TArray<TLogEntry>; overload;
|
||||
function GetLogs(Level: TLogLevel = llTrace): TArray<TLogEntry>; overload;
|
||||
function ExportToJSON: TJSONArray;
|
||||
procedure SaveToFile(const FileName: string);
|
||||
property Enabled: Boolean read FEnabled write FEnabled;
|
||||
property Categories: TLogCategories read FCategories write FCategories;
|
||||
property MinLevel: TLogLevel read FMinLevel write FMinLevel;
|
||||
property MaxLogCount: Integer read FMaxLogCount write FMaxLogCount;
|
||||
property OnLog: TOnLogEvent read FOnLog write FOnLog;
|
||||
property LogFileDir: string read FLogFileDir write FLogFileDir;
|
||||
procedure LogUIOperation(const UIOperation: string; const ControlName: string; const ElapsedMS: Int64 = -1);
|
||||
procedure LogNetworkRequest(const URL: string; const Method: string; const StatusCode: Integer; const ElapsedMS: Int64);
|
||||
procedure LogFormShow(const FormName: string; const ElapsedMS: Int64 = -1);
|
||||
procedure LogFormClose(const FormName: string; const ElapsedMS: Int64 = -1);
|
||||
procedure LogDataOperation(const Operation: string; const RecordCount: Integer; const ElapsedMS: Int64 = -1);
|
||||
end;
|
||||
|
||||
TPerformanceLogger = class
|
||||
private
|
||||
FOperationName: string;
|
||||
FStartTime: TDateTime;
|
||||
FTag: string;
|
||||
public
|
||||
constructor Create(const AOperationName: string; ATag: string = '');
|
||||
destructor Destroy; override;
|
||||
procedure Finish;
|
||||
procedure FinishWithInfo(const Info: string);
|
||||
class function Measure<T>(const AOperationName: string; AFunc: TFunc<T>; ATag: string = ''): T;
|
||||
class procedure MeasureProc(const AOperationName: string; AProc: TProc; ATag: string = '');
|
||||
end;
|
||||
|
||||
TOperationContext = class
|
||||
private
|
||||
FUserID: string;
|
||||
FSessionID: string;
|
||||
FRequestID: string;
|
||||
FStartTime: TDateTime;
|
||||
FTags: TDictionary<string, string>;
|
||||
public
|
||||
constructor Create(const AUserID: string = '');
|
||||
destructor Destroy; override;
|
||||
procedure SetTag(const Key, Value: string);
|
||||
function GetTag(const Key: string): string;
|
||||
procedure ClearTags;
|
||||
property UserID: string read FUserID write FUserID;
|
||||
property SessionID: string read FSessionID write FSessionID;
|
||||
property RequestID: string read FRequestID write FRequestID;
|
||||
end;
|
||||
|
||||
function LogManager: TLogManager;
|
||||
|
||||
implementation
|
||||
|
||||
var
|
||||
FLogManager: TLogManager;
|
||||
|
||||
function LogManager: TLogManager;
|
||||
begin
|
||||
if FLogManager = nil then
|
||||
FLogManager := TLogManager.Create;
|
||||
Result := FLogManager;
|
||||
end;
|
||||
|
||||
{ TLogEntry }
|
||||
|
||||
procedure TLogEntry.Clear;
|
||||
begin
|
||||
Timestamp := 0;
|
||||
Level := llTrace;
|
||||
Category := lcSystem;
|
||||
Message := '';
|
||||
Tag := '';
|
||||
UserID := '';
|
||||
ThreadID := 0;
|
||||
end;
|
||||
|
||||
{ TLogManager }
|
||||
|
||||
constructor TLogManager.Create;
|
||||
begin
|
||||
inherited;
|
||||
FLogs := TList<TLogEntry>.Create;
|
||||
FMaxLogCount := 10000;
|
||||
FEnabled := True;
|
||||
FCategories := [Low(TLogCategory)..High(TLogCategory)];
|
||||
FMinLevel := llTrace;
|
||||
FLock := TObject.Create;
|
||||
FLogFileDir := ExtractFilePath(ParamStr(0)) + 'log\';
|
||||
end;
|
||||
|
||||
destructor TLogManager.Destroy;
|
||||
begin
|
||||
FLogs.Free;
|
||||
FLock.Free;
|
||||
inherited;
|
||||
end;
|
||||
|
||||
procedure TLogManager.AddLogInternal(const Entry: TLogEntry);
|
||||
begin
|
||||
TMonitor.Enter(FLock);
|
||||
try
|
||||
if FLogs.Count >= FMaxLogCount then
|
||||
FLogs.Delete(0);
|
||||
FLogs.Add(Entry);
|
||||
finally
|
||||
TMonitor.Exit(FLock);
|
||||
end;
|
||||
|
||||
if Assigned(FOnLog) then
|
||||
FOnLog(Entry);
|
||||
end;
|
||||
|
||||
function TLogManager.GetLevelString(Level: TLogLevel): string;
|
||||
begin
|
||||
case Level of
|
||||
llTrace: Result := '[TRACE]';
|
||||
llDebug: Result := '[DEBUG]';
|
||||
llInfo: Result := '[INFO]';
|
||||
llWarn: Result := '[WARN]';
|
||||
llError: Result := '[ERROR]';
|
||||
llFatal: Result := '[FATAL]';
|
||||
else
|
||||
Result := '[UNKNOWN]';
|
||||
end;
|
||||
end;
|
||||
|
||||
function TLogManager.GetCategoryString(Category: TLogCategory): string;
|
||||
begin
|
||||
case Category of
|
||||
lcSystem: Result := 'System';
|
||||
lcNetwork: Result := 'Network';
|
||||
lcDatabase: Result := 'Database';
|
||||
lcBusiness: Result := 'Business';
|
||||
lcDevice: Result := 'Device';
|
||||
lcUI: Result := 'UI';
|
||||
lcSecurity: Result := 'Security';
|
||||
lcPerformance:Result := 'Performance';
|
||||
else
|
||||
Result := 'Unknown';
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TLogManager.Log(Level: TLogLevel; Category: TLogCategory; const Message: string; const Args: array of const);
|
||||
var
|
||||
Entry: TLogEntry;
|
||||
begin
|
||||
if not FEnabled then Exit;
|
||||
if not (Category in FCategories) then Exit;
|
||||
if Ord(Level) < Ord(FMinLevel) then Exit;
|
||||
|
||||
Entry.Timestamp := Now;
|
||||
Entry.Level := Level;
|
||||
Entry.Category := Category;
|
||||
if Length(Args) > 0 then
|
||||
Entry.Message := Format(Message, Args)
|
||||
else
|
||||
Entry.Message := Message;
|
||||
Entry.Tag := '';
|
||||
Entry.UserID := '';
|
||||
Entry.ThreadID := TThread.CurrentThread.ThreadID;
|
||||
|
||||
AddLogInternal(Entry);
|
||||
end;
|
||||
|
||||
procedure TLogManager.Log(Level: TLogLevel; Category: TLogCategory; const Message: string);
|
||||
begin
|
||||
Log(Level, Category, Message, []);
|
||||
end;
|
||||
|
||||
procedure TLogManager.Trace(const Message: string; const Args: array of const);
|
||||
begin
|
||||
Log(llTrace, lcSystem, Message, Args);
|
||||
end;
|
||||
|
||||
procedure TLogManager.Trace(const Message: string);
|
||||
begin
|
||||
Trace(Message, []);
|
||||
end;
|
||||
|
||||
procedure TLogManager.Debug(const Message: string; const Args: array of const);
|
||||
begin
|
||||
Log(llDebug, lcSystem, Message, Args);
|
||||
end;
|
||||
|
||||
procedure TLogManager.Debug(const Message: string);
|
||||
begin
|
||||
Debug(Message, []);
|
||||
end;
|
||||
|
||||
procedure TLogManager.Info(const Message: string; const Args: array of const);
|
||||
begin
|
||||
Log(llInfo, lcSystem, Message, Args);
|
||||
end;
|
||||
|
||||
procedure TLogManager.Info(const Message: string);
|
||||
begin
|
||||
Info(Message, []);
|
||||
end;
|
||||
|
||||
procedure TLogManager.Warn(const Message: string; const Args: array of const);
|
||||
begin
|
||||
Log(llWarn, lcSystem, Message, Args);
|
||||
end;
|
||||
|
||||
procedure TLogManager.Warn(const Message: string);
|
||||
begin
|
||||
Warn(Message, []);
|
||||
end;
|
||||
|
||||
procedure TLogManager.Error(const Message: string; const Args: array of const);
|
||||
begin
|
||||
Log(llError, lcSystem, Message, Args);
|
||||
end;
|
||||
|
||||
procedure TLogManager.Error(const Message: string);
|
||||
begin
|
||||
Error(Message, []);
|
||||
end;
|
||||
|
||||
procedure TLogManager.Fatal(const Message: string; const Args: array of const);
|
||||
begin
|
||||
Log(llFatal, lcSystem, Message, Args);
|
||||
end;
|
||||
|
||||
procedure TLogManager.Fatal(const Message: string);
|
||||
begin
|
||||
Fatal(Message, []);
|
||||
end;
|
||||
|
||||
procedure TLogManager.TraceCategory(Category: TLogCategory; const Message: string; const Args: array of const);
|
||||
begin
|
||||
Log(llTrace, Category, Message, Args);
|
||||
end;
|
||||
|
||||
procedure TLogManager.TraceCategory(Category: TLogCategory; const Message: string);
|
||||
begin
|
||||
TraceCategory(Category, Message, []);
|
||||
end;
|
||||
|
||||
procedure TLogManager.DebugCategory(Category: TLogCategory; const Message: string; const Args: array of const);
|
||||
begin
|
||||
Log(llDebug, Category, Message, Args);
|
||||
end;
|
||||
|
||||
procedure TLogManager.DebugCategory(Category: TLogCategory; const Message: string);
|
||||
begin
|
||||
DebugCategory(Category, Message, []);
|
||||
end;
|
||||
|
||||
procedure TLogManager.InfoCategory(Category: TLogCategory; const Message: string; const Args: array of const);
|
||||
begin
|
||||
Log(llInfo, Category, Message, Args);
|
||||
end;
|
||||
|
||||
procedure TLogManager.InfoCategory(Category: TLogCategory; const Message: string);
|
||||
begin
|
||||
InfoCategory(Category, Message, []);
|
||||
end;
|
||||
|
||||
procedure TLogManager.WarnCategory(Category: TLogCategory; const Message: string; const Args: array of const);
|
||||
begin
|
||||
Log(llWarn, Category, Message, Args);
|
||||
end;
|
||||
|
||||
procedure TLogManager.WarnCategory(Category: TLogCategory; const Message: string);
|
||||
begin
|
||||
WarnCategory(Category, Message, []);
|
||||
end;
|
||||
|
||||
procedure TLogManager.ErrorCategory(Category: TLogCategory; const Message: string; const Args: array of const);
|
||||
begin
|
||||
Log(llError, Category, Message, Args);
|
||||
end;
|
||||
|
||||
procedure TLogManager.ErrorCategory(Category: TLogCategory; const Message: string);
|
||||
begin
|
||||
ErrorCategory(Category, Message, []);
|
||||
end;
|
||||
|
||||
procedure TLogManager.FatalCategory(Category: TLogCategory; const Message: string; const Args: array of const);
|
||||
begin
|
||||
Log(llFatal, Category, Message, Args);
|
||||
end;
|
||||
|
||||
procedure TLogManager.FatalCategory(Category: TLogCategory; const Message: string);
|
||||
begin
|
||||
FatalCategory(Category, Message, []);
|
||||
end;
|
||||
|
||||
procedure TLogManager.LogException(E: Exception; Category: TLogCategory; const AdditionalInfo: string);
|
||||
var
|
||||
Msg: string;
|
||||
begin
|
||||
if AdditionalInfo <> '' then
|
||||
Msg := Format('%s [Additional: %s]', [E.Message, AdditionalInfo])
|
||||
else
|
||||
Msg := E.Message;
|
||||
Log(llError, Category, 'Exception: %s: %s', [E.ClassName, Msg]);
|
||||
end;
|
||||
|
||||
procedure TLogManager.LogException(E: Exception; const AdditionalInfo: string);
|
||||
begin
|
||||
LogException(E, lcSystem, AdditionalInfo);
|
||||
end;
|
||||
|
||||
procedure TLogManager.LogPerformance(const OperationName: string; const ElapsedMS: Int64);
|
||||
begin
|
||||
Log(llInfo, lcPerformance, 'Operation [%s] took %d ms', [OperationName, Integer(ElapsedMS)]);
|
||||
end;
|
||||
|
||||
procedure TLogManager.LogUIOperation(const UIOperation: string; const ControlName: string; const ElapsedMS: Int64);
|
||||
begin
|
||||
if ElapsedMS >= 0 then
|
||||
Log(llInfo, lcUI, 'UI Operation [%s] on [%s] took %d ms', [UIOperation, ControlName, Integer(ElapsedMS)])
|
||||
else
|
||||
Log(llInfo, lcUI, 'UI Operation [%s] on [%s]', [UIOperation, ControlName]);
|
||||
end;
|
||||
|
||||
procedure TLogManager.LogNetworkRequest(const URL: string; const Method: string; const StatusCode: Integer; const ElapsedMS: Int64);
|
||||
begin
|
||||
if (StatusCode >= 200) and (StatusCode < 300) then
|
||||
Log(llInfo, lcNetwork, 'Network Request [%s] %s -> %d (%d ms)', [Method, URL, StatusCode, Integer(ElapsedMS)])
|
||||
else if StatusCode >= 400 then
|
||||
Log(llError, lcNetwork, 'Network Request [%s] %s -> %d (%d ms)', [Method, URL, StatusCode, Integer(ElapsedMS)])
|
||||
else
|
||||
Log(llWarn, lcNetwork, 'Network Request [%s] %s -> %d (%d ms)', [Method, URL, StatusCode, Integer(ElapsedMS)]);
|
||||
end;
|
||||
|
||||
procedure TLogManager.LogFormShow(const FormName: string; const ElapsedMS: Int64);
|
||||
begin
|
||||
if ElapsedMS >= 0 then
|
||||
Log(llInfo, lcUI, 'Form Show [%s] took %d ms', [FormName, Integer(ElapsedMS)])
|
||||
else
|
||||
Log(llInfo, lcUI, 'Form Show [%s]', [FormName]);
|
||||
end;
|
||||
|
||||
procedure TLogManager.LogFormClose(const FormName: string; const ElapsedMS: Int64);
|
||||
begin
|
||||
if ElapsedMS >= 0 then
|
||||
Log(llInfo, lcUI, 'Form Close [%s] took %d ms', [FormName, Integer(ElapsedMS)])
|
||||
else
|
||||
Log(llInfo, lcUI, 'Form Close [%s]', [FormName]);
|
||||
end;
|
||||
|
||||
procedure TLogManager.LogDataOperation(const Operation: string; const RecordCount: Integer; const ElapsedMS: Int64);
|
||||
begin
|
||||
if ElapsedMS >= 0 then
|
||||
Log(llInfo, lcDatabase, 'Data Operation [%s] (%d records) took %d ms', [Operation, RecordCount, Integer(ElapsedMS)])
|
||||
else
|
||||
Log(llInfo, lcDatabase, 'Data Operation [%s] (%d records)', [Operation, RecordCount]);
|
||||
end;
|
||||
|
||||
procedure TLogManager.ClearLogs;
|
||||
begin
|
||||
TMonitor.Enter(FLock);
|
||||
try
|
||||
FLogs.Clear;
|
||||
finally
|
||||
TMonitor.Exit(FLock);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TLogManager.GetLogs(Level: TLogLevel; Category: TLogCategory): TArray<TLogEntry>;
|
||||
var
|
||||
I, Count: Integer;
|
||||
begin
|
||||
TMonitor.Enter(FLock);
|
||||
try
|
||||
Count := 0;
|
||||
for I := 0 to FLogs.Count - 1 do
|
||||
begin
|
||||
if (FLogs[I].Level = Level) and (FLogs[I].Category = Category) then
|
||||
Inc(Count);
|
||||
end;
|
||||
SetLength(Result, Count);
|
||||
Count := 0;
|
||||
for I := 0 to FLogs.Count - 1 do
|
||||
begin
|
||||
if (FLogs[I].Level = Level) and (FLogs[I].Category = Category) then
|
||||
begin
|
||||
Result[Count] := FLogs[I];
|
||||
Inc(Count);
|
||||
end;
|
||||
end;
|
||||
finally
|
||||
TMonitor.Exit(FLock);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TLogManager.GetLogs(Level: TLogLevel; Categories: TLogCategories): TArray<TLogEntry>;
|
||||
var
|
||||
I, Count: Integer;
|
||||
begin
|
||||
TMonitor.Enter(FLock);
|
||||
try
|
||||
Count := 0;
|
||||
for I := 0 to FLogs.Count - 1 do
|
||||
begin
|
||||
if (FLogs[I].Level >= Level) and (FLogs[I].Category in Categories) then
|
||||
Inc(Count);
|
||||
end;
|
||||
SetLength(Result, Count);
|
||||
Count := 0;
|
||||
for I := 0 to FLogs.Count - 1 do
|
||||
begin
|
||||
if (FLogs[I].Level >= Level) and (FLogs[I].Category in Categories) then
|
||||
begin
|
||||
Result[Count] := FLogs[I];
|
||||
Inc(Count);
|
||||
end;
|
||||
end;
|
||||
finally
|
||||
TMonitor.Exit(FLock);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TLogManager.GetLogs(Level: TLogLevel): TArray<TLogEntry>;
|
||||
var
|
||||
I, Count: Integer;
|
||||
begin
|
||||
TMonitor.Enter(FLock);
|
||||
try
|
||||
Count := 0;
|
||||
for I := 0 to FLogs.Count - 1 do
|
||||
begin
|
||||
if FLogs[I].Level >= Level then
|
||||
Inc(Count);
|
||||
end;
|
||||
SetLength(Result, Count);
|
||||
Count := 0;
|
||||
for I := 0 to FLogs.Count - 1 do
|
||||
begin
|
||||
if FLogs[I].Level >= Level then
|
||||
begin
|
||||
Result[Count] := FLogs[I];
|
||||
Inc(Count);
|
||||
end;
|
||||
end;
|
||||
finally
|
||||
TMonitor.Exit(FLock);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TLogManager.ExportToJSON: TJSONArray;
|
||||
var
|
||||
I: Integer;
|
||||
Entry: TJSONObject;
|
||||
begin
|
||||
Result := TJSONArray.Create;
|
||||
TMonitor.Enter(FLock);
|
||||
try
|
||||
for I := 0 to FLogs.Count - 1 do
|
||||
begin
|
||||
Entry := TJSONObject.Create;
|
||||
Entry.AddPair('timestamp', FormatDateTime('yyyy-mm-dd hh:nn:ss.zzz', FLogs[I].Timestamp));
|
||||
Entry.AddPair('level', GetLevelString(FLogs[I].Level));
|
||||
Entry.AddPair('category', GetCategoryString(FLogs[I].Category));
|
||||
Entry.AddPair('message', FLogs[I].Message);
|
||||
Entry.AddPair('threadId', TJSONNumber.Create(FLogs[I].ThreadID));
|
||||
Result.AddElement(Entry);
|
||||
end;
|
||||
finally
|
||||
TMonitor.Exit(FLock);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TLogManager.SaveToFile(const FileName: string);
|
||||
var
|
||||
I: Integer;
|
||||
Lines: TStringList;
|
||||
Line: string;
|
||||
begin
|
||||
Lines := TStringList.Create;
|
||||
try
|
||||
TMonitor.Enter(FLock);
|
||||
try
|
||||
for I := 0 to FLogs.Count - 1 do
|
||||
begin
|
||||
Line := Format('%s %s [%s] %s',
|
||||
[FormatDateTime('yyyy-mm-dd hh:nn:ss.zzz', FLogs[I].Timestamp),
|
||||
GetLevelString(FLogs[I].Level),
|
||||
GetCategoryString(FLogs[I].Category),
|
||||
FLogs[I].Message]);
|
||||
Lines.Add(Line);
|
||||
end;
|
||||
finally
|
||||
TMonitor.Exit(FLock);
|
||||
end;
|
||||
if not ForceDirectories(ExtractFilePath(FileName)) then
|
||||
Exit;
|
||||
Lines.SaveToFile(FileName, TEncoding.UTF8);
|
||||
finally
|
||||
Lines.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ TPerformanceLogger }
|
||||
|
||||
constructor TPerformanceLogger.Create(const AOperationName: string; ATag: string);
|
||||
begin
|
||||
inherited Create;
|
||||
FOperationName := AOperationName;
|
||||
FStartTime := Now;
|
||||
FTag := ATag;
|
||||
end;
|
||||
|
||||
destructor TPerformanceLogger.Destroy;
|
||||
begin
|
||||
Finish;
|
||||
inherited;
|
||||
end;
|
||||
|
||||
procedure TPerformanceLogger.Finish;
|
||||
var
|
||||
ElapsedMS: Int64;
|
||||
begin
|
||||
ElapsedMS := MilliSecondsBetween(Now, FStartTime);
|
||||
LogManager.LogPerformance(FOperationName, ElapsedMS);
|
||||
end;
|
||||
|
||||
procedure TPerformanceLogger.FinishWithInfo(const Info: string);
|
||||
var
|
||||
ElapsedMS: Int64;
|
||||
begin
|
||||
ElapsedMS := MilliSecondsBetween(Now, FStartTime);
|
||||
LogManager.InfoCategory(lcPerformance, 'Operation [%s] with info [%s] took %d ms', [FOperationName, Info, Integer(ElapsedMS)]);
|
||||
end;
|
||||
|
||||
class function TPerformanceLogger.Measure<T>(const AOperationName: string; AFunc: TFunc<T>; ATag: string): T;
|
||||
var
|
||||
StartTime: TDateTime;
|
||||
begin
|
||||
StartTime := Now;
|
||||
try
|
||||
Result := AFunc;
|
||||
finally
|
||||
LogManager.LogPerformance(AOperationName, MilliSecondsBetween(Now, StartTime));
|
||||
end;
|
||||
end;
|
||||
|
||||
class procedure TPerformanceLogger.MeasureProc(const AOperationName: string; AProc: TProc; ATag: string);
|
||||
var
|
||||
StartTime: TDateTime;
|
||||
begin
|
||||
StartTime := Now;
|
||||
try
|
||||
AProc;
|
||||
finally
|
||||
LogManager.LogPerformance(AOperationName, MilliSecondsBetween(Now, StartTime));
|
||||
end;
|
||||
end;
|
||||
|
||||
{ TOperationContext }
|
||||
|
||||
constructor TOperationContext.Create(const AUserID: string);
|
||||
begin
|
||||
inherited Create;
|
||||
FUserID := AUserID;
|
||||
FSessionID := '';
|
||||
FRequestID := '';
|
||||
FStartTime := Now;
|
||||
FTags := TDictionary<string, string>.Create;
|
||||
end;
|
||||
|
||||
destructor TOperationContext.Destroy;
|
||||
begin
|
||||
FTags.Free;
|
||||
inherited;
|
||||
end;
|
||||
|
||||
procedure TOperationContext.SetTag(const Key, Value: string);
|
||||
begin
|
||||
FTags.AddOrSetValue(Key, Value);
|
||||
end;
|
||||
|
||||
function TOperationContext.GetTag(const Key: string): string;
|
||||
begin
|
||||
if not FTags.TryGetValue(Key, Result) then
|
||||
Result := '';
|
||||
end;
|
||||
|
||||
procedure TOperationContext.ClearTags;
|
||||
begin
|
||||
FTags.Clear;
|
||||
end;
|
||||
|
||||
end.
|
||||
Reference in New Issue
Block a user