Introducción al registro de eventos de Windows y ETW — llevar los registros de aplicaciones de negocio al mecanismo estándar del sistema operativo
· Actualizado el: · Go Komura · CSharp, .NET, Registro de eventos, ETW, EventSource, Diseño de registros, Investigación de fallos, Desarrollo de Windows
Historial de revisiones (1 actualizaciones, última el 22 Aug 2026)
Registro de los cambios realizados en este artículo. Cuando se archivó una versión previa, sigue siendo legible mediante un enlace permanente con DOI.
- Se ha sustituido la traducción, que estaba abreviada, por una traducción completa del artículo japonés en su versión actual: el texto crece un 81 %. Se han incorporado 2 apartados, 15 filas de tabla, 2 notas al pie, 2 bloques de código y 1 diagrama que no estaban en la edición anterior. El contenido no cambia respecto al original japonés; esta edición simplemente ya no lo resume. Además, los enlaces a otros artículos que ya tienen edición en español apuntan ahora a esa edición en lugar de a la japonesa. Leer la versión anterior a esta actualización (DOI: 10.5281/zenodo.21638301)
- Primera publicación
Citar este artículo(DOI: 10.5281/zenodo.21638300)
Este artículo está archivado en Zenodo. A continuación se muestran tanto el DOI que siempre resuelve a la última versión como el DOI fijado a la versión que está leyendo.
Go Komura (2026). Introducción al registro de eventos de Windows y ETW — llevar los registros de aplicaciones de negocio al mecanismo estándar del sistema operativo. KomuraSoft LLC. https://doi.org/10.5281/zenodo.21638300 https://comcomponent.com/es/blog/windows-eventlog-etw-structured-logging/
- DOI (última versión)
- 10.5281/zenodo.21638300
- DOI (esta versión)
- 10.5281/zenodo.22053447
Cuando se desarrollan aplicaciones de negocio o servicios de Windows en C#, lo habitual es emitir el registro diario con un logger de archivo propio o con una biblioteca como Serilog o NLog. Entonces, ¿significa esto que el registro de eventos de Windows y ETW (Event Tracing for Windows) ya no son necesarios? No es así. Estos dos mecanismos no son «un sustituto del registro en archivo»: son una capa de registro distinta, visible para el personal de operaciones y las herramientas estándar del sistema operativo.
En este artículo repasamos cuándo usar cada uno de los registros en archivo, de eventos y ETW, cómo implementarlos desde .NET, los puntos mínimos imprescindibles de ETW, la práctica de recogida e investigación, y las trampas habituales en el terreno.
Versión de referencia: el código de ejemplo de este artículo está escrito para .NET 8 (Windows). Las dos diferencias principales respecto a .NET Framework 4.8 son las siguientes. La primera es que System.Diagnostics.EventLog forma parte de la BCL en .NET Framework, mientras que en .NET (la serie Core) hay que hacer referencia explícita al paquete NuGet del mismo nombre. La segunda es el destino de EventSource: en .NET Framework el único destino es ETW, pero en .NET (la serie Core) los eventos también fluyen a EventPipe (el mecanismo de trazas integrado en el runtime), lo que permite recogerlos con herramientas como dotnet-trace sin necesidad de privilegios de administrador. 12
1. Conclusión principal
- Los tres mecanismos no son sustitutos entre sí, sino un reparto de funciones. El registro en archivo es el que permite a los desarrolladores rastrear los detalles después de los hechos; el registro de eventos es el que permite al personal de operaciones y al Visor de eventos o herramientas de supervisión estándar del sistema operativo detectar anomalías; ETW es una traza de alta frecuencia que se activa bajo demanda para el análisis de rendimiento o de incidencias difíciles de reproducir. Lo habitual es usarlos combinados, variando la cantidad de información que se escribe en cada uno.
- En el registro de eventos solo se escriben el «inicio, la parada y los errores fatales». Si se envía también todo el registro detallado al registro de eventos, las anomalías que el personal de operaciones realmente necesita ver quedan sepultadas. El registro en archivo sigue siendo tan detallado como siempre; el registro de eventos se acota.
- Registrar la fuente de eventos exige privilegios de administrador. Desde Windows Vista,
EventLog.CreateEventSourceno se puede invocar sin privilegios de administrador. Evite el diseño que intenta registrarla en el primer acceso en tiempo de ejecución; regístrela de antemano en el instalador. 3 - ETW no es «recogida permanente». Aunque defina eventos con
EventSource, si no hay suscriptores (dotnet-trace, PerfView, herramientas basadas en ETW) no se registra nada. El uso básico consiste en indicar el proveedor correspondiente y recoger datos solo durante un análisis de rendimiento o la investigación de una incidencia concreta. 4 - Los mensajes se escriben en forma de plantilla, no mediante concatenación o interpolación de cadenas. Si escribe
logger.LogInformation("Order {OrderId} failed", orderId), podrá buscarOrderIdpor su nombre de marcador de posición como registro estructurado. Si lo construye con concatenación o interpolación, pierde esta información estructural. 5 - El crecimiento del registro suele deberse a lo pequeño que es el valor predeterminado. El tamaño máximo predeterminado del registro de eventos es de solo 512 KB. Si una aplicación de negocio usa el registro de eventos a diario, hay que ampliarlo explícitamente y decidir en el diseño el comportamiento al alcanzar el límite (sobrescribir o descartar). 6
A continuación, una tabla de decisión.
| Aspecto | Registro en archivo | Registro de eventos | ETW |
|---|---|---|---|
| Lector principal | Desarrolladores y personal de mantenimiento | Personal de operaciones, herramientas de supervisión, Visor de eventos estándar del SO | Personal de análisis de rendimiento, ingenieros de soporte |
| Volumen de salida orientativo | Detallado (puede incluir Trace/Debug) | Escaso (solo inicio, parada y errores fatales) | Grande solo cuando está activado; por defecto no se registra nada |
| Vida útil y retención | Fácil de conservar a largo plazo según la configuración de rotación | Al alcanzar el límite de tamaño, se sobrescriben o descartan los más antiguos | Por sesión. Al terminar la recogida se guarda como archivo .etl/.nettrace |
| Integración con herramientas estándar del SO | Ninguna (requiere un visor propio) | Se ve de forma estándar con el Visor de eventos, wevtutil o Get-WinEvent |
Se ve con dotnet-trace, PerfView, WPR/WPA |
| Permisos | Solo el permiso de escritura del usuario que ejecuta la aplicación | Registrar la fuente requiere privilegios de administrador (la escritura en sí es posible con un usuario estándar si la fuente ya está registrada) | Iniciar la recogida suele requerir privilegios de administrador |
2. Fundamentos del registro de eventos de Windows
Windows dispone por defecto de tres registros: Application, System y Security; Security es de solo lectura. Las aplicaciones de negocio y los servicios escriben en el registro Application o en un registro personalizado propio de la aplicación (canal). Los controladores de dispositivo, por convención, escriben en el registro System. 7
La unidad de escritura es la «fuente de eventos» (event source). La fuente es un nombre que identifica a la aplicación y se registra de antemano con EventLog.CreateEventSource. Desde Windows Vista, registrar la fuente requiere privilegios de administrador. Esto se debe a que, para comprobar que el nombre de la fuente es único, hay que buscar en todos los registros de eventos, incluido Security, y un usuario estándar no tiene acceso al registro Security. 3
using System.Diagnostics;
// Ejecutar dentro del instalador o del proceso de configuración, mientras se dispone de privilegios de administrador
const string SourceName = "KomuraSoft.OrderService";
const string LogName = "Application";
if (!EventLog.SourceExists(SourceName))
{
EventLog.CreateEventSource(SourceName, LogName);
}
Si se intenta crear la fuente en el primer acceso en tiempo de ejecución, esta llamada falla en cualquier entorno donde la aplicación se ejecute con un usuario estándar. La cuestión general de cuándo se necesitan privilegios de administrador está tratada en «Cuándo se necesitan privilegios de administrador en Windows», y el registro de la fuente de eventos es exactamente este patrón: el diseño seguro consiste en registrarla en el instalador y hacer que la aplicación solo escriba en una fuente ya registrada.
Cada evento lleva dos datos de identificación: «nivel» e «ID de evento». El nivel es EventLogEntryType (Information, Warning, Error, SuccessAudit, FailureAudit) y se usa para los iconos del Visor de eventos y los filtros predeterminados. El ID de evento es un entero definido por la aplicación que sirve de clave para buscar y agregar más tarde eventos del mismo tipo.
3. Escribir en el registro de eventos desde .NET
Hay, a grandes rasgos, dos vías para escribir en el registro de eventos desde .NET. Antes de nada, comparamos sus requisitos previos.
| Aspecto | 3.1 Usar System.Diagnostics.EventLog directamente |
3.2 ILogger + AddEventLog |
|---|---|---|
| ¿Requiere registrar la fuente de eventos? | Sí. El nombre de fuente que se pasa a WriteEntry debe estar ya registrado con CreateEventSource en el instalador 3 |
Sí. El nombre indicado en SourceName debe registrarse igualmente en el instalador. Si se omite, toma el nombre genérico .NET Runtime 8 |
| Privilegios necesarios para el registro | Privilegios de administrador (solo al registrar; la escritura en una fuente ya registrada es posible con un usuario estándar) | Igual que a la izquierda |
| Referencia adicional necesaria | En .NET (serie Core), el paquete System.Diagnostics.EventLog |
El paquete Microsoft.Extensions.Logging.EventLog (habilitado por defecto en Windows con Generic Host) 9 |
| Datos que se pueden especificar | Nivel e ID de evento, además de un control detallado de categoría y datos binarios adjuntos | Nivel, ID de evento y plantilla de mensaje. No admite categoría ni datos binarios adjuntos |
| Acotar el volumen de salida | Se decide manualmente en cada punto de llamada | settings.Filter permite elevar el nivel solo para el registro de eventos |
| Escenario recomendado | Servicios pequeños sin infraestructura de registro propia, migraciones desde un diseño Win32 existente | Aplicaciones que ya usan ILogger para el registro estructurado |
En ambas vías, se presupone que el nombre de fuente indicado ya está registrado de antemano. Si se escribe con un nombre de fuente no registrado, el evento sí se guarda en el registro Application, pero como no existe el recurso de mensaje correspondiente, el Visor de eventos no puede mostrar el texto descriptivo. 10
3.1 Usar System.Diagnostics.EventLog directamente
Es una API de bajo nivel, adecuada cuando se necesita un control detallado (categoría, datos binarios adjuntos, etc.). En .NET (fuera de .NET Framework) hay que hacer referencia al paquete NuGet System.Diagnostics.EventLog.
using System.Diagnostics;
public sealed class OrderServiceEventLog
{
private const string SourceName = "KomuraSoft.OrderService";
public void WriteServiceStarted()
{
EventLog.WriteEntry(SourceName, "Se ha iniciado OrderService.",
EventLogEntryType.Information, eventID: 1000);
}
public void WriteFatalError(Exception ex)
{
EventLog.WriteEntry(SourceName,
$"Se ha producido un error fatal y no se puede continuar el procesamiento. Consulte el registro en archivo para más detalles. {ex.GetType().Name}: {ex.Message}",
EventLogEntryType.Error, eventID: 1999);
}
}
3.2 Usar ILogger + AddEventLog
Si ya tiene el registro estructurado montado con ILogger, usar AddEventLog del paquete Microsoft.Extensions.Logging.EventLog se integra de forma más natural en el pipeline de registro existente. En los Worker Service basados en ASP.NET Core o Generic Host, el proveedor EventLog está habilitado por defecto cuando se ejecutan en Windows. 9
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";
// Además del filtro de categoría predeterminado, al registro de eventos
// solo se envía Warning o superior (los detalles quedan en el registro en archivo)
settings.Filter = (_, level) => level >= LogLevel.Warning;
});
using IHost host = builder.Build();
await host.RunAsync();
Si se omite EventLogSettings, LogName toma por defecto "Application" y SourceName toma por defecto ".NET Runtime". 8 Si se deja el nombre de fuente genérico .NET Runtime, resulta difícil distinguir en el Visor de eventos si un registro pertenece a su aplicación o a otra aplicación .NET, así que especifique siempre SourceName de forma explícita para su propia aplicación.
En los servicios de Windows o en los procesos por lotes que se ejecutan desde el Programador de tareas, el equilibrio práctico consiste en escribir en el registro de eventos solo «inicio», «parada» y «errores fatales», dejando el resto de los detalles al registro en archivo. Cómo construir y operar un servicio se trata en «Cómo crear y operar un servicio de Windows», y los problemas de ejecución a través del Programador de tareas en «La tarea del Programador de tareas no se ejecuta o termina con 0x1». En ambos casos, lo primero que suele consultar el personal de operaciones ante una anomalía es el registro de eventos, y que los puntos esenciales queden ahí determina la velocidad de la investigación inicial.
3.3 Verificar que se ha escrito correctamente
Una vez escrito el código, conviene comprobar al menos una vez que el resultado se ve realmente en el Visor de eventos. Los pasos son los siguientes.
- Ejecute
eventvwr.mscdesdeWin + Rpara abrir el Visor de eventos. - En el panel izquierdo, abra Visor de eventos (local) > Registros de Windows > Application (en español puede aparecer como «Aplicación»). Si ha creado un registro personalizado, el nombre de su registro aparecerá bajo Registros de aplicaciones y servicios.
- Si hay demasiados eventos y se pierden entre los demás, abra Filtrar el registro actual en el panel derecho e introduzca su nombre de fuente en «Origen del evento» y el ID que desea comprobar en «Todos los ID de evento» para acotar la búsqueda.
La correspondencia entre los valores indicados en el código y los campos donde aparecen en el Visor de eventos es la siguiente. Tenerla presente ayuda a saber dónde mirar cuando «lo que debería haberse escrito no aparece».
| Valor indicado en el código | Dónde aparece en el Visor de eventos |
|---|---|
Primer argumento de WriteEntry / settings.SourceName |
Columna «Origen» |
Argumento eventID / EventId de ILogger |
Columna «Id. de evento» |
EventLogEntryType (Information, Warning, Error) / LogLevel |
Columna «Nivel» (Información, Advertencia, Error) |
Cadena pasada a WriteEntry / mensaje ya expandido de la plantilla |
Descripción en la pestaña «General», en la parte inferior de la lista |
LogName (por defecto Application) |
Bajo qué registro aparece |
Si prefiere comprobarlo desde la línea de comandos, Get-WinEvent de PowerShell resulta cómodo. Si pasa el nombre del registro y el nombre del proveedor (= nombre de fuente) a -FilterHashtable, puede obtener solo los eventos escritos por esa fuente. 11
# Mostrar los últimos 10 eventos escritos por la fuente propia, limitados a fecha/hora, ID, nivel y cuerpo del mensaje
Get-WinEvent -FilterHashtable @{ LogName = 'Application'; ProviderName = 'KomuraSoft.OrderService' } -MaxEvents 10 |
Select-Object TimeCreated, Id, LevelDisplayName, Message
Si esto no devuelve ningún resultado, la causa suele ser alguna de estas tres: «el nombre de la fuente está mal escrito», «la fuente no está registrada» o «la escritura ha fallado y la excepción se ha silenciado». Puede comprobar si la fuente está registrada con [System.Diagnostics.EventLog]::SourceExists('KomuraSoft.OrderService').
4. Qué es ETW — la infraestructura de trazas que atraviesa todo el sistema operativo
Event Tracing for Windows (ETW) es un mecanismo de trazas que permite instrumentar, con una infraestructura común, desde el kernel hasta las aplicaciones en modo usuario. Su característica más destacada es que permite registrar y analizar juntos, en la misma línea de tiempo, los eventos del kernel (E/S de disco, creación de procesos, etc.) y los eventos propios de la aplicación. 12
En .NET se puede definir un proveedor ETW propio creando una clase que herede de System.Diagnostics.Tracing.EventSource. 1 ETW funciona con un modelo de publicación-suscripción, y si no hay suscriptores no se registra ningún evento. Es decir, con solo implementar EventSource no ocurre nada; los eventos solo se registran cuando una herramienta de recogida lo habilita explícitamente. 4
La diferencia que se planteaba en la tabla de decisión del capítulo 1 —«registro de eventos = permanente, orientado a operaciones» frente a «ETW = bajo demanda, orientado a la investigación»— proviene precisamente de esta presencia o ausencia de suscriptores. Representado en un diagrama, queda así.
flowchart LR
accTitle: Diferencia entre el registro de eventos y ETW
accDescr: Diagrama que muestra que la aplicación de negocio escribe solo inicio, parada y errores fatales en el registro de eventos, que queda grabado de forma permanente y visible en el Visor de eventos, wevtutil o Get-WinEvent, y que por separado EventSource instrumenta un proveedor cuyos eventos no se registran si no hay suscriptores, o se recogen en una sesión mediante dotnet-trace, PerfView o WPA cuando se inicia la recogida
APP["Aplicación de negocio"]
APP -->|"Solo inicio, parada y errores fatales"| EL["Registro de eventos<br/>Se graba siempre; el SO lo conserva de forma permanente"]
EL --> EV["Visor de eventos<br/>wevtutil / Get-WinEvent<br/>El personal de operaciones puede verlo en cualquier momento"]
APP -->|"Instrumentado con EventSource"| SRC["Proveedor<br/>Define eventos de alta frecuencia"]
SRC -->|"Sin suscriptores"| NONE["No se registra en ningún sitio<br/>El coste es casi nulo"]
SRC -->|"Al iniciar la recogida"| SES["Sesión<br/>Se activa solo durante la investigación"]
SES --> TOOL["Consumidor<br/>dotnet-trace / PerfView / WPA<br/>Analiza un periodo delimitado"]
Figura 1: el registro de eventos se graba siempre de forma permanente; ETW solo registra cuando coinciden proveedor → sesión → consumidor
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 = "Se ha iniciado el procesamiento del pedido. OrderId={0}")]
public void OrderProcessingStart(string orderId)
{
if (IsEnabled())
{
WriteEvent(1, orderId);
}
}
[Event(2, Level = EventLevel.Informational, Message = "Se ha completado el procesamiento del pedido. OrderId={0}")]
public void OrderProcessingStop(string orderId)
{
if (IsEnabled())
{
WriteEvent(2, orderId);
}
}
}
En el lado de la llamada se usa así. Comprobar con IsEnabled() si está habilitado antes de escribir realmente el evento permite evitar costes innecesarios cuando no se está recogiendo.
OrderServiceEventSource.Log.OrderProcessingStart(order.Id);
try
{
ProcessOrder(order);
}
finally
{
OrderServiceEventSource.Log.OrderProcessingStop(order.Id);
}
Para recoger este evento, lo más sencillo es usar la herramienta multiplataforma dotnet-trace. 13
dotnet-trace collect --providers KomuraSoft-OrderService -- OrderService.exe
Aquí conviene tener claro que lo que usa dotnet-trace no es ETW en sí, sino otra vía llamada EventPipe. EventPipe es un mecanismo de trazas integrado en el runtime de .NET que, igual que ETW, puede recoger los eventos de EventSource. Hay tres diferencias. EventPipe funciona de la misma manera en todas las plataformas que soporta .NET, mientras que ETW es exclusivo de Windows. Iniciar la recogida con ETW requiere privilegios de administrador, mientras que EventPipe no los necesita si se ejecuta con el mismo usuario que la aplicación de destino. Y el alcance de EventPipe se limita al código administrado y al runtime: no puede capturar eventos del sistema operativo o del kernel ni pilas de llamadas nativas. 2 Esta tercera limitación es la razón por la que, cuando se quiere llegar hasta el kernel, hace falta ETW (PerfView, WPR/WPA).
El archivo .nettrace recogido se abre y se examina con Visual Studio o PerfView. Para una investigación de rendimiento más completa, por ejemplo un análisis que incluya eventos del kernel, la configuración pasa por usar Windows Performance Recorder (WPR), incluido en el Windows Assessment and Deployment Kit (ADK), y verlo con Windows Performance Analyzer (WPA). 14 No obstante, el alcance de este artículo llega hasta «qué puede hacer ETW y cuándo usarlo», y no entra en los procedimientos detallados de análisis con PerfView o WPA. Desde el punto de vista del desarrollo y mantenimiento de aplicaciones de negocio, basta con saber definir un proveedor propio con EventSource y poder recogerlo con dotnet-trace.
5. La práctica del registro estructurado
La plantilla de mensaje de ILogger se escribe como una cadena fija que contiene marcadores de posición con nombre, del tipo {PlaceHolder}. Esto no es una simple cuestión de estilo: al no cambiar la plantilla y pasar solo los argumentos, la infraestructura de registro puede conservar la correspondencia entre el nombre del marcador y el valor (los datos estructurados). 15
// Recomendado: la plantilla es fija, los argumentos se pasan aparte
logger.LogWarning("No se pudo reservar el stock para el pedido {OrderId}. Almacén={WarehouseId}", orderId, warehouseId);
// No recomendado: la concatenación e interpolación de cadenas rompen la correspondencia entre plantilla y valores
logger.LogWarning("No se pudo reservar el stock para el pedido " + orderId + ". Almacén=" + warehouseId);
logger.LogWarning($"No se pudo reservar el stock para el pedido {orderId}. Almacén={warehouseId}");
La regla CA2254 del analizador de código detecta este patrón no recomendado (una forma de escribir en la que la plantilla cambia en cada llamada). 5 En las rutas críticas de alta frecuencia de llamada, usar además la generación de código fuente mediante LoggerMessageAttribute permite evitar el coste de boxing y de analizar la plantilla. 16
using Microsoft.Extensions.Logging;
internal static partial class Log
{
[LoggerMessage(
EventId = 2001,
Level = LogLevel.Warning,
Message = "No se pudo reservar el stock para el pedido {OrderId}. Almacén={WarehouseId}")]
public static partial void StockReservationFailed(
this ILogger logger, string orderId, string warehouseId);
}
// Lado de la llamada
logger.StockReservationFailed(orderId, warehouseId);
Con esta configuración, desde la misma llamada de registro se puede repartir el contenido: detalles al registro en archivo (sinks como Serilog/NLog), contenido acotado al registro de eventos, y trazas de bajo coste a ETW a través de EventSourceLoggerProvider. La forma básica consiste en registrar varios ILoggerProvider y variar el nivel de salida de cada proveedor con Filter. Los requisitos mínimos de un logger propio se tratan en «Requisitos mínimos de un logger propio y checklist de pruebas de integración», y cómo vincular registros y volcados en caso de bloqueo, en «Diseño para conservar registros y volcados cuando falla una aplicación de Windows».
6. Recogida e investigación — la perspectiva de quien lee los registros
En el Visor de eventos se puede usar «Filtrar» o «Vista personalizada» desde la lista de registros para extraer solo una fuente, un nivel o un ID de evento concretos. Guardar las condiciones que se usan con frecuencia como vista personalizada agiliza las investigaciones posteriores. Las vistas personalizadas se definen mediante una consulta XPath; por ejemplo, una consulta que extrae solo un nombre de evento concreto tiene esta forma. 17
<QueryList>
<Query Id="0" Path="Application">
<Select Path="Application">
*[System[Provider[@Name='KomuraSoft.OrderService'] and (Level=2 or Level=3)]]
</Select>
</Query>
</QueryList>
Este XML se pega en: el panel derecho del Visor de eventos, «Crear vista personalizada» > pestaña «XML» > marque «Editar la consulta manualmente». Al guardarla, aparece bajo «Vistas personalizadas» en el panel izquierdo, y a partir de entonces basta con hacer clic para abrir la lista con solo los errores (Level=2) y advertencias (Level=3) escritos por KomuraSoft.OrderService. El Level del esquema de eventos coincide con la columna «Nivel» del Visor de eventos, así que si quiere incluir también el nivel de información, añada Level=4 a la condición. El filtrado que se crea en el cuadro de diálogo de filtro también puede consultarse como XPath abriendo la pestaña «XML» del mismo cuadro de diálogo, así que el atajo más rápido es acotar primero con la GUI y luego copiar el XML.
Desde la línea de comandos, wevtutil permite exportar registros y cambiar su configuración. También sirve, como parte de una investigación de incidencias, para exportar el registro de eventos alrededor del momento en que ocurrió el problema y enviarlo a soporte. 18
:: Exportar todo el registro Application a un archivo evtx
wevtutil epl Application C:\logs\application_20260707.evtx
:: Mostrar solo los eventos de una fuente concreta (los últimos 10)
wevtutil qe Application /q:"*[System[Provider[@Name='KomuraSoft.OrderService']]]" /c:10 /rd:true /f:text
Lo que se pasa a /q: es el mismo contenido del elemento Select de XPath que se usó en la vista personalizada anterior. /f: indica el formato de salida: elija text si lo va a revisar una persona, o xml si lo va a procesar un script de forma automática. Con xml se obtiene el mismo esquema que el XML de la vista personalizada, por lo que se pueden extraer Provider o EventID por nombre de elemento. El archivo .evtx exportado se puede abrir tal cual en otro equipo desde «Abrir el registro guardado» del Visor de eventos.
En la investigación de bloqueos, lo básico es cotejar por hora los tres elementos: registro de eventos, registro en archivo y volcado de bloqueo. Tomando como referencia la marca de tiempo del «error fatal» que quedó en el registro de eventos, se contrasta con el detalle del registro en archivo del mismo momento y con el volcado obtenido mediante WER/ProcDump. Cómo obtener el volcado se explica en «Introducción a la recogida de volcados de bloqueo en Windows - WER/ProcDump/WinDbg», y el procedimiento real de análisis del volcado obtenido, en «Leer un volcado de bloqueo con WinDbg + SOS».
7. Trampas habituales
- Intentar escribir sin haber registrado la fuente, y fallar. Si se realiza una llamada equivalente a
RegisterEventSourcecon un nombre de fuente no registrado, el evento en sí se escribe en el registro Application, pero como no existe la DLL de recursos de mensaje correspondiente, el Visor de eventos no puede mostrar el texto descriptivo y aparece como error. 10 Además, en un diseño que intenta autorregistrarse en tiempo de ejecución conCreateEventSource, es habitual el incidente de que el proceso falle con una excepción en el primer arranque cuando se ejecuta con un usuario no administrador. Asegúrese siempre de completar el registro de la fuente en el instalador. - La confusión de que «se puede escribir con otro nombre de fuente». Basta con tener permiso de escritura para que el registro de eventos permita escribir incluso con un nombre de fuente que la aplicación no recuerda haber registrado. El nombre de fuente debe ser único en el equipo, pero no hay ningún mecanismo del sistema operativo que lo garantice: queda a la disciplina del lado de la aplicación. 7 Elegir un nombre de fuente demasiado genérico (un nombre corto que no incluya el nombre de la empresa o del producto) puede provocar colisiones con aplicaciones de otros proveedores, o el uso involuntario del nombre de fuente de otra aplicación.
- Crecimiento del registro y política de retención. El tamaño máximo predeterminado del registro de eventos es de tan solo 512 KB. 6 Si una aplicación de negocio usa el registro de eventos a diario, amplíe el tamaño explícitamente con
wevtutil slo desde el instalador, y configure de forma consciente si, al alcanzar el límite, se debe «sobrescribir lo más antiguo» o «descartar lo nuevo». Tenga en cuenta también queOverwriteOlderestá en desuso, y que aunque se especifique puede acabar comportándose en la práctica como «no sobrescribir». 19 - Visualización de mensajes en entornos multilingües. Si se configura el uso de un archivo de recursos de mensaje localizado (
MessageResourceFile), al ver el registro en un entorno donde esa DLL de recursos no existe o tiene una versión distinta, aparece «No se puede encontrar la descripción del ID de evento tal». Este problema es frecuente cuando se ve en otro servidor un registro de eventos reenviado, o cuando solo quedan los registros después de desinstalar la aplicación. Con una configuración que escribe la cadena directamente medianteWriteEntry(sin usar archivo de recursos), se evita por completo este tipo de problema. - Casos en los que no se puede escribir por falta de privilegios. Es un malentendido frecuente: registrar la fuente requiere privilegios de administrador, pero escribir en una fuente ya registrada se puede hacer con un usuario estándar. Antes de dar por hecho que «no funciona sin privilegios de administrador» y ejecutar toda la aplicación como administrador, aísle qué operación concreta necesita realmente esos privilegios.
8. Resumen
El esqueleto de este artículo se resume en tres puntos.
- Los tres mecanismos son un reparto de funciones. El registro en archivo sirve para que los desarrolladores rastreen los detalles; el registro de eventos, para que el personal de operaciones y las herramientas estándar del SO detecten anomalías; ETW/EventPipe, para investigar el rendimiento o incidencias difíciles de reproducir. La forma básica consiste en escribir en el registro de eventos solo el inicio, la parada y los errores fatales, y dejar el detalle al registro en archivo (capítulo 1).
- Registrar la fuente de eventos es tarea del instalador. El registro requiere privilegios de administrador, pero la escritura en una fuente ya registrada se puede hacer con un usuario estándar. Un diseño que intenta autorregistrarse en tiempo de ejecución con
CreateEventSourceprovoca fallos en el primer arranque en entornos de usuario estándar (capítulos 2, 3 y 7). - ETW solo registra cuando hay suscriptores. Con solo escribir
EventSourceno ocurre nada. Dicho de otro modo, el coste de dejar preparada la instrumentación es prácticamente nulo, y permite dejar el sistema listo para recogerlo condotnet-tracecuando haga falta (capítulo 4).
Si va a ponerse manos a la obra a continuación, este orden es el más realista.
- Haga un inventario de la salida al registro de eventos de la aplicación existente y compruebe si el contenido que envía al registro de eventos se limita a «inicio, parada y errores fatales». Si también envía registros detallados, acótelo con
FilterdeAddEventLog(capítulo 3). - Defina las reglas de numeración de ID de evento (rangos por área funcional, no cambiar el significado de un ID ya asignado) y déjelas documentadas (capítulo 2).
- Compruebe si el instalador incluye el registro de la fuente de eventos y si el tamaño máximo del registro se ha ampliado explícitamente respecto a los 512 KB predeterminados (capítulo 7).
- Si en las investigaciones de incidencias aplica siempre el mismo filtro, guarde ese XPath como vista personalizada (capítulo 6).
- En los procesos donde previsiblemente surgirán consultas de rendimiento, deje preparados de antemano solo los eventos de inicio y fin con
EventSource. Mientras no se recoja, el coste es prácticamente nulo (capítulo 4).
Artículos relacionados
- Cuándo se necesitan privilegios de administrador en Windows - UAC, áreas protegidas y cómo distinguirlo en el diseño
- Cómo crear y operar un servicio de Windows — desde cuándo usarlo en vez del Programador de tareas hasta convertir un BackgroundService en servicio
- La tarea del Programador de tareas no se ejecuta o termina con 0x1 — aislar la causa y un diseño operativo seguro
- Requisitos mínimos de un logger propio y checklist de pruebas de integración
- Diseño para conservar registros y volcados cuando falla una aplicación de Windows
- Introducción a la recogida de volcados de bloqueo en Windows - WER/ProcDump/WinDbg
- Leer un volcado de bloqueo con WinDbg + SOS — introducción práctica al análisis tras la recogida
Áreas de consultoría relacionadas
KomuraSoft LLC ofrece asesoría técnica sobre el diseño de la infraestructura de registros, registro de eventos y ETW de aplicaciones de negocio Windows, así como el diseño de puntos de observación pensando en la investigación de incidencias.
- Desarrollo de aplicaciones Windows
- Investigación de fallos y análisis de causa
- Consultoría técnica y revisión de diseño
- Contacto
Referencias
-
Microsoft Learn, EventSource. Sobre que EventSource es un mecanismo de registro estructurado de alto rendimiento integrado en .NET, compatible con ETW y EventPipe. ↩ ↩2
-
Microsoft Learn, EventPipe. Sobre que EventPipe es un mecanismo de trazas integrado en el runtime de .NET similar a ETW o perf_events, que puede recoger los eventos de EventSource; sobre que ETW es exclusivo de Windows y requiere privilegios de administrador mientras que EventPipe es multiplataforma y no los requiere; y sobre que el alcance de EventPipe se limita al código administrado y al runtime, sin poder obtener eventos del kernel ni pilas de llamadas nativas. ↩ ↩2
-
Microsoft Learn, EventLog.CreateEventSource Method. Sobre la razón por la que, desde Windows Vista, crear una fuente de eventos requiere privilegios de administrador (porque hay que buscar en todos los registros, incluido Security). ↩ ↩2 ↩3
-
Microsoft Learn, Getting Started with EventSource. Sobre que EventSource funciona con el patrón de publicación-suscripción y no registra eventos si no hay suscriptores (ETW o EventPipe), y sobre cómo recogerlos con dotnet-trace collect. ↩ ↩2
-
Microsoft Learn, CA2254: Template should be a static expression. Sobre que usar concatenación o interpolación de cadenas en la plantilla de un mensaje de registro hace que se pierda la correspondencia entre el nombre del marcador de posición y el valor. ↩ ↩2
-
Microsoft Learn, EventLog.MaximumKilobytes Property. Sobre que el tamaño máximo predeterminado del registro de eventos es de 512 kilobytes. ↩ ↩2
-
Microsoft Learn, EventLog Class. Sobre los tres registros predeterminados Application/System/Security, la necesidad de que la fuente sea única en un mismo equipo, y el mecanismo por el que basta con permiso de escritura para escribir con cualquier nombre de fuente ya registrado. ↩ ↩2
-
Microsoft Learn, EventLogSettings Class. Sobre los valores predeterminados de AddEventLog (LogName es “Application”, SourceName es “.NET Runtime”). ↩ ↩2
-
Microsoft Learn, Logging providers in .NET. Sobre que los proveedores de registro predeterminados de Generic Host incluyen Console, Debug, EventSource y EventLog (solo Windows). ↩ ↩2
-
Microsoft Learn, Event Sources. Sobre que escribir con un nombre de fuente no registrado recae por defecto en el registro Application, pero que, al no existir el archivo de mensajes, el Visor de eventos no puede mostrar el texto descriptivo y aparece como error. ↩ ↩2
-
Microsoft Learn, Get-WinEvent. Sobre cómo acotar eventos pasando claves como LogName y ProviderName a -FilterHashtable, y sobre que los eventos obtenidos tienen propiedades como TimeCreated, Id, LevelDisplayName y Message. ↩
-
Microsoft Learn, Event Tracing. Sobre que Event Tracing for Windows (ETW) es el mecanismo que inicia, detiene, instrumenta y consume los eventos de traza de las aplicaciones. ↩
-
Microsoft Learn, dotnet-trace performance analysis utility. Sobre la descripción general de dotnet-trace, la herramienta multiplataforma de recogida de trazas basada en EventPipe, y el comando collect. ↩
-
Microsoft Learn, Introduction to WPR. Sobre que Windows Performance Recorder (WPR) es una herramienta que amplía ETW y proporciona un registro detallado del sistema y de las aplicaciones. ↩
-
Microsoft Learn, Logging in C# and .NET. Sobre la sintaxis {PlaceHolder} de la plantilla de mensaje de registro y el mecanismo por el que los nombres de clave incluidos en la plantilla pasan a ser nombres de propiedad del registro. ↩
-
Microsoft Learn, High-performance logging in .NET. Sobre que el registro con generación de código fuente mediante LoggerMessageAttribute permite evitar el coste de boxing y de análisis de la plantilla. ↩
-
Microsoft Learn, Comparison of ETW and EventLog logger functionality. Sobre cómo crear una vista personalizada en el Visor de eventos usando una consulta XPath, por ejemplo por nombre de evento. ↩
-
Microsoft Learn, wevtutil. Sobre las operaciones de línea de comandos para exportar (epl), consultar (qe) y cambiar la configuración (sl) del registro de eventos. ↩
-
Microsoft Learn, OverflowAction Enum. Sobre el comportamiento del registro de eventos al alcanzar el tamaño máximo (sobrescribir o descartar), y sobre que OverwriteOlder está en desuso. ↩
Artículos relacionados
Artículos recientes con las mismas etiquetas para profundizar en temas cercanos.
Identificar qué es «lento» con PerfView y dotnet-trace — introducción práctica a la investigación de rendimiento en .NET
Qué herramientas y datos conviene mirar cuando una aplicación de negocio va lenta, mantiene la CPU al máximo o se queda congelada ocasion...
Las profundidades de la E/S de Windows (parte 1) — Toda lectura y escritura se convierte en un IRP: panorama general del sistema de E/S
Primera entrega de la serie que explica desde la base el sistema de E/S de Windows: el espacio de nombres del Administrador de objetos, l...
Internacionalización de aplicaciones WinForms/WPF — la práctica de resx, ensamblados satélite y el cambio de cultura
Organizamos la internacionalización de aplicaciones de escritorio Windows: la diferencia entre CurrentCulture y CurrentUICulture, el meca...
No solo appsettings.json — gestión práctica de configuración en aplicaciones de negocio Windows (configuración por entorno, secretos y ubicaciones de escritura)
Organizamos la gestión de configuración de aplicaciones de negocio Windows: jerarquía de appsettings.json, uso de IOptions/IOptionsMonito...
Impresión y salida en PDF en aplicaciones empresariales de Windows ── cómo elegir entre System.Drawing.Printing, WPF y bibliotecas de informes
Organiza en una tabla de decisión por requisitos la impresión WinForms con PrintDocument, la impresión WPF con FlowDocument o FixedDocume...
Temas relacionados
Estas páginas sitúan el tema en un contexto más amplio de servicios y decisiones.
Temas técnicos de Windows
Portal sobre desarrollo de Windows, investigación de fallos y aprovechamiento de activos existentes.
Investigación de fallos y problemas prolongados
Fallos intermitentes, diagnóstico de comunicaciones, bloqueos prolongados y pruebas de rutas de error.
Servicios relacionados con este tema
El artículo está directamente relacionado con los siguientes servicios.
Desarrollo de aplicaciones para Windows
El diseño de la infraestructura de registros, registro de eventos y ETW forma parte de las consultas sobre desarrollo de aplicaciones Windows.
Investigación de fallos y causas
El diseño de registros pensando en la investigación de incidencias se relaciona directamente con la consulta de investigación de fallos y análisis de causa.
Preguntas frecuentes
Preguntas habituales en las consultas sobre el tema del artículo.
- ¿Si tengo registros en archivo, no necesito el registro de eventos?
- Para una investigación detallada, muchas veces basta con archivos. Sin embargo, si desea que el personal de operaciones detecte anomalías de la aplicación mediante el Visor de eventos estándar o herramientas de supervisión —notificaciones de fallo del Programador de tareas, SCOM, etc.—, es práctico combinarlo con una salida al registro de eventos que contenga solo los puntos esenciales. No son sustitutos: son capas de registro distintas para lectores diferentes.
- ¿Cómo debo definir la numeración de ID de evento?
- No hay una única respuesta correcta, pero en la práctica se reducen accidentes si se respetan tres puntos: separar rangos por área funcional —inicio en la serie 1000, comunicaciones en la 2000, por ejemplo—, no cambiar el significado ni reutilizar un ID asignado y permitir huecos. EventId de ILogger también se utiliza como clave de búsqueda de registros estructurados, por lo que una numeración fácil de documentar ayuda al mantenimiento.
- Uso Serilog o NLog; ¿cómo se relaciona esto con el artículo?
- Serilog y NLog son una forma de distribuir, bajo ILogger, el mismo registro a varios sinks, como archivos, registro de eventos, ETW o SaaS externo. El criterio de diseño tratado aquí, «solo lo esencial en el registro de eventos» y «no romper las plantillas de mensajes», se aplica tanto al uso directo de ILogger como al uso a través de Serilog/NLog. Elegir un sink para EventLog, como Serilog.Sinks.EventLog, o AddEventLog estándar es una decisión de implementación.
- ¿Hasta dónde necesito aprender ETW?
- Si el objetivo principal es desarrollar y mantener aplicaciones de negocio, basta con poder crear un proveedor propio con EventSource y recoger sus eventos con dotnet-trace. El análisis de pilas en PerfView o la recogida de eventos del kernel con WPR pertenecen a la etapa de especialización en investigación de rendimiento y se dejan deliberadamente fuera de este artículo.
Perfil del autor
Página de presentación del autor del artículo.
Go Komura
Representante de KomuraSoft LLC
Especializado en desarrollo de software para Windows, consultoría técnica e investigación de fallos, sobre todo en proyectos con sistemas existentes y errores difíciles de reproducir.