614 lines
15 KiB
ObjectPascal
614 lines
15 KiB
ObjectPascal
unit KM_Log;
|
|||
|
|
{$I KaM_Remake.inc}
|
||
|
|
interface
|
||
|
|
uses
|
||
|
|
SyncObjs, KM_CommonTypes
|
||
|
|
{$IFDEF KMR_GAME} // Not needed for server and other tools
|
||
|
|
, Generics.Collections
|
||
|
|
{$ENDIF}
|
||
|
|
;
|
||
|
|
|
||
|
|
|
||
|
|
type
|
||
|
|
// Log message type
|
||
|
|
TKMLogMessageType = (
|
||
|
|
lmtDefault, // Default type
|
||
|
|
lmtDelivery, // Delivery messages
|
||
|
|
lmtCommands, // All GIC commands
|
||
|
|
lmtRandomChecks, // Random checks
|
||
|
|
lmtNetConnection, // Messages about net connection/disconnection/reconnection
|
||
|
|
lmtNetPacketOther, // Messages about net packets (all packets, except GIP commands/ping/fps)
|
||
|
|
lmtNetPacketCommand, // Messages about GIP commands net packets
|
||
|
|
lmtNetPacketPingFps, // Messages about ping/fps net packets
|
||
|
|
lmtDebug // Debug
|
||
|
|
);
|
||
|
|
|
||
|
|
TKMLogMessageTypeSet = set of TKMLogMessageType;
|
||
|
|
|
||
|
|
// Logging system
|
||
|
|
TKMLog = class
|
||
|
|
private
|
||
|
|
CS: TCriticalSection;
|
||
|
|
fLogFile: TextFile;
|
||
|
|
fLogPath: UnicodeString;
|
||
|
|
fWriteErrCnt: Integer;
|
||
|
|
fFirstTick: cardinal;
|
||
|
|
fPreviousTick: cardinal;
|
||
|
|
fPreviousDate: TDateTime;
|
||
|
|
|
||
|
|
{$IFDEF KMR_GAME}
|
||
|
|
fOnLogMessageList: TList<TUnicodeStringEvent>;
|
||
|
|
{$ENDIF}
|
||
|
|
|
||
|
|
procedure Lock;
|
||
|
|
procedure Unlock;
|
||
|
|
|
||
|
|
procedure InitLog;
|
||
|
|
|
||
|
|
procedure AppendText(aTxt: String);
|
||
|
|
function IsFileAssignedAndAppend: Boolean;
|
||
|
|
|
||
|
|
procedure NotifyLogSubs(aText: UnicodeString);
|
||
|
|
|
||
|
|
procedure AddLineTime(const aText: UnicodeString; aLogType: TKMLogMessageType); overload;
|
||
|
|
procedure AddLineTime(const aText: UnicodeString); overload;
|
||
|
|
procedure AddLineNoTime(const aText: UnicodeString; aWithPrefix: Boolean = True); overload;
|
||
|
|
procedure AddLineNoTime(const aText: UnicodeString; aLogType: TKMLogMessageType; aWithPrefix: Boolean = True); overload;
|
||
|
|
public
|
||
|
|
MessageTypes: TKMLogMessageTypeSet;
|
||
|
|
constructor Create(const aPath: UnicodeString);
|
||
|
|
destructor Destroy; override;
|
||
|
|
|
||
|
|
// AppendLog adds the line to Log along with time passed since previous line added
|
||
|
|
procedure AddTime(const aText: UnicodeString); overload;
|
||
|
|
procedure AddTime(const aText: UnicodeString; aArgs: array of const); overload;
|
||
|
|
function IsDegubLogEnabled: Boolean;
|
||
|
|
procedure LogDebug(const aText: UnicodeString);
|
||
|
|
procedure LogDelivery(const aText: UnicodeString);
|
||
|
|
procedure LogCommands(const aText: UnicodeString);
|
||
|
|
procedure LogRandomChecks(const aText: UnicodeString);
|
||
|
|
procedure LogNetConnection(const aText: UnicodeString);
|
||
|
|
procedure LogNetPacketOther(const aText: UnicodeString);
|
||
|
|
procedure LogNetPacketCommand(const aText: UnicodeString);
|
||
|
|
procedure LogNetPacketPingFps(const aText: UnicodeString);
|
||
|
|
function CanLogDelivery: Boolean;
|
||
|
|
function CanLogCommands: Boolean;
|
||
|
|
function CanLogRandomChecks: Boolean;
|
||
|
|
function CanLogNetConnection: Boolean;
|
||
|
|
function CanLogNetPacketOther: Boolean;
|
||
|
|
function CanLogNetPacketCommand: Boolean;
|
||
|
|
function CanLogNetPacketPingFps: Boolean;
|
||
|
|
|
||
|
|
procedure SetDefaultMessageTypes;
|
||
|
|
|
||
|
|
// Add line if TestValue=False
|
||
|
|
procedure AddAssert(const aMessageText: UnicodeString);
|
||
|
|
// AddToLog simply adds the text
|
||
|
|
procedure AddNoTime(const aText: UnicodeString; aWithPrefix: Boolean = True);
|
||
|
|
procedure DeleteOldLogs(aDeleteWhenOlderThanDays: Integer);
|
||
|
|
property LogPath: UnicodeString read fLogPath; //Used by dedicated server
|
||
|
|
// property OnLogMessage: TUnicodeStringEvent read fOnLogMessage write fOnLogMessage;
|
||
|
|
procedure AddOnLogEventSub(const aOnLogMessage: TUnicodeStringEvent);
|
||
|
|
procedure RemoveOnLogEventSub(const aOnLogMessage: TUnicodeStringEvent);
|
||
|
|
end;
|
||
|
|
|
||
|
|
var
|
||
|
|
gLog: TKMLog;
|
||
|
|
|
||
|
|
|
||
|
|
implementation
|
||
|
|
uses
|
||
|
|
{$IFDEF WDC}IOUtils,{$ENDIF}
|
||
|
|
Classes, SysUtils,
|
||
|
|
KM_FileIO,
|
||
|
|
KM_Defaults, KM_CommonUtils;
|
||
|
|
|
||
|
|
const
|
||
|
|
DEFAULT_LOG_TYPES_TO_WRITE: TKMLogMessageTypeSet = [lmtDefault, lmtNetConnection];
|
||
|
|
|
||
|
|
|
||
|
|
type
|
||
|
|
// New thread, in which old logs are deleted (used internally)
|
||
|
|
TKMOldLogsDeleter = class(TThread)
|
||
|
|
private
|
||
|
|
fPathToLogs: UnicodeString;
|
||
|
|
fDeleteWhenOlderThanDays: Integer;
|
||
|
|
public
|
||
|
|
constructor Create(const aPathToLogs: UnicodeString; aDeleteWhenOlderThanDays: Integer);
|
||
|
|
procedure Execute; override;
|
||
|
|
end;
|
||
|
|
|
||
|
|
|
||
|
|
{ TKMOldLogsDeleter }
|
||
|
|
constructor TKMOldLogsDeleter.Create(const aPathToLogs: UnicodeString; aDeleteWhenOlderThanDays: Integer);
|
||
|
|
begin
|
||
|
|
//Thread isn't started until all constructors have run to completion
|
||
|
|
//so Create(False) may be put in front as well
|
||
|
|
inherited Create(False);
|
||
|
|
|
||
|
|
{$IFDEF DEBUG}
|
||
|
|
TThread.NameThreadForDebugging('OldLogsDeleter', ThreadID);
|
||
|
|
{$ENDIF}
|
||
|
|
|
||
|
|
//Must set these values BEFORE starting the thread
|
||
|
|
FreeOnTerminate := True; //object can be automatically removed after its termination
|
||
|
|
fPathToLogs := aPathToLogs;
|
||
|
|
end;
|
||
|
|
|
||
|
|
|
||
|
|
procedure TKMOldLogsDeleter.Execute;
|
||
|
|
var
|
||
|
|
SearchRec: TSearchRec;
|
||
|
|
fileDateTime: TDateTime;
|
||
|
|
begin
|
||
|
|
if not DirectoryExists(fPathToLogs) then Exit;
|
||
|
|
try
|
||
|
|
if FindFirst(fPathToLogs + 'KaM*.log', faAnyFile - faDirectory, SearchRec) = 0 then
|
||
|
|
repeat
|
||
|
|
Assert(FileAge(fPathToLogs + SearchRec.Name, fileDateTime), 'How is that it does not exists any more?');
|
||
|
|
|
||
|
|
if (Abs(Now - fileDateTime) > fDeleteWhenOlderThanDays) then
|
||
|
|
KMDeleteFile(fPathToLogs + SearchRec.Name);
|
||
|
|
until (FindNext(SearchRec) <> 0);
|
||
|
|
finally
|
||
|
|
FindClose(SearchRec);
|
||
|
|
end;
|
||
|
|
end;
|
||
|
|
|
||
|
|
|
||
|
|
{ TKMLog }
|
||
|
|
constructor TKMLog.Create(const aPath: UnicodeString);
|
||
|
|
begin
|
||
|
|
inherited Create;
|
||
|
|
|
||
|
|
fLogPath := aPath;
|
||
|
|
fFirstTick := TimeGet;
|
||
|
|
fPreviousTick := TimeGet;
|
||
|
|
SetDefaultMessageTypes;
|
||
|
|
|
||
|
|
if DEBUG_LOGS then
|
||
|
|
Include(MessageTypes, lmtDebug);
|
||
|
|
|
||
|
|
CS := TCriticalSection.Create;
|
||
|
|
{$IFDEF KMR_GAME}
|
||
|
|
fOnLogMessageList := TList<TUnicodeStringEvent>.Create;
|
||
|
|
{$ENDIF}
|
||
|
|
|
||
|
|
InitLog;
|
||
|
|
end;
|
||
|
|
|
||
|
|
|
||
|
|
destructor TKMLog.Destroy;
|
||
|
|
begin
|
||
|
|
CS.Free;
|
||
|
|
{$IFDEF KMR_GAME}
|
||
|
|
fOnLogMessageList.Free;
|
||
|
|
{$ENDIF}
|
||
|
|
|
||
|
|
inherited;
|
||
|
|
end;
|
||
|
|
|
||
|
|
|
||
|
|
procedure TKMLog.SetDefaultMessageTypes;
|
||
|
|
begin
|
||
|
|
MessageTypes := DEFAULT_LOG_TYPES_TO_WRITE;
|
||
|
|
end;
|
||
|
|
|
||
|
|
|
||
|
|
procedure TKMLog.Lock;
|
||
|
|
begin
|
||
|
|
CS.Enter;
|
||
|
|
end;
|
||
|
|
|
||
|
|
|
||
|
|
procedure TKMLog.Unlock;
|
||
|
|
begin
|
||
|
|
CS.Leave;
|
||
|
|
end;
|
||
|
|
|
||
|
|
|
||
|
|
// Check if the log file is assigned
|
||
|
|
// File will be appended in case the file is assigned to the file variable
|
||
|
|
function TKMLog.IsFileAssignedAndAppend: Boolean;
|
||
|
|
begin
|
||
|
|
Result := True;
|
||
|
|
try
|
||
|
|
Append(fLogFile);
|
||
|
|
except
|
||
|
|
Result := False;
|
||
|
|
end;
|
||
|
|
end;
|
||
|
|
|
||
|
|
|
||
|
|
procedure TKMLog.AppendText(aTxt: String);
|
||
|
|
const
|
||
|
|
MAX_LOG_ERROR_CNT = 5;
|
||
|
|
|
||
|
|
procedure doAppend(aE: Exception = nil);
|
||
|
|
begin
|
||
|
|
if not IsFileAssignedAndAppend then
|
||
|
|
begin
|
||
|
|
AssignFile(fLogFile, fLogPath);
|
||
|
|
Append(fLogFile);
|
||
|
|
end;
|
||
|
|
|
||
|
|
// Only show few log errors, don't overspam it
|
||
|
|
if fWriteErrCnt <= MAX_LOG_ERROR_CNT then
|
||
|
|
begin
|
||
|
|
if aE <> nil then
|
||
|
|
WriteLn(fLogFile, 'Error appending to the log file using TFile.AppendAllText: ' + aE.Message);
|
||
|
|
end
|
||
|
|
else
|
||
|
|
Inc(fWriteErrCnt);
|
||
|
|
|
||
|
|
WriteLn(fLogFile, aTxt);
|
||
|
|
CloseFile(fLogFile);
|
||
|
|
end;
|
||
|
|
|
||
|
|
|
||
|
|
begin
|
||
|
|
{$IFDEF WDC}
|
||
|
|
try
|
||
|
|
// Try to use TFile.AppendAllText for few times
|
||
|
|
// Then use oldschool Writeln instead
|
||
|
|
if fWriteErrCnt < MAX_LOG_ERROR_CNT then
|
||
|
|
TFile.AppendAllText(fLogPath, aTxt + sLineBreak, TEncoding.UTF8)
|
||
|
|
else
|
||
|
|
doAppend();
|
||
|
|
except
|
||
|
|
on E: Exception do
|
||
|
|
doAppend(E);
|
||
|
|
end;
|
||
|
|
{$ENDIF}
|
||
|
|
end;
|
||
|
|
|
||
|
|
|
||
|
|
procedure TKMLog.InitLog;
|
||
|
|
const
|
||
|
|
INIT_STR = ' Timestamp Elapsed Delta Thread Description';
|
||
|
|
begin
|
||
|
|
if BLOCK_FILE_WRITE then Exit;
|
||
|
|
|
||
|
|
try
|
||
|
|
ForceDirectories(ExtractFilePath(fLogPath));
|
||
|
|
|
||
|
|
// hh:nn:ss.zzz 12345.678s 1234567ms text-text-text
|
||
|
|
{$IFDEF WDC}
|
||
|
|
try
|
||
|
|
TFile.WriteAllText(fLogPath, INIT_STR + sLineBreak, TEncoding.UTF8);
|
||
|
|
except
|
||
|
|
on E: Exception do
|
||
|
|
begin
|
||
|
|
// Write to log anyway, even if we can't do it using TFile.WriteAllText
|
||
|
|
if not IsFileAssignedAndAppend then
|
||
|
|
begin
|
||
|
|
AssignFile(fLogFile, fLogPath);
|
||
|
|
Rewrite(fLogFile);
|
||
|
|
end;
|
||
|
|
WriteLn(fLogFile, INIT_STR);
|
||
|
|
WriteLn(fLogFile, 'Error creating file using TFile.WriteAllText: ' + E.Message);
|
||
|
|
CloseFile(fLogFile);
|
||
|
|
end;
|
||
|
|
end;
|
||
|
|
|
||
|
|
{$ENDIF}
|
||
|
|
{$IFDEF FPC}
|
||
|
|
AssignFile(fLogFile, fLogPath);
|
||
|
|
Rewrite(fLogFile);
|
||
|
|
// hh:nn:ss.zzz 12345.678s 1234567ms text-text-text
|
||
|
|
WriteLn(fLogFile, ' Timestamp Elapsed Delta Thread Description');
|
||
|
|
CloseFile(fLogFile);
|
||
|
|
{$ENDIF}
|
||
|
|
except
|
||
|
|
on E: Exception do
|
||
|
|
begin
|
||
|
|
E.Message := E.Message + '. Tried to init Log on path ''' + fLogPath + '''';
|
||
|
|
raise E;
|
||
|
|
end;
|
||
|
|
end;
|
||
|
|
AddLineTime('Log is up and running. Game version: ' + UnicodeString(GAME_VERSION));
|
||
|
|
end;
|
||
|
|
|
||
|
|
|
||
|
|
// Run thread to delete old logs
|
||
|
|
procedure TKMLog.DeleteOldLogs(aDeleteWhenOlderThanDays: Integer);
|
||
|
|
begin
|
||
|
|
if Self = nil then Exit;
|
||
|
|
if not DELETE_OLD_LOGS then Exit;
|
||
|
|
|
||
|
|
// No need to remember the instance, it's set to FreeOnTerminate
|
||
|
|
TKMOldLogsDeleter.Create(ExtractFilePath(fLogPath), aDeleteWhenOlderThanDays);
|
||
|
|
end;
|
||
|
|
|
||
|
|
|
||
|
|
procedure TKMLog.AddOnLogEventSub(const aOnLogMessage: TUnicodeStringEvent);
|
||
|
|
begin
|
||
|
|
{$IFDEF KMR_GAME}
|
||
|
|
fOnLogMessageList.Add(aOnLogMessage);
|
||
|
|
{$ENDIF}
|
||
|
|
end;
|
||
|
|
|
||
|
|
|
||
|
|
procedure TKMLog.RemoveOnLogEventSub(const aOnLogMessage: TUnicodeStringEvent);
|
||
|
|
begin
|
||
|
|
{$IFDEF KMR_GAME}
|
||
|
|
fOnLogMessageList.Remove(aOnLogMessage);
|
||
|
|
{$ENDIF}
|
||
|
|
end;
|
||
|
|
|
||
|
|
|
||
|
|
procedure TKMLog.NotifyLogSubs(aText: UnicodeString);
|
||
|
|
{$IFDEF KMR_GAME}
|
||
|
|
var
|
||
|
|
I: Integer;
|
||
|
|
{$ENDIF}
|
||
|
|
begin
|
||
|
|
{$IFDEF KMR_GAME}
|
||
|
|
for I := 0 to fOnLogMessageList.Count - 1 do
|
||
|
|
if Assigned(fOnLogMessageList[I]) then
|
||
|
|
fOnLogMessageList[I](aText);
|
||
|
|
{$ENDIF}
|
||
|
|
end;
|
||
|
|
|
||
|
|
|
||
|
|
// Lines are timestamped, each line invokes file open/close for writing,
|
||
|
|
// meaning that no lines will be lost if Remake crashes
|
||
|
|
procedure TKMLog.AddLineTime(const aText: UnicodeString; aLogType: TKMLogMessageType);
|
||
|
|
var
|
||
|
|
txt, txt2: String;
|
||
|
|
begin
|
||
|
|
if Self = nil then Exit;
|
||
|
|
|
||
|
|
if BLOCK_FILE_WRITE then Exit;
|
||
|
|
|
||
|
|
if not (aLogType in MessageTypes) then // write into log only for allowed types
|
||
|
|
Exit;
|
||
|
|
|
||
|
|
// Do not allow multiple threads write into the same file
|
||
|
|
Lock;
|
||
|
|
try
|
||
|
|
if not FileExists(fLogPath) then
|
||
|
|
InitLog; // Recreate log file, if it was deleted
|
||
|
|
|
||
|
|
txt := '';
|
||
|
|
|
||
|
|
{$IFDEF FPC} Append(fLogFile); {$ENDIF}
|
||
|
|
|
||
|
|
//Write a line when the day changed since last time (useful for dedicated server logs that could be over months)
|
||
|
|
if Abs(Trunc(fPreviousDate) - Trunc(Now)) >= 1 then
|
||
|
|
begin
|
||
|
|
{$IFDEF WDC}
|
||
|
|
txt := txt + '========================' + sLineBreak
|
||
|
|
+ ' Date: ' + FormatDateTime('yyyy/mm/dd', Now) + sLineBreak
|
||
|
|
+ '========================' + sLineBreak;
|
||
|
|
{$ENDIF}
|
||
|
|
{$IFDEF FPC}
|
||
|
|
WriteLn(fLogFile, '========================');
|
||
|
|
WriteLn(fLogFile, ' Date: ' + FormatDateTime('yyyy/mm/dd', Now));
|
||
|
|
WriteLn(fLogFile, '========================');
|
||
|
|
{$ENDIF}
|
||
|
|
end;
|
||
|
|
|
||
|
|
txt2 := Format('%12s %9.3fs %7dms %6d %s', [
|
||
|
|
FormatDateTime('hh:nn:ss.zzz', Now),
|
||
|
|
TimeSince(fFirstTick) / 1000,
|
||
|
|
TimeSince(fPreviousTick),
|
||
|
|
TThread.CurrentThread.ThreadID,
|
||
|
|
aText]);
|
||
|
|
{$IFDEF WDC}
|
||
|
|
AppendText(txt + txt2);
|
||
|
|
{$ENDIF}
|
||
|
|
{$IFDEF FPC}
|
||
|
|
WriteLn(fLogFile, txt2);
|
||
|
|
CloseFile(fLogFile);
|
||
|
|
{$ENDIF}
|
||
|
|
|
||
|
|
fPreviousTick := TimeGet;
|
||
|
|
fPreviousDate := Now;
|
||
|
|
finally
|
||
|
|
UnLock;
|
||
|
|
end;
|
||
|
|
|
||
|
|
NotifyLogSubs(aText);
|
||
|
|
end;
|
||
|
|
|
||
|
|
|
||
|
|
// Add line with timestamp
|
||
|
|
procedure TKMLog.AddLineTime(const aText: UnicodeString);
|
||
|
|
begin
|
||
|
|
AddLineTime(aText, lmtDefault);
|
||
|
|
end;
|
||
|
|
|
||
|
|
|
||
|
|
// Add line but without timestamp
|
||
|
|
procedure TKMLog.AddLineNoTime(const aText: UnicodeString; aLogType: TKMLogMessageType; aWithPrefix: Boolean = True);
|
||
|
|
begin
|
||
|
|
if Self = nil then Exit;
|
||
|
|
|
||
|
|
if BLOCK_FILE_WRITE then Exit;
|
||
|
|
|
||
|
|
if not (aLogType in MessageTypes) then // write into log only for allowed types
|
||
|
|
Exit;
|
||
|
|
|
||
|
|
// Do not allow multiple threads write into the same file
|
||
|
|
Lock;
|
||
|
|
try
|
||
|
|
if not FileExists(fLogPath) then
|
||
|
|
InitLog; // Recreate log file, if it was deleted
|
||
|
|
|
||
|
|
{$IFDEF FPC} Append(fLogFile); {$ENDIF}
|
||
|
|
|
||
|
|
if aWithPrefix then
|
||
|
|
begin
|
||
|
|
{$IFDEF WDC}
|
||
|
|
AppendText(' ' + aText);
|
||
|
|
{$ENDIF}
|
||
|
|
{$IFDEF FPC}
|
||
|
|
WriteLn(fLogFile, ' ' + aText);
|
||
|
|
{$ENDIF}
|
||
|
|
end
|
||
|
|
else
|
||
|
|
begin
|
||
|
|
{$IFDEF WDC} AppendText(aText); {$ENDIF}
|
||
|
|
{$IFDEF FPC} WriteLn(fLogFile, aText); {$ENDIF}
|
||
|
|
end;
|
||
|
|
{$IFDEF FPC} CloseFile(fLogFile); {$ENDIF}
|
||
|
|
finally
|
||
|
|
// Do not allow multiple threads write into the same file
|
||
|
|
UnLock;
|
||
|
|
end;
|
||
|
|
|
||
|
|
NotifyLogSubs(aText);
|
||
|
|
end;
|
||
|
|
|
||
|
|
|
||
|
|
//Add line without timestamp
|
||
|
|
procedure TKMLog.AddLineNoTime(const aText: UnicodeString; aWithPrefix: Boolean = True);
|
||
|
|
begin
|
||
|
|
AddLineNoTime(aText, lmtDefault, aWithPrefix);
|
||
|
|
end;
|
||
|
|
|
||
|
|
|
||
|
|
procedure TKMLog.AddTime(const aText: UnicodeString);
|
||
|
|
begin
|
||
|
|
AddLineTime(aText);
|
||
|
|
end;
|
||
|
|
|
||
|
|
|
||
|
|
procedure TKMLog.AddTime(const aText: UnicodeString; aArgs: array of const);
|
||
|
|
begin
|
||
|
|
AddLineTime(Format(aText, aArgs));
|
||
|
|
end;
|
||
|
|
|
||
|
|
|
||
|
|
function TKMLog.IsDegubLogEnabled: Boolean;
|
||
|
|
begin
|
||
|
|
Result := lmtDebug in MessageTypes;
|
||
|
|
end;
|
||
|
|
|
||
|
|
|
||
|
|
procedure TKMLog.LogDebug(const aText: UnicodeString);
|
||
|
|
begin
|
||
|
|
if Self = nil then Exit;
|
||
|
|
AddLineTime(aText, lmtDebug);
|
||
|
|
end;
|
||
|
|
|
||
|
|
|
||
|
|
procedure TKMLog.LogDelivery(const aText: UnicodeString);
|
||
|
|
begin
|
||
|
|
if Self = nil then Exit;
|
||
|
|
AddLineTime(aText, lmtDelivery);
|
||
|
|
end;
|
||
|
|
|
||
|
|
|
||
|
|
procedure TKMLog.LogCommands(const aText: UnicodeString);
|
||
|
|
begin
|
||
|
|
if Self = nil then Exit;
|
||
|
|
AddLineTime(aText, lmtCommands);
|
||
|
|
end;
|
||
|
|
|
||
|
|
|
||
|
|
procedure TKMLog.LogRandomChecks(const aText: UnicodeString);
|
||
|
|
begin
|
||
|
|
if Self = nil then Exit;
|
||
|
|
if not CanLogRandomChecks then Exit;
|
||
|
|
|
||
|
|
AddLineNoTime(aText, lmtRandomChecks);
|
||
|
|
end;
|
||
|
|
|
||
|
|
|
||
|
|
procedure TKMLog.LogNetConnection(const aText: UnicodeString);
|
||
|
|
begin
|
||
|
|
if Self = nil then Exit;
|
||
|
|
AddLineTime(aText, lmtNetConnection);
|
||
|
|
end;
|
||
|
|
|
||
|
|
|
||
|
|
procedure TKMLog.LogNetPacketOther(const aText: UnicodeString);
|
||
|
|
begin
|
||
|
|
if Self = nil then Exit;
|
||
|
|
AddLineTime(aText, lmtNetPacketOther);
|
||
|
|
end;
|
||
|
|
|
||
|
|
|
||
|
|
procedure TKMLog.LogNetPacketCommand(const aText: UnicodeString);
|
||
|
|
begin
|
||
|
|
if Self = nil then Exit;
|
||
|
|
AddLineTime(aText, lmtNetPacketCommand);
|
||
|
|
end;
|
||
|
|
|
||
|
|
|
||
|
|
procedure TKMLog.LogNetPacketPingFps(const aText: UnicodeString);
|
||
|
|
begin
|
||
|
|
if Self = nil then Exit;
|
||
|
|
AddLineTime(aText, lmtNetPacketPingFps);
|
||
|
|
end;
|
||
|
|
|
||
|
|
|
||
|
|
function TKMLog.CanLogDelivery: Boolean;
|
||
|
|
begin
|
||
|
|
if Self = nil then Exit(False);
|
||
|
|
Result := lmtDelivery in MessageTypes;
|
||
|
|
end;
|
||
|
|
|
||
|
|
|
||
|
|
function TKMLog.CanLogCommands: Boolean;
|
||
|
|
begin
|
||
|
|
if Self = nil then Exit(False);
|
||
|
|
Result := lmtCommands in MessageTypes;
|
||
|
|
end;
|
||
|
|
|
||
|
|
|
||
|
|
function TKMLog.CanLogRandomChecks: Boolean;
|
||
|
|
begin
|
||
|
|
if Self = nil then Exit(False);
|
||
|
|
Result := lmtRandomChecks in MessageTypes;
|
||
|
|
end;
|
||
|
|
|
||
|
|
|
||
|
|
function TKMLog.CanLogNetConnection: Boolean;
|
||
|
|
begin
|
||
|
|
if Self = nil then Exit(False);
|
||
|
|
Result := lmtNetConnection in MessageTypes;
|
||
|
|
end;
|
||
|
|
|
||
|
|
|
||
|
|
function TKMLog.CanLogNetPacketOther: Boolean;
|
||
|
|
begin
|
||
|
|
if Self = nil then Exit(False);
|
||
|
|
Result := lmtNetPacketOther in MessageTypes;
|
||
|
|
end;
|
||
|
|
|
||
|
|
|
||
|
|
function TKMLog.CanLogNetPacketCommand: Boolean;
|
||
|
|
begin
|
||
|
|
if Self = nil then Exit(False);
|
||
|
|
Result := lmtNetPacketCommand in MessageTypes;
|
||
|
|
end;
|
||
|
|
|
||
|
|
|
||
|
|
function TKMLog.CanLogNetPacketPingFps: Boolean;
|
||
|
|
begin
|
||
|
|
if Self = nil then Exit(False);
|
||
|
|
Result := lmtNetPacketPingFps in MessageTypes;
|
||
|
|
end;
|
||
|
|
|
||
|
|
|
||
|
|
procedure TKMLog.AddAssert(const aMessageText: UnicodeString);
|
||
|
|
begin
|
||
|
|
if Self = nil then Exit;
|
||
|
|
|
||
|
|
AddLineNoTime('ASSERTION FAILED! Msg: ' + aMessageText);
|
||
|
|
raise Exception.Create('ASSERTION FAILED! Msg: ' + aMessageText);
|
||
|
|
end;
|
||
|
|
|
||
|
|
|
||
|
|
procedure TKMLog.AddNoTime(const aText: UnicodeString; aWithPrefix: Boolean = True);
|
||
|
|
begin
|
||
|
|
if Self = nil then Exit;
|
||
|
|
|
||
|
|
AddLineNoTime(aText, aWithPrefix);
|
||
|
|
end;
|
||
|
|
|
||
|
|
|
||
|
|
end.
|