Logging

Logging

🌍 Language: English | Español

Structured logging infrastructure for Delphi inspired by .NET’s Microsoft.Extensions.Logging. Write log entries via a unified ILogger interface — swappable providers (NNLog, console, custom) registered at startup.

Delphi 12+ License


Why use this?

  • 🎚️ Six log levels — Trace, Debug, Information, Warning, Error, Critical
  • 📝 Structured logging — Named {Key} placeholders in message templates
  • 🔌 Provider model — Register one or more ILoggerProvider implementations; all receive each entry
  • 🏷️ Categories — Loggers are tagged by class or string name for filtering
  • 🔗 Scopes — Attach contextual data to a block of log entries with BeginScope
  • 🛠️ DI-readyAddLogging(Services, ...) registers ILoggerFactory in the container

Quick Start

uses
  Daf.Extensions.Logging,
  Daf.Logging,
  DAF.Logging.Builder,
  DAF.NNLog; // any provider

// Standalone (no DI)
var Factory := TMultiProviderLoggerFactory.Create;
Factory.AddProvider(TNNLogProvider.Create(Targets, Rules));
var Logger := Factory.CreateLogger('MyApp');

Logger.LogInformation('Server started on port {Port}', [8080]);
Logger.LogError(Ex, 'Unhandled exception in {Operation}', ['ProcessOrder']);

Log Levels

Level Value When to use
Trace 0 Extremely detailed — disabled in production
Debug 1 Development diagnostics
Information 2 Normal app flow milestones
Warning 3 Unexpected but recoverable situations
Error 4 Failures in the current operation
Critical 5 Requires immediate attention
None 6 Disables logging

Structured Logging

Use named placeholders in message templates:

Logger.LogInformation('User {UserId} logged in from {IP}', [UserId, RemoteIP]);
Logger.LogWarning('Retry {Attempt} of {Max} for {Operation}', [3, 5, 'SendEmail']);

The template and arguments are kept together in TLogState, letting providers format or index them independently.


Integration with DI and Hosting

uses DAF.Logging.Builder, DAF.NNLog;

// In ConfigureServices:
AddLogging(Services, procedure(Builder: ILoggingBuilder)
begin
  Builder.AddProvider(TNNLogProvider.Create(Targets, Rules));
end);

// Resolve in a service:
var Factory := Provider.GetRequiredService<ILoggerFactory>;
var Logger  := Factory.CreateLogger<TMyService>;

Documentation

  • 📖 Usage Guide — scopes, structured logging, providers, DI, creating custom providers

Abstractions

Logging.Abstractions

🌍 Language: English | Español

Core contracts for the DAFce logging infrastructure. Reference these interfaces when building components that emit log entries or when implementing custom log providers — without taking a dependency on any concrete logging implementation.


Interfaces

ILogger

Per-category façade that emits log entries.

ILogger = interface
  procedure Log(Level: TLogLevel; const Msg: string; const Args: array of const); overload;
  procedure Log(Level: TLogLevel; E: Exception; const Msg: string; const Args: array of const); overload;

  procedure LogTrace      (const Msg: string; const Args: array of const); overload;
  procedure LogDebug      (const Msg: string; const Args: array of const); overload;
  procedure LogInformation(const Msg: string; const Args: array of const); overload;
  procedure LogWarning    (const Msg: string; const Args: array of const); overload;
  procedure LogError      (const Msg: string; const Args: array of const); overload;
  procedure LogError      (E: Exception; const Msg: string; const Args: array of const); overload;
  procedure LogCritical   (const Msg: string; const Args: array of const); overload;
  procedure LogCritical   (E: Exception; const Msg: string; const Args: array of const); overload;

  function BeginScope(const Msg: string; const Args: array of const;
                      ScopedProc: TProc): ILogScopeVoid; overload;
end;

ILoggerFactory

Creates ILogger instances and fans writes out to all registered providers.

ILoggerFactory = interface
  function  CreateLogger(const Category: string): ILogger; overload;
  function  CreateLogger(AClass: TClass): ILogger; overload;
  function  CreateLogger(TypeInfo: PTypeInfo): ILogger; overload;
  procedure AddProvider(Provider: ILoggerProvider);
end;

Generic helper: Factory.CreateLogger<TMyClass> — uses the class name as category.


ILoggerProvider

Produce ILogger instances for a specific output destination.

ILoggerProvider = interface
  function CreateLogger(const Category: string): ILogger;
end;

ILoggingBuilder

Fluent interface for configuring providers before the host starts (used inside AddLogging).

ILoggingBuilder = interface
  procedure AddProvider(Provider: ILoggerProvider);
  function  Build: ILoggerFactory;
end;

ILogScope / ILogScopeVoid

Represent an active logging scope. ILogScopeVoid is the version returned by BeginScope when the scope proc does not return a value.


Value types

TLogLevel

TLogLevel = (Trace, Debug, Information, Warning, Error, Critical, None);

TLogState

Holds a structured log message — template string plus positional args.

TLogState = record
  Template: string;
  Args: TArray<TVarRec>;
  function Format: string;
end;

TLogEntry

Single log entry delivered to a provider’s Write method.

TLogEntry = record
  Level     : TLogLevel;
  Category  : string;
  EventId   : Integer;
  Exception : Exception;
  Scope     : string;
  State     : TLogState;
  Message   : string;
end;