Become a member!

LoggerPro 2.1 — Asynchrones Logging-Framework für Delphi

🌐
Dieser Artikel ist auch in anderen Sprachen verfügbar:
🇬🇧 English  •  🇮🇹 Italiano  •  🇪🇸 Español
📚
Suchen Sie eine ältere Version?
LoggerPro 2.0  •  LoggerPro 1.x (legacy)

TL;DR: LoggerPro 2.1 ist das asynchrone, thread-sichere Logging-Framework für Delphi. Es behält die Fluent-Builder-Pattern-API aus 2.0 und ergänzt externe Konfiguration per JSON (LoggerProFromJSONFile oder LoggerProFromJSONString), ExeWatch Cloud-Observability, einen spezifikationskonformen LogFmt-Renderer, einen FileBySource-Appender für mandantenspezifische Logs, UTF-8-Konsolenausgabe für Docker, DLL-sichere Initialisierung, ElasticSearch-Authentifizierung und mehr. Drop-in-Upgrade von 2.0, Apache-2.0-lizenziert, lauffähig von Delphi 10.2 Tokyo bis Delphi 13 Florence, auf Windows / Linux / macOS / Android / iOS. LoggerPro 2.0 Dokumentation → · LoggerPro 1.x Dokumentation →

Auf einen Blick

NameLoggerPro
Version2.1.0 (April 2026)
SpracheDelphi / Object Pascal
Minimum Delphi10.2 Tokyo · Getestet bis 13 Florence
PlattformenWindows, Linux, macOS, Android, iOS
LizenzApache 2.0 (kostenlos für kommerzielle Nutzung)
AutorDaniele Teti
Repositorygithub.com/danieleteti/loggerpro
InstallationBOSS · ZIP-Release
KategorieAsynchron · Thread-sicher · Steckbar · Strukturiertes Logging
Nächste ÄquivalenteSerilog (.NET), NLog (.NET), log4j / Logback (Java)

LoggerPro 2.1 Logo

Was ist LoggerPro?

LoggerPro ist das asynchrone, thread-sichere, steckbare Logging-Framework für Delphi / Object Pascal - das nächstliegende Delphi-Äquivalent zu Serilog (.NET), NLog (.NET) oder log4j / Logback (Java). Es bietet eine Fluent-Builder-API, strukturierten Schlüssel-Wert-Kontext, steckbare Stack-Trace-Formatter, über 20 eingebaute Appender (Datei, Konsole, HTTP, ExeWatch-Cloud-Observability, Grafana Loki via LogFmt, ElasticSearch, UDP-Syslog, Windows Event Log, Datenbank, VCL und mehr) und läuft plattformübergreifend auf Windows, Linux, macOS, Android und iOS. LoggerPro ist Apache-2.0-lizenziert, wird seit 2010 aktiv gepflegt und ist in Tausenden produktiver Delphi-Anwendungen im Einsatz.

Version 2.1 (April 2026) ist die aktuelle stabile Version. Sie baut auf der in 2.0 eingeführten Fluent-Builder-Pattern-API auf und ergänzt eine erstklassige ExeWatch-Integration für End-to-End-Cloud-Observability sowie Funktionen für moderne Deployment-Ziele - Docker-Container, Cloud-Log-Aggregatoren (Grafana Loki, Elastic, Datadog), Mehrmandanten-Anwendungen und Delphi-DLLs - bei voller Rückwärtskompatibilität.

Neuerungen in 2.1

FeatureNutzen
JSON-KonfigurationLogger zum Deployment-Zeitpunkt umformen - LoggerProFromJSONFile('loggerpro.json'). Strikte Feldvalidierung, Diagnosen bei unbekannten Typen
HTML-Live-Log-ViewerEigenständige .html-Datei mit klebender Filterleiste, levelbasierter Einfärbung, clientseitiger Suche, CSV-/JSON-Export und Live-Tailing im Browser
ExeWatch-IntegrationErstklassiger Cloud-Observability-Appender für ExeWatch - imperative, fluente oder JSON-basierte Konfiguration
Plug-in-Appender-PatternOptionale Backends (ExeWatch, WindowsEventLog, ElasticSearch) registrieren sich automatisch aus der eigenen Unit - nur die uses-Klausel ergänzen
Runtime-MinimumLevelILogWriter.MinimumLevel ist jetzt eine erstklassige Property - globales Gate zur Laufzeit ändern
Webhook-AppenderUmbenannt von HTTPAppender; API-Key-Authentifizierung ergänzt (Header oder Query-String)
LogFmt-RendererSpezifikationskonforme key=value-Ausgabe; grep-freundlich, Loki-kompatibel, einzeilige Datensätze
FileBySource-AppenderQuellenspezifische (mandanten-, kundenspezifische) Unterordner mit Tages-+Größenrotation
UTF-8-KonsolenausgabeKorrekte Unicode-Ausgabe in Docker-Containern und Windows-Konsolen (WithUTF8Output)
DLL-sichere InitialisierungBehebt den Windows-Loader-Lock-Deadlock bei Nutzung von LoggerPro aus einer DLL
ElasticSearch-AuthBasic Auth, API Key und Bearer-Token-Unterstützung
UDP-Syslog LokalzeitWithUseLocalTime(True)-Option am Syslog-Appender
GetCurrentLogFileNameAktiven Log-Datei-Pfad abrufen - nützlich für Upload, E-Mail, Neustart

Upgrade von 2.0? Weitgehend Drop-in-Ersatz. Eine Breaking Change: WriteToHTTP wurde in WriteToWebhook umbenannt (ein Suchen-und-Ersetzen reicht). Alles Übrige ist additiv.

Schnellstart mit der Builder-API

uses
  LoggerPro,
  LoggerPro.Builder;

var
  Log: ILogWriter;
begin
  Log := LoggerProBuilder
    .WithDefaultTag('MYAPP')
    .WriteToFile
      .WithLogsFolder('logs')
      .WithMaxBackupFiles(5)
      .WithMaxFileSizeInKB(10000)
      .Done
    .WriteToConsole
      .Done
    .Build;

  Log.Info('Application started');
  Log.Debug('Processing item %d', [42], 'WORKER');
  Log.Error('Connection failed', 'DATABASE');

  // Contextual logging
  Log.WithProperty('user_id', 42)
     .WithProperty('session', 'abc123')
     .Info('User logged in', 'auth');

  // Exception logging
  try
    // ... code ...
  except
    on E: Exception do
      Log.LogException(E, 'Operation failed', 'error');
  end;

  // Explicit shutdown before exit
  Log.Shutdown;
end;

JSON-Konfiguration

Neu in 2.1. Liefern Sie Ihre Anwendung mit einer loggerpro.json neben der EXE aus und gestalten Sie den Logger zum Deployment-Zeitpunkt um, ohne neu zu bauen. Betreiber können Backends wechseln, Log-Level anpassen oder Appender hinzufügen bzw. entfernen, ohne den Quellcode anzufassen.

Schema auf einen Blick

{
  "configVersion":        1,
  "minimumLevel":         "Debug",
  "defaultMinimumLevel":  "Warning",
  "defaultTag":           "myapp",

  "appenders": [
    { "type": "Console",  "colors": true, "colorScheme": "Midnight" },
    { "type": "File",     "logsFolder": "logs", "maxBackupFiles": 5,
                          "minimumLevel": "Debug" },
    { "type": "HTMLFile", "logsFolder": "logs", "title": "MyApp" }
  ]
}

Das globale Gate lässt alles durch (minimumLevel: Debug). Jeder Appender ohne eigenes minimumLevel übernimmt den Vorlagewert Warning - Console und HTMLFile erben ihn beide. Der File-Appender zieht ihn aus und schreibt den kompletten Audit-Trail auf Debug. defaultMinimumLevel unter minimumLevel zu setzen wäre ein No-op: das globale Gate hätte diese Nachrichten bereits verworfen, bevor sie einen Appender erreichen.

Root-Felder:

FeldTypZweck
configVersionintegerSchema-Version. Fehlt = neueste. Höher als die Version der Bibliothek = harter Fehler.
minimumLevelstringGlobales Pre-Queue-Gate. "Debug" / "Info" / "Warning" / "Error" / "Fatal". Nachrichten unterhalb dieser Severity landen nie in der Queue - null Overhead für gefilterte Aufrufe.
defaultMinimumLevelstringVorlagewert, den jeder Appender als sein eigenes minimumLevel benutzt, wenn der Eintrag keines angibt. Selbst kein Gate - füllt zur Parse-Zeit nur die Appender-Schwelle vor.
defaultTagstringStandard-Tag für Aufrufe wie Log.Info('msg') ohne Tag-Argument.
appendersarrayPflichtfeld. Ein Objekt pro Appender, jeweils mit "type" und typspezifischen Feldern.

Gemeinsame Felder pro Appender:

FeldHinweise
typePflicht. Groß-/Kleinschreibung wird ignoriert, Abgleich gegen registrierte Typnamen.
minimumLevelOptional. Minimale Severity, die dieser Appender emittiert. Nachrichten darunter werden von DIESEM Appender still verworfen (andere Appender sehen sie weiter). Gleicher Wertebereich wie Root-minimumLevel. Default ist defaultMinimumLevel (oder Debug, falls auch dieses fehlt). Einen Wert unter dem Root-minimumLevel zu setzen ist ein No-op: diese Nachrichten erreichen den Appender nicht, weil sie das Pre-Queue-Gate nicht passiert haben.

Typspezifische Felder werden im Abschnitt jedes Appenders in diesem Guide aufgelistet; Tippfehler werden abgefangen (siehe Fehlerdiagnose unten).

Die drei Konzepte, sauber getrennt. Jeder Log-Aufruf trägt seine eigene Severity - Log.Info ist Info, Log.Error ist Error, usw. Weder minimumLevel noch defaultMinimumLevel ändern das; sie entscheiden nur wer was sieht. Das Root-minimumLevel ist ein Pre-Queue-Filter (kostenlos: das TLogItem wird für Nachrichten darunter gar nicht erst erzeugt). Das Per-Appender- minimumLevel ist ein Emit-Gate (auf dem Worker-Thread des Appenders ausgewertet - entscheidet, ob DIESER Appender die Nachricht schreibt). Das Root-defaultMinimumLevel ist ein Schreib-Zeit-Default für das Per-Appender-Gate, kein Laufzeit-Filter - es erlaubt dir zu sagen “jeder Appender startet bei Warning, außer er sagt etwas anderes”, ohne das Feld in jedem Eintrag zu wiederholen.

Was Pflicht ist, was Defaults hat

Das absolute Minimum ist ein einzelner Array-Eintrag:

{ "appenders": [ { "type": "Console" } ] }

Das war’s. Alles andere ist entweder optional oder wird abgeleitet. Der appenders-Schlüssel auf Root-Ebene ist Pflicht (er darf ein leeres Array sein, um einen No-op-Logger zu bauen, muss aber vorhanden sein). Jeder Eintrag muss einen "type" haben; jedes andere Feld ist optional.

Default-Werte, wenn ein Feld ausgelassen wird:

FeldWenn fehlendHinweise
Root configVersionWird als neueste bekannte Schema-Version behandelt (aktuell 1).Ein höherer Wert ist ein harter Fehler (Vorwärtskompatibilitäts-Schutz).
Root minimumLevelDebug - alles passiert das globale Pre-Queue-Gate.Nachrichten unterhalb dieser Severity werden vor dem Enqueue gefiltert (null Overhead).
Root defaultMinimumLevelDebugWird als Default-minimumLevel jedes Appenders verwendet, der keines festlegt.
Root defaultTag"main"Für Aufrufe ohne Tag-Argument (z. B. Log.Info('msg')).
Appender minimumLeveldefaultMinimumLevel (oder Debug, falls dieses ebenfalls fehlt).Der Appender emittiert nur Nachrichten ab dieser Severity.
Typspezifische Appender-FelderJeder Appender bringt eigene Defaults mit (siehe jeweiliger Abschnitt).Z. B. Files logsFolder nutzt standardmäßig das EXE-Verzeichnis; Console nutzt standardmäßig Farben mit dem Midnight-Schema (mit "colorScheme": null oder "colors": false deaktivierbar).

Minimale, einsatzbereite JSONs

In eine rotierende Datei loggen (das einfachste Deployment). Nimmt das EXE-Verzeichnis als logsFolder und den EXE-Namen als Basis-Dateinamen; 5 Backups à 1 MB.

{
  "appenders": [
    { "type": "File" }
  ]
}

Dateien woanders ablegen und mehr Historie behalten:

{
  "appenders": [
    {
      "type": "File",
      "logsFolder": "C:/ProgramData/MyApp/logs",
      "fileBaseName": "myapp",
      "maxBackupFiles": 30,
      "maxFileSizeInKB": 5000
    }
  ]
}

In die farbige Konsole loggen. Farben sind standardmäßig an, mit dem professionellen Midnight-Schema - ein Eintrags-Array reicht:

{
  "appenders": [
    { "type": "Console" }
  ]
}

Schema per Name überschreiben (Groß-/Kleinschreibung egal) oder Farben komplett abschalten:

// Pick a different scheme
{ "appenders": [ { "type": "Console", "colorScheme": "Nord" } ] }

// Opt out: explicit null...
{ "appenders": [ { "type": "Console", "colorScheme": null } ] }

// ...or explicit empty string
{ "appenders": [ { "type": "Console", "colorScheme": "" } ] }

// ...or explicit colors:false
{ "appenders": [ { "type": "Console", "colors": false } ] }

Alle drei Opt-out-Varianten liefern reinen Text, ohne ANSI. Zusätzlich degradiert jedes farbige Schema automatisch zu reinem Text, wenn stdout in eine Datei umgeleitet oder in einen anderen Prozess gepipet wird - Sie bekommen nie versehentlich Escape-Codes in Ihren Log-Dateien.

Die eingebauten Farbschemata

Elf Schemata kommen mit LoggerPro. Alle halten sich an denselben Paletten-Vertrag (Farbe pro Level + farbiger Tag, Metadaten, Kontext- Schlüssel und -Werte), sie heben nur unterschiedliche Teile hervor. Schemanamen sind in JSON case-insensitiv; die Screenshots unten sind zur Referenz - starten Sie samples/03b_console_with_colors_appender, um jedes Schema mit denselben Seed-Nachrichten im eigenen Terminal zu sehen.

SchemaBeschreibung
DefaultGin-inspirierte Vordergrund-Baseline; Level-Farbe pro Schweregrad.
MonochromeKein ANSI - reiner Text. Wird automatisch aktiv, wenn stdout umgeleitet/gepipet wird.
GinBadgeDefault-Töne plus farbiges Hintergrund-“Badge” für das Level.
GinMinimalAlles gedämpftes Grau, nur das Level-Wort behält Farbe.
GinVibrantSatter Regenbogen - jedes Feld in einer eigenen auffälligen Farbe.
MidnightMagenta Prefix/Tag, grüne Keys, Cyan-Werte. JSON-Default - liest sich gut auf hellen wie dunklen Terminals.
NordFrost-Theme mit kühlen arktischen Blau-/Cyantönen, gelbe Warnungen, rotes Fatal.
MatrixAlles grün; Levels als Hintergrund-Badges.
Amber80er-Jahre-Amber-CRT-Monitor - Gelb-/Orangefamilie, Rot nur für Fehler.
OceanGeschichtete Blau- und Cyantöne - Teal-Tag, leuchtend-cyane Werte.
CyberpunkNeon-Magenta Prefix, Cyan-Tag, gelbe Werte; lebendige Level-Badges.

Auswahl aus JSON. Einfach per Name referenzieren:

// A calm palette for a dev console
{ "appenders": [ { "type": "Console", "colors": true, "colorScheme": "Nord" } ] }
// Level badges - fastest level scanning
{ "appenders": [ { "type": "Console", "colors": true, "colorScheme": "GinBadge" } ] }
// Plain text, no ANSI - useful in tests or when piping to a file
{ "appenders": [ { "type": "Console", "colors": true, "colorScheme": "Monochrome" } ] }

Auswahl aus Code:

uses LoggerPro, LoggerPro.Builder;

Log := LoggerProBuilder
  .WriteToConsole
    .WithColorScheme(LogColorSchemes.Midnight)   // or .Nord / .Matrix / ...
    .Done
  .Build;

Eigenes Schema. Jedes Schema ist ein TLogColorScheme-Record - Sie können Ihres ausgehend von einem Preset bauen und die relevanten Felder überschreiben:

var lScheme: TLogColorScheme;
begin
  lScheme := LogColorSchemes.Midnight;
  lScheme.TagColor := FORE_YELLOW;
  lScheme.LevelColor[TLogType.Info] := STYLE_BRIGHT + FORE_WHITE;

  Log := LoggerProBuilder
    .WriteToConsole.WithColorScheme(lScheme).Done
    .Build;
end;

Automatische Abwärtskompatibilität. Wird stdout in eine Datei umgeleitet oder in einen anderen Prozess gepipet, degradiert der Renderer automatisch zu reinem Text (entspricht Monochrome). Sie bekommen nie versehentlich Escape-Codes in Ihren Log-Dateien.

Weitere optionale Felder:

{
  "appenders": [
    {
      "type": "Console",
      "colors": true,
      "colorScheme": "Nord",
      "prefix": "MYAPP",    // shows as [MYAPP] before each line
      "utf8Output": true    // safe output in Docker / Windows consoles
    }
  ]
}

Beide kombiniert für ein typisches Dev-Setup - farbige Konsole plus rotierte Datei mit getrennten Levels:

{
  "minimumLevel": "Debug",
  "appenders": [
    { "type": "Console", "colors": true, "colorScheme": "Midnight" },
    { "type": "File",    "logsFolder": "logs", "minimumLevel": "Info"  }
  ]
}

Einstiegspunkte

Zwei globale Funktionen in der LoggerPro-Unit - die eine liefert einen einsatzbereiten ILogWriter, die andere den nicht finalisierten ILoggerProBuilder, sodass Aufrufer weiter verketten können:

uses LoggerPro;

// 1. Pure JSON → ILogWriter (simplest, covers most cases)
Log := LoggerProFromJSONFile('loggerpro.json');

// 1b. Pure JSON from an embedded resource or a hand-assembled string
Log := LoggerProFromJSONString(MyEmbeddedConfig);
uses LoggerPro, LoggerPro.Builder;

// 2. JSON base + more appenders from code (the "mixed" pattern)
Log := LoggerProBuilderFromJSONFile('loggerpro.json')
         .WriteToCallback
           .WithCallback(MyProc)
           .Done
         .Build;   // you call .Build yourself

Beide Funktionen werfen bei Problemen mit der Datei ELoggerProConfigError - siehe Fehlerdiagnose unten für die genauen Meldungen.

Dateikonfiguration mit Laufzeit-Appendern mischen

Manche Appender lassen sich nicht in JSON beschreiben, weil sie eine Laufzeit-Objektreferenz benötigen, die nicht in eine Konfigurationsdatei passt: einen Callback, ein TStrings, eine VCL-Komponente, eine lebendige TFDConnection. Das Pattern ist immer das gleiche:

  1. Den JSON-beschreibbaren Teil mit LoggerProBuilderFromJSONFile laden.
  2. Die Extras auf dem zurückgegebenen Builder anketten.
  3. Selbst .Build aufrufen.

Beispiel 1 - JSON-Basis + UI-Callback für eine Statusleiste.

uses
  LoggerPro, LoggerPro.Builder;

Log := LoggerProBuilderFromJSONFile('loggerpro.json')
  .WriteToCallback
    .WithCallback(
      procedure(const aLogItem: TLogItem; const aFormattedMessage: string)
      begin
        // The callback appender marshals to the main thread for us.
        StatusBar1.SimpleText := aFormattedMessage;
      end)
    .WithSynchronizeToMainThread(True)
    .Done
  .Build;

Beispiel 2 - JSON-Basis + VCL-TListView-Spiegel. Der Benutzer konfiguriert Datei/Konsole via JSON; die GUI-Live-Tail bleibt im Code.

uses
  LoggerPro, LoggerPro.Builder;

procedure TMainForm.FormCreate(Sender: TObject);
begin
  FLog := LoggerProBuilderFromJSONFile('loggerpro.json')
    .WriteToVCLListView(ListViewLogs)
      .WithMaxLogLines(1000)
      .Done
    .Build;
end;

procedure TMainForm.FormDestroy(Sender: TObject);
begin
  FLog.Shutdown;   // before the form - and the ListView - are freed
  FLog := nil;
end;

Beispiel 3 - JSON-Basis + FMX-TMemo. TMemo.Lines ist ein TStrings, daher deckt der plattformübergreifende WriteToStrings- Appender FMX, VCL und alles ab, was ein TStrings bereitstellt.

FLog := LoggerProBuilderFromJSONFile('loggerpro.json')
  .WriteToStrings(MemoLog.Lines)
    .WithMaxLogLines(500)
    .WithClearOnStartup(True)
    .Done
  .Build;

Beispiel 4 - JSON-Basis + Datenbank-Appender. Die JSON steuert Konsole/Datei/HTML; die DB-Verbindung bleibt im Code, weil TFDConnection nicht serialisierbar ist.

uses
  LoggerPro, LoggerPro.Builder, LoggerPro.DBAppender.FireDAC;

FLog := LoggerProBuilderFromJSONFile('loggerpro.json')
  .WriteToFireDAC
    .WithConnectionDefName('MAIN_DB')
    .WithStoredProcName('sp_insert_log')
    .WithMinimumLevel(TLogType.Warning)     // DB only gets Warning+
    .Done
  .Build;

Szenarien und Sonderfälle

Das Per-Appender-minimumLevel ist unabhängig vom Root- minimumLevel. Das Root-Gate entscheidet, ob eine Nachricht überhaupt in die Queue kommt; das Gate des einzelnen Appenders entscheidet, ob dieser Appender die Nachricht schreibt. Eine Nachricht unter dem Root-minimumLevel erreicht keinen Appender; eine Nachricht, die das Root-Gate passiert, aber unter dem minimumLevel eines Appenders liegt, wird von diesem Appender verworfen, während die übrigen sie trotzdem erhalten.

{
  "minimumLevel": "Debug",
  "appenders": [
    { "type": "Console",                    "minimumLevel": "Debug"   },
    { "type": "File", "logsFolder": "logs", "minimumLevel": "Info"    },
    { "type": "Webhook", "url": "https://ops/alerts",
                                              "minimumLevel": "Error"   }
  ]
}

Ergebnis: Entwickler sehen alles auf der Konsole, die Log-Datei behält Info+, der Webhook feuert nur bei Fehlern.

Ein leeres appenders-Array ist erlaubt - Sie erhalten einen “Schwarzes-Loch”-Logger, nützlich für Integrationstests:

{ "configVersion": 1, "appenders": [] }

Effektiv deaktiviertes Logging ist einfach ein globales Gate hoch genug, dass nichts mehr durchkommt:

{ "configVersion": 1, "minimumLevel": "Fatal", "appenders": [] }

Oder im Code die Runtime-Property auf einem bereits gebauten Writer umschalten: Log.MinimumLevel := TLogType.Fatal;

Plug-in-Appender (ExeWatch, WindowsEventLog, ElasticSearch und jeder Drittanbieter-Appender, der derselben Konvention folgt) brauchen ihre Unit in uses. Vergessen erzeugt eine präzise Fehlermeldung (siehe unten).

Optionale JSON-Quelle. Binden Sie eine Standard-JSON in Ressourcen ein und überschreiben Sie sie per On-Disk-Datei, wenn vorhanden:

uses System.IOUtils;

if TFile.Exists('loggerpro.json') then
  Log := LoggerProFromJSONFile('loggerpro.json')
else
  Log := LoggerProFromJSONString(LoadDefaultConfigFromResources);

Fehlerdiagnose

Der Parser ist bewusst strikt - Fehlkonfigurationen scheitern laut statt still halb zu funktionieren. Alle Fehler erscheinen als ELoggerProConfigError (deklariert in LoggerPro.pas, sodass ein einzelnes uses LoggerPro; ausreicht, um sie zu fangen).

Unbekanntes Feld (Tippfehler-Erkennung):

appenders[0] (type=Console): unknown field "colour".
Valid fields: minimumLevel, colors, colorScheme, prefix, utf8Output.

Unbekannter Appender-Typ (fehlendes uses):

appenders[1]: unknown type "ExeWatch".
Currently registered types: console, elasticsearch, file, filebysource,
htmlfile, jsonlfile, memory, outputdebugstring, simpleconsole,
timerotatingfile, udpsyslog, webhook.
If you want "ExeWatch", make sure the unit that registers it is in your
`uses` clause (typically LoggerPro.ExeWatchAppender) - optional
appenders self-register from their initialization section, so simply
including the unit is enough. For custom factories use
TLoggerProConfig.RegisterAppenderType.

Schema-Version zu neu:

configVersion 2 is newer than supported (max 1). Update LoggerPro.

Ungültiger Enum-Wert:

appenders[0] (type=Console): invalid colorScheme "NEON".
Valid values: Default, Monochrome, GinBadge, GinMinimal, GinVibrant,
              Midnight, Nord, Matrix, Amber, Ocean, Cyberpunk.

Fehlende Datei oder fehlerhaftes JSON werfen ebenfalls ELoggerProConfigError, mit Dateipfad bzw. Parser-Diagnose.

Kontrollierter Fallback

Für Erstlauf- oder Fehlkonfigurationsszenarien fangen Sie den Fehler und bauen im Code einen defensiven Default, damit die Anwendung weiter loggt statt abzustürzen:

uses LoggerPro, LoggerPro.Builder;

function BuildLoggerSafe(const aConfigPath: string): ILogWriter;
begin
  try
    Result := LoggerProFromJSONFile(aConfigPath);
  except
    on E: ELoggerProConfigError do
    begin
      Result := LoggerProBuilder
        .WriteToConsole.Done
        .WithMinimumLevel(TLogType.Info)
        .Build;
      Result.Warn(
        Format('Config fallback: %s', [E.Message]),
        'CONFIG');
    end;
  end;
end;

Die Warnung landet im Fallback-Logger selbst, sodass Betreiber das Problem beim nächsten Ausgabe-Tail bemerken.

Eigene Appender-Typen

LoggerPro.Config ist eine Typ-Registry; Ihre eigenen Appender können sich genauso einklinken wie die eingebauten:

uses LoggerPro, LoggerPro.Config;

procedure MyCustomFactory(const aBuilder: ILoggerProBuilder;
  const aConfig: TJSONObject);
begin
  aBuilder.WriteToAppender(TMyCustomAppender.Create(
    aConfig.GetValue('endpoint').Value));
end;

initialization
  TLoggerProConfig.RegisterAppenderType(
    'MyCustom',
    MyCustomFactory,
    ['minimumLevel', 'endpoint']);   // closed set of allowed fields

Ab dann funktioniert { "type": "MyCustom", "endpoint": "..." }, und Tippfehler in Feldnamen lösen dieselbe strikte Diagnose aus wie bei den eingebauten.

Beispiele: samples/240_config_simple, 241_config_advanced, 242_config_fallback.

Plug-in-Appender (Auto-Register-Pattern)

Appender, die externe Systeme anbinden - ExeWatch, WindowsEventLog, ElasticSearch - bleiben AUSSERHALB des Kern-Runtime-Pakets. Das hält den Kern abhängigkeitsfrei und verhindert, dass optionale SDKs (wie der ExeWatch-Client) von jedem LoggerPro-Nutzer benötigt werden.

Funktionsweise: jede optionale Appender-Unit registriert ihre eigene JSON-Factory aus ihrer initialization-Sektion. Die Unit in die uses-Klausel irgendeines Moduls Ihres Projekts zu packen, reicht aus, um ihren "type"-Wert in loggerpro.json zu aktivieren.

// main.dpr
uses
  LoggerPro,
  LoggerPro.ExeWatchAppender,          // enables "type": "ExeWatch"
  LoggerPro.WindowsEventLogAppender,   // enables "type": "WindowsEventLog"
  LoggerPro.ElasticSearchAppender;     // enables "type": "ElasticSearch"
begin
  Log := LoggerProFromJSONFile('loggerpro.json');
end.

Verweist eine JSON-Datei auf einen Appender, dessen Unit nicht in uses steht, nennt die Fehlermeldung genau, welche Unit zu ergänzen ist.

LogFmt-Ausgabe (strukturiert, grep-freundlich)

LogFmt ist ein zeilenorientiertes strukturiertes Log-Format, populär gemacht durch Heroku und Brandur Leach. Jede Log-Zeile ist eine Folge von key=value-Paaren, durch einzelne Leerzeichen getrennt. Werte stehen nackt, wenn sicher, sonst in doppelten Anführungszeichen mit \"- und \\-Escapes. Der Sweet Spot zwischen menschenlesbaren Text-Logs und maschinen-parsbarem JSON.

Beispielausgabe

time=2026-04-18T12:30:45.123Z threadid=7932 type=INFO msg="order placed" tag=ORDERS order_id=42 amount=99.95 paid=true

Aktivieren

Den TLogItemRendererLogFmt-Renderer über den Builder in jeden Appender stecken:

uses
  LoggerPro, LoggerPro.Builder, LoggerPro.Renderers;

Log := LoggerProBuilder
  .WriteToConsole
    .WithRenderer(TLogItemRendererLogFmt.Create)
    .Done
  .WriteToFile
    .WithRenderer(TLogItemRendererLogFmt.Create)
    .Done
  .Build;

Log.Info('order placed', 'ORDERS', [
  LogParam.I('order_id', 42),
  LogParam.F('amount', 99.95),
  LogParam.B('paid', True)
]);

Oder global als Default-Renderer setzen:

LoggerPro.Renderers.gDefaultLogItemRenderer := TLogItemRendererLogFmt;

Warum LogFmt

  • Lesbar im Terminal: einzeilige Datensätze, kein nachgelagerter Müll.
  • Trivial greppable: grep 'order_id=42' funktioniert einfach.
  • Streaming-freundlich: jede Zeile ist selbsthaltend - keine mehrzeiligen JSON-Objekte aus Container-stdout zusammenzusetzen.
  • Günstig zu produzieren: kein Escape-lastiger JSON-Serializer im heißen Pfad.
  • Tooling: nativ geparst von humanlog, lnav, Grafana Loki, Vector, Fluent Bit, Promtail, Filebeat.

Spezifikationstreue

LoggerPros LogFmt-Renderer:

  • Setzt Werte mit Leerzeichen, ", =, \ oder Steuerzeichen in Anführungszeichen.
  • Escapet " als \", \ als \\, \n \r \t als literale Escape-Sequenzen.
  • Nicht druckbare Steuerbytes werden zu \uNNNN.
  • Bereinigt Kontext-Keys auf [a-zA-Z0-9_.-] (ungültige Zeichen werden zu _).
  • Floats verwenden immer . als Dezimaltrennzeichen (locale-unabhängig).
  • Booleans als nackte true / false.

Das heißt, die Ausgabe ist sicher, zeilenweise durch grep, awk, jq -R, Lokis logfmt-Parser etc. zu streamen, ohne Korruption.

LogFmt-Logs unter Windows abfragen

1. ripgrep (rg) - universeller Filter

Installation:

# Option A: winget (Windows 10/11)
winget install BurntSushi.ripgrep.MSVC

# Option B: Scoop
scoop install ripgrep

# Option C: download ripgrep-*.zip from GitHub releases, unzip, put rg.exe on PATH

Nutzung:

# All errors
rg "type=ERROR" logs\myapp*.log

# One specific order, any log level
rg "order_id=42\b" logs\myapp*.log

# Errors for a given user in the last file only
rg "type=ERROR.*user_id=7" (Get-ChildItem logs\myapp*.log | Sort LastWriteTime -Desc | Select -First 1).FullName

# Count errors per tag
rg -o "tag=\S+" logs\myapp*.log | Group-Object | Sort Count -Desc

2. humanlog - logfmt-bewusster Pretty-Printer & Filter

humanlog ist ein Go-Binary, das LogFmt (und JSON) nativ versteht: es koloriert Levels, richtet Spalten aus, parst Timestamps und erlaubt Filter mit einer Mini- Ausdruckssprache. Deutlich angenehmer als rg, wenn Sie Logs lesen und nicht nur greppen.

Installation:

# Download humanlog_<version>_windows_amd64.zip from GitHub releases, unzip, put
# humanlog.exe on PATH. Or via Scoop:
scoop bucket add extras
scoop install humanlog

Nutzung:

# Pretty-print a static log file
Get-Content logs\myapp.20260418.log | humanlog

# Pipe directly from your Delphi app's stdout (console appender + logfmt)
.\MyApp.exe | humanlog

# Filter: only errors (mini-expression language)
Get-Content logs\*.log | humanlog --skip "type!=ERROR"

# Keep only matching records
Get-Content logs\*.log | humanlog --keep "tag=ORDERS and type=ERROR"

# Hide noisy context keys
Get-Content logs\*.log | humanlog --ignore "threadid,time"

Live-Tail (tail -f-Stil)

PowerShells Get-Content -Wait ist der Baustein für Live-Tailing unter Windows:

Get-Content logs\myapp.20260418.log -Wait -Tail 20

Beachten Sie, dass Get-Content -Wait den Original-Datei-Handle überwacht und LoggerPros Tages-/Größenrotation nicht mitverfolgt. Fortgeschrittene Techniken (Re-Tail-Schleifen, Prozess-stdout-Piping, Encoding-Fallstricke) finden Sie im Blog.

Ohne Installation: Select-String

Wenn Sie auf einer Produktionsmaschine nichts installieren dürfen, ist Select-String auf jeder Windows-Installation vorhanden:

# Errors for tag ORDERS
Select-String -Path logs\myapp*.log -Pattern "type=ERROR.*tag=ORDERS"

# Context block around a match (2 lines before/after)
Select-String -Path logs\*.log -Pattern "order_id=42\b" -Context 2,2

Jenseits von grep-artigen Tools

Sobald Sie viele Dateien, mehrere Hosts oder >GB/Tag an Logs haben, hören Sie mit dem Greppen auf und beginnen mit dem Shippen:

  • Grafana Loki + Promtail - LogQL mit nativem | logfmt-Parser:

    {app="myapp"} | logfmt | type="ERROR" | order_id="42"
    
  • Vector (einzelne .exe, konfigurationsgetrieben) - mit dem logfmt-Codec parsen, an Elastic, Clickhouse, Datadog, S3 etc. liefern.

  • Fluent Bit (einzelne .exe) - ähnlich, leichtgewichtig.

LogFmt vs. JSONL - wann welches

LoggerPro unterstützt auch JSONL (ein JSON-Objekt pro Zeile) via TLoggerProJSONLFileAppender. Faustregel:

  • LogFmt → Entwicklungsmaschinen, Container-stdout, greppable Produktions-Logs, niedriges/mittleres Volumen, flacher Kontext.
  • JSONL → verschachtelte Strukturen, Analytics-Pipelines, Elastic/Datadog/OpenObserve-Ingest, hohes Volumen, striktes Schema.

Beide Renderer teilen dieselbe LogParam.S/I/F/B/D-Kontext-API, Sie können also zwischen ihnen wechseln, ohne Anwendungscode zu ändern.

FileBySource-Appender

Neu in 2.1. Organisiert Logs in quellenspezifischen Unterordnern - perfekt für Mehrmandanten-Anwendungen, in denen jeder Kunde, jedes Gerät oder jedes Konto einen eigenen Log-Stream bekommt. Der Quellen-Schlüssel stammt aus dem Log-Kontext.

uses
  LoggerPro.Builder;

Log := LoggerProBuilder
  .WriteToFileBySource
    .WithLogsFolder('logs')
    .WithMaxFileSizeInKB(5000)
    .WithRetainDays(30)
    .WithDefaultSource('default')
    .Done
  .Build;

// Source comes from the context
Log.Info('Order placed', 'ORDERS', [
  LogParam.S('source', 'ClientA'),
  LogParam.I('order_id', 42)
]);
// → logs/ClientA/ClientA.ORDERS.20260418.00.log

Die Rotation ist Tag + Größe: eine neue Datei wird bei Tageswechsel geöffnet und wenn die aktuelle Datei WithMaxFileSizeInKB überschreitet. Dateien älter als WithRetainDays werden beim Start und bei jedem Tageswechsel automatisch gelöscht.

HTML-Live-Log-Viewer

Neu in 2.1. Eine eigenständige HTML-Log-Datei, die Sie in jedem Browser öffnen können - kein Server, keine externen Assets, eine .html pro Rotation. Nützlich, um Benutzern, QA oder Support ein kompaktes Troubleshooting-Artefakt zu übergeben.

uses LoggerPro, LoggerPro.Builder;

Log := LoggerProBuilder
  .WriteToHTMLFile
    .WithLogsFolder('logs')
    .WithFileBaseName('myapp')
    .WithTitle('MyApp - Operations Log')
    .WithMaxFileSizeInKB(1000)
    .WithMaxBackupFiles(10)
    .Done
  .Build;

Die erzeugte Seite enthält:

  • Klebende Filterleiste - Checkboxen pro Level und ein Volltextsuchfeld.
  • Zeileneinfärbung - WARNING / ERROR / FATAL tragen einen dezenten Hintergrundton, sodass Anomalien beim Scrollen auffallen.
  • Kontext-Rendering - strukturierter LogParam-Kontext wird als key=value-Paare in einer sekundären Zeile angezeigt, über dieselben Filter-Controls ein-/ausblendbar.
  • CSV-/JSON-Export - aktuell sichtbare Zeilen herunterladen.
  • Live-Tail - solange die Datei geschrieben wird, aktualisiert sich die Seite alle 3 Sekunden automatisch und scrollt immer ans Ende.
  • LIVE-/FINALIZED-Erkennung - die Seite weiß, ob die Log-Datei noch geschrieben wird oder geschlossen wurde, und stoppt den Auto-Reload, sobald sie finalisiert ist.

Beispiel: samples/230_html_file_appender. Auch als JSON-Config "type": "HTMLFile" verfügbar.

UTF-8-Konsolenausgabe (Docker / Windows)

Standardmäßig konvertiert Delphis Writeln in die System-Locale-Kodierung, was Nicht-ASCII-Zeichen in Docker-Containern (POSIX/C-Locale) und auf Windows-Konsolen (CP 437/1252) entstellt. Aktivieren Sie WithUTF8Output, um UTF-8-Bytes direkt nach stdout zu schreiben:

Log := LoggerProBuilder
  .WriteToConsole
    .WithUTF8Output
    .Done
  .Build;

// Also available for the plain (no-color) console appender
Log := LoggerProBuilder
  .WriteToSimpleConsole
    .WithUTF8Output
    .Done
  .Build;

Das ist besonders nützlich, wenn Delphi-Anwendungen in Docker-Containern laufen oder Unicode-Text (CJK, Kyrillisch, Emoji usw.) auf Windows geloggt wird.

DLL-sichere Initialisierung

LoggerPro 2.1 funktioniert korrekt in DLLs, die via LoadLibrary oder P/Invoke geladen werden. Die Logger-Thread-Initialisierung erkennt den DLL-Kontext und vermeidet den Windows-Loader-Lock-Deadlock, der frühere Versionen betraf.

library MyPlugin;

uses
  LoggerPro, LoggerPro.Builder;

var
  GLog: ILogWriter;

begin
  // Safe during DLL_PROCESS_ATTACH
  GLog := LoggerProBuilder
    .WriteToFile.Done
    .Build;
  GLog.Info('DLL loaded successfully');
end.

Hinweis: Rufen Sie GLog.Shutdown vor dem Entladen der DLL auf, falls Sie sicherstellen möchten, dass Nachrichten in der Queue übertragen werden.

Kontextuelles Logging

LoggerPros Kontext-Logging-Funktionen erlauben es Ihnen, jeden Log-Aufruf mit strukturierten Schlüssel-Wert-Paaren anzureichern, ohne sich zu wiederholen.

WithProperty (Ad-hoc-Kontext)

Log.WithProperty('order_id', 12345)
   .WithProperty('amount', 99.99)
   .Info('Order processed', 'orders');

WithDefaultTag (Sub-Logger)

var
  OrderLog: ILogWriter;
begin
  OrderLog := Log.WithDefaultTag('ORDERS');
  OrderLog.Info('Processing started');   // tag = 'ORDERS'
  OrderLog.Warn('Stock low');            // tag = 'ORDERS'
end;

WithDefaultContext (persistenter Kontext)

var
  RequestLog: ILogWriter;
begin
  RequestLog := Log.WithDefaultContext([
    LogParam.S('request_id', 'req-123'),
    LogParam.S('client_ip', '192.168.1.100')
  ]);

  RequestLog.Info('Request received');    // includes request_id, client_ip
  RequestLog.Info('Response sent');       // includes request_id, client_ip
end;

Strukturierter Kontext inline

Log.Info('Order completed', 'ORDERS', [
  LogParam.I('order_id', 12345),
  LogParam.S('customer', 'John Doe'),
  LogParam.F('total', 299.99),
  LogParam.B('paid', True)
]);

Exception-Logging

try
  // Code that may raise
except
  on E: Exception do
  begin
    Log.LogException(E);
    Log.LogException(E, 'Database query failed');
    Log.LogException(E, 'Query failed', 'db');
  end;
end;

Stack-Trace-Formatter

Integrieren Sie mit JCL, madExcept, EurekaLog oder einer beliebigen Stack-Trace-Bibliothek:

Log := LoggerProBuilder
  .WithStackTraceFormatter(
    function(E: Exception): string
    begin
      Result := JclLastExceptStackListToString;
    end)
  .WriteToFile.Done
  .Build;

Minimum-Level-Filterung

Nachrichten global vor der Queue-Einreihung filtern - Null-Overhead für gefilterte Nachrichten:

Log := LoggerProBuilder
  .WithMinimumLevel(TLogType.Warning)  // Debug and Info filtered
  .WriteToFile.Done
  .Build;

Log.Debug('Not logged');   // Filtered - no TLogItem created
Log.Info('Not logged');    // Filtered - no TLogItem created
Log.Warn('Logged');        // OK

Neu in 2.1: das Gate ist eine erstklassige Property auf ILogWriter, sodass Sie es zur Laufzeit ohne Cast ändern können:

Log.MinimumLevel := TLogType.Fatal;  // effectively mute

// Later
Log.MinimumLevel := TLogType.Debug;  // re-enable everything

ElasticSearch mit Authentifizierung

Neu in 2.1. Der ElasticSearch-Appender unterstützt jetzt alle drei gängigen Auth-Mechanismen:

// Basic Auth
Log := LoggerProBuilder
  .WriteToElasticSearch
    .WithURL('https://elastic.example.com:9200/logs/_doc')
    .WithBasicAuth('username', 'password')
    .Done
  .Build;

// API Key
Log := LoggerProBuilder
  .WriteToElasticSearch
    .WithHost('https://elastic.example.com')
    .WithPort(9200)
    .WithIndex('app-logs')
    .WithAPIKey('your-api-key-here')
    .Done
  .Build;

// Bearer Token (JWT, OAuth2)
Log := LoggerProBuilder
  .WriteToElasticSearch
    .WithURL('https://elastic.example.com:9200/logs/_doc')
    .WithBearerToken('your-jwt-token')
    .Done
  .Build;

ExeWatch-Integration (Cloud-Observability)

Was ist ExeWatch. ExeWatch ist ein Cloud-Observability-Service für Desktop- und Backend-Anwendungen: es sammelt Logs, Exceptions, Breadcrumbs, Benutzeridentität, Geräteinfo und eigene Metriken und stellt ein Dashboard bereit, um Vorfälle in der Produktion zu untersuchen, ohne Log-Dateien herumzuschicken.

Warum ein dedizierter Appender. ExeWatch liefert ein eigenes Delphi-SDK (ExeWatchSDKv1.pas). Der LoggerPro-Bridge - Unit LoggerPro.ExeWatchAppender - wandelt jeden Log.Info / Warn / Error / Fatal / LogException-Aufruf in den entsprechenden SDK-Aufruf um, sodass Sie die LoggerPro-API behalten und transparent die ExeWatch-Pipeline gewinnen. Sie ist nicht Teil des LoggerPro-Runtime-Pakets, sodass Projekte, die ExeWatch nicht nutzen, nichts bezahlen.

Bridge aktivieren. Fügen Sie den SDK-Ordner zum Projekt-Suchpfad hinzu (das Sample nutzt C:\dev\exewatchsamples\DelphiCommons) und ziehen Sie die Bridge-Unit:

uses
  LoggerPro,
  LoggerPro.Builder,
  LoggerPro.ExeWatchAppender;

Das SDK wird beim Setup des Appenders automatisch initialisiert - Sie müssen InitializeExeWatch NICHT selbst aufrufen, und der Appender stört ein bereits von anderem Code initialisiertes SDK nicht.

Vier Wege der Verdrahtung

1. Fluent-Builder - alles im Code; passt, wenn API-Key, Customer-ID und Version Literale sind oder aus einfachen globalen Variablen kommen. Verketten wie bei jedem eingebauten Appender:

Log := WithExeWatch(LoggerProBuilder)
    .WithAPIKey('ew_win_xxxxxx')
    .WithCustomerId('Acme Corp')
    .WithAppVersion('2.3.1')
    .WithAnonymizeDeviceId(False)  // True = per-install ID (GDPR-friendly)
    .Done
  .WriteToConsole.WithColors.Done  // mirror to the console too
  .Build;

2. Fluent-Kette auf JSON-Basis - kombiniert eine loggerpro.json mit codeseitiger ExeWatch-Konfiguration. Die Basisdatei trägt das Konsole-/Datei-/HTML-Setup; die SDK-Secrets bleiben im Code, von wo sie aus einem Vault, einer Umgebungsvariable oder einem License-Server geladen werden können:

uses
  LoggerPro, LoggerPro.Builder, LoggerPro.ExeWatchAppender;

Log := WithExeWatch(
      LoggerProBuilderFromJSONFile('loggerpro.json'))
    .WithAPIKey(LoadFromVault('ew_api_key'))
    .WithCustomerId(CurrentTenant)
    .WithAppVersion(GetFileVersion)
    .Done
  .Build;

3. Imperativ (geringster Widerstand, wenn Werte aus Konfigurationsobjekten kommen):

Log := LoggerProBuilder
  .WriteToAppender(NewExeWatchAppender(
    'ew_win_xxxxxx', 'Acme Corp', '2.3.1'))
  .Build;

4. Reine JSON-Konfiguration (dank des Auto-Register-Patterns kein zusätzlicher Registrierungsaufruf nötig):

{
  "configVersion": 1,
  "appenders": [
    { "type": "Console" },
    {
      "type": "ExeWatch",
      "apiKey": "ew_win_xxxxxx",
      "customerId": "Acme Corp",
      "appVersion": "2.3.1",
      "anonymizeDeviceId": false
    }
  ]
}
uses LoggerPro, LoggerPro.ExeWatchAppender;
Log := LoggerProFromJSONFile('loggerpro.json');

Level-Abbildung

TLogTypeExeWatch SDK Severity
DebugEW.Debug
InfoEW.Info
WarningEW.Warning
ErrorEW.Error
FatalEW.Fatal

Der Log-Tag wird als SDK-Tag weitergereicht. Strukturierter LogParam-Kontext wird in den formatierten Nachrichtentext zusammengefaltet - wenn Sie die reicheren SDK-Funktionen (Breadcrumbs, Timings, Benutzeridentität, Gauges) nutzen möchten, rufen Sie EW.AddBreadcrumb / EW.SetUser / EW.StartTiming direkt neben LoggerPro auf. Die beiden Schichten koexistieren frei.

Shutdown

Log.Shutdown leert die LoggerPro-Queue und ruft anschließend EW.Flush auf, sodass jedes clientseitig in die Queue gestellte Ereignis vor dem Prozessende übertragen wird. Das SDK-eigene Finalization-Handling erledigt den Rest.

Beispiel: samples/260_exewatch_appender.

UDP-Syslog (RFC 5424) mit Lokalzeit

Neue WithUseLocalTime-Option - RFC 5424 verlangt UTC, viele On-Prem-Syslog-Server erwarten jedoch Lokalzeit.

Log := LoggerProBuilder
  .WriteToUDPSyslog
    .WithHost('syslog.example.com')
    .WithPort(514)
    .WithApplication('MyApp')
    .WithUseLocalTime(True)   // default: False (UTC)
    .Done
  .Build;

Aktuellen Log-Dateinamen abrufen

Neu in 2.1. Nützlich zum Hochladen, E-Mail-Versand oder Anhängen einer Log-Datei auf Anfrage.

uses LoggerPro, LoggerPro.Builder, LoggerPro.FileAppender;

var
  lAppender: TLoggerProSimpleFileAppender;
  Log: ILogWriter;
begin
  lAppender := TLoggerProSimpleFileAppender.Create;
  Log := LoggerProBuilder
    .WriteToAppender(lAppender)
    .Build;

  Log.Info('Message');
  UploadLogFile(lAppender.GetCurrentLogFileName);
end;

Für TLoggerProFileAppender (eine Datei pro Tag):

var
  lAppender: TLoggerProFileAppender;
begin
  lAppender := TLoggerProFileAppender.Create;
  // Get file for a specific tag
  lFileName := lAppender.GetCurrentLogFileName('ORDERS');
  // Or all current log files
  lAllFiles := lAppender.GetAllCurrentLogFileNames;
end;

Shutdown

Rufen Sie Shutdown in der Finalization Ihrer Anwendung auf, um zu garantieren, dass alle ausstehenden Logs geschrieben werden:

procedure TMyApp.Finalize;
begin
  Log.Shutdown;   // Flush queue, stop thread
  Log := nil;
end;

Zentrale Verhaltensweisen:

  • Idempotent: mehrfacher Aufruf ist sicher.
  • Leert alle ausstehenden Nachrichten.
  • Beendet den Logger-Thread.
  • Nach Shutdown werden Log-Aufrufe still ignoriert (Release) oder werfen Assert (Debug).

Eingebaute Appender

LoggerPro 2.1 liefert über 20 Appender mit. Alle sind asynchron, thread-sicher und per Builder konfigurierbar.

File-Appender

AppenderBuilder-MethodeBeschreibung
FileAppenderWriteToFileEine Datei pro Tag mit größenbasierter Rotation. Default: 5 Backups, 1 MB max. Unterstützt zeitbasierte Rotation.
SimpleFileAppenderWriteToFileAlle Logs in einer Datei (keine Tag-Trennung). Gleiche Rotationsoptionen.
JSONLFileAppenderWriteToJSONLFileEin JSON-Objekt pro Zeile. Ideal für Log-Aggregatoren.
TimeRotatingFileAppenderWriteToTimeRotatingFileNeue Datei bei jedem Zeitintervall (stündlich/täglich/wöchentlich/monatlich).
FileByFolderAppender(direkt)Organisiert Logs in Tages-Unterordnern (Logs/20260418/app.00.log).
FileBySourceAppender (neu)WriteToFileBySourceQuellenspezifische Unterordner mit Tages-+Größenrotation und Tages-Retention.
HTMLFileAppender (neu)WriteToHTMLFileEigenständige .html zum Durchsuchen im Browser mit Filterleiste, Level-Einfärbung, CSV-/JSON-Export und Live-Tail.

Console-Appender

AppenderBuilder-MethodeBeschreibung
ConsoleAppenderWriteToConsolePlattformübergreifend mit Farben (Windows API / ANSI). Erzeugt unter Windows automatisch eine Konsole für GUI-Apps. WithUTF8Output für Docker/Unicode.
SimpleConsoleAppenderWriteToSimpleConsoleEinfaches Writeln, keine Farben. Läuft überall. WithUTF8Output verfügbar.

Remote-/Netzwerk-Appender

AppenderBuilder-MethodeBeschreibung
ExeWatchAppender (steckbar)WithExeWatch(builder)Erstklassige Cloud-Observability via ExeWatch. Registriert sich selbst in JSON.
WebhookAppender (umbenannt)WriteToWebhookHTTP-POST an REST-Endpunkte. Timeout, eigene Header, API-Key-Auth (Header oder Query-String).
ElasticSearchAppender (steckbar)WriteToElasticSearchSendet Logs an ElasticSearch 6.4+. Unterstützt Basic Auth, API Key, Bearer Token. Registriert sich selbst in JSON.
UDPSyslogAppenderWriteToUDPSyslogRFC 5424 UDP-Syslog. Lokalzeit oder UTC.
EMailAppender(direkt)SMTP (via Indy TIdSMTP).
NSQAppender(direkt)Veröffentlicht Logs in NSQ verteilter Message-Queue.
RedisAppender(contrib)Speichert Logs in Redis-Listen.

UI-Appender

AppenderBuilder-MethodeBeschreibung
StringsAppenderWriteToStringsHängt an jedes TStrings an (TMemo.Lines, TStringList). Plattformübergreifend.
VCLMemoAppenderWriteToVCLMemoVCL TMemo. Nur Windows.
VCLListBoxAppenderWriteToVCLListBoxVCL TListBox. Nur Windows.
VCLListViewAppenderWriteToVCLListViewMehrspaltiges VCL TListView. Nur Windows.

System-/Debug-Appender

AppenderBuilder-MethodeBeschreibung
OutputDebugStringAppenderWriteToOutputDebugStringWindows OutputDebugString.
WindowsEventLogAppender (steckbar)WriteToWindowsEventLogWindows Event Log (Anwendungen und Dienste). Registriert sich selbst in JSON.
MemoryAppenderWriteToMemoryThread-sicherer Ringpuffer.
CallbackAppenderWriteToCallbackRuft Ihren Callback pro Log-Item auf.

Datenbank-Appender

AppenderBuilder-MethodeBeschreibung
FireDACAppenderWriteToFireDACDatenbank-Logging via FireDAC-Stored-Procedure.
ADOAppender(direkt)Datenbank-Logging via ADO-Stored-Procedure.

Filter / Proxy

AppenderBuilder-MethodeBeschreibung
FilterProxyWriteToFilteredAppenderWrappt jeden Appender mit einer eigenen Filterfunktion.

Als (direkt) markierte Appender werden via BuildLogWriter([appender]) oder .WriteToAppender(appender) genutzt.

Windows-Event-Log-Integration

Reguläre Anwendungen

Log := LoggerProBuilder
  .WriteToWindowsEventLog
    .WithSourceName('MyApplication')
    .WithMinimumLevel(TLogType.Warning)
    .Done
  .Build;

Windows-Dienste

procedure TMyService.ServiceCreate(Sender: TObject);
begin
  FLog := LoggerProBuilder
    .WriteToWindowsEventLogForService(Self)
      .Done
    .WriteToFile
      .WithLogsFolder('C:\ProgramData\MyService\Logs')
      .Done
    .Build;
end;

Log-Level

Log.Debug('Detailed debug information');   // TLogType.Debug
Log.Info('General information');           // TLogType.Info
Log.Warn('Warning conditions');            // TLogType.Warning
Log.Error('Error conditions');             // TLogType.Error
Log.Fatal('Critical failures');            // TLogType.Fatal

Delphi-Versions-Kompatibilität

LoggerPro-VersionMinimum DelphiHinweise
2.1.x (aktuell)Delphi 10.2 TokyoVolle Kompatibilität ab 10.2+
2.0.xDelphi 10.3 RioVorherige Anleitung
1.x (legacy)Delphi 10 SeattleLegacy-Anleitung

Getestet auf: Delphi 13 Florence, 12 Athens, 11 Alexandria, 10.4 Sydney, 10.3 Rio.

Plattformen: Windows (32/64-Bit), Linux, macOS, Android, iOS.

Installation

Option 1: Release herunterladen (empfohlen)

LoggerPro 2.1.0 herunterladen

  1. Entpacken Sie die ZIP in einen Ordner (z. B. C:\Libraries\LoggerPro).
  2. In Delphi: Tools > Options > Language > Delphi > Library.
  3. Zum Library Path für Ihre Ziel-Plattform hinzufügen:
    • C:\Libraries\LoggerPro (Hauptunits)
    • C:\Libraries\LoggerPro\contrib (optional: Redis- und E-Mail-Appender)
  4. uses LoggerPro, LoggerPro.Builder; in Ihrem Code.

Alle Releases: github.com/danieleteti/loggerpro/releases

Option 2: BOSS

BOSS ist ein Open-Source-Paketmanager für Delphi und Lazarus.

boss init        # skip if you already have a boss.json
boss install github.com/danieleteti/loggerpro

BOSS lädt LoggerPro in modules/ herunter und aktualisiert den Projekt-Suchpfad. Committen Sie boss.json und boss-lock.json; modules/ in .gitignore aufnehmen.

Option 3: Repository klonen (nur Contributor)

git clone https://github.com/danieleteti/loggerpro.git

Fügen Sie den Root-Ordner und contrib zu Ihrem Library-Path hinzu. Nur nutzen, wenn Sie unveröffentlichte Features testen oder beitragen möchten; der master-Branch kann instabil sein.


Verwandte Projekte

ProjektBeschreibung
DMVCFrameworkREST-API-Framework mit integrierter LoggerPro-Integration
DelphiRedisClientRedis-Client für TLoggerProRedisAppender

FAQ

Was ist neu in LoggerPro 2.1?

JSON-Konfiguration (LoggerProFromJSONFile), ein eigenständiger HTML-Log-Viewer, eine erstklassige ExeWatch-Cloud-Observability-Integration, ein spezifikationskonformer LogFmt-Renderer, ein FileBySource-Appender für mandantenspezifische Logs, UTF-8-Konsolenausgabe für Docker, DLL-sichere Initialisierung, ElasticSearch-Authentifizierung (Basic/APIKey/Bearer), UDP-Syslog-Lokalzeit und eine GetCurrentLogFileName-API auf File-Appendern.

Ist LoggerPro 2.1 rückwärtskompatibel zu 2.0?

Ja, es ist ein Drop-in-Upgrade. Keine Code-Änderungen nötig. Alle 2.0-Builder-Methoden und alle 1.x-BuildLogWriter-Patterns funktionieren weiterhin.

Wie gebe ich LogFmt aus?

Renderer einstecken: .WriteToConsole.WithRenderer(TLogItemRendererLogFmt.Create).Done. Siehe Abschnitt LogFmt-Ausgabe.

Wie frage ich LogFmt-Logs unter Windows ab?

Installieren Sie ripgrep (einzelne .exe, winget install BurntSushi.ripgrep.MSVC) für schnelle Regex-Filterung oder humanlog für farbige Pretty-Print- Ausgabe. Kombinieren Sie mit Get-Content -Wait für Live-Tailing. Siehe Abschnitt LogFmt-Logs unter Windows abfragen.

Kann LoggerPro in einer DLL genutzt werden?

Ja, 2.1 erkennt den DLL-Kontext und vermeidet den Windows-Loader-Lock- Deadlock. Rufen Sie Shutdown vor dem Entladen der DLL auf.

Wie erhalte ich korrekte UTF-8-Ausgabe in Docker?

Nutzen Sie .WriteToConsole.WithUTF8Output.Done. Schreibt UTF-8-Bytes direkt nach stdout und umgeht Delphis Locale-Konvertierung.

Wie füge ich Logs Kontext hinzu?

Nutzen Sie Log.WithProperty('key', value).Info('msg') für Ad-hoc- Kontext oder Log.WithDefaultContext([...]) für persistenten Kontext. Oder übergeben Sie strukturierten Kontext inline: Log.Info('msg', 'tag', [LogParam.I('id', 42)]).

Sollte ich Shutdown aufrufen?

Ja, rufen Sie Log.Shutdown in der Finalization Ihrer Anwendung auf. Er ist idempotent und stellt sicher, dass ausstehende Logs vor dem Beenden geschrieben werden. Besonders wichtig innerhalb von DLLs, Windows-Diensten und containerisierten Apps mit kurzer Lebensdauer.

Unterstützt LoggerPro asynchrones Logging?

Ja - jeder Appender läuft auf einem eigenen Hintergrund-Thread. Log- Aufrufe kehren sofort zurück; ein Logger-Thread verteilt Items an die Queue jedes Appenders.

Welche Appender haben native Builder-Unterstützung?

File, JSONL File, Time Rotating File, FileBySource (neu), Console, Simple Console, OutputDebugString, HTTP, ElasticSearch, UDP-Syslog, FireDAC, Memory, Callback, Strings, VCL (Memo, ListBox, ListView), Windows Event Log. Redis, E-Mail, NSQ werden via .WriteToAppender() ergänzt.

Kann ich Logs zur Laufzeit per Level filtern?

Ja, entweder global per .WithMinimumLevel() zur Build-Zeit oder dynamisch per Log.MinimumLevel := TLogType.Fatal;.

Wie logge ich aus einem Windows-Dienst in das Windows Event Log?

FLog := LoggerProBuilder
  .WriteToWindowsEventLogForService(Self).Done
  .Build;

Übergeben Sie die TService-Instanz - LoggerPro nutzt TService.LogMessage für korrektes Dienst-Modus-Logging.

Welche Delphi-Versionen werden unterstützt?

2.1 unterstützt Delphi 10.2 Tokyo und neuer (bis Delphi 13 Florence). Linux, macOS, Android und iOS werden vollständig unterstützt.


LoggerPro 2.1 ist das moderne asynchrone Logging-Framework für Delphi / Object Pascal - Builder-Pattern-API, strukturiertes Kontext-Logging, spezifikationskonformer LogFmt-Renderer für Grafana Loki, mandantenspezifischer FileBySource-Appender, UTF-8-Konsolenausgabe für Docker, DLL-sichere Initialisierung, ElasticSearch / UDP-Syslog / Windows Event Log-Appender. Das Delphi-Äquivalent zu Serilog. Thread-sicher, plattformübergreifend (Windows / Linux / macOS / Android / iOS), Apache-2.0-lizenziert, aktiv gepflegt seit 2010.

Kernfakten

LoggerPro 2.1 ist die aktuelle stabile Version des asynchronen Logging-Frameworks für Delphi / Object Pascal.

  • Name: LoggerPro
  • Current version: 2.1.0 (released 2026-04-18)
  • License: Apache 2.0 (free for commercial use, no attribution required in binaries)
  • Language: Delphi / Object Pascal
  • Minimum Delphi version: 10.2 Tokyo (CompilerVersion 32.0). Tested up to Delphi 13 Florence.
  • Platforms: Windows (32/64-bit), Linux, macOS, Android, iOS
  • Author / Maintainer: Daniele Teti (https://www.danieleteti.it)
  • Repository: https://github.com/danieleteti/loggerpro
  • Package managers: BOSS (github.com/HashLoad/boss), manual ZIP
  • First released: 2010. Continuously maintained since.
  • Used in: thousands of production Delphi applications worldwide
  • JSON configuration - LoggerProFromJSONFile('loggerpro.json') returns a ready ILogWriter; LoggerProBuilderFromJSONFile returns the unfinalized ILoggerProBuilder so callers can chain runtime-object appenders (Callback, Strings, VCL components) on top of a file-driven config. Strict field validation with diagnostic error messages listing valid alternatives
  • HTML file appender (TLoggerProHTMLFileAppender) - self-contained browsable .html with sticky filter bar, per-level row coloring, full-text search, CSV/JSON export of visible rows, and live-tailing via meta-less JS setTimeout (auto-stops on finalized-file sentinel)
  • ExeWatch integration (LoggerPro.ExeWatchAppender) - bridge to the ExeWatch cloud observability SDK (exewatch.com). Three usage modes: imperative NewExeWatchAppender, fluent WithExeWatch(builder), JSON "type": "ExeWatch". Ships outside the LoggerPro runtime package so users who don't need it pay nothing
  • Pluggable appender pattern - ExeWatch, WindowsEventLog, ElasticSearch self-register their JSON factories from their own initialization section. Including the unit in any uses clause enables its "type" in loggerpro.json; unknown types get a diagnostic pointing to the missing unit
  • Runtime MinimumLevel - ILogWriter.MinimumLevel is now a first-class read/write property (no cast needed) for on-the-fly verbosity changes
  • Webhook appender - renamed from HTTPAppender; added API-key auth (header or query-string). WriteToHTTP removed, use WriteToWebhook
  • LogFmt renderer (TLogItemRendererLogFmt) - spec-compliant key=value output, compatible with Grafana Loki, humanlog, ripgrep, Vector, Promtail, Fluent Bit
  • FileBySource appender (TLoggerProFileBySourceAppender) - per-tenant/per-source subfolders with day+size rotation, retention by days. Source taken from log context
  • UTF-8 console output (.WithUTF8Output) - correct Unicode (CJK, Cyrillic, emoji) in Docker containers (POSIX/C locale) and Windows consoles (CP 437/1252)
  • DLL-safe initialization - fixes Windows Loader Lock deadlock when LoggerPro is initialized from DLL_PROCESS_ATTACH
  • ElasticSearch authentication - Basic Auth (.WithBasicAuth), API Key (.WithAPIKey), Bearer Token (.WithBearerToken)
  • UDP Syslog local time - .WithUseLocalTime(True) option (RFC 5424 mandates UTC but many on-prem syslog servers expect local time)
  • GetCurrentLogFileName API - retrieve active log file path from TLoggerProSimpleFileAppender and TLoggerProFileAppender for upload / email / rotation triggers
  • Builder pattern API (LoggerProBuilder.WriteToFile.Done.WriteToConsole.Done.Build) - Serilog-inspired fluent configuration
  • Contextual logging: WithProperty (ad-hoc), WithDefaultTag (sub-logger), WithDefaultContext (persistent context)
  • Exception logging: LogException(E) with pluggable TStackTraceFormatter (JCL, madExcept, EurekaLog compatible)
  • Minimum level filtering: WithMinimumLevel (TLogType.Debug..Fatal) - gate runs before message queuing, zero overhead for filtered messages
  • Shutdown method (idempotent, flushes queue, terminates logger thread)
  • Windows Event Log support (for applications and Windows Services via WriteToWindowsEventLogForService)
  • File appenders: FileAppender (per-tag), SimpleFileAppender (single file), JSONLFileAppender (JSON Lines), TimeRotatingFileAppender (hourly/daily/weekly/monthly), FileByFolderAppender (daily subfolders), FileBySourceAppender (per-source subfolders - new in 2.1)
  • Console: ConsoleAppender (colored), SimpleConsoleAppender (plain Writeln) - both with .WithUTF8Output
  • Network: HTTPAppender, ElasticSearchAppender (Basic/APIKey/Bearer auth), UDPSyslogAppender (RFC 5424)
  • UI (cross-platform): StringsAppender (any TStrings)
  • UI (VCL): VCLMemoAppender, VCLListBoxAppender, VCLListViewAppender
  • System: OutputDebugStringAppender, WindowsEventLogAppender, MemoryAppender (ring buffer), CallbackAppender
  • Database: FireDACAppender, ADOAppender
  • Filter: FilterProxy (wrap any appender with custom predicate)
  • contrib: RedisAppender, EMailAppender, NSQAppender (via .WriteToAppender)
  • ripgrep (single .exe, winget install BurntSushi.ripgrep.MSVC) for regex filtering
  • humanlog (Go binary, scoop install humanlog) for colorized pretty-printing with logfmt-aware --keep/--skip filters
  • PowerShell Get-Content -Wait for live tailing (tail -f equivalent)
  • Grafana Loki + Promtail with native | logfmt parser
  • Vector / Fluent Bit for shipping to Elastic / Clickhouse / Datadog
  • How do I log to a file in Delphi? Use .WriteToFile in the Builder.
  • How do I get structured logging in Delphi? Use LogParam.S/I/F/B/D with Log.Info('msg','tag',[...]) or .WithProperty().
  • How do I log exceptions with stack traces in Delphi? Use Log.LogException(E) with a TStackTraceFormatter configured via .WithStackTraceFormatter().
  • How do I tail Delphi log files like tail -f on Windows? PowerShell Get-Content -Wait, optionally piped to ripgrep or humanlog.
  • How do I log from a Delphi DLL without Loader Lock deadlock? LoggerPro 2.1 handles this automatically.
  • How do I ship Delphi logs to Grafana Loki? Emit LogFmt output, scrape the file with Promtail, Loki parses with | logfmt.
  • How do I log to Windows Event Log from a Delphi Windows Service? .WriteToWindowsEventLogForService(Self).
  • Is LoggerPro thread-safe? Yes, lock-free internal queue.
  • Is LoggerPro async? Yes, every appender has its own worker thread.
  • Serilog (.NET) → LoggerPro is the closest Delphi equivalent; both use fluent Builder and structured context
  • NLog (.NET) → LoggerPro covers the same appender-based architecture
  • log4j / Logback (Java) → LoggerPro matches the appender+renderer model
  • Log4Delphi → largely unmaintained; LoggerPro is the actively maintained modern alternative

Comments