diff --git a/Logger.AbstractLogger.pp b/Logger.AbstractLogger.pp index de8a4fc..e619d0d 100644 --- a/Logger.AbstractLogger.pp +++ b/Logger.AbstractLogger.pp @@ -70,6 +70,7 @@ type procedure Info(Message: UTF8String; Context: array of const); procedure Debug(Message: UTF8String; Context: array of const); function ConvertLogErrorToString(LogLevel: LogLevels): ansistring; + function ConvertLogStringToError( LogString : AnsiString): LogLevels; procedure Log(LogLevel: LogLevels; Message: UTF8String; Context: array of const); virtual; abstract; published @@ -95,6 +96,21 @@ begin Result := 'Unknown'; end; end; +function AbstractLogger.ConvertLogStringToError(LogString : AnsiString) : LogLevels; +begin + case lowerCase(LogString) of + 'emergency': Result := LOG_EMERG; + 'alert': Result := LOG_ALERT; + 'critical': Result := LOG_CRIT; + 'error': Result := LOG_ERR; + 'warning': Result := LOG_WARNING; + 'notice': Result := LOG_NOTICE; + 'info': Result := LOG_INFO; + 'debug': Result := LOG_DEBUG; + else + Result := LOG_UNKNOWN; + end; +end; procedure AbstractLogger.SetHandler(LoggingHandler: LoggingHandlerInterface); begin diff --git a/Logger.LoggerInterface.pp b/Logger.LoggerInterface.pp index bb3ad2c..ec3716e 100644 --- a/Logger.LoggerInterface.pp +++ b/Logger.LoggerInterface.pp @@ -54,7 +54,8 @@ type LOG_WARNING, LOG_NOTICE, LOG_INFO, - LOG_DEBUG); + LOG_DEBUG, + LOG_UNKNOWN); const LOG_PRIMASK = $07; // Internal Unix Use; diff --git a/Logger.RecordHandler.pp b/Logger.RecordHandler.pp new file mode 100644 index 0000000..1e9a599 --- /dev/null +++ b/Logger.RecordHandler.pp @@ -0,0 +1,164 @@ +{*******************************************************} + +{ Renegade BBS } + +{ Copyright (c) 1990-2013 The Renegade Dev Team } +{ Copyleft (ↄ) 2016-2017 Renegade BBS } + +{ This file is part of Renegade BBS } + +{ Renegade is free software: you can redistribute it } +{ and/or modify it under the terms of the GNU General } +{ Public License as published by the Free Software } +{ Foundation, either version 3 of the License, or } +{ (at your option) any later version. } + +{ Renegade is distributed in the hope that it will be } +{ useful, but WITHOUT ANY WARRANTY; without even the } +{ implied warranty of MERCHANTABILITY or FITNESS FOR } +{ A PARTICULAR PURPOSE. See the GNU General Public } +{ License for more details. } + +{ You should have received a copy of the GNU General } +{ Public License along with Renegade. If not, see } +{ . } + +{*******************************************************} +{ _______ __ } +{ | _ .-----.-----.-----.-----.---.-.--| .-----. } +{ |. l | -__| | -__| _ | _ | _ | -__| } +{ |. _ |_____|__|__|_____|___ |___._|_____|_____| } +{ |: | | |_____| } +{ |::.|:. | } +{ `--- ---' } +{*******************************************************} +{$mode objfpc} +{$codepage utf8} +{$h+} +{$packrecords c} +{ namespace Renegade.Logger } +{ Record Log Handler } +{ This handler just write messages to a pascal record file. } +unit Logger.RecordHandler; + +interface + +uses + Classes, + SysUtils, + StrUtils, + DateUtils, + Logger.HandlerInterface; + +type + TLogRecord = record + Level: byte; + Process: longint; + Identifier: string[255]; + LevelString: string[10]; + Message: string[255]; + Context: string[255]; + LogDateTime: TDateTime; + end; + + RecordHandler = class(TObject, LoggingHandlerInterface) + private + LogIdentifier: UTF8String; + LogRecord: TLogRecord; + LogRecordFile: file of TLogRecord; + function ConvertLogStringToError(LogString: ansistring): byte; + public + constructor Create; + destructor Destroy; + function Open(Identifier: UTF8String): boolean; + function Close: boolean; + function Write(const LogData: UTF8String): boolean; + end; + +implementation + +constructor RecordHandler.Create; +begin + inherited Create; +end; + +destructor RecordHandler.Destroy; +begin + inherited Destroy; +end; + +function RecordHandler.Open(Identifier: UTF8String): boolean; +begin + LogIdentifier := Identifier; + AssignFile(LogRecordFile, LogIdentifier + '.log'); + + {$I-} + if FileExists(LogIdentifier + '.log') then + begin + Reset(LogRecordFile); + end + else + begin + ReWrite(LogRecordFile); + end; + {$I+} + Seek(LogRecordFile, FileSize(LogRecordFile)); + if IOResult <> 0 then + begin + Result := True; + end + else + begin + Result := False; + end; + +end; + +function RecordHandler.Close: boolean; +begin + System.Close(LogRecordFile); + Result := True; +end; + +function RecordHandler.ConvertLogStringToError(LogString: ansistring): byte; +begin + case lowerCase(LogString) of + 'emergency': Result := 0; + 'alert': Result := 1; + 'critical': Result := 2; + 'error': Result := 3; + 'warning': Result := 4; + 'notice': Result := 5; + 'info': Result := 6; + 'debug': Result := 7; + else + Result := 8; + end; +end; + +function RecordHandler.Write(const LogData: UTF8String): boolean; +var + LogMessage, LogContext: UTF8String; + LogLevelString: ansistring; + Delims: TSysCharSet = ['[', ']']; + DateTime: TDateTime; +begin + + LogLevelString := ExtractWord(1, LogData, Delims); + LogContext := ExtractWord(3, LogData, Delims); + LogMessage := Format('[%S] %S[%D] %S', [DateTimeToStr(Now), LogIdentifier, GetProcessId(), LogData]); + with LogRecord do + begin + Level := ConvertLogStringToError(LogLevelString); + Identifier := LogIdentifier; + Process := GetProcessId(); + LevelString := LogLevelString; + Message := LogMessage; + Context := LogContext; + LogDateTime := Now; + end; + System.Write(LogRecordFile, LogRecord); + Result := True; +end; + +end. diff --git a/Renegade.Logger.pp b/Renegade.Logger.pp index 2adfa45..601eaeb 100644 --- a/Renegade.Logger.pp +++ b/Renegade.Logger.pp @@ -104,7 +104,6 @@ begin else begin Formatted := Format('[%s] %s', [ConvertLogErrorToString(LogLevel), Message]); - LoggingHandler.Write(Formatted); end; LoggingHandler.Close(); diff --git a/tests/LoggerRecordRead.pp b/tests/LoggerRecordRead.pp new file mode 100644 index 0000000..f962756 --- /dev/null +++ b/tests/LoggerRecordRead.pp @@ -0,0 +1,102 @@ +{*******************************************************} + +{ Renegade BBS } + +{ Copyright (c) 1990-2013 The Renegade Dev Team } +{ Copyleft (ↄ) 2016-2017 Renegade BBS } + +{ This file is part of Renegade BBS } + +{ Renegade is free software: you can redistribute it } +{ and/or modify it under the terms of the GNU General } +{ Public License as published by the Free Software } +{ Foundation, either version 3 of the License, or } +{ (at your option) any later version. } + +{ Renegade is distributed in the hope that it will be } +{ useful, but WITHOUT ANY WARRANTY; without even the } +{ implied warranty of MERCHANTABILITY or FITNESS FOR } +{ A PARTICULAR PURPOSE. See the GNU General Public } +{ License for more details. } + +{ You should have received a copy of the GNU General } +{ Public License along with Renegade. If not, see } +{ . } + +{*******************************************************} +{ _______ __ } +{ | _ .-----.-----.-----.-----.---.-.--| .-----. } +{ |. l | -__| | -__| _ | _ | _ | -__| } +{ |. _ |_____|__|__|_____|___ |___._|_____|_____| } +{ |: | | |_____| } +{ |::.|:. | } +{ `--- ---' } +{*******************************************************} +{$mode objfpc} +{$h+} +{$codepage utf8} +{$packrecords c} +{ namespace Renegade.Logger } +{ + Program to read data we wrote to renegade.log + using Logger.RecordHandler. +} +program LoggerRecordRead; + +uses + SysUtils, + Classes; + +type + TLogRecord = record + Level: byte; + Process: longint; + Identifier: string[255]; + LevelString: string[10]; + Message: string[255]; + Context: string[255]; + LogDateTime: TDateTime; + end; +var + LogRecord: TLogRecord; + FileRecord: file of TLogRecord; + i: byte; +begin + if FileExists('renegade.log') then + begin + AssignFile(FileRecord, 'renegade.log'); + + Reset(FileRecord); + + if IOResult <> 0 then + begin + Writeln('Error in opening file.'); + exit; + end + else + begin + for i := 0 to FileSize(FileRecord) - 1 do + begin + Seek(FileRecord, i); + Read(FileRecord, LogRecord); + with LogRecord do + begin + Writeln('Message ID : ', i); + Writeln('Process ID : ', Process); + Writeln('Message : ', Message); + Writeln('Log Level : ', Level); + Writeln('Level String : ', LevelString); + Writeln('Datetime : ', DateTimeToStr(LogDateTime)); + Writeln('Log Identifier : ', Identifier); + Writeln('Log Context : ', Context, #10#13); + end; + end; + end; + Close(FileRecord); + end + else + begin + Writeln('File doesn''t exist'); + exit; + end; +end. diff --git a/tests/LoggerTest.pp b/tests/LoggerTest.pp index a4beb7d..348d3ac 100644 --- a/tests/LoggerTest.pp +++ b/tests/LoggerTest.pp @@ -34,6 +34,7 @@ {*******************************************************} {$mode objfpc} {$codepage utf8} +{$packrecords c} {$h+} program LoggerTest; @@ -45,7 +46,8 @@ uses Logger.StreamHandler, Logger.FileHandler, Logger.NullHandler, - Logger.ConsoleHandler; + Logger.ConsoleHandler, + Logger.RecordHandler; var StreamLogHandler: StreamHandler; @@ -54,15 +56,19 @@ var MemoryStream: TMemoryStream; NullLogHandler: NullHandler; ConsoleLogHandler: ConsoleHandler; + RecordLogHandler : RecordHandler; begin //MemoryStream := TMemoryStream.Create; //StreamLogHandler := StreamHandler.Create('test.log'); //StreamLogHandler := StreamHandler.Create(MemoryStream); //LogFileHandler := FileHandler.Create('test.log'); //NullLogHandler := NullHandler.Create; - ConsoleLogHandler := ConsoleHandler.Create; - Log := RTLogger.Create(ConsoleLogHandler); - Log.Log(LOG_E, 'Test', []); + //ConsoleLogHandler := ConsoleHandler.Create; + RecordLogHandler := RecordHandler.Create; + + Log := RTLogger.Create(RecordLogHandler); + + //Log.Log(LOG_E, 'Test', []); Log.Info('Testing', ['File', True, 'Error', True, 'Extended', 'Extend']); Log.Debug('Debugging', []); Log.Error('Error', []);