diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..922b314 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.o +*.ppu +*~ diff --git a/Logger.HandlerInterface.pp b/Logger.HandlerInterface.pp new file mode 100644 index 0000000..a23e66d --- /dev/null +++ b/Logger.HandlerInterface.pp @@ -0,0 +1,56 @@ +{*******************************************************} + +{ 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} +{$interfaces corba} +{$codepage utf8} +{$h+} +unit Logger.HandlerInterface; + +interface + +uses + Classes; + +type + LoggingHandlerInterface = interface + ['{C6E95830-5B13-4A51-BC03-757A3A1C779F}'] + function Open(Identifier: UTF8String): boolean; + function Close(): boolean; + function Write(const LogData: UTF8String): boolean; + end; + +implementation + +end. diff --git a/Logger.LoggerInterface.pp b/Logger.LoggerInterface.pp new file mode 100644 index 0000000..e9605a3 --- /dev/null +++ b/Logger.LoggerInterface.pp @@ -0,0 +1,81 @@ +{*******************************************************} + +{ 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} +{$interfaces corba} +{$codepage utf8} +{$h+} +{ namespace Renegade.Logger } +unit Logger.LoggerInterface; + +interface + +uses + Classes, + Logger.HandlerInterface; + +type + LogLevels = ( + LOG_EMERG, + LOG_ALERT, + LOG_CRIT, + LOG_ERR, + LOG_WARNING, + LOG_NOTICE, + LOG_INFO, + LOG_DEBUG); + +const + LOG_PRIMASK = $07; // Internal Unix Use; + +type + LoggerInterface = interface + ['{3220524c-fae0-11e6-8b70-9c5c8e742ab6}'] + procedure SetHandler(Handler: LoggingHandlerInterface); + 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); + procedure Log(LogLevel: LogLevels; Message: UTF8String; + Context: array of const); + property LoggingHandler: LoggingHandlerInterface write SetHandler; + end; + +implementation + +end. diff --git a/Logger.LoggerTrait.pp b/Logger.LoggerTrait.pp new file mode 100644 index 0000000..00238a4 --- /dev/null +++ b/Logger.LoggerTrait.pp @@ -0,0 +1,148 @@ +{*******************************************************} +{ } +{ 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.SysLogHandler.pp b/Logger.SysLogHandler.pp new file mode 100644 index 0000000..a1d7b6b --- /dev/null +++ b/Logger.SysLogHandler.pp @@ -0,0 +1,129 @@ +{*******************************************************} + +{ 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} +{$interfaces corba} +{$linklib c} +{$codepage utf8} +{$h+} + +unit Logger.SysLogHandler; + +interface + +uses + Classes, + FPJson, + Logger.HandlerInterface; + +const + LOG_PID = $01; // log the pid with each message + LOG_CONS = $02; // log on the console if errors in sending + LOG_ODELAY = $04; // delay open until first syslog() (default) + LOG_NDELAY = $08; // don't delay open + LOG_NOWAIT = $10; // don't wait for console forks; (DEPRECATED) + LOG_PERROR = $20; // log to stderr as well + + LOG_KERN = 0 shl 3; // kernel messages + LOG_USER = 1 shl 3; // random user-level messages + LOG_MAIL = 2 shl 3; // mail system + LOG_DAEMON = 3 shl 3; // system daemons + LOG_AUTH = 4 shl 3; // security/authorization messages + LOG_SYSLOG = 5 shl 3; // messages generated internally by syslogd + LOG_LPR = 6 shl 3; // line printer subsystem + LOG_NEWS = 7 shl 3; // network news subsystem + LOG_UUCP = 8 shl 3; // UUCP subsystem + LOG_CRON = 9 shl 3; // clock daemon + LOG_AUTHPRIV = 10 shl 3; // security/authorization messages (private) + +var + UnixFacility: longint; + +type + SysLogHandler = class(TObject, LoggingHandlerInterface) + private + FUnixFacility: longint; + procedure SetFacility(const UnixFacility: longint); + public + constructor Create(const LoggingFacility: longint); + + function Open(Identifier: UTF8String): boolean; + function Close(): boolean; + function Write(const LogData: UTF8String): boolean; + published + property UnixFacility: longint read FUnixFacility write SetFacility; + end; + +procedure closelog; cdecl; external; +procedure openlog(__ident: PChar; __option: longint; __facilit: longint); cdecl; external; +function setlogmask(__mask: longint): longint; cdecl; external; +procedure syslog(__pri: longint; __fmt: PChar; args: array of const); cdecl; external; + +implementation + +constructor SysLogHandler.Create(const LoggingFacility: longint); +begin + FUnixFacility := LoggingFacility; +end; + +procedure SysLogHandler.SetFacility(const UnixFacility: longint); +begin + FUnixFacility := UnixFacility; +end; + +function SysLogHandler.Open(Identifier: UTF8String): boolean; +var + SysLogIdentifier: PAnsiChar; +begin + SysLogIdentifier := PAnsiChar(Identifier); + openlog(SysLogIdentifier, LOG_PID xor LOG_CONS xor LOG_NDELAY, FUnixFacility); + Result := True; +end; + +function SysLogHandler.Close(): boolean; +begin + closelog; + Result := True; +end; + +function SysLogHandler.Write(const LogData: UTF8String): boolean; +var + SysLogData: PAnsiChar; +begin + SysLogData := PAnsiChar(LogData); + syslog(FUnixFacility, SysLogData, []); + Result := True; +end; + +end. diff --git a/README.md b/README.md new file mode 100644 index 0000000..ce60e74 --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# Renegade Logger Class + diff --git a/Renegade.Logger.pp b/Renegade.Logger.pp new file mode 100644 index 0000000..283f40e --- /dev/null +++ b/Renegade.Logger.pp @@ -0,0 +1,104 @@ +{*******************************************************} + +{ 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 Renegade.Logger; + +interface + +uses + Classes, + SysUtils, + FPJson, + Logger.HandlerInterface, + Logger.LoggerInterface, + Logger.LoggerTrait; + +type + RTLogger = class(LoggerTrait, LoggerInterface) + public + constructor Create(Handler: LoggingHandlerInterface); + procedure Log(LogLevel: LogLevels; Message: UTF8String; + Context: array of const); override; + end; + +implementation + +constructor RTLogger.Create(Handler: LoggingHandlerInterface); +begin + LoggingHandler := Handler; +end; + +procedure RTLogger.Log(LogLevel: LogLevels; Message: UTF8String; + Context: array of const); +var + JsonObject, JsonObjectContext: TJsonObject; + JsonArray: TJsonArray; +begin + + if Length(Context) <> 0 then + begin + + try + JsonObjectContext := TJsonObject.Create(Context); + JsonObject := TJsonObject.Create(); + JsonArray := TJsonArray.Create(); + JsonArray.Add(JsonObjectContext); + JsonObject.Add('Context', JsonObjectContext); + JsonObject.CompressedJSON := True; + except + On e: Exception do + begin + Writeln(e.Message); + end; + end; + end; + LoggingHandler.Open('renegade'); + if Length(Context) <> 0 then + begin + LoggingHandler.Write(Format('[%s] %s [%s]', + [ConvertLogErrorToString(LogLevel), Message, JsonObject.AsJSON])); + end + else + begin + LoggingHandler.Write(Format('[%s] %s', + [ConvertLogErrorToString(LogLevel), Message])); + end; + LoggingHandler.Close(); +end; + +end. diff --git a/tests/LoggerTest.pp b/tests/LoggerTest.pp new file mode 100644 index 0000000..d0cb1d0 --- /dev/null +++ b/tests/LoggerTest.pp @@ -0,0 +1,55 @@ +{*******************************************************} + +{ 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+} + +program LoggerTest; + +uses + Classes, + Renegade.Logger, + Logger.SysLogHandler; + +var + LogHandler: SysLogHandler; + Log: RTLogger; +begin + LogHandler := SysLogHandler.Create(LOG_DAEMON); + Log := RTLogger.Create(LogHandler); + Log.Info('Testing', ['File', True, 'Error', True, 'Extended', 'Extend']); + Log.Debug('Debugging', []); + Log.Error('Error', []); +end.