diff --git a/Logger.AbstractLogger.pp b/Logger.AbstractLogger.pp index 9042db7..de8a4fc 100644 --- a/Logger.AbstractLogger.pp +++ b/Logger.AbstractLogger.pp @@ -36,6 +36,11 @@ {$codepage utf8} {$h+} { namespace Renegade.Logger } +{ Abstract Logger Class } +{ + If you don't need any custom code for the procedures Emergency to Debug + you can extend this class and only implement the Log procedure. +} unit Logger.AbstractLogger; interface @@ -87,7 +92,7 @@ begin LOG_INFO: Result := 'Info'; LOG_DEBUG: Result := 'Debug'; else - Result := 'Unkown'; + Result := 'Unknown'; end; end; diff --git a/Logger.ConsoleHandler.pp b/Logger.ConsoleHandler.pp index 8016788..e4e7c01 100644 --- a/Logger.ConsoleHandler.pp +++ b/Logger.ConsoleHandler.pp @@ -35,6 +35,9 @@ {$mode objfpc} {$codepage utf8} {$h+} +{ namespace Renegade.Logger } +{ Console Log Handler } +{ This handler just write messages to the console or terminal. } unit Logger.ConsoleHandler; interface @@ -46,14 +49,14 @@ uses type ConsoleHandler = class(TObject, LoggingHandlerInterface) - Private - LogIdentifier : UTF8String; - Public - constructor Create(); - destructor Destroy(); - function Open(Identifier: UTF8String): boolean; - function Close(): boolean; - function Write(const LogData: UTF8String): boolean; + private + LogIdentifier: UTF8String; + public + constructor Create(); + destructor Destroy(); + function Open(Identifier: UTF8String): boolean; + function Close(): boolean; + function Write(const LogData: UTF8String): boolean; end; implementation @@ -68,9 +71,10 @@ begin inherited Destroy; end; -function ConsoleHandler.Open(Identifier: UTF8String) : boolean; +function ConsoleHandler.Open(Identifier: UTF8String): boolean; begin - LogIdentifier := Identifier; + LogIdentifier := Identifier; + Result := True; end; function ConsoleHandler.Close(): boolean; @@ -80,7 +84,7 @@ end; function ConsoleHandler.Write(const LogData: UTF8String): boolean; var - LogMessage : UTF8String; + LogMessage: UTF8String; begin LogMessage := Format('%S[%D] %S', [LogIdentifier, GetProcessId(), LogData]); Writeln(LogMessage); diff --git a/Logger.FileHandler.pp b/Logger.FileHandler.pp index 8153e84..4063a58 100644 --- a/Logger.FileHandler.pp +++ b/Logger.FileHandler.pp @@ -35,45 +35,52 @@ {$mode objfpc} {$codepage utf8} {$h+} -Unit Logger.FileHandler; +{ namespace Renegade.Logger } +{ FileHandler Log Class } +{ + This class write a file to the filename passed to the constructor, + it just implements the StreamHandler class and passes a filename + to the StreamHandler filename constructor. +} +unit Logger.FileHandler; interface -Uses +uses Classes, SysUtils, Logger.HandlerInterface, Logger.StreamHandler; -Type FileHandler = class(StreamHandler, LoggingHandlerInterface) - Public - constructor Create( const FileName: UTF8String); - function Open(Identifier: UTF8String): boolean; - function Close(): boolean; - function Write(const LogData: UTF8String): boolean; -end; +type + FileHandler = class(StreamHandler, LoggingHandlerInterface) + public + constructor Create(const FileName: UTF8String); + function Open(Identifier: UTF8String): boolean; + function Close(): boolean; + function Write(const LogData: UTF8String): boolean; + end; implementation -constructor FileHandler.Create( const FileName: UTF8String); +constructor FileHandler.Create(const FileName: UTF8String); begin inherited Create(FileName); end; function FileHandler.Open(Identifier: UTF8String): boolean; begin - Result := inherited Open(Identifier); + Result := inherited Open(Identifier); end; -function FileHandler.Close() : boolean; +function FileHandler.Close(): boolean; begin - Result := inherited Close; + Result := inherited Close; end; function FileHandler.Write(const LogData: UTF8String): boolean; begin - Result := inherited Write(LogData); + Result := inherited Write(LogData); end; -End. - +end. diff --git a/Logger.HandlerInterface.pp b/Logger.HandlerInterface.pp index a23e66d..4bd5710 100644 --- a/Logger.HandlerInterface.pp +++ b/Logger.HandlerInterface.pp @@ -46,8 +46,19 @@ uses type LoggingHandlerInterface = interface ['{C6E95830-5B13-4A51-BC03-757A3A1C779F}'] + + { This method is called to do anything special to + open the log, an example would be making a + connection to a database or opening a file. } function Open(Identifier: UTF8String): boolean; + + { This method is called to do any closing of the log, + an example would be closing a database or a file. } function Close(): boolean; + + { This method is called to write log data, + and example would be inserting database records + or writing a line to a file. } function Write(const LogData: UTF8String): boolean; end; diff --git a/Logger.LoggerInterface.pp b/Logger.LoggerInterface.pp index e9605a3..bb3ad2c 100644 --- a/Logger.LoggerInterface.pp +++ b/Logger.LoggerInterface.pp @@ -60,19 +60,46 @@ const LOG_PRIMASK = $07; // Internal Unix Use; type + { Every procedure takes an array of const as Context, this is for any + extra information that doesn't fit well in the message, + (e.g. User id, menu name, etc.) } LoggerInterface = interface ['{3220524c-fae0-11e6-8b70-9c5c8e742ab6}'] + + // Sets the Logging Handler to use. (e.g. SysLogHandler, FileHandler, etc.) procedure SetHandler(Handler: LoggingHandlerInterface); + + // System is unusable procedure Emergency(Message: UTF8String; Context: array of const); + + // Action must be taken immediately procedure Alert(Message: UTF8String; Context: array of const); + + // Critical conditions procedure Critical(Message: UTF8String; Context: array of const); + + // Error conditions procedure Error(Message: UTF8String; Context: array of const); + + // Warning conditions procedure Warning(Message: UTF8String; Context: array of const); + + // Normal, but significant, condition procedure Notice(Message: UTF8String; Context: array of const); + + // Informational message procedure Info(Message: UTF8String; Context: array of const); + + // Debug-level message procedure Debug(Message: UTF8String; Context: array of const); + + { General logging procedure + LogLevel : array of const containing the different log levels + Message : The Log Message } procedure Log(LogLevel: LogLevels; Message: UTF8String; Context: array of const); + + // Holds the current logging handler. property LoggingHandler: LoggingHandlerInterface write SetHandler; end; diff --git a/Logger.NullHandler.pp b/Logger.NullHandler.pp index fe612b9..25b954c 100644 --- a/Logger.NullHandler.pp +++ b/Logger.NullHandler.pp @@ -35,6 +35,14 @@ {$mode objfpc} {$codepage utf8} {$h+} +{ Namespace Renegade.Logger } +{ Null Handler Log Class } +{ This class doesn't do anything. } +{ + If you want to implement a logger, but you aren't sure what kind of logger + you need, you can implement this. You could probably also use it for testing + purposes +} unit Logger.NullHandler; interface @@ -46,12 +54,12 @@ uses type NullHandler = class(TObject, LoggingHandlerInterface) - Public - constructor Create(); - destructor Destroy(); - function Open(Identifier: UTF8String): boolean; - function Close(): boolean; - function Write(const LogData: UTF8String): boolean; + public + constructor Create(); + destructor Destroy(); + function Open(Identifier: UTF8String): boolean; + function Close(): boolean; + function Write(const LogData: UTF8String): boolean; end; implementation @@ -66,7 +74,7 @@ begin inherited Destroy; end; -function NullHandler.Open(Identifier: UTF8String) : boolean; +function NullHandler.Open(Identifier: UTF8String): boolean; begin Result := True; end; diff --git a/Logger.StreamHandler.pp b/Logger.StreamHandler.pp index 39d5ebc..0e9c7c5 100644 --- a/Logger.StreamHandler.pp +++ b/Logger.StreamHandler.pp @@ -35,7 +35,12 @@ {$mode objfpc} {$codepage utf8} {$h+} - +{ namespace Renegade.Logger } +{ StreamHandler Logger Class } +{ + This class should take any TStream decendant and use it to + write log messages. +} unit Logger.StreamHandler; interface diff --git a/Logger.SysLogHandler.pp b/Logger.SysLogHandler.pp index a1d7b6b..4e247c1 100644 --- a/Logger.SysLogHandler.pp +++ b/Logger.SysLogHandler.pp @@ -33,28 +33,41 @@ { `--- ---' } {*******************************************************} {$mode objfpc} -{$interfaces corba} {$linklib c} {$codepage utf8} {$h+} - +{ + Unix System Log Handler. + The constructor takes one of the defined Logging Facilities. +} 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 the pid with each message + LOG_PID = $01; + // Write directly to system console if there is an error + // while sending to system logger. + LOG_CONS = $02; + // The converse of LOG_NDELAY; opening of the connection is delayed until + // syslog() is called. (This is the default, and need not be specified.) + LOG_ODELAY = $04; + // Open the connection immediately (normally, the connection is opened when + // the first message is logged). + LOG_NDELAY = $08; + // Don't wait for child processes that may have been created while logging + // the message. (The GNU C library does not create a child process, so this + // option has no effect on Linux.) + LOG_NOWAIT = $10; + // log to stderr as well + LOG_PERROR = $20; + { Logging Facilities } LOG_KERN = 0 shl 3; // kernel messages LOG_USER = 1 shl 3; // random user-level messages LOG_MAIL = 2 shl 3; // mail system @@ -77,7 +90,6 @@ type 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; @@ -86,7 +98,8 @@ type end; procedure closelog; cdecl; external; -procedure openlog(__ident: PChar; __option: longint; __facilit: longint); 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; diff --git a/Renegade.Logger.pp b/Renegade.Logger.pp index 5703e32..2adfa45 100644 --- a/Renegade.Logger.pp +++ b/Renegade.Logger.pp @@ -36,6 +36,12 @@ {$codepage utf8} {$h+} { namespace Renegade.Logger } +{ The Renegade logger class } +{ + This takes a HandlerInterface object to create the method of + writing logs. Inspiration was taken from the php psr/3 LoggerInterface. + @link https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md +} unit Renegade.Logger; interface @@ -48,6 +54,7 @@ uses Logger.LoggerInterface, Logger.AbstractLogger; + type RTLogger = class(AbstractLogger, LoggerInterface) public diff --git a/tests/LoggerTest.pp b/tests/LoggerTest.pp index 0ace54e..a4beb7d 100644 --- a/tests/LoggerTest.pp +++ b/tests/LoggerTest.pp @@ -48,12 +48,12 @@ uses Logger.ConsoleHandler; var - StreamLogHandler : StreamHandler; + StreamLogHandler: StreamHandler; Log: RTLogger; - LogFileHandler : FileHandler; - MemoryStream : TMemoryStream; - NullLogHandler : NullHandler; - ConsoleLogHandler : ConsoleHandler; + LogFileHandler: FileHandler; + MemoryStream: TMemoryStream; + NullLogHandler: NullHandler; + ConsoleLogHandler: ConsoleHandler; begin //MemoryStream := TMemoryStream.Create; //StreamLogHandler := StreamHandler.Create('test.log'); @@ -62,6 +62,7 @@ begin //NullLogHandler := NullHandler.Create; ConsoleLogHandler := ConsoleHandler.Create; Log := RTLogger.Create(ConsoleLogHandler); + Log.Log(LOG_E, 'Test', []); Log.Info('Testing', ['File', True, 'Error', True, 'Extended', 'Extend']); Log.Debug('Debugging', []); Log.Error('Error', []);