Skip to content

michaelJustin/slf4p

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

217 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

slf4p - Simple Logging Facade for Pascal

Pascal Stars Last Commit Delphi Lazarus Workflow Status

The Simple Logging Facade for Pascal serves as a simple facade or abstraction for various logging frameworks (e.g. Log4D, LazLogger), allowing the end user to plug in the desired logging framework at build time.

Developed with Delphi 2009 and Lazarus 4.4, tested with DUnit and FPCUnit.

To register a specific logging framework, add one of the djLogOver... units to the project.

  • djLogOverNOPLogger for logging over NOPLogger
  • djLogOverSimpleLogger for logging over SimpleLogger
  • djLogOverLog4D for logging over Log4D
  • djLogOverLazLogger for logging over LazLogger

One of the LogOver... units must be added to the project. When no unit is added, a NOPLogger factory will be used as a fallback, and a message indicating the fallback will be printed.

Choosing Between SLF4P and Log4D

Before deciding which logging tool to use, it’s important to understand what each one does.

SLF4P is not a logging implementation on its own. It’s an abstraction layer that lets you plug in a logging framework at runtime, such as Log4D or LazLogger. You write your code against the SLF4P API and then link it to a logging backend via the source path.

Log4D, by contrast, is a complete logging implementation. It provides its own APIs, configuration mechanisms for generating logs, and powerful built-in features, including filtering, custom appenders, and advanced formatting.

Examples

NOPLogger

Since no unit for registering a logger factory is used, a factory for NOP loggers will be registered.

program HelloWorld;

uses
  djLoggerFactory, djLogAPI;

procedure RunDemo;
var
  Log: ILogger;
begin
  Log := TLoggerFactory.GetLogger;

  Log.Debug('Using slf4p %s', [SLF4P_VERSION]);
  Log.Info('Hello, World!');
  Log.Debug('Hit any key');

  ReadLn;
end;

begin
  RunDemo;
end.

Program output

SLF4P: Logger factory is not assigned
SLF4P: Defaulting to no-operation (NOP) logger implementation

SimpleLogger

The first unit used, djLogOverSimpleLogger, registers a factory for console loggers.

program HelloWorld;

uses
  djLogOverSimpleLogger,
  djLoggerFactory, djLogAPI;

procedure RunDemo;
var
  Log: ILogger;
begin
  Log := TLoggerFactory.GetLogger;

  Log.Debug('Using slf4p %s', [SLF4P_VERSION]);
  Log.Info('Hello, World!');
  Log.Debug('Hit any key');

  ReadLn;
end;

begin
  RunDemo;
end.

Program output

[12:05:46.732] DEBUG - Using slf4p 1.0.8
[12:05:46.732] INFO - Hello, World!
[12:05:46.733] DEBUG - Hit any key

Log4D

The first unit used, djLogOverLog4D, registers a logger factory which created Log4D loggers.

program HelloWorld;

uses
  djLogOverLog4D, 
  djLoggerFactory, djLogAPI,
  LogConsoleAppender, Log4d;

procedure RunDemo;
var
  Log: ILogger;
  ConsoleAppender: ILogAppender;
begin
  ConsoleAppender := TLogConsoleAppender.Create('console');
  TLogBasicConfigurator.Configure(ConsoleAppender);

  TLogLogger.GetRootLogger.Level := Debug;
  WriteLn('Logging with Log4D version ' + Log4DVersion);

  Log := TLoggerFactory.GetLogger('slf4p/log4d');
  Log.Debug('Using slf4p %s', [SLF4P_VERSION]);
  Log.Info('Hello, World!');
  Log.Debug('Hit any key');
  ReadLn;
end;

begin
  RunDemo;
end.

Program output

Logging with Log4D version 1.2.12
debug - Using slf4p 1.0.8
info - Hello, World!
debug - Hit any key

LazLogger

The first unit used, djLogOverLazLogger, registers a logger factory which creates LazLogger loggers.

program HelloWorld;

uses
  djLogOverLazLogger,
  djLoggerFactory, djLogAPI;

var
  Log: ILogger;
begin
  Log := TLoggerFactory.GetLogger;
  Log.Debug('Using slf4p %s', [SLF4P_VERSION]);
  Log.Info('Hello, World!');
  Log.Debug('Hit any key');
  ReadLn;
end.

Program output

0 DEBUG  - Using slf4p 1.0.8
0 INFO  - Hello, World!
0 DEBUG  - Hit any key

Named loggers

The example uses named loggers in the classes TFirstClass and TSecondClass. The logger is created in the constructor of each class, using the class type as a parameter for the GetLogger method. With the help of classic published RTTI, the example classes write their unit name and class name to the log.

program HelloWorld;

uses
  djLogOverSimpleLogger, SimpleLogger, 
  djLoggerFactory, djLogAPI,
  MyClasses in 'MyClasses.pas';

procedure RunDemo;
var
  Log: ILogger;
  Obj1: TFirstClass;
  Obj2: TSecondClass;
begin
  SimpleLogger.Configure('defaultLogLevel', 'trace');
  SimpleLogger.Configure('showDateTime', 'false');

  Log := TLoggerFactory.GetLogger;
  Log.Info('Using slf4p %s', [SLF4P_VERSION]);

  Obj1 := TFirstClass.Create;
  Obj2 := TSecondClass.Create;
  try
    Log.Info('Instances created');
  finally
    Obj2.Free;
    Obj1.Free;
  end;

  Log.Info('Hit any key');
  ReadLn;
end;

begin
  RunDemo;
end.

With the help of classic published RTTI, the example classes write their unit name and class name to the log.

unit MyClasses;

interface

uses
  djLoggerFactory, djLogAPI;

type
  {$TYPEINFO ON}
  TFirstClass = class(TObject)
  private
    Log: ILogger;
  public
    constructor Create;
    destructor Destroy; override;
  end;

  TSecondClass = class(TFirstClass)
  private
    Log: ILogger;
  public
    constructor Create;
    destructor Destroy; override;
  end;
  {$TYPEINFO OFF}

implementation

uses
  slf4p;

{ TFirstClass }

constructor TFirstClass.Create;
begin
  Log := TLoggerFactory.GetLogger(TFirstClass);

  Log.Debug('in constructor');
end;

destructor TFirstClass.Destroy;
begin
  Log.Debug('in destructor');
end;

{ TSecondClass }

constructor TSecondClass.Create;
begin
  Log := TLoggerFactory.GetLogger(TSecondClass);

  if Log.IsTraceEnabled then
    Log.Trace('entering constructor');

  inherited;

  if Log.IsTraceEnabled then
    Log.Trace('leaving constructor');
end;

destructor TSecondClass.Destroy;
begin
  if Log.IsTraceEnabled then
    Log.Trace('entering destructor');

  inherited;

  if Log.IsTraceEnabled then
    Log.Trace('leaving destructor');
end;

end.

Program output

0 INFO - Using slf4p 1.0.8
0 DEBUG MyClasses.TFirstClass in constructor
0 TRACE MyClasses.TSecondClass entering constructor
0 DEBUG MyClasses.TFirstClass in constructor
0 TRACE MyClasses.TSecondClass leaving constructor
0 INFO - Instances created
0 TRACE MyClasses.TSecondClass entering destructor
0 DEBUG MyClasses.TFirstClass in destructor
0 TRACE MyClasses.TSecondClass leaving destructor
0 DEBUG MyClasses.TFirstClass in destructor
0 INFO - Hit any key

About

A simple logging facade for Object Pascal (Delphi and FPC)

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages