A lightweight, thread-safe logging system for Delphi applications. Write log messages to multiple outputs simultaneously - files, console, or GUI memos. Uses a singleton pattern so you can log from anywhere in your code without passing logger instances around.
Automatic pruning of old log files (Files_To_Keep), an On_Error
hook for the file output, new Write overloads for logging a value against a
label (string, boolean or integer), and a Last_Severe property for
watchdog-style tracking of the last severe exception.
Two changes to be aware of if you're updating from Version 1.0:
ATime : Boolean parameter is gone from TLogger.Write.
Timestamp suppression is now controlled with the Include_TimeStamp class
property instead - see the updated example below.Add_Output previously discarded a second output of the same class,
which silently broke the "Multiple File Outputs" pattern further down this page. That's
fixed in 2.0 - TFile_Log_Output now explicitly allows more than one
instance, so logging to two files at once works as documented again.Add outputs at application startup (e.g., in your .dpr file or main form's OnCreate):
uses
PBS.LIB.Log, PBS.LIB.Log.Disk, PBS.LIB.Log.Console;
var
LLog_Path : string;
begin
// Setup file logging
LLog_Path := 'C:\MyApp\Logs\';
TLogger.Add_Output(TFile_Log_Output.Create(LLog_Path, 'MyApp'));
// Add console output for debugging
TLogger.Add_Output(TConsole_Log_Output.Create);
end;
The logger will create daily log files named MyApp_YYYYMMDD.log in the
specified directory. If the path is empty, it defaults to a 'logs' folder next to your
executable. The directory is created automatically if it doesn't exist.
Once configured, you can log from anywhere in your application:
// Simple message with timestamp
TLogger.Write('Application started');
// Message with class and method context
TLogger.Write('Processing order #12345', 'TOrderProcessor', 'ProcessOrder');
// Message without timestamp - Include_TimeStamp is a class property,
// so this affects every subsequent Write until you turn it back on
TLogger.Include_TimeStamp := False;
TLogger.Write('Raw message');
TLogger.Include_TimeStamp := True;
// Log a value against a label - overloads for string, boolean, integer
TLogger.Write('Order Total', 42);
TLogger.Write('Order Valid', True);
// Precise timing (includes milliseconds)
TLogger.Write_Precise('Query executed in 123ms');
// Exception handling
try
// your code
except
on E: Exception do
TLogger.Write(E, 'TOrderProcessor', 'ProcessOrder');
end;
// Add visual separator
TLogger.Write_Error; // Adds error separator line
TLogger.Write_New_Line; // Adds blank line
You can also log directly to a TMemo on your form for real-time display:
uses
PBS.LIB.Log.Memo;
procedure TMainForm.FormCreate(Sender: TObject);
begin
// Add memo output alongside file logging
TLogger.Add_Output(TMemo_Log_Output.Create(Memo_Log));
end;
All log messages will now appear in both the file and the memo simultaneously.
Here's what your log file will look like:
14:23:45 Application started
14:23:45 TOrderProcessor: ProcessOrder: Processing order #12345
14:23:46.123 Query executed in 123ms
14:23:47 Error ------------------------------------
14:23:47 TOrderProcessor: ProcessOrder: Access violation at address 004A2B10
14:23:50 Shutdown complete
The file logger automatically handles file operations:
Prefix_YYYYMMDD.logClose_After_Secs property)Files_To_Keep
(defaults to 15) - hook On_Error if you want to know when pruning failsAll logger operations use critical sections for thread safety. Multiple threads can
safely call TLogger.Write simultaneously. The file logger has additional
locking for file operations.
The logger uses a singleton pattern with pluggable outputs:
TLogger - Main singleton class, manages outputsTLog_Output - Abstract base class for outputs; override
Allow_Duplicates if more than one instance of your output type is validTFile_Log_Output - Logs to daily rotating files, prunes old ones via
PBS.LIB.Prune_Files, uses PBS.LIB.CmdLine for the default
exe-relative log pathTConsole_Log_Output - Logs to console (WriteLn)TMemo_Log_Output - Logs to TMemo controlYou can create custom outputs by inheriting from TLog_Output and
implementing the Write_Line method.
PBS.LIB.CmdLine, PBS.LIB.Prune_Files) and the shared
PBS.LIB.Common unit that the file output now uses internallyYou can log to multiple files simultaneously:
var
LMain_Path, LError_Path : string;
begin
LMain_Path := 'C:\Logs\Main\';
LError_Path := 'C:\Logs\Errors\';
TLogger.Add_Output(TFile_Log_Output.Create(LMain_Path, 'App'));
TLogger.Add_Output(TFile_Log_Output.Create(LError_Path, 'Errors'));
end;
Create your own output by inheriting from TLog_Output:
type
TDatabase_Log_Output = class(TLog_Output)
public
procedure Write_Line(const AMessage: string); override;
end;
procedure TDatabase_Log_Output.Write_Line(const AMessage: string);
begin
// Insert into database table
MyDB.Execute('INSERT INTO logs (message) VALUES (?)', [AMessage]);
end;
You can remove all outputs if needed:
TLogger.Clear_Outputs; // Frees all output objects
Please donate if helpful