Introduzione al registro eventi di Windows e a ETW — usare per le app aziendali i meccanismi standard del sistema operativo
· Go Komura · CSharp, .NET, Registro eventi, ETW, EventSource, Progettazione dei log, Indagine sui bug, Sviluppo Windows
Quando sviluppate app aziendali o servizi Windows in C#, probabilmente scrivete già i log quotidiani con un logger file interno o librerie come Serilog e NLog. Significa che Registro eventi di Windows ed ETW, Event Tracing for Windows, non servono più? No. Non sono sostituti del file logging: sono registrazioni visibili a un livello diverso, al personale operativo e agli strumenti standard del sistema operativo.
Vediamo quando usare file di log, registro eventi ed ETW, come implementarli da .NET, il minimo indispensabile di ETW, raccolta e indagine pratiche e le insidie più frequenti.
1. Prima la conclusione
- I tre meccanismi non sono sostituti: sono una divisione del lavoro. I file di log permettono agli sviluppatori di ricostruire dettagli a posteriori; il registro eventi permette a operatori e strumenti standard, Visualizzatore eventi e monitoraggio, di accorgersi del problema; ETW è una traccia ad alta frequenza abilitata su richiesta per prestazioni o bug difficili da riprodurre. Usateli insieme, variando quanto scrivere in ciascuno.
- Nel registro eventi scrivete solo avvio, arresto ed errori fatali. Se inviate ogni riga anche al registro, le anomalie che l’operatore deve vedere si perdono. Lasciate il file di log dettagliato e restringete l’output nel registro eventi.
- Registrare una sorgente eventi richiede privilegi di amministratore. Da Windows Vista,
EventLog.CreateEventSourcenon può essere chiamato senza tali privilegi. Non tentate di registrare la sorgente al primo accesso in runtime: fatelo prima nell’installer.1 - ETW non è una raccolta sempre attiva. Anche se definite eventi con
EventSource, nulla viene registrato finché un sottoscrittore, dotnet-trace, PerfView o uno strumento ETW, non ascolta. Indicate il provider e raccogliete solo durante analisi prestazionale o indagine di un bug specifico.2 - Scrivete messaggi come template, non con concatenazione o interpolazione.
logger.LogInformation("Order {OrderId} failed", orderId)consente di cercare il log strutturato per il nome OrderId; concatenazione e interpolazione perdono questa struttura.3 - La crescita eccessiva del log dipende spesso dal limite predefinito troppo piccolo. Il massimo predefinito del registro eventi è solo 512 KB. Se l’app lo usa regolarmente, espandetelo esplicitamente e decidete in progettazione se alla saturazione sovrascrivere i vecchi eventi o scartare i nuovi.4
| Aspetto | File di log | Registro eventi | ETW |
|---|---|---|---|
| Lettore principale | Sviluppatori e manutentori | Operatori, monitoraggio, Visualizzatore eventi | Investigatori di prestazioni e supporto |
| Volume | Dettagliato, anche Trace/Debug | Basso, solo avvio/arresto/errori fatali | Alto solo quando abilitato; nessuna registrazione predefinita |
| Conservazione | Semplice conservarlo a lungo secondo la rotazione | Voci vecchie sovrascritte o nuove scartate al limite di dimensione | Legato alla sessione; al termine si salva come .etl/.nettrace |
| Strumenti standard del sistema | Nessuno, richiede un proprio visualizzatore | Visualizzatore eventi, wevtutil e Get-WinEvent |
dotnet-trace, PerfView, WPR/WPA |
| Privilegi | Scrittura dell’utente che esegue l’app | La registrazione della sorgente richiede amministratore; dopo la registrazione uno standard user può scrivere | Avviare la raccolta richiede spesso amministratore |
2. Fondamenti del registro eventi di Windows
Windows ha per impostazione predefinita tre log: Application, System e Security; Security è in sola lettura. Le app e i servizi aziendali scrivono in Application oppure in un log/canale personalizzato. Per convenzione, i driver scrivono in System.5
L’unità di scrittura è la «sorgente evento». È il nome che identifica l’applicazione e viene registrato in anticipo con EventLog.CreateEventSource. Da Windows Vista, registrarla richiede privilegi di amministratore. Per confermare l’unicità del nome occorre cercare in tutti i log, incluso Security, a cui gli utenti standard non accedono.1
using System.Diagnostics;
// Eseguire dal programma di installazione o dalla procedura di configurazione mentre si dispone ancora dei privilegi di amministratore
const string SourceName = "KomuraSoft.OrderService";
const string LogName = "Application";
if (!EventLog.SourceExists(SourceName))
{
EventLog.CreateEventSource(SourceName, LogName);
}
Se create la sorgente al primo accesso, la chiamata fallisce in produzione quando l’app viene eseguita da un utente standard. La guida su quando siano davvero necessari privilegi di amministratore su Windows spiega il modello generale; qui il design sicuro è registrare la sorgente nell’installer e far sì che l’app scriva solo su una sorgente già registrata.
Ogni evento contiene due identificatori: livello e ID evento. Il livello è un EventLogEntryType, Information, Warning, Error, SuccessAudit o FailureAudit, e determina icona e filtri predefiniti di Visualizzatore eventi. L’ID è un intero definito dall’app che serve da chiave per cercare e aggregare in seguito eventi dello stesso tipo.
3. Scrivere nel registro eventi da .NET
Da .NET esistono due grandi percorsi per scrivere nel registro eventi.
3.1 Usare direttamente System.Diagnostics.EventLog
È un’API di basso livello, adatta quando servono controlli fini, categorie o dati binari allegati. In .NET, a differenza di .NET Framework, occorre il pacchetto NuGet System.Diagnostics.EventLog.
using System.Diagnostics;
public sealed class OrderServiceEventLog
{
private const string SourceName = "KomuraSoft.OrderService";
public void WriteServiceStarted()
{
EventLog.WriteEntry(SourceName, "OrderService è stato avviato.",
EventLogEntryType.Information, eventID: 1000);
}
public void WriteFatalError(Exception ex)
{
EventLog.WriteEntry(SourceName,
$"Si è verificato un errore irreversibile e non è possibile continuare l'elaborazione. Per i dettagli, consultare il log dei file. {ex.GetType().Name}: {ex.Message}",
EventLogEntryType.Error, eventID: 1999);
}
}
3.2 Usare ILogger + AddEventLog
Se avete già strutturato il logging attorno a ILogger, AddEventLog del pacchetto Microsoft.Extensions.Logging.EventLog si inserisce più naturalmente nella pipeline esistente. In ASP.NET Core e nei Worker Service basati su Generic Host, il provider EventLog è abilitato per impostazione predefinita su Windows.6
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.EventLog;
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Logging.AddEventLog(settings =>
{
settings.SourceName = "KomuraSoft.OrderService";
settings.LogName = "Application";
// Oltre al filtro delle categorie predefinito, inviare al registro eventi
// solo Warning e livelli superiori (lasciare i dettagli al log dei file)
settings.Filter = (_, level) => level >= LogLevel.Warning;
});
using IHost host = builder.Build();
await host.RunAsync();
Se omettete EventLogSettings, LogName predefinito è Application e SourceName è .NET Runtime.7 Lasciare .NET Runtime, un nome generico, rende difficile capire in Visualizzatore eventi se la voce appartenga alla vostra app o a un’altra app .NET; impostate sempre SourceName in modo esplicito.
Per elaborazioni batch eseguite come servizio Windows o tramite Utilità di pianificazione, il compromesso pratico è scrivere nel registro solo avvio, arresto ed errore fatale e lasciare tutto il resto al file di log. Vedere creare e gestire servizi Windows e quando un’attività dell’Utilità di pianificazione non parte o termina con 0x1. In entrambi i casi, il registro eventi è spesso il primo posto che gli operatori guardano e la presenza dei punti essenziali determina la velocità della prima indagine.
4. Che cos’è ETW? — una base di traccia che attraversa l’intero sistema operativo
Event Tracing for Windows, ETW, è un meccanismo che consente di strumentare su una base condivisa tutto, dal kernel alle app in user mode. La sua forza maggiore è poter registrare e analizzare eventi kernel, come I/O disco e creazione di processi, insieme agli eventi personalizzati dell’applicazione sulla stessa linea temporale.8
In .NET definite un vostro provider ETW creando una classe derivata da System.Diagnostics.Tracing.EventSource. ETW usa publish-subscribe e gli eventi non vengono registrati senza sottoscrittore. Implementare EventSource da solo non fa nulla: gli eventi vengono raccolti solo dopo l’abilitazione esplicita con uno strumento di raccolta.2
using System.Diagnostics.Tracing;
[EventSource(Name = "KomuraSoft-OrderService")]
internal sealed class OrderServiceEventSource : EventSource
{
public static readonly OrderServiceEventSource Log = new();
[Event(1, Level = EventLevel.Informational, Message = "Avviata l'elaborazione dell'ordine. OrderId={0}")]
public void OrderProcessingStart(string orderId)
{
if (IsEnabled())
{
WriteEvent(1, orderId);
}
}
[Event(2, Level = EventLevel.Informational, Message = "Completata l'elaborazione dell'ordine. OrderId={0}")]
public void OrderProcessingStop(string orderId)
{
if (IsEnabled())
{
WriteEvent(2, orderId);
}
}
}
Il chiamante lo usa così. Verificare IsEnabled() prima di scrivere evita overhead inutile quando nessuno sta raccogliendo.
OrderServiceEventSource.Log.OrderProcessingStart(order.Id);
try
{
ProcessOrder(order);
}
finally
{
OrderServiceEventSource.Log.OrderProcessingStop(order.Id);
}
Il modo più semplice per raccogliere questi eventi è dotnet-trace.9
dotnet-trace collect --providers KomuraSoft-OrderService -- OrderService.exe
Aprite il file .nettrace risultante in Visual Studio o PerfView. Per analisi prestazionali più serie, comprese quelle con eventi kernel, la configurazione passa a Windows Performance Recorder, WPR, incluso nel Windows Assessment and Deployment Kit, ADK, e alla visualizzazione in Windows Performance Analyzer, WPA.10 Qui ci fermiamo a che cosa ETW possa fare e quando usarlo: per sviluppo e manutenzione di un’app aziendale è sufficiente saper definire un provider EventSource e raccoglierlo con dotnet-trace.
5. La pratica del logging strutturato
I template di messaggio di ILogger sono stringhe fisse con segnaposto nominati come {PlaceHolder}. Non è solo stile: passare gli argomenti separatamente lasciando invariato il template consente al framework di conservare l’associazione fra nomi e valori, i dati strutturati.11
// Consigliato: mantenere fisso il modello e passare gli argomenti separatamente
logger.LogWarning("Impossibile riservare l'inventario per l'ordine {OrderId}. Magazzino={WarehouseId}", orderId, warehouseId);
// Sconsigliato: la concatenazione o l'interpolazione rompono la corrispondenza tra modello e valori
logger.LogWarning("Impossibile riservare l'inventario per l'ordine " + orderId + ". Magazzino=" + warehouseId);
logger.LogWarning($"Impossibile riservare l'inventario per l'ordine {orderId}. Magazzino={warehouseId}");
La regola dell’analizzatore CA2254 rileva il modello sconsigliato, in cui il template cambia a ogni chiamata.3 Nei percorsi caldi potete usare la source generation con LoggerMessageAttribute per evitare boxing e parsing del template.12
using Microsoft.Extensions.Logging;
internal static partial class Log
{
[LoggerMessage(
EventId = 2001,
Level = LogLevel.Warning,
Message = "Impossibile riservare l'inventario per l'ordine {OrderId}. Magazzino={WarehouseId}")]
public static partial void StockReservationFailed(
this ILogger logger, string orderId, string warehouseId);
}
// Codice chiamante
logger.StockReservationFailed(orderId, warehouseId);
Con questa impostazione una singola chiamata può essere inviata a destinazioni diverse: dettaglio al file log, tramite sink Serilog/NLog; versione ristretta al registro eventi; tracing a basso costo a ETW tramite EventSourceLoggerProvider. Il modello è registrare più ILoggerProvider e variare il livello con Filter. Per requisiti minimi di un logger interno, vedere Requisiti minimi per un logger personalizzato e checklist di test d’integrazione; per legare log e dump durante un crash, Progettare app Windows per conservare log e dump in caso di crash.
6. Raccolta e indagine — leggere i log scritti
In Visualizzatore eventi, usate «Filtro» o «Visualizzazioni personalizzate» dall’elenco del log per estrarre solo sorgente, livello o ID evento. Salvare le condizioni ricorrenti come visualizzazione personalizzata accelera le indagini. Le visualizzazioni usano XPath; per esempio:13
<QueryList>
<Query Id="0" Path="Application">
<Select Path="Application">
*[System[Provider[@Name='KomuraSoft.OrderService'] and (Level=2 or Level=3)]]
</Select>
</Query>
</QueryList>
Da riga di comando, wevtutil esporta log e modifica impostazioni. Durante un guasto potete esportare l’intervallo interessante e inviarlo al supporto.14
:: Esportare l'intero registro Application in un file evtx
wevtutil epl Application C:\logs\application_20260707.evtx
:: Mostrare solo gli eventi di una fonte specifica (i 10 più recenti)
wevtutil qe Application /q:"*[System[Provider[@Name='KomuraSoft.OrderService']]]" /c:10 /rd:true /f:text
Per un crash, confrontate per timestamp registro eventi, file di log e dump. Partendo dall’istante dell’errore fatale nel registro, confrontate dettagli del file log e dump acquisito con WER/ProcDump. Vedere Introduzione alla raccolta di crash dump di Windows — WER/ProcDump/WinDbg e Leggere un crash dump con WinDbg + SOS.
7. Insidie
- Scrivere con una sorgente non registrata e fallire. Una chiamata equivalente a
RegisterEventSourcecon nome non registrato può scrivere l’evento in Application, ma senza DLL di risorse messaggio Visualizzatore eventi non mostra la descrizione e presenta un errore.15 Un design che si autoregistra conCreateEventSourceal primo avvio di un processo non amministratore tende inoltre a lanciare eccezione. Completate sempre la registrazione nell’installer. - L’equivoco «si può scrivere con un nome di sorgente diverso». Se c’è il permesso di scrittura, il registro permette di scrivere con un nome che l’app non ha registrato. I nomi devono essere unici sul computer, ma il sistema non impone il controllo: è disciplina dell’applicazione.5 Nomi troppo generici, senza azienda/prodotto, causano collisioni o riuso accidentale.
- Crescita dei log e politica di conservazione. Il massimo predefinito è 512 KB.4 Per un uso abituale, espandete con
wevtutil slo nell’installer e decidete se alla saturazione sovrascrivere i più vecchi o scartare i nuovi.OverwriteOlderè deprecato e può comportarsi in pratica come «non sovrascrivere».16 - Visualizzazione dei messaggi in ambienti multilingua. Se configurate file di risorse localizzate (
MessageResourceFile), visualizzare il log in un ambiente dove manca la DLL o ne esiste una versione diversa mostra «The description for Event ID XX cannot be found». Accade in caso di forwarding a un altro server o dopo la disinstallazione. Scrivere stringhe direttamente conWriteEntry, senza resource file, evita questa classe di problema. - Mancata scrittura per privilegi insufficienti. È frequente confondere la registrazione, che richiede amministratore, con la scrittura su sorgente già registrata, che funziona con utente standard. Prima di eseguire tutta l’app elevata, isolate quale operazione richiede davvero il privilegio.
Articoli correlati
- Quando un’app Windows richiede privilegi di amministratore — UAC, aree protette e criteri di progettazione
- Creare e gestire servizi Windows — dalla scelta rispetto a Utilità di pianificazione alla trasformazione di BackgroundService in servizio
- Quando un’attività dell’Utilità di pianificazione non parte o termina con 0x1 — diagnosi delle cause e progettazione operativa sicura
- Requisiti minimi per un logger personalizzato e checklist di test d’integrazione
- Progettare app Windows per conservare log e dump in caso di crash
- Introduzione alla raccolta di crash dump di Windows — WER/ProcDump/WinDbg
- Leggere un crash dump con WinDbg + SOS — guida pratica all’analisi dopo la raccolta
Ambiti di consulenza correlati
Komura Soft LLC offre consulenza sulla progettazione di basi di log, registro eventi ed ETW per applicazioni aziendali Windows, compresa la progettazione di punti di osservabilità in previsione delle indagini sui guasti.
- Sviluppo di app Windows
- Indagine sui difetti e analisi delle cause
- Consulenza tecnica e revisione della progettazione
- Contatti
Riferimenti
-
Microsoft Learn, EventLog.CreateEventSource Method. Spiega perché dalla versione Windows Vista la creazione di una sorgente eventi richiede privilegi di amministratore: deve cercare in tutti i log, compreso Security. ↩ ↩2
-
Microsoft Learn, Getting Started with EventSource. Spiega che EventSource usa il modello publish-subscribe, non registra eventi senza un sottoscrittore ETW o EventPipe e può essere raccolto con
dotnet-trace collect. ↩ ↩2 -
Microsoft Learn, CA2254: Template should be a static expression. Spiega che concatenazione e interpolazione nel template del messaggio fanno perdere l’associazione fra nomi dei segnaposto e valori. ↩ ↩2
-
Microsoft Learn, EventLog.MaximumKilobytes Property. Indica che la dimensione massima predefinita di un registro eventi è 512 KB. ↩ ↩2
-
Microsoft Learn, EventLog Class. Descrive i tre log predefiniti Application/System/Security, l’obbligo che una sorgente sia univoca su un computer e il fatto che, con il permesso di scrittura, è possibile scrivere usando qualunque nome di sorgente già registrato. ↩ ↩2
-
Microsoft Learn, Logging providers in .NET. Documenta che i provider predefiniti del Generic Host includono Console, Debug, EventSource ed EventLog, quest’ultimo solo in Windows. ↩
-
Microsoft Learn, EventLogSettings Class. Indica i valori predefiniti di
AddEventLog:LogNameèApplicationeSourceNameè.NET Runtime. ↩ -
Microsoft Learn, Event Tracing. Descrive Event Tracing for Windows, ETW, come meccanismo per avviare, arrestare, strumentare e consumare eventi di tracing delle applicazioni. ↩
-
Microsoft Learn, dotnet-trace performance analysis utility. Panoramica di
dotnet-trace, strumento multipiattaforma per raccogliere tracce basate su EventPipe, e del comandocollect. ↩ -
Microsoft Learn, Introduction to WPR. Spiega che Windows Performance Recorder, WPR, estende ETW e produce registrazioni dettagliate di sistema e applicazioni. ↩
-
Microsoft Learn, Logging in C# and .NET. Documenta la sintassi
{PlaceHolder}dei template e il modo in cui il nome nel template diventa la proprietà del log. ↩ -
Microsoft Learn, High-performance logging in .NET. Spiega che il logging generato con
LoggerMessageAttributeevita i costi di boxing e parsing del template. ↩ -
Microsoft Learn, Comparison of ETW and EventLog logger functionality. Mostra come creare in Visualizzatore eventi visualizzazioni personalizzate filtrate, per esempio per nome dell’evento, usando query XPath. ↩
-
Microsoft Learn, wevtutil. Riferimento alle operazioni da riga di comando sul registro eventi, fra cui esportazione (
epl), query (qe) e modifica delle impostazioni (sl). ↩ -
Microsoft Learn, Event Sources. Spiega che la scrittura con un nome di sorgente non registrato ricade nel log Application, ma Visualizzatore eventi non può mostrare la descrizione senza un file messaggi e segnala un errore. ↩
-
Microsoft Learn, OverflowAction Enum. Descrive sovrascrittura e scarto quando un registro eventi raggiunge il limite, e la deprecazione di
OverwriteOlder. ↩
Articoli correlati
Articoli recenti con gli stessi tag per approfondire argomenti vicini.
Individuare con PerfView e dotnet-trace la causa di un rallentamento — introduzione pratica all'analisi delle prestazioni .NET
Quando un'app aziendale è lenta, satura la CPU o si blocca, quale strumento usare e cosa osservare? Questa guida spiega la divisione dei ...
Oltre appsettings.json — Guida pratica alla gestione della configurazione nelle applicazioni aziendali Windows (impostazioni per ambiente, segreti e percorsi di scrittura)
Uno sguardo pratico alla gestione della configurazione nelle applicazioni aziendali Windows: stratificazione di appsettings.json, scelta ...
Stampa e output PDF nelle applicazioni aziendali Windows — come scegliere tra System.Drawing.Printing, WPF e librerie di report
Organizza in una tabella decisionale la stampa WinForms con PrintDocument, la stampa WPF con FlowDocument/FixedDocument e le alternative ...
Google Ads BtoB con un budget ridotto — come progettare e gestire una routine settimanale efficace con poche decine di migliaia di yen al mese
Guida pratica a Google Ads per aziende BtoB che vogliono iniziare con poche decine di migliaia di yen al mese. Illustra il funzionamento ...
Far comparire il sito nelle ricerche con il nome della zona — guida pratica alla SEO locale per PMI (pagine per area e Google Business Profile)
Per le PMI il cui sito non compare nelle ricerche «nome della zona + settore». L'articolo illustra l'ordine con cui migliorare la SEO loc...
Argomenti correlati
Queste pagine collocano l’argomento in un contesto più ampio di servizi e decisioni.
Argomenti tecnici Windows
Portale su sviluppo Windows, analisi dei problemi e valorizzazione delle risorse esistenti.
Analisi dei bug e guasti di lunga durata
Errori intermittenti, diagnosi delle comunicazioni, crash prolungati e test dei percorsi di errore.
Servizi collegati all’argomento
L’articolo è direttamente collegato ai servizi seguenti.
Sviluppo di applicazioni Windows
Progettare la base di logging, registro eventi ed ETW rientra nella consulenza per lo sviluppo di app Windows.
Analisi dei bug e delle cause
Una progettazione dei log attenta all'indagine dei guasti è direttamente collegata alla consulenza su indagine dei bug e analisi della causa principale.
Domande frequenti
Domande che ricorrono nelle consulenze sull’argomento dell’articolo.
- Se ho già file di log, mi serve ancora il registro eventi?
- Per l'indagine dettagliata, i file di log spesso bastano. Se però volete che il personale operativo rilevi problemi dell'app tramite Visualizzatore eventi o strumenti di monitoraggio standard, come notifiche di errori dell'Utilità di pianificazione o SCOM, è pratico inviare al registro eventi solo i punti essenziali. Non sono sostituti: sono registrazioni su livelli diversi e per lettori diversi.
- Come devo decidere le regole di numerazione degli ID evento?
- Non c'è una risposta unica, ma tre regole pratiche riducono gli errori: dividere gli intervalli per area funzionale, per esempio 1000 per avvio e 2000 per comunicazione; non cambiare mai il significato né riutilizzare un ID emesso; lasciare lacune nella numerazione. L'EventId di ILogger è anche una chiave di ricerca nei log strutturati, quindi una numerazione facile da documentare facilita la manutenzione.
- Uso Serilog o NLog: come si collega questo articolo?
- Serilog e NLog sono implementazioni sotto ILogger che indirizzano le stesse voci a più sink, file, registro eventi, ETW o SaaS esterno. I principi qui descritti, mantenere essenziale il registro eventi e non rompere il template del messaggio, valgono sia usando ILogger direttamente sia passando da Serilog/NLog. Usare un sink specifico per il registro eventi o AddEventLog standard è una scelta di implementazione.
- Quanto ETW devo imparare?
- Per sviluppare e mantenere un'app aziendale basta saper definire un provider con EventSource e raccoglierne gli eventi con dotnet-trace. Analisi dello stack in PerfView e raccolta eventi kernel con WPR sono approfondimenti da affrontare specializzandosi nell'analisi delle prestazioni: questo articolo li lascia deliberatamente fuori ambito.
Profilo dell’autore
Pagina di presentazione dell’autore dell’articolo.
Go Komura
Rappresentante di KomuraSoft LLC
Specializzato nello sviluppo di software Windows, nella consulenza tecnica e nell’analisi dei malfunzionamenti, soprattutto nei progetti con sistemi esistenti e guasti difficili da riprodurre.
Link pubblici