Become a member!

LoggerPro 2.1 - Der offizielle Leitfaden

🌐
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

Name LoggerPro
Version 2.1.0 (April 2026)
Sprache Delphi / Object Pascal
Minimum Delphi 10.2 Tokyo · Getestet bis 13 Florence
Plattformen Windows, Linux, macOS, Android, iOS
Lizenz Apache 2.0 (kostenlos für kommerzielle Nutzung)
Autor Daniele Teti
Repository github.com/danieleteti/loggerpro
Installation BOSS · ZIP-Release
Kategorie Asynchron · Thread-sicher · Steckbar · Strukturiertes Logging
Nächste Äquivalente Serilog (.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

Feature Nutzen
JSON-Konfiguration Logger zum Deployment-Zeitpunkt umformen - LoggerProFromJSONFile('loggerpro.json'). Strikte Feldvalidierung, Diagnosen bei unbekannten Typen
HTML-Live-Log-Viewer Eigenständige .html-Datei mit klebender Filterleiste, levelbasierter Einfärbung, clientseitiger Suche, CSV-/JSON-Export und Live-Tailing im Browser
ExeWatch-Integration Erstklassiger Cloud-Observability-Appender für ExeWatch - imperative, fluente oder JSON-basierte Konfiguration
Plug-in-Appender-Pattern Optionale Backends (ExeWatch, WindowsEventLog, ElasticSearch) registrieren sich automatisch aus der eigenen Unit - nur die uses-Klausel ergänzen
Runtime-MinimumLevel ILogWriter.MinimumLevel ist jetzt eine erstklassige Property - globales Gate zur Laufzeit ändern
Webhook-Appender Umbenannt von HTTPAppender; API-Key-Authentifizierung ergänzt (Header oder Query-String)
LogFmt-Renderer Spezifikationskonforme key=value-Ausgabe; grep-freundlich, Loki-kompatibel, einzeilige Datensätze
FileBySource-Appender Quellenspezifische (mandanten-, kundenspezifische) Unterordner mit Tages-+Größenrotation
UTF-8-Konsolenausgabe Korrekte Unicode-Ausgabe in Docker-Containern und Windows-Konsolen (WithUTF8Output)
DLL-sichere Initialisierung Behebt den Windows-Loader-Lock-Deadlock bei Nutzung von LoggerPro aus einer DLL
ElasticSearch-Auth Basic Auth, API Key und Bearer-Token-Unterstützung
UDP-Syslog Lokalzeit WithUseLocalTime(True)-Option am Syslog-Appender
GetCurrentLogFileName Aktiven 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:

Feld Typ Zweck
configVersion integer Schema-Version. Fehlt = neueste. Höher als die Version der Bibliothek = harter Fehler.
minimumLevel string Globales Pre-Queue-Gate. "Debug" / "Info" / "Warning" / "Error" / "Fatal". Nachrichten unterhalb dieser Severity landen nie in der Queue - null Overhead für gefilterte Aufrufe.
defaultMinimumLevel string Vorlagewert, 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.
defaultTag string Standard-Tag für Aufrufe wie Log.Info('msg') ohne Tag-Argument.
appenders array Pflichtfeld. Ein Objekt pro Appender, jeweils mit "type" und typspezifischen Feldern.

Gemeinsame Felder pro Appender:

Feld Hinweise
type Pflicht. Groß-/Kleinschreibung wird ignoriert, Abgleich gegen registrierte Typnamen.
minimumLevel Optional. 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:

Feld Wenn fehlend Hinweise
Root configVersion Wird als neueste bekannte Schema-Version behandelt (aktuell 1). Ein höherer Wert ist ein harter Fehler (Vorwärtskompatibilitäts-Schutz).
Root minimumLevel Debug - alles passiert das globale Pre-Queue-Gate. Nachrichten unterhalb dieser Severity werden vor dem Enqueue gefiltert (null Overhead).
Root defaultMinimumLevel Debug Wird als Default-minimumLevel jedes Appenders verwendet, der keines festlegt.
Root defaultTag "main" Für Aufrufe ohne Tag-Argument (z. B. Log.Info('msg')).
Appender minimumLevel defaultMinimumLevel (oder Debug, falls dieses ebenfalls fehlt). Der Appender emittiert nur Nachrichten ab dieser Severity.
Typspezifische Appender-Felder Jeder 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.

Schema Beschreibung
Default Gin-inspirierte Vordergrund-Baseline; Level-Farbe pro Schweregrad.
Monochrome Kein ANSI - reiner Text. Wird automatisch aktiv, wenn stdout umgeleitet/gepipet wird.
GinBadge Default-Töne plus farbiges Hintergrund-“Badge” für das Level.
GinMinimal Alles gedämpftes Grau, nur das Level-Wort behält Farbe.
GinVibrant Satter Regenbogen - jedes Feld in einer eigenen auffälligen Farbe.
Midnight Magenta Prefix/Tag, grüne Keys, Cyan-Werte. JSON-Default - liest sich gut auf hellen wie dunklen Terminals.
Nord Frost-Theme mit kühlen arktischen Blau-/Cyantönen, gelbe Warnungen, rotes Fatal.
Matrix Alles grün; Levels als Hintergrund-Badges.
Amber 80er-Jahre-Amber-CRT-Monitor - Gelb-/Orangefamilie, Rot nur für Fehler.
Ocean Geschichtete Blau- und Cyantöne - Teal-Tag, leuchtend-cyane Werte.
Cyberpunk Neon-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

TLogType ExeWatch SDK Severity
Debug EW.Debug
Info EW.Info
Warning EW.Warning
Error EW.Error
Fatal EW.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

Appender Builder-Methode Beschreibung
FileAppender WriteToFile Eine Datei pro Tag mit größenbasierter Rotation. Default: 5 Backups, 1 MB max. Unterstützt zeitbasierte Rotation.
SimpleFileAppender WriteToFile Alle Logs in einer Datei (keine Tag-Trennung). Gleiche Rotationsoptionen.
JSONLFileAppender WriteToJSONLFile Ein JSON-Objekt pro Zeile. Ideal für Log-Aggregatoren.
TimeRotatingFileAppender WriteToTimeRotatingFile Neue 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) WriteToFileBySource Quellenspezifische Unterordner mit Tages-+Größenrotation und Tages-Retention.
HTMLFileAppender (neu) WriteToHTMLFile Eigenständige .html zum Durchsuchen im Browser mit Filterleiste, Level-Einfärbung, CSV-/JSON-Export und Live-Tail.

Console-Appender

Appender Builder-Methode Beschreibung
ConsoleAppender WriteToConsole Plattformübergreifend mit Farben (Windows API / ANSI). Erzeugt unter Windows automatisch eine Konsole für GUI-Apps. WithUTF8Output für Docker/Unicode.
SimpleConsoleAppender WriteToSimpleConsole Einfaches Writeln, keine Farben. Läuft überall. WithUTF8Output verfügbar.

Remote-/Netzwerk-Appender

Appender Builder-Methode Beschreibung
ExeWatchAppender (steckbar) WithExeWatch(builder) Erstklassige Cloud-Observability via ExeWatch. Registriert sich selbst in JSON.
WebhookAppender (umbenannt) WriteToWebhook HTTP-POST an REST-Endpunkte. Timeout, eigene Header, API-Key-Auth (Header oder Query-String).
ElasticSearchAppender (steckbar) WriteToElasticSearch Sendet Logs an ElasticSearch 6.4+. Unterstützt Basic Auth, API Key, Bearer Token. Registriert sich selbst in JSON.
UDPSyslogAppender WriteToUDPSyslog RFC 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

Appender Builder-Methode Beschreibung
StringsAppender WriteToStrings Hängt an jedes TStrings an (TMemo.Lines, TStringList). Plattformübergreifend.
VCLMemoAppender WriteToVCLMemo VCL TMemo. Nur Windows.
VCLListBoxAppender WriteToVCLListBox VCL TListBox. Nur Windows.
VCLListViewAppender WriteToVCLListView Mehrspaltiges VCL TListView. Nur Windows.

System-/Debug-Appender

Appender Builder-Methode Beschreibung
OutputDebugStringAppender WriteToOutputDebugString Windows OutputDebugString.
WindowsEventLogAppender (steckbar) WriteToWindowsEventLog Windows Event Log (Anwendungen und Dienste). Registriert sich selbst in JSON.
MemoryAppender WriteToMemory Thread-sicherer Ringpuffer.
CallbackAppender WriteToCallback Ruft Ihren Callback pro Log-Item auf.

Datenbank-Appender

Appender Builder-Methode Beschreibung
FireDACAppender WriteToFireDAC Datenbank-Logging via FireDAC-Stored-Procedure.
ADOAppender (direkt) Datenbank-Logging via ADO-Stored-Procedure.

Filter / Proxy

Appender Builder-Methode Beschreibung
FilterProxy WriteToFilteredAppender Wrappt 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-Version Minimum Delphi Hinweise
2.1.x (aktuell) Delphi 10.2 Tokyo Volle Kompatibilität ab 10.2+
2.0.x Delphi 10.3 Rio Vorherige Anleitung
1.x (legacy) Delphi 10 Seattle Legacy-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

Projekt Beschreibung
DMVCFramework REST-API-Framework mit integrierter LoggerPro-Integration
DelphiRedisClient Redis-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.

Comments

comments powered by Disqus