From fe20d46e2544af698203f41542a6c47fd0cbcd35 Mon Sep 17 00:00:00 2001 From: "R. Eric Wheeler" Date: Sat, 25 Feb 2017 18:54:43 -0800 Subject: [PATCH] Changed LoggerTrait to AbstractLogger because that is more what it is. Added Log StreamHandler --- Logger.AbstractLogger.pp | 147 ++++++++++++++++++++++++++++++++++++++ Logger.LoggerTrait.pp | 148 --------------------------------------- Logger.StreamHandler.pp | 120 +++++++++++++++++++++++++++++++ README.md | 4 +- Renegade.Logger.pp | 18 ++--- tests/LoggerTest.pp | 12 ++-- 6 files changed, 287 insertions(+), 162 deletions(-) create mode 100644 Logger.AbstractLogger.pp delete mode 100644 Logger.LoggerTrait.pp create mode 100644 Logger.StreamHandler.pp diff --git a/Logger.AbstractLogger.pp b/Logger.AbstractLogger.pp new file mode 100644 index 0000000..27b223d --- /dev/null +++ b/Logger.AbstractLogger.pp @@ -0,0 +1,147 @@ +{*******************************************************} + +{ 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+} +{ namespace Renegade.Logger } +unit Logger.AbstractLogger; + +interface + +uses + Classes, + SysUtils, + Math, + Logger.LoggerInterface, + Logger.HandlerInterface, + Logger.SysLogHandler; + +type + AbstractLogger = class abstract(TObject, LoggerInterface) + private + FLoggingHandler: LoggingHandlerInterface; + procedure SetHandler(LoggingHandler: LoggingHandlerInterface); + public + constructor Create(LoggingHandler: LoggingHandlerInterface); + destructor Destroy; override; + procedure Emergency(Message: UTF8String; Context: array of const); + procedure Alert(Message: UTF8String; Context: array of const); + procedure Critical(Message: UTF8String; Context: array of const); + procedure Error(Message: UTF8String; Context: array of const); + procedure Warning(Message: UTF8String; Context: array of const); + procedure Notice(Message: UTF8String; Context: array of const); + procedure Info(Message: UTF8String; Context: array of const); + procedure Debug(Message: UTF8String; Context: array of const); + function ConvertLogErrorToString(LogLevel: LogLevels): ansistring; + procedure Log(LogLevel: LogLevels; Message: UTF8String; + Context: array of const); virtual; abstract; + published + property LoggingHandler: LoggingHandlerInterface + read FLoggingHandler write SetHandler; + end; + + +implementation + +function AbstractLogger.ConvertLogErrorToString(LogLevel: LogLevels): ansistring; +begin + case LogLevel of + LOG_EMERG: Result := 'Emergency'; + LOG_ALERT: Result := 'Alert'; + LOG_CRIT: Result := 'Critical'; + LOG_ERR: Result := 'Error'; + LOG_WARNING: Result := 'Warning'; + LOG_NOTICE: Result := 'Notice'; + LOG_INFO: Result := 'Info'; + LOG_DEBUG: Result := 'Debug'; + end; +end; + +procedure AbstractLogger.SetHandler(LoggingHandler: LoggingHandlerInterface); +begin + FLoggingHandler := LoggingHandler; +end; + +constructor AbstractLogger.Create(LoggingHandler: LoggingHandlerInterface); +begin + FLoggingHandler := LoggingHandler; +end; + +destructor AbstractLogger.Destroy; +begin + inherited Destroy; +end; + +procedure AbstractLogger.Emergency(Message: UTF8String; Context: array of const); +begin + Log(LOG_EMERG, Message, Context); +end; + +procedure AbstractLogger.Alert(Message: UTF8String; Context: array of const); +begin + Log(LOG_ALERT, Message, Context); +end; + +procedure AbstractLogger.Critical(Message: UTF8String; Context: array of const); +begin + Log(LOG_CRIT, Message, Context); +end; + +procedure AbstractLogger.Error(Message: UTF8String; Context: array of const); +begin + Log(LOG_ERR, Message, Context); +end; + +procedure AbstractLogger.Warning(Message: UTF8String; Context: array of const); +begin + Log(LOG_WARNING, Message, Context); +end; + +procedure AbstractLogger.Notice(Message: UTF8String; Context: array of const); +begin + Log(LOG_NOTICE, Message, Context); +end; + +procedure AbstractLogger.Info(Message: UTF8String; Context: array of const); +begin + Log(LOG_INFO, Message, Context); +end; + +procedure AbstractLogger.Debug(Message: UTF8String; Context: array of const); +begin + Log(LOG_DEBUG, Message, Context); +end; + +end. diff --git a/Logger.LoggerTrait.pp b/Logger.LoggerTrait.pp deleted file mode 100644 index 00238a4..0000000 --- a/Logger.LoggerTrait.pp +++ /dev/null @@ -1,148 +0,0 @@ -{*******************************************************} -{ } -{ 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+} -{ namespace Renegade.Logger } -Unit Logger.LoggerTrait; - -interface - -uses - Classes, - SysUtils, - Math, - Logger.LoggerInterface, - Logger.HandlerInterface, - Logger.SysLogHandler; - -Type LoggerTrait = class(TObject, LoggerInterface) - Private - FLoggingHandler : LoggingHandlerInterface; - procedure SetHandler( LoggingHandler : LoggingHandlerInterface ); - Public - constructor Create(LoggingHandler : LoggingHandlerInterface); - destructor Destroy; override; - procedure Emergency(Message : UTF8String; Context : array of const); - procedure Alert(Message : UTF8String; Context : array of const); - procedure Critical(Message : UTF8String; Context : array of const); - procedure Error(Message : UTF8String; Context : array of const); - procedure Warning(Message : UTF8String; Context : array of const); - procedure Notice(Message : UTF8String; Context : array of const); - procedure Info(Message : UTF8String; Context : array of const); - procedure Debug(Message : UTF8String; Context : array of const); - function ConvertLogErrorToString(LogLevel : LogLevels) : AnsiString; - procedure Log(LogLevel : LogLevels; Message :UTF8String; Context : array of const);virtual; - Published - property LoggingHandler : LoggingHandlerInterface read FLoggingHandler write SetHandler; -end; - - -implementation -function LoggerTrait.ConvertLogErrorToString(LogLevel : LogLevels) : AnsiString; -begin - Case LogLevel of - LOG_EMERG : Result := 'Emergency'; - LOG_ALERT : Result := 'Alert'; - LOG_CRIT : Result := 'Critical'; - LOG_ERR : Result := 'Error'; - LOG_WARNING : Result := 'Warning'; - LOG_NOTICE : Result := 'Notice'; - LOG_INFO : Result := 'Info'; - LOG_DEBUG : Result := 'Debug'; - end; -end; - -procedure LoggerTrait.SetHandler( LoggingHandler : LoggingHandlerInterface ); -begin - FLoggingHandler := LoggingHandler; -end; - -constructor LoggerTrait.Create(LoggingHandler :LoggingHandlerInterface); -begin - FLoggingHandler := LoggingHandler; -end; - -destructor LoggerTrait.Destroy; -begin - inherited Destroy; -end; -procedure LoggerTrait.Emergency(Message : UTF8String; Context : array of const); -begin - Log(LOG_EMERG, Message, Context); -end; - -procedure LoggerTrait.Alert(Message : UTF8String; Context : array of const); -begin - Log(LOG_ALERT, Message, Context); -end; -procedure LoggerTrait.Critical(Message : UTF8String; Context : array of const); -begin - Log(LOG_CRIT, Message, Context); -end; -procedure LoggerTrait.Error(Message : UTF8String; Context : array of const); -begin - Log(LOG_ERR, Message, Context); -end; -procedure LoggerTrait.Warning(Message : UTF8String; Context : array of const); -begin - Log(LOG_WARNING, Message, Context); -end; - -procedure LoggerTrait.Notice(Message : UTF8String; Context : array of const); -begin - Log(LOG_NOTICE, Message, Context); -end; - -procedure LoggerTrait.Info(Message : UTF8String; Context : array of const); -begin - Log(LOG_INFO, Message, Context); -end; - -procedure LoggerTrait.Debug(Message : UTF8String; Context : array of const); -begin - Log(LOG_DEBUG, Message, Context); -end; -procedure LoggerTrait.Log(LogLevel : LogLevels; Message :UTF8String; Context : array of const); -begin - - raise Exception.Create( - Format(#10#13' You need override the LoggerInterface.Log method in your class.'#10#13 + - ' Implemented class was %s.%s.'#10#13, - [self.UnitName, self.ClassName])) at - get_caller_addr(get_frame), - get_caller_frame(get_frame); -end; -end. diff --git a/Logger.StreamHandler.pp b/Logger.StreamHandler.pp new file mode 100644 index 0000000..39d5ebc --- /dev/null +++ b/Logger.StreamHandler.pp @@ -0,0 +1,120 @@ +{*******************************************************} + +{ 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+} + +unit Logger.StreamHandler; + +interface + +uses + Classes, + SysUtils, + Logger.HandlerInterface; + +type + StreamHandler = class(TObject, LoggingHandlerInterface) + private + HandlerStream: TStream; + StreamIdentifier: UTF8String; + public + constructor Create(const Stream: TStream); overload; + constructor Create(const FileName: UTF8String); overload; + destructor Destroy; override; + function Open(Identifier: UTF8String): boolean; + function Close(): boolean; + function Write(const LogData: UTF8String): boolean; + published + end; + +implementation + +constructor StreamHandler.Create(const Stream: TStream); overload; +begin + inherited Create; + HandlerStream := Stream; +end; + +constructor StreamHandler.Create(const FileName: UTF8String); overload; +begin + inherited Create; + try + if FileExists(FileName) then + begin + HandlerStream := TFileStream.Create(FileName, fmOpenWrite); + end + else + begin + HandlerStream := TFileStream.Create(FileName, fmCreate); + end; + except + on e: Exception do + begin + Destroy; + HandlerStream.Free; + end; + end; +end; + +destructor StreamHandler.Destroy; +begin + inherited Destroy; +end; + +function StreamHandler.Open(Identifier: UTF8String): boolean; +begin + StreamIdentifier := Identifier; + Result := True; +end; + +function StreamHandler.Close(): boolean; +begin + // Nothing do be done here. + Result := True; +end; + +function StreamHandler.Write(const LogData: UTF8String): boolean; +var + LogMessage: UTF8String; + WrittenBytes: longint; +begin + LogMessage := Format('%S[%D] %S'#10#13, [StreamIdentifier, GetProcessId(), LogData]); + HandlerStream.Seek(0, soEnd); + WrittenBytes := HandlerStream.Write(LogMessage[1], Length(LogMessage)); + Result := (WrittenBytes > 0); +end; + +end. diff --git a/README.md b/README.md index e4d3144..02d15d5 100644 --- a/README.md +++ b/README.md @@ -7,11 +7,11 @@ Logger class for Free Pascal ```pascal uses Renegade.Logger, - { Only handler at the moment - Implement Logger.LoggingHandlerInterface + { Implement Logger.LoggingHandlerInterface (Logger.HandlerInterface unit) to create your own. } Logger.SysLogHandler, + // or Logger.StreamHandler, //... other units; var diff --git a/Renegade.Logger.pp b/Renegade.Logger.pp index 283f40e..195f764 100644 --- a/Renegade.Logger.pp +++ b/Renegade.Logger.pp @@ -46,10 +46,10 @@ uses FPJson, Logger.HandlerInterface, Logger.LoggerInterface, - Logger.LoggerTrait; + Logger.AbstractLogger; type - RTLogger = class(LoggerTrait, LoggerInterface) + RTLogger = class(AbstractLogger, LoggerInterface) public constructor Create(Handler: LoggingHandlerInterface); procedure Log(LogLevel: LogLevels; Message: UTF8String; @@ -68,11 +68,11 @@ procedure RTLogger.Log(LogLevel: LogLevels; Message: UTF8String; var JsonObject, JsonObjectContext: TJsonObject; JsonArray: TJsonArray; + Formatted: UTF8String; begin if Length(Context) <> 0 then begin - try JsonObjectContext := TJsonObject.Create(Context); JsonObject := TJsonObject.Create(); @@ -83,20 +83,22 @@ begin except On e: Exception do begin - Writeln(e.Message); + Destroy; end; end; end; LoggingHandler.Open('renegade'); if Length(Context) <> 0 then begin - LoggingHandler.Write(Format('[%s] %s [%s]', - [ConvertLogErrorToString(LogLevel), Message, JsonObject.AsJSON])); + Formatted := Format('[%s] %s [%s]', [ConvertLogErrorToString(LogLevel), + Message, JsonObject.AsJSON]); + LoggingHandler.Write(Formatted); end else begin - LoggingHandler.Write(Format('[%s] %s', - [ConvertLogErrorToString(LogLevel), Message])); + Formatted := Format('[%s] %s', [ConvertLogErrorToString(LogLevel), Message]); + + LoggingHandler.Write(Formatted); end; LoggingHandler.Close(); end; diff --git a/tests/LoggerTest.pp b/tests/LoggerTest.pp index d0cb1d0..37d875d 100644 --- a/tests/LoggerTest.pp +++ b/tests/LoggerTest.pp @@ -41,14 +41,18 @@ program LoggerTest; uses Classes, Renegade.Logger, - Logger.SysLogHandler; + Logger.SysLogHandler, + Logger.StreamHandler; var - LogHandler: SysLogHandler; + StreamLogHandler : StreamHandler; Log: RTLogger; + MemoryStream : TMemoryStream; begin - LogHandler := SysLogHandler.Create(LOG_DAEMON); - Log := RTLogger.Create(LogHandler); + MemoryStream := TMemoryStream.Create; + //StreamLogHandler := StreamHandler.Create('test.log'); + StreamLogHandler := StreamHandler.Create(MemoryStream); + Log := RTLogger.Create(StreamLogHandler); Log.Info('Testing', ['File', True, 'Error', True, 'Extended', 'Extend']); Log.Debug('Debugging', []); Log.Error('Error', []);