LoggerPro 2.1 — Framework di Logging Asincrono per Delphi
TL;DR: LoggerPro 2.1 è il framework di logging asincrono e thread-safe per Delphi. Mantiene l’API fluente con pattern Builder della 2.0 e aggiunge configurazione esterna via JSON (
LoggerProFromJSONFileoLoggerProFromJSONString), osservabilità cloud con ExeWatch, un renderer LogFmt conforme alla spec, un appender FileBySource per log per-tenant, output console UTF-8 per Docker, inizializzazione DLL-safe, autenticazione ElasticSearch e altro ancora. Aggiornamento drop-in dalla 2.0, licenza Apache 2.0, funziona da Delphi 10.2 Tokyo fino a Delphi 13 Florence, su Windows / Linux / macOS / Android / iOS. Documentazione LoggerPro 2.0 → · Documentazione LoggerPro 1.x →
In sintesi
| Nome | LoggerPro |
| Versione | 2.1.0 (Aprile 2026) |
| Linguaggio | Delphi / Object Pascal |
| Delphi minimo | 10.2 Tokyo · Testato fino a 13 Florence |
| Piattaforme | Windows, Linux, macOS, Android, iOS |
| Licenza | Apache 2.0 (libera per uso commerciale) |
| Autore | Daniele Teti |
| Repository | github.com/danieleteti/loggerpro |
| Installazione | BOSS · Release ZIP |
| Categoria | Asincrono · Thread-safe · Pluggable · Logging strutturato |
| Equivalenti più prossimi | Serilog (.NET), NLog (.NET), log4j / Logback (Java) |
Cos’è LoggerPro?
LoggerPro è il framework di logging asincrono, thread-safe e pluggable per Delphi / Object Pascal - l’equivalente Delphi più prossimo di Serilog (.NET), NLog (.NET) o log4j / Logback (Java). Offre un’API fluente con pattern Builder, contesto strutturato key-value, formatter di stack trace pluggable, 20+ appender integrati (file, console, HTTP, osservabilità cloud ExeWatch, Grafana Loki via LogFmt, ElasticSearch, UDP syslog, Windows Event Log, database, VCL e altro), e gira cross-platform su Windows, Linux, macOS, Android e iOS. LoggerPro è rilasciato con licenza Apache 2.0, mantenuto attivamente dal 2010 e utilizzato in migliaia di applicazioni Delphi in produzione.
La versione 2.1 (Aprile 2026) è la release stabile corrente. Si basa sull’API fluente con pattern Builder introdotta nella 2.0 e aggiunge un’integrazione first-class con ExeWatch per l’osservabilità cloud end-to-end, insieme a feature focalizzate sui target di deployment moderni - container Docker, aggregatori di log cloud (Grafana Loki, Elastic, Datadog), applicazioni multi-tenant e DLL Delphi - rimanendo completamente backward compatible.
Novità della 2.1
| Feature | Cosa ti offre |
|---|---|
| Configurazione JSON | Rimodella il logger al deploy - LoggerProFromJSONFile('loggerpro.json'). Validazione stretta dei campi, diagnostica per type sconosciuti |
| HTML live log viewer | File .html autocontenuto con barra filtri sticky, colorazione per livello, ricerca client-side, export CSV/JSON e live tailing nel browser |
| Integrazione ExeWatch | Appender first-class per l’osservabilità cloud ExeWatch - uso imperativo, fluente o via JSON |
| Pattern appender pluggable | I backend opzionali (ExeWatch, WindowsEventLog, ElasticSearch) si auto-registrano dalla propria unit - basta aggiungere la clausola uses |
MinimumLevel a runtime |
ILogWriter.MinimumLevel è ora una property first-class - cambia il gate globale al volo |
| Webhook appender | Rinominato da HTTPAppender; aggiunta autenticazione API-key (header o query-string) |
| Renderer LogFmt | Output key=value conforme alla spec; greppable, Loki-friendly, record su singola riga |
| FileBySource appender | Sottocartelle per-sorgente (per-tenant, per-client) con rotazione giorno+dimensione |
| Output console UTF-8 | Unicode corretto in container Docker e console Windows (WithUTF8Output) |
| Init DLL-safe | Risolve il deadlock del Windows Loader Lock quando LoggerPro viene usato da una DLL |
| Auth ElasticSearch | Supporto per Basic Auth, API Key e Bearer Token |
| UDP Syslog local time | Opzione WithUseLocalTime(True) sull’appender syslog |
GetCurrentLogFileName |
Recupera il path del file di log attivo - utile per upload, email, riavvio |
Aggiornamento dalla 2.0? Sostituzione drop-in nella maggior parte dei casi. Un solo breaking change:
WriteToHTTPè stato rinominato inWriteToWebhook(basta un find-and-replace). Tutto il resto è additivo.
Quick Start con l’API Builder
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;
Configurazione JSON
Novità della 2.1. Distribuisci la tua app con un loggerpro.json accanto
all’EXE e rimodella il logger al deploy senza ricompilare. Gli operatori
possono cambiare backend, modificare i livelli di log o aggiungere/rimuovere
appender senza toccare il codice sorgente.
Schema in breve
{
"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" }
]
}
Il gate globale accetta tutto (minimumLevel: Debug). Ogni appender
che non specifica il proprio minimumLevel prende il valore template
Warning - Console e HTMLFile lo ereditano entrambi. Il File
appender fa opt-out e scrive l’audit trail completo a Debug.
Mettere defaultMinimumLevel sotto minimumLevel sarebbe un
no-op: il gate globale avrebbe già scartato quei messaggi prima che
raggiungano un qualsiasi appender.
Campi root:
| Campo | Tipo | Scopo |
|---|---|---|
configVersion |
integer | Versione dello schema. Assente = ultima versione. Superiore alla versione della libreria = errore bloccante. |
minimumLevel |
string | Gate globale pre-coda. "Debug" / "Info" / "Warning" / "Error" / "Fatal". I messaggi sotto questa severity non entrano mai in coda - zero overhead per le chiamate filtrate. |
defaultMinimumLevel |
string | Valore template che ogni appender usa come proprio minimumLevel quando l’entry non ne specifica uno. Non è un gate - pre-popola soltanto la soglia per-appender al momento del parsing. |
defaultTag |
string | Tag di default per chiamate come Log.Info('msg') senza argomento tag. |
appenders |
array | Obbligatorio. Un oggetto per appender, ciascuno con un "type" e campi type-specific. |
Campi comuni per-appender:
| Campo | Note |
|---|---|
type |
Obbligatorio. Case-insensitive, confrontato con i nomi di tipo registrati. |
minimumLevel |
Opzionale. Severity minima che questo appender emette. I messaggi sotto vengono silenziosamente scartati da QUESTO appender (gli altri appender li vedono comunque). Stesso dominio di valori del minimumLevel root. Default a defaultMinimumLevel (o Debug se anche quello è assente). Impostarlo sotto il minimumLevel root è un no-op: quei messaggi non arrivano all’appender perché non hanno passato il gate pre-coda. |
I campi type-specific sono elencati nella sezione di ciascun appender in questa guida; i typo vengono intercettati (vedi Diagnostica degli errori sotto).
I tre concetti, disambiguati. Ogni chiamata di log porta con sé la propria severity -
Log.Infoè Info,Log.Errorè Error, e così via. NéminimumLevelnédefaultMinimumLevello cambiano; decidono soltanto chi vede cosa. IlminimumLevelroot è un filtro pre-coda (gratuito: ilTLogItemnon viene nemmeno costruito per messaggi sotto soglia). IlminimumLevelper-appender è un gate di emissione (valutato sul worker thread dell’appender, decide se QUESTO appender scrive il messaggio). IldefaultMinimumLevelal root è un default a write-time per il gate per-appender, non un filtro runtime - ti permette di dire “ogni appender va di default a Warning se non specifica diversamente” senza ripetere il campo su ogni entry.
Cos’è obbligatorio, cosa ha default
Il minimo assoluto è una singola entry nell’array:
{ "appenders": [ { "type": "Console" } ] }
Fine. Tutto il resto è opzionale o inferito. La chiave appenders al
root è obbligatoria (può essere un array vuoto per costruire un
logger no-op, ma deve essere presente). Ogni entry deve avere un
"type"; ogni altro campo è opzionale.
Valori di default quando un campo è omesso:
| Campo | Se assente | Note |
|---|---|---|
Root configVersion |
Trattato come l’ultima versione di schema nota (attualmente 1). |
Un valore superiore è un errore bloccante (guard forward-compat). |
Root minimumLevel |
Debug - tutto passa il gate globale pre-coda. |
I messaggi sotto questa severity vengono filtrati prima dell’accodamento (zero overhead). |
Root defaultMinimumLevel |
Debug |
Usato come minimumLevel di default per ogni appender che non ne specifica uno. |
Root defaultTag |
"main" |
Usato dalle chiamate che non passano un tag (es. Log.Info('msg')). |
Appender minimumLevel |
defaultMinimumLevel (o Debug se anche quello è assente). |
L’appender emette solo messaggi a questa severity o superiore. |
| Campi type-specific dell’appender | Ogni appender porta i propri default (elencati nella sua sezione). | Es. logsFolder di File punta di default alla directory dell’EXE; Console ha i colori ON con scheme Midnight (usa "colorScheme": null o "colors": false per disattivarli). |
JSON minimali pronti all’uso
Log su file rotante (il deploy più semplice). Usa la directory
dell’EXE per logsFolder e il nome dell’EXE come base filename; 5
backup da 1 MB ciascuno.
{
"appenders": [
{ "type": "File" }
]
}
Vuoi piazzare i file altrove e tenere più storia:
{
"appenders": [
{
"type": "File",
"logsFolder": "C:/ProgramData/MyApp/logs",
"fileBaseName": "myapp",
"maxBackupFiles": 30,
"maxFileSizeInKB": 5000
}
]
}
Log sulla console colorata. I colori sono ON di default con il professionale scheme Midnight - è sufficiente una singola entry:
{
"appenders": [
{ "type": "Console" }
]
}
Sovrascrivi lo scheme per nome (case-insensitive), o disattiva totalmente i colori:
// 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 } ] }
Tutte e tre le forme “opt out” producono testo piano, senza ANSI. Inoltre, ogni scheme colorato si auto-degrada a testo piano quando stdout è rediretto su file o pipato a un altro processo - non ti ritroverai mai con codici escape nei tuoi file di log per sbaglio.
Gli schemi di colore predefiniti
Undici schemi sono inclusi con LoggerPro. Tutti rispettano lo stesso
contratto di palette (colore per-livello + tag colorato, metadati,
chiavi e valori di contesto), ma enfatizzano parti diverse. I nomi
degli scheme sono case-insensitive in JSON; gli screenshot sotto sono
di riferimento - lancia samples/03b_console_with_colors_appender per
vedere ogni scheme renderizzato nel tuo terminale con gli stessi
messaggi seed.
| Scheme | Descrizione |
|---|---|
| Default | Baseline Gin-inspired solo foreground; colore livello per severità. |
| Monochrome | Nessun ANSI - testo piano. Auto-applicato quando stdout è pipato/rediretto. |
| GinBadge | Toni Default più “badge” con sfondo colorato per il livello. |
| GinMinimal | Tutto grigio scuro, solo la parola livello mantiene il colore. |
| GinVibrant | Arcobaleno saturato - ogni campo un colore distinto acceso. |
| Midnight | Prefisso/tag magenta, chiavi verdi, valori cyan. Default JSON - si legge bene su terminali chiari e scuri. |
| Nord | Tema Frost con blu/cyan artici, warning gialli, fatal rossi. |
| Matrix | Tutto verde; livelli renderizzati come badge di sfondo. |
| Amber | Monitor CRT ambrato anni ‘80 - famiglia giallo/arancio, rosso solo per errori. |
| Ocean | Blu e cyan stratificati - tag teal, valori cyan brillante. |
| Cyberpunk | Prefisso magenta neon, tag cyan, valori gialli; badge di livello vivaci. |
Selezione da JSON. Basta referenziarlo per nome:
// 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" } ] }
Selezione da codice:
uses LoggerPro, LoggerPro.Builder;
Log := LoggerProBuilder
.WriteToConsole
.WithColorScheme(LogColorSchemes.Midnight) // or .Nord / .Matrix / ...
.Done
.Build;
Scheme custom. Ogni scheme è un record TLogColorScheme - puoi
costruirne uno tuo partendo da qualsiasi preset e sovrascrivendo i
campi che contano:
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;
Auto-downgrade. Quando stdout è rediretto su file o pipato a un
altro processo, il renderer degrada automaticamente a testo piano
(equivalente a Monochrome). Non ti ritroverai mai con codici escape
nei tuoi file di log per sbaglio.
Altri campi opzionali:
{
"appenders": [
{
"type": "Console",
"colors": true,
"colorScheme": "Nord",
"prefix": "MYAPP", // shows as [MYAPP] before each line
"utf8Output": true // safe output in Docker / Windows consoles
}
]
}
Combina i due per un tipico setup di sviluppo - console colorata più un file rotante con livelli separati:
{
"minimumLevel": "Debug",
"appenders": [
{ "type": "Console", "colors": true, "colorScheme": "Midnight" },
{ "type": "File", "logsFolder": "logs", "minimumLevel": "Info" }
]
}
Entry point
Due funzioni globali nell’unit LoggerPro - una restituisce un
ILogWriter pronto all’uso, l’altra restituisce l’ILoggerProBuilder
non finalizzato così il chiamante può continuare a chainare:
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
Entrambe le funzioni sollevano ELoggerProConfigError su qualsiasi
problema con il file - vedi Diagnostica degli errori sotto per il
testo esatto.
Mescolare config da file con appender solo a runtime
Alcuni appender non possono essere descritti in JSON perché
richiedono un riferimento a un oggetto runtime che non sta in un
file di configurazione: una callback, un TStrings, un componente
VCL, una TFDConnection viva. Il pattern è sempre lo stesso:
- Carica la parte JSON-descrivibile con
LoggerProBuilderFromJSONFile. - Chaina gli extra sul builder restituito.
- Chiama
.Buildtu stesso.
Esempio 1 - Base JSON + callback UI per una status bar.
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;
Esempio 2 - Base JSON + mirror VCL TListView. L’utente configura
file/console da JSON; il live-tail GUI resta in codice.
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;
Esempio 3 - Base JSON + TMemo FMX. TMemo.Lines è un TStrings,
quindi l’appender cross-platform WriteToStrings copre FMX, VCL e
qualsiasi altro componente che esponga un TStrings.
FLog := LoggerProBuilderFromJSONFile('loggerpro.json')
.WriteToStrings(MemoLog.Lines)
.WithMaxLogLines(500)
.WithClearOnStartup(True)
.Done
.Build;
Esempio 4 - Base JSON + appender database. Il JSON controlla
console/file/HTML; la connessione DB resta in codice perché
TFDConnection non è serializzabile.
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;
Scenari e casi limite
Il minimumLevel per-appender è indipendente dal minimumLevel
root. Il gate root decide se un messaggio viene accodato; il gate
del singolo appender decide se quell‘appender scrive il messaggio.
Un messaggio sotto il minimumLevel root non raggiunge mai alcun
appender; un messaggio che passa il gate root ma è sotto il
minimumLevel di un appender viene scartato da quell’appender,
mentre gli altri lo ricevono comunque.
{
"minimumLevel": "Debug",
"appenders": [
{ "type": "Console", "minimumLevel": "Debug" },
{ "type": "File", "logsFolder": "logs", "minimumLevel": "Info" },
{ "type": "Webhook", "url": "https://ops/alerts",
"minimumLevel": "Error" }
]
}
Risultato: lo sviluppatore vede tutto in console, il file di log tiene
Info+, il webhook scatta solo su errori.
L’array appenders vuoto è ammesso - ottieni un logger “black
hole” utile per test di integrazione:
{ "configVersion": 1, "appenders": [] }
Logging effettivamente disabilitato significa solo un gate globale abbastanza alto da non far passare nulla:
{ "configVersion": 1, "minimumLevel": "Fatal", "appenders": [] }
Oppure, in codice, modifica la property a runtime su un writer già
costruito: Log.MinimumLevel := TLogType.Fatal;
Appender pluggable (ExeWatch, WindowsEventLog,
ElasticSearch e qualsiasi appender di terze parti che segua la
stessa convenzione) richiedono la loro unit nella clausola uses.
Dimenticarla produce un errore preciso (vedi sotto).
Sorgente JSON opzionale. Incorpora un JSON di default nelle risorse e sovrascrivi con un file su disco se presente:
uses System.IOUtils;
if TFile.Exists('loggerpro.json') then
Log := LoggerProFromJSONFile('loggerpro.json')
else
Log := LoggerProFromJSONString(LoadDefaultConfigFromResources);
Diagnostica degli errori
Il parser è strict by design - le misconfigurazioni falliscono ad alta
voce invece di funzionare a metà silenziosamente. Tutti gli errori
vengono sollevati come ELoggerProConfigError (dichiarata in
LoggerPro.pas, quindi un singolo uses LoggerPro; è sufficiente
per intercettarla).
Campo sconosciuto (cattura dei typo):
appenders[0] (type=Console): unknown field "colour".
Valid fields: minimumLevel, colors, colorScheme, prefix, utf8Output.
Type di appender sconosciuto (uses mancante):
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 troppo nuova:
configVersion 2 is newer than supported (max 1). Update LoggerPro.
Valore enum non valido:
appenders[0] (type=Console): invalid colorScheme "NEON".
Valid values: Default, Monochrome, GinBadge, GinMinimal, GinVibrant,
Midnight, Nord, Matrix, Amber, Ocean, Cyberpunk.
File mancante o JSON malformato sollevano anch’essi
ELoggerProConfigError, rispettivamente con il path del file e la
diagnostica del parser.
Fallback graceful
Per scenari di first-run o deploy misconfigurati, intercetta l’errore e costruisci un default difensivo in codice così l’app continua a loggare invece di crashare:
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;
Il warning finisce nel logger di fallback stesso, così gli operatori notano il problema la prossima volta che fanno il tail dell’output.
Tipi di appender custom
LoggerPro.Config è un registry di tipi; i tuoi appender possono
collegarsi nello stesso modo in cui lo fanno quelli predefiniti:
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
Da quel momento in poi { "type": "MyCustom", "endpoint": "..." }
funziona semplicemente, e i typo nei nomi di campo scatenano la stessa
diagnostica strict dei predefiniti.
Sample: samples/240_config_simple, 241_config_advanced,
242_config_fallback.
Appender Pluggable (Pattern Auto-register)
Gli appender che puntano a sistemi esterni - ExeWatch, WindowsEventLog, ElasticSearch - restano FUORI dal package runtime core. Questo mantiene il core senza dipendenze e impedisce che SDK opzionali (come il client ExeWatch) diventino un requisito per ogni utente LoggerPro.
Come funziona: ogni unit di appender opzionale registra la propria
factory JSON dalla propria sezione initialization. Aggiungere l’unit
alla clausola uses di qualsiasi modulo del tuo progetto è
sufficiente ad abilitare il suo valore "type" in loggerpro.json.
// 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.
Se un file JSON referenzia un appender la cui unit non è in uses, il
messaggio di errore indica esattamente quale unit aggiungere.
Output LogFmt (Strutturato, grep-friendly)
LogFmt è un formato di logging strutturato orientato alle righe,
reso popolare da Heroku e Brandur Leach. Ogni riga di log è una
sequenza di coppie key=value separate da singoli spazi. I valori
sono nudi quando è sicuro, altrimenti racchiusi tra doppie virgolette
con escape \" e \\. È il punto di equilibrio fra testo
leggibile dall’umano e JSON parseabile dalla macchina.
Esempio di output
time=2026-04-18T12:30:45.123Z threadid=7932 type=INFO msg="order placed" tag=ORDERS order_id=42 amount=99.95 paid=true
Come abilitarlo
Collega il renderer TLogItemRendererLogFmt a qualsiasi appender tramite il Builder:
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)
]);
Oppure impostalo globalmente come renderer di default:
LoggerPro.Renderers.gDefaultLogItemRenderer := TLogItemRendererLogFmt;
Perché LogFmt
- Leggibile nei terminali: record su una riga, nessun rumore finale.
- Banalmente greppable:
grep 'order_id=42'funziona e basta. - Streaming-friendly: ogni riga è autocontenuta - nessun oggetto JSON multi-riga da ricomporre dallo stdout del container.
- Economico da produrre: nessun serializzatore JSON escape-heavy nel path caldo.
- Tooling: parsato nativamente da
humanlog,lnav, Grafana Loki, Vector, Fluent Bit, Promtail, Filebeat.
Conformità alla spec
Il renderer LogFmt di LoggerPro:
- Virgoletta i valori contenenti spazio,
",=,\o caratteri di controllo. - Escapa
"come\",\come\\,\n\r\tcome sequenze di escape letterali. - I byte di controllo non stampabili diventano
\uNNNN. - Sanifica le chiavi di contesto a
[a-zA-Z0-9_.-](i caratteri invalidi diventano_). - I float usano sempre
.come separatore decimale (locale-independent). - I booleani vengono renderizzati come
true/falsenudi.
Questo significa che l’output è sicuro da streamare una-riga-alla-volta
attraverso grep, awk, jq -R, il parser logfmt di Loki, ecc.,
senza corruzione.
Interrogare log LogFmt su Windows
1. ripgrep (rg) - filtro universale
Installazione:
# 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
Uso:
# 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 - pretty-printer & filtro logfmt-aware
humanlog è un binario Go che
comprende logfmt (e JSON) nativamente: colora i livelli, allinea le
colonne, parsa i timestamp e ti permette di filtrare con un
mini-linguaggio di espressioni. Molto più piacevole di rg quando
stai leggendo i log, non solo greppando.
Installazione:
# 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
Uso:
# 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 (stile tail -f)
Get-Content -Wait di PowerShell è il mattoncino per il live tailing
su Windows:
Get-Content logs\myapp.20260418.log -Wait -Tail 20
Nota che Get-Content -Wait osserva l’handle del file originale e non
seguirà la rotazione giornaliera/dimensionale di LoggerPro. Per
tecniche avanzate (loop re-tail, piping dello stdout di processo,
insidie di encoding), vedi il
blog.
Fallback zero-install: Select-String
Se non puoi installare nulla su una macchina di produzione,
Select-String è incluso in ogni installazione Windows:
# 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
Quando andare oltre i tool grep-style
Una volta che hai molti file, host multipli o >GB/giorno di log, smetti di greppare e inizia a spedire:
-
Grafana Loki + Promtail - LogQL con parser nativo
| logfmt:{app="myapp"} | logfmt | type="ERROR" | order_id="42" -
Vector (singolo
.exe, config-driven) - parsa con il codeclogfmt, spedisci a Elastic, Clickhouse, Datadog, S3, ecc. -
Fluent Bit (singolo
.exe) - simile, leggero.
LogFmt vs JSONL - quando scegliere quale
LoggerPro supporta anche JSONL (un oggetto JSON per riga) tramite
TLoggerProJSONLFileAppender. Regola del pollice:
- LogFmt → macchine di sviluppo, stdout di container, log di produzione greppable, volume basso/medio, contesto flat.
- JSONL → strutture annidate, pipeline di analytics, ingest Elastic/Datadog/OpenObserve, volume alto, schema stretto.
Entrambi i renderer condividono la stessa API di contesto
LogParam.S/I/F/B/D, quindi puoi passare dall’uno all’altro senza
cambiare il codice applicativo.
FileBySource Appender
Novità della 2.1. Organizza i log in sottocartelle per-sorgente - perfetto per applicazioni multi-tenant dove ogni client, device o account ottiene il proprio stream di log. La chiave sorgente viene estratta dal contesto del log.
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
La rotazione è giorno + dimensione: un nuovo file viene aperto al
cambio giorno, e quando il file corrente supera WithMaxFileSizeInKB.
I file più vecchi di WithRetainDays vengono eliminati
automaticamente all’avvio e a ogni cambio giorno.
Visualizzatore HTML di Log in Tempo Reale
Novità della 2.1. Un file di log HTML autocontenuto che puoi aprire in
qualsiasi browser - nessun server, nessun asset esterno, un .html
per rotazione. Utile per consegnare un artefatto compatto di
troubleshooting a utenti, QA o supporto.
uses LoggerPro, LoggerPro.Builder;
Log := LoggerProBuilder
.WriteToHTMLFile
.WithLogsFolder('logs')
.WithFileBaseName('myapp')
.WithTitle('MyApp - Operations Log')
.WithMaxFileSizeInKB(1000)
.WithMaxBackupFiles(10)
.Done
.Build;
La pagina generata include:
- Barra filtri sticky - checkbox per-livello e una casella di ricerca full-text.
- Colorazione delle righe - le righe WARNING / ERROR / FATAL portano una tinta di sfondo delicata così le anomalie saltano all’occhio durante lo scroll.
- Rendering del contesto - il contesto strutturato
LogParamviene mostrato come coppie key=value in una riga secondaria, nascosta o mostrata dagli stessi controlli di filtro. - Export CSV / JSON - scarica le righe attualmente visibili.
- Live tail - mentre il file è ancora in scrittura, la pagina si ricarica automaticamente ogni 3 secondi e fa sempre lo scroll al fondo.
- Consapevolezza LIVE / FINALIZED - la pagina sa se il file di log è ancora in scrittura o è stato chiuso e ferma l’auto-reload nel momento in cui viene finalizzato.
Sample: samples/230_html_file_appender. Esposto anche alla config
JSON come "type": "HTMLFile".
Output Console UTF-8 (Docker / Windows)
Di default, il Writeln di Delphi converte all’encoding del locale di
sistema, il che storpia i caratteri non-ASCII nei container Docker
(locale POSIX/C) e nelle console Windows (CP 437/1252). Abilita
WithUTF8Output per scrivere byte UTF-8 direttamente su stdout:
Log := LoggerProBuilder
.WriteToConsole
.WithUTF8Output
.Done
.Build;
// Also available for the plain (no-color) console appender
Log := LoggerProBuilder
.WriteToSimpleConsole
.WithUTF8Output
.Done
.Build;
È particolarmente utile quando esegui applicazioni Delphi in container Docker o quando logghi testo Unicode (CJK, cirillico, emoji, ecc.) su Windows.
Inizializzazione DLL-Safe
LoggerPro 2.1 funziona correttamente all’interno di DLL caricate via
LoadLibrary o P/Invoke. L’inizializzazione del thread logger rileva
il contesto DLL ed evita il deadlock del Windows Loader Lock che
affliggeva le versioni precedenti.
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.
Nota: Chiama
GLog.Shutdownprima che la DLL venga scaricata se devi garantire il flush dei messaggi in coda.
Logging Contestuale
Le feature di logging contestuale di LoggerPro ti permettono di arricchire ogni chiamata di log con coppie key-value strutturate senza ripeterti.
WithProperty (contesto ad-hoc)
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 (contesto persistente)
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;
Contesto strutturato 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;
Formatter di stack trace
Integra con JCL, madExcept, EurekaLog o qualsiasi libreria di stack trace:
Log := LoggerProBuilder
.WithStackTraceFormatter(
function(E: Exception): string
begin
Result := JclLastExceptStackListToString;
end)
.WriteToFile.Done
.Build;
Filtro per Livello Minimo
Filtra i messaggi globalmente prima che vengano accodati - overhead zero per i messaggi filtrati:
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
Novità della 2.1: il gate è una property first-class su ILogWriter,
così puoi cambiarlo a runtime senza cast:
Log.MinimumLevel := TLogType.Fatal; // effectively mute
// Later
Log.MinimumLevel := TLogType.Debug; // re-enable everything
ElasticSearch con Autenticazione
Novità della 2.1. L’appender ElasticSearch ora supporta tutti e tre i meccanismi di autenticazione comuni:
// 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;
Integrazione con ExeWatch (Cloud Observability)
Cos’è ExeWatch. ExeWatch è un servizio di cloud observability per applicazioni desktop e backend: raccoglie log, eccezioni, breadcrumb, identità utente, info device e metriche custom, e ti dà una dashboard per investigare gli incident in produzione senza dover spostare file di log.
Perché un appender dedicato. ExeWatch distribuisce il proprio SDK
Delphi (ExeWatchSDKv1.pas). Il bridge LoggerPro - unit
LoggerPro.ExeWatchAppender - trasforma ogni chiamata Log.Info / Warn / Error / Fatal / LogException nella corrispondente chiamata
SDK, così mantieni l’API LoggerPro e guadagni trasparentemente la
pipeline ExeWatch. Non fa parte del package runtime di LoggerPro,
quindi i progetti che non usano ExeWatch non pagano nulla.
Abilitare il bridge. Aggiungi la cartella SDK al search path del
progetto (il sample usa C:\dev\exewatchsamples\DelphiCommons) e
includi l’unit bridge:
uses
LoggerPro,
LoggerPro.Builder,
LoggerPro.ExeWatchAppender;
L’SDK viene inizializzato automaticamente al Setup dell’appender -
NON devi chiamare tu InitializeExeWatch, e l’appender non
interferirà con un SDK già inizializzato da altro codice.
Quattro modi per collegarlo
1. Builder fluente - tutto in codice; OK quando API key, customer ID e versione sono literal o arrivano da variabili globali semplici. Chaina come qualsiasi appender predefinito:
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. Chain fluente su base JSON - abbina un loggerpro.json con
la configurazione ExeWatch lato codice. Il file di base porta il
setup console/file/HTML; i segreti SDK restano in codice, da dove
possono essere letti da un vault, una variabile d’ambiente o un
license server:
uses
LoggerPro, LoggerPro.Builder, LoggerPro.ExeWatchAppender;
Log := WithExeWatch(
LoggerProBuilderFromJSONFile('loggerpro.json'))
.WithAPIKey(LoadFromVault('ew_api_key'))
.WithCustomerId(CurrentTenant)
.WithAppVersion(GetFileVersion)
.Done
.Build;
3. Imperativo (minor attrito quando i valori arrivano da oggetti di configurazione):
Log := LoggerProBuilder
.WriteToAppender(NewExeWatchAppender(
'ew_win_xxxxxx', 'Acme Corp', '2.3.1'))
.Build;
4. Configurazione JSON pura (grazie al pattern auto-register, non serve alcuna chiamata extra di registrazione):
{
"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');
Mappatura dei livelli
TLogType |
Severity SDK ExeWatch |
|---|---|
Debug |
EW.Debug |
Info |
EW.Info |
Warning |
EW.Warning |
Error |
EW.Error |
Fatal |
EW.Fatal |
Il Tag del log viene inoltrato come tag SDK. Il contesto LogParam
strutturato viene collassato nel corpo del messaggio formattato - se
vuoi le feature SDK più ricche (breadcrumb, timings, identità utente,
gauge), chiama direttamente EW.AddBreadcrumb / EW.SetUser / EW.StartTiming affianco a LoggerPro. I due livelli convivono
liberamente.
Shutdown
Log.Shutdown drena la coda LoggerPro e poi chiama EW.Flush, così
ogni evento accodato lato client viene spedito prima che il processo
termini. La finalization dell’SDK si occupa del resto.
Sample: samples/260_exewatch_appender.
UDP Syslog (RFC 5424) con Local Time
Nuova opzione WithUseLocalTime - la RFC 5424 richiede UTC, ma molti
server syslog on-premise si aspettano local time.
Log := LoggerProBuilder
.WriteToUDPSyslog
.WithHost('syslog.example.com')
.WithPort(514)
.WithApplication('MyApp')
.WithUseLocalTime(True) // default: False (UTC)
.Done
.Build;
Ottenere il Nome del File di Log Corrente
Novità della 2.1. Utile per upload, invio via email o attach di un file di log on-demand.
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;
Per TLoggerProFileAppender (un file per 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
Chiama Shutdown nella finalization della tua applicazione per
garantire che tutti i log pendenti vengano scritti:
procedure TMyApp.Finalize;
begin
Log.Shutdown; // Flush queue, stop thread
Log := nil;
end;
Comportamenti chiave:
- Idempotente: sicuro da chiamare più volte.
- Fa il flush di tutti i messaggi pendenti.
- Termina il thread logger.
- Dopo lo shutdown, le chiamate di log vengono ignorate silenziosamente (Release) o scattano un assert (Debug).
Appender Integrati
LoggerPro 2.1 include 20+ appender. Tutti sono asincroni, thread-safe e configurabili tramite il Builder.
File Appender
| Appender | Metodo Builder | Descrizione |
|---|---|---|
| FileAppender | WriteToFile |
Un file per tag con rotazione per dimensione. Default: 5 backup, 1 MB max. Supporta rotazione per tempo. |
| SimpleFileAppender | WriteToFile |
Tutti i log in un singolo file (nessuna separazione per tag). Stesse opzioni di rotazione. |
| JSONLFileAppender | WriteToJSONLFile |
Un oggetto JSON per riga. Ideale per aggregatori di log. |
| TimeRotatingFileAppender | WriteToTimeRotatingFile |
Nuovo file a ogni intervallo temporale (orario/giornaliero/settimanale/mensile). |
| FileByFolderAppender | (diretto) | Organizza i log in sottocartelle giornaliere (Logs/20260418/app.00.log). |
| FileBySourceAppender (nuovo) | WriteToFileBySource |
Sottocartelle per-sorgente con rotazione giorno+dimensione e retention per giorni. |
| HTMLFileAppender (nuovo) | WriteToHTMLFile |
.html autocontenuto navigabile con barra filtri, colorazione per livello, export CSV/JSON e live tail. |
Console Appender
| Appender | Metodo Builder | Descrizione |
|---|---|---|
| ConsoleAppender | WriteToConsole |
Cross-platform con colori (Windows API / ANSI). Auto-crea la console per le app GUI su Windows. WithUTF8Output per Docker/Unicode. |
| SimpleConsoleAppender | WriteToSimpleConsole |
Writeln semplice, nessun colore. Funziona ovunque. WithUTF8Output disponibile. |
Appender Remoti / Network
| Appender | Metodo Builder | Descrizione |
|---|---|---|
| ExeWatchAppender (pluggable) | WithExeWatch(builder) |
Osservabilità cloud first-class via ExeWatch. Si auto-registra in JSON. |
| WebhookAppender (rinominato) | WriteToWebhook |
HTTP POST verso endpoint REST. Timeout, header custom, autenticazione API-key (header o query string). |
| ElasticSearchAppender (pluggable) | WriteToElasticSearch |
Spedisce log a ElasticSearch 6.4+. Supporta Basic Auth, API Key, Bearer Token. Si auto-registra in JSON. |
| UDPSyslogAppender | WriteToUDPSyslog |
Syslog UDP RFC 5424. Local time o UTC. |
| EMailAppender | (diretto) | SMTP (via Indy TIdSMTP). |
| NSQAppender | (diretto) | Pubblica i log sulla message queue distribuita NSQ. |
| RedisAppender | (contrib) | Memorizza i log in liste Redis. |
UI Appender
| Appender | Metodo Builder | Descrizione |
|---|---|---|
| StringsAppender | WriteToStrings |
Aggiunge a qualsiasi TStrings (TMemo.Lines, TStringList). Cross-platform. |
| VCLMemoAppender | WriteToVCLMemo |
TMemo VCL. Solo Windows. |
| VCLListBoxAppender | WriteToVCLListBox |
TListBox VCL. Solo Windows. |
| VCLListViewAppender | WriteToVCLListView |
TListView VCL multi-colonna. Solo Windows. |
Appender di Sistema / Debug
| Appender | Metodo Builder | Descrizione |
|---|---|---|
| OutputDebugStringAppender | WriteToOutputDebugString |
OutputDebugString di Windows. |
| WindowsEventLogAppender (pluggable) | WriteToWindowsEventLog |
Windows Event Log (applicazioni e Service). Si auto-registra in JSON. |
| MemoryAppender | WriteToMemory |
Ring buffer thread-safe. |
| CallbackAppender | WriteToCallback |
Invoca la tua callback per ogni log item. |
Appender Database
| Appender | Metodo Builder | Descrizione |
|---|---|---|
| FireDACAppender | WriteToFireDAC |
Logging su database via stored procedure FireDAC. |
| ADOAppender | (diretto) | Logging su database via stored procedure ADO. |
Filtro / Proxy
| Appender | Metodo Builder | Descrizione |
|---|---|---|
| FilterProxy | WriteToFilteredAppender |
Avvolge un qualsiasi appender con una funzione di filtro custom. |
Gli appender marcati (diretto) si usano via
BuildLogWriter([appender])o.WriteToAppender(appender).
Integrazione Windows Event Log
Applicazioni regolari
Log := LoggerProBuilder
.WriteToWindowsEventLog
.WithSourceName('MyApplication')
.WithMinimumLevel(TLogType.Warning)
.Done
.Build;
Windows Service
procedure TMyService.ServiceCreate(Sender: TObject);
begin
FLog := LoggerProBuilder
.WriteToWindowsEventLogForService(Self)
.Done
.WriteToFile
.WithLogsFolder('C:\ProgramData\MyService\Logs')
.Done
.Build;
end;
Livelli di Log
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
Compatibilità con le Versioni Delphi
| Versione LoggerPro | Delphi minimo | Note |
|---|---|---|
| 2.1.x (corrente) | Delphi 10.2 Tokyo | Piena compatibilità da 10.2+ |
| 2.0.x | Delphi 10.3 Rio | Guida precedente |
| 1.x (legacy) | Delphi 10 Seattle | Guida legacy |
Testato su: Delphi 13 Florence, 12 Athens, 11 Alexandria, 10.4 Sydney, 10.3 Rio.
Piattaforme: Windows (32/64-bit), Linux, macOS, Android, iOS.
Installazione
Opzione 1: Download della release (consigliato)
- Estrai lo ZIP in una cartella (es.
C:\Libraries\LoggerPro). - In Delphi: Tools > Options > Language > Delphi > Library.
- Aggiungi al Library Path per la tua target platform:
C:\Libraries\LoggerPro(unit principali)C:\Libraries\LoggerPro\contrib(opzionale: appender Redis ed Email)
uses LoggerPro, LoggerPro.Builder;nel tuo codice.
Tutte le release: github.com/danieleteti/loggerpro/releases
Opzione 2: BOSS
BOSS è un package manager open-source per Delphi e Lazarus.
boss init # skip if you already have a boss.json
boss install github.com/danieleteti/loggerpro
BOSS scarica LoggerPro in modules/ e aggiorna il search path del progetto.
Committa boss.json e boss-lock.json; aggiungi modules/ al .gitignore.
Opzione 3: Clone del repository (solo contributor)
git clone https://github.com/danieleteti/loggerpro.git
Aggiungi la cartella root e contrib al tuo Library Path. Usa questo
solo se vuoi testare feature non rilasciate o contribuire; il branch
master potrebbe essere instabile.
Progetti Correlati
| Progetto | Descrizione |
|---|---|
| DMVCFramework | Framework REST API con integrazione LoggerPro built-in |
| DelphiRedisClient | Client Redis per TLoggerProRedisAppender |
Link
- GitHub: github.com/danieleteti/loggerpro
- Documentazione LoggerPro 2.0: /loggerpro_2_0/
- Guida legacy 1.x: /loggerpro_1_3/
- Supporto: Gruppo Facebook
FAQ
Cosa c’è di nuovo in LoggerPro 2.1?
Configurazione JSON (LoggerProFromJSONFile), un visualizzatore
HTML di log autocontenuto, integrazione first-class con
l’osservabilità cloud ExeWatch, un
renderer LogFmt conforme alla spec, un appender FileBySource
per log per-tenant, output console UTF-8 per Docker,
inizializzazione DLL-safe, autenticazione ElasticSearch
(Basic/APIKey/Bearer), UDP Syslog local time e un’API
GetCurrentLogFileName sugli appender file.
LoggerPro 2.1 è backward compatible con la 2.0?
Sì, è un aggiornamento drop-in. Non serve alcuna modifica al codice.
Tutti i metodi Builder della 2.0 e tutti i pattern BuildLogWriter
della 1.x continuano a funzionare.
Come emetto output LogFmt?
Collega il renderer: .WriteToConsole.WithRenderer(TLogItemRendererLogFmt.Create).Done.
Vedi la sezione Output LogFmt.
Come interrogo log LogFmt su Windows?
Installa ripgrep (singolo .exe, winget install BurntSushi.ripgrep.MSVC)
per filtri regex veloci, o humanlog per pretty-printing colorato.
Combina con Get-Content -Wait per il live tailing. Vedi la sezione
Interrogare log LogFmt su Windows.
LoggerPro può essere usato in una DLL?
Sì, la 2.1 rileva il contesto DLL ed evita il deadlock del Windows
Loader Lock. Chiama Shutdown prima dell’unload della DLL.
Come ottengo output UTF-8 corretto in Docker?
Usa .WriteToConsole.WithUTF8Output.Done. Scrive byte UTF-8
direttamente su stdout, bypassando la conversione locale di Delphi.
Come aggiungo contesto ai log?
Usa Log.WithProperty('key', value).Info('msg') per contesto ad-hoc, o
Log.WithDefaultContext([...]) per contesto persistente. Oppure passa
contesto strutturato inline: Log.Info('msg', 'tag', [LogParam.I('id', 42)]).
Devo chiamare Shutdown?
Sì, chiama Log.Shutdown nella finalization della tua applicazione. È
idempotente e garantisce che i log pendenti vengano scritti prima
dell’uscita. Particolarmente importante all’interno di DLL, Windows
Service e app containerizzate con lifetime brevi.
LoggerPro supporta il logging asincrono?
Sì - ogni appender gira sul proprio thread di background. Le chiamate di log ritornano immediatamente; un thread logger dispaccia gli item alla coda di ogni appender.
Quali appender hanno supporto Builder nativo?
File, JSONL File, Time Rotating File, FileBySource (nuovo), Console,
Simple Console, OutputDebugString, HTTP, ElasticSearch, UDP Syslog, FireDAC,
Memory, Callback, Strings, VCL (Memo, ListBox, ListView), Windows Event Log.
Redis, Email, NSQ vengono aggiunti via .WriteToAppender().
Posso filtrare i log per livello a runtime?
Sì, sia globalmente con .WithMinimumLevel() al build, sia
dinamicamente via Log.MinimumLevel := TLogType.Fatal;.
Come loggo su Windows Event Log da un Windows Service?
FLog := LoggerProBuilder
.WriteToWindowsEventLogForService(Self).Done
.Build;
Passa l’istanza TService - LoggerPro usa TService.LogMessage per un
logging corretto in modalità Service.
Quali versioni di Delphi sono supportate?
La 2.1 supporta Delphi 10.2 Tokyo e successive (fino a Delphi 13 Florence). Linux, macOS, Android e iOS sono pienamente supportati.
LoggerPro 2.1 è il moderno framework di logging asincrono per Delphi / Object Pascal - API con pattern Builder, logging contestuale strutturato, renderer LogFmt conforme alla spec per Grafana Loki, appender FileBySource per-tenant, output console UTF-8 per Docker, inizializzazione DLL-safe, appender ElasticSearch / UDP Syslog / Windows Event Log. L’equivalente Delphi di Serilog. Thread-safe, cross-platform (Windows / Linux / macOS / Android / iOS), licenza Apache 2.0, mantenuto attivamente dal 2010.
Comments
comments powered by Disqus