Registros en .NET Core y ASP.NET Core
Nota:
Esta no es la versión más reciente de este artículo. Para la versión actual, consulte la versión .NET 8 de este artículo.
Advertencia
Esta versión de ASP.NET Core ya no se admite. Para obtener más información, consulte la Directiva de soporte técnico de .NET y .NET Core. Para la versión actual, consulte la versión .NET 8 de este artículo.
Importante
Esta información hace referencia a un producto en versión preliminar, el cual puede sufrir importantes modificaciones antes de que se publique la versión comercial. Microsoft no proporciona ninguna garantía, expresa o implícita, con respecto a la información proporcionada aquí.
Para la versión actual, consulte la versión .NET 8 de este artículo.
Por Kirk Larkin, Juergen Gutsch y Rick Anderson
En este articulo se describe el registro en .NET tal y como se aplica a las aplicaciones de ASP.NET Core. Para obtener información detallada sobre el registro en .NET, vea Registro en .NET. Para obtener más información sobre el registro en aplicaciones Blazor, consulte Registro de Blazor en ASP.NET Core.
Proveedores de registro
Los proveedores de registro almacenan los registros, a excepción del proveedor Console
, que los muestra. Por ejemplo, el proveedor de Azure Application Insights almacena los registros en Azure Application Insights. Se pueden habilitar varios proveedores.
Las plantillas de aplic. web predeterminadas de ASP.NET Core llaman a WebApplication.CreateBuilder, que agrega los siguientes proveedores de registro:
- Consola
- Depurar
- EventSource
- EventLog: Solo Windows
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
En el código anterior se muestra el archivo Program.cs
creado con las plantillas de aplicación web de ASP.NET Core. En las siguientes secciones se proporcionan ejemplos basados en las plantillas de aplicación web de ASP.NET Core.
El código siguiente invalida el conjunto predeterminado de proveedores de registro agregados por WebApplication.CreateBuilder
:
var builder = WebApplication.CreateBuilder(args);
builder.Logging.ClearProviders();
builder.Logging.AddConsole();
builder.Services.AddRazorPages();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
Como alternativa, el código de registro anterior se puede escribir de la siguiente manera:
var builder = WebApplication.CreateBuilder();
builder.Host.ConfigureLogging(logging =>
{
logging.ClearProviders();
logging.AddConsole();
});
Para otros proveedores, vea:
Creación de registros
Para crear registros, use un objeto ILogger<TCategoryName> desde la inserción de dependencias (DI):
En el ejemplo siguiente:
- Crea un registrador,
ILogger<AboutModel>
, que utiliza una categoría de registro del nombre completo del tipoAboutModel
. La categoría de registro es una cadena que está asociada con cada registro. - Llama a LogInformation para realizar el registro en el nivel de Information. El nivel de registro indica la gravedad del evento registrado.
public class AboutModel : PageModel
{
private readonly ILogger _logger;
public AboutModel(ILogger<AboutModel> logger)
{
_logger = logger;
}
public void OnGet()
{
_logger.LogInformation("About page visited at {DT}",
DateTime.UtcNow.ToLongTimeString());
}
}
Los niveles y las categorías se explican con más detalle posteriormente en este artículo.
Para obtener información sobre Blazor, consulte Registro de Blazor en ASP.NET Core.
registro
La configuración del registro la suele proporcionar la sección Logging
de los archivos appsettings.{ENVIRONMENT}.json
, donde el marcador de posición {ENVIRONMENT}
es el entorno. El siguiente archivo appsettings.Development.json
se genera mediante las plantillas de aplicación web de ASP.NET Core:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}
En el código JSON anterior:
- Se especifican las categorías
"Default"
y"Microsoft.AspNetCore"
. - La categoría
"Microsoft.AspNetCore"
se aplica a todas las categorías que comienzan por"Microsoft.AspNetCore"
. Por ejemplo, esta configuración se aplica a la categoría"Microsoft.AspNetCore.Routing.EndpointMiddleware"
. - La categoría
"Microsoft.AspNetCore"
registra en el nivel de registroWarning
y superiores. - No se especifica un proveedor de registro específico, por lo que
LogLevel
se aplica a todos los proveedores de registro habilitados, excepto Windows EventLog.
La propiedad Logging
puede tener LogLevel y registrar propiedades del proveedor de registro. LogLevel
especifica el nivel mínimo que se va a registrar para las categorías seleccionadas. En el código JSON anterior, se especifican los niveles de registro Information
y Warning
. LogLevel
indica la gravedad del registro y los valores están entre 0 y 6:
Trace
= 0, Debug
= 1, Information
= 2, Warning
= 3, Error
= 4, Critical
= 5 y None
= 6.
Cuando se especifica LogLevel
, el registro está habilitado para los mensajes tanto en el nivel especificado como en los superiores. En el código JSON anterior, se registra la categoría Default
para Information
y los niveles posteriores. Por ejemplo, se registran los mensajes Information
, Warning
, Error
y Critical
. Si no se especifica LogLevel
, el nivel predeterminado del registro es Information
. Para obtener más información, consulte Niveles de registro.
Una propiedad de proveedor puede especificar una propiedad de LogLevel
. LogLevel
en un proveedor especifica los niveles que se van a registrar para ese proveedor, e invalida la configuración de registro que no es de proveedor. Fíjese en el siguiente archivo appsettings.json
:
{
"Logging": {
"LogLevel": { // All providers, LogLevel applies to all the enabled providers.
"Default": "Error", // Default logging, Error and higher.
"Microsoft": "Warning" // All Microsoft* categories, Warning and higher.
},
"Debug": { // Debug provider.
"LogLevel": {
"Default": "Information", // Overrides preceding LogLevel:Default setting.
"Microsoft.Hosting": "Trace" // Debug:Microsoft.Hosting category.
}
},
"EventSource": { // EventSource provider
"LogLevel": {
"Default": "Warning" // All categories of EventSource provider.
}
}
}
}
La configuración de Logging.{PROVIDER NAME}.LogLevel
anula la configuración de Logging.LogLevel
, donde el marcador de posición {PROVIDER NAME}
es el nombre del proveedor. En el código JSON anterior, el nivel de registro predeterminado del proveedor de Debug
se establece en Information
:
Logging:Debug:LogLevel:Default:Information
La configuración anterior especifica el nivel de registro Information
para cada categoría de Logging:Debug:
, excepto Microsoft.Hosting
. Cuando se muestra una categoría específica, esa categoría invalida la categoría predeterminada. En el JSON anterior, las categorías de Logging:Debug:LogLevel
"Microsoft.Hosting"
y "Default"
invalidan la configuración de Logging:LogLevel
.
Se puede especificar el nivel de registro mínimo para:
- Proveedores específicos: Por ejemplo,
Logging:EventSource:LogLevel:Default:Information
. - Categorías específicas: Por ejemplo,
Logging:LogLevel:Microsoft:Warning
. - Todos los proveedores y todas las categorías:
Logging:LogLevel:Default:Warning
Los registros situados por debajo del nivel mínimo no hacen lo siguiente:
- no se pasan proveedor;
- no se registran ni se muestran.
Para suprimir todos los registros, especifique LogLevel.None. LogLevel.None
tiene un valor de 6, que es mayor que LogLevel.Critical
(5).
Si un proveedor admite ámbitos de registro, IncludeScopes
indica si están habilitados. Para obtener más información, consulte Ámbitos de registro.
El siguiente archivo appsettings.json
contiene todos los proveedores habilitados de forma predeterminada:
{
"Logging": {
"LogLevel": { // No provider, LogLevel applies to all the enabled providers.
"Default": "Error",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Warning"
},
"Debug": { // Debug provider.
"LogLevel": {
"Default": "Information" // Overrides preceding LogLevel:Default setting.
}
},
"Console": {
"IncludeScopes": true,
"LogLevel": {
"Microsoft.AspNetCore.Mvc.Razor.Internal": "Warning",
"Microsoft.AspNetCore.Mvc.Razor.Razor": "Debug",
"Microsoft.AspNetCore.Mvc.Razor": "Error",
"Default": "Information"
}
},
"EventSource": {
"LogLevel": {
"Microsoft": "Information"
}
},
"EventLog": {
"LogLevel": {
"Microsoft": "Information"
}
},
"AzureAppServicesFile": {
"IncludeScopes": true,
"LogLevel": {
"Default": "Warning"
}
},
"AzureAppServicesBlob": {
"IncludeScopes": true,
"LogLevel": {
"Microsoft": "Information"
}
},
"ApplicationInsights": {
"LogLevel": {
"Default": "Information"
}
}
}
}
En el ejemplo anterior:
- Las categorías y los niveles no son valores sugeridos. El objetivo del ejemplo es mostrar todos los proveedores predeterminados.
- La configuración de
Logging.{PROVIDER NAME}.LogLevel
anula la configuración deLogging.LogLevel
, donde el marcador de posición{PROVIDER NAME}
es el nombre del proveedor. Por ejemplo, el nivel deDebug.LogLevel.Default
invalida el nivel deLogLevel.Default
. - Se usa cada alias de proveedor predeterminado. Cada proveedor define un alias que se puede utilizar en la configuración en lugar del nombre de tipo completo. Los alias de proveedores integrados son los siguientes:
Console
Debug
EventSource
EventLog
AzureAppServicesFile
AzureAppServicesBlob
ApplicationInsights
Registro en Program.cs
En el ejemplo siguiente se llama a Builder.WebApplication.Logger en Program.cs
y registra mensajes informativos:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.Logger.LogInformation("Adding Routes");
app.MapGet("/", () => "Hello World!");
app.Logger.LogInformation("Starting the app");
app.Run();
En el ejemplo siguiente se llama a AddConsole en Program.cs
y se registra el punto de conexión /Test
:
var builder = WebApplication.CreateBuilder(args);
builder.Logging.AddConsole();
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.MapGet("/Test", async (ILogger<Program> logger, HttpResponse response) =>
{
logger.LogInformation("Testing logging in Program.cs");
await response.WriteAsync("Testing");
});
app.Run();
En el ejemplo siguiente se llama a AddSimpleConsole en Program.cs
, se deshabilita la salida de color y se registra el punto de conexión /Test
:
using Microsoft.Extensions.Logging.Console;
var builder = WebApplication.CreateBuilder(args);
builder.Logging.AddSimpleConsole(i => i.ColorBehavior = LoggerColorBehavior.Disabled);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.MapGet("/Test", async (ILogger<Program> logger, HttpResponse response) =>
{
logger.LogInformation("Testing logging in Program.cs");
await response.WriteAsync("Testing");
});
app.Run();
Establecimiento del nivel de registro mediante la línea de comandos, las variables de entorno y otra configuración
El nivel de registro se puede establecer con cualquiera de los proveedores de configuración.
El separador :
no funciona con claves jerárquicas de variables de entorno en todas las plataformas. __
, el carácter de subrayado doble, tiene las siguientes características:
- Es compatible con todas las plataformas. Por ejemplo, el separador
:
no es compatible con Bash, pero__
sí. - Se reemplaza automáticamente por un signo
:
.
Los siguientes comandos:
- establecen la clave de entorno
Logging:LogLevel:Microsoft
en un valor deInformation
en Windows; - prueban la configuración cuando use una aplicación creada con las plantillas de aplicación web de ASP.NET Core. El comando
dotnet run
debe ejecutarse en el directorio del proyecto después de usarset
.
set Logging__LogLevel__Microsoft=Information
dotnet run
La configuración del entorno anterior:
- solo se establece en procesos iniciados desde la ventana de comandos en la que se establecieron;
- no podrá ser leída por los exploradores que se inician con Visual Studio.
El siguiente comando setx también establece la clave y el valor de entorno en Windows. A diferencia de set
, la configuración de setx
se conserva. El modificador /M
establece la variable en el entorno del sistema. Si no se usa /M
, se establece una variable de entorno de usuario.
setx Logging__LogLevel__Microsoft Information /M
Fíjese en el siguiente archivo appsettings.json
:
"Logging": {
"Console": {
"LogLevel": {
"Microsoft.Hosting.Lifetime": "Trace"
}
}
}
El comando siguiente establece la configuración anterior en el entorno:
setx Logging__Console__LogLevel__Microsoft.Hosting.Lifetime Trace /M
Nota:
Al configurar variables de entorno con nombres que contienen .
(puntos) en macOS y Linux, considere la posibilidad de "Exportar una variable con un punto (.) en ella" en Stack Exchange y su respuesta aceptada correspondiente.
En Azure App Service, seleccione Nueva configuración de la aplicación en la página Configuración > Configuración. Los ajustes de configuración de Azure App Service:
- Se cifran en reposo y se transmiten a través de un canal cifrado.
- Se exponen como variables de entorno.
Para más información, consulte el artículo sobre Azure Apps: Invalidación de la configuración de la aplicación con Azure Portal.
Para obtener más información sobre cómo establecer los valores de configuración de ASP.NET Core mediante variables de entorno, vea Variables de entorno. Para obtener información sobre el uso de otros orígenes de configuración, como la línea de comandos, Azure Key Vault, Azure App Configuration, otros formatos de archivo, etc., vea Configuración en ASP.NET Core.
Cómo se aplican las reglas de filtro
Cuando se crea un objeto ILogger<TCategoryName>, el objeto ILoggerFactory selecciona una sola regla por proveedor para aplicar a ese registrador. Todos los mensajes escritos por una instancia ILogger
se filtran según las reglas seleccionadas. De las reglas disponibles, se selecciona la más específica para cada par de categoría y proveedor.
Cuando se crea un ILogger
para una categoría determinada, se usa el algoritmo siguiente para cada proveedor:
- Se seleccionan todas las reglas que coinciden con el proveedor o su alias. Si no se encuentra ninguna coincidencia, se seleccionan todas las reglas con un proveedor vacío.
- Del resultado del paso anterior, se seleccionan las reglas con el prefijo de categoría coincidente más largo. Si no se encuentra ninguna coincidencia, se seleccionan todas las reglas que no especifican una categoría.
- Si se seleccionan varias reglas, se toma la última.
- Si no se selecciona ninguna regla, se usa
MinimumLevel
.
Registro de la salida de dotnet run y Visual Studio
Se muestran los registros creados con los proveedores de registro predeterminados:
- En Visual Studio
- En la ventana de salida de Debug al depurar.
- En la ventana de ASP.NET Core Web Server.
- En la ventana de la consola cuando la aplicación se ejecuta con
dotnet run
.
Los registros que comienzan por categorías de "Microsoft" son de .NET. .NET y el código de la aplicación usan la misma API y los mismos proveedores de registro.
Categoría de registro
Cuando se crea un objeto ILogger
, se especifica una categoría. Esa categoría se incluye con cada mensaje de registro creado por esa instancia de ILogger
. La cadena de categoría es arbitraria, pero la convención es usar el nombre de clase completo. Por ejemplo, en un controlador, el nombre podría ser "TodoApi.Controllers.TodoController"
. Las aplicaciones web de ASP.NET Core usan ILogger<T>
para obtener automáticamente una instancia de ILogger
que utiliza el nombre de tipo completo de T
como la categoría:
public class PrivacyModel : PageModel
{
private readonly ILogger<PrivacyModel> _logger;
public PrivacyModel(ILogger<PrivacyModel> logger)
{
_logger = logger;
}
public void OnGet()
{
_logger.LogInformation("GET Pages.PrivacyModel called.");
}
}
Si se desea una categorización adicional, la convención consiste en usar un nombre jerárquico anexando una subcategoría al nombre de clase completo y especificando explícitamente la categoría mediante ILoggerFactory.CreateLogger
:
public class ContactModel : PageModel
{
private readonly ILogger _logger;
public ContactModel(ILoggerFactory logger)
{
_logger = logger.CreateLogger("TodoApi.Pages.ContactModel.MyCategory");
}
public void OnGet()
{
_logger.LogInformation("GET Pages.ContactModel called.");
}
La llamada a CreateLogger
con un nombre fijo puede ser útil cuando se usa en varios métodos, por lo que los eventos se pueden organizar por categoría.
ILogger<T>
es equivale a llamar a CreateLogger
con el nombre de tipo completo de T
.
Nivel de registro
En la tabla siguiente se enumeran los valores de LogLevel, el método de extensión Log{LogLevel}
oportuno y el uso sugerido:
LogLevel | Valor | Método | Descripción |
---|---|---|---|
Trace | 0 | LogTrace | Contienen los mensajes más detallados. Estos mensajes pueden contener datos confidenciales de la aplicación. Están deshabilitados de forma predeterminada y no se deben habilitar en un entorno de producción. |
Debug | 1 | LogDebug | Para depuración y desarrollo. Debido al elevado volumen, tenga precaución cuando lo use en producción. |
Information | 2 | LogInformation | Realiza el seguimiento del flujo general de la aplicación. Puede tener un valor a largo plazo. |
Warning | 3 | LogWarning | Para eventos anómalos o inesperados. Normalmente incluye errores o estados que no provocan un error en la aplicación. |
Error | 4 | LogError | Para los errores y excepciones que no se pueden controlar. Estos mensajes indican un error en la operación o solicitud actual, no un error de toda la aplicación. |
Critical | 5 | LogCritical | Para los errores que requieren atención inmediata. Ejemplos: escenarios de pérdida de datos, espacio en disco insuficiente. |
None | 6 | Especifica que una categoría de registro no debe escribir mensajes. |
En la tabla anterior, LogLevel
aparece de menor a mayor gravedad.
El primer parámetro del método Log, LogLevel, indica la gravedad del registro. En lugar de llamar a Log(LogLevel, ...)
, la mayoría de los desarrolladores llaman a los métodos de extensión Log{LOG LEVEL}
, donde el marcador de posición {LOG LEVEL}
es el nivel de registro. Por ejemplo, las dos llamadas de registro siguientes son funcionalmente equivalentes y generan el mismo registro:
[HttpGet]
public IActionResult Test1(int id)
{
var routeInfo = ControllerContext.ToCtxString(id);
_logger.Log(LogLevel.Information, MyLogEvents.TestItem, routeInfo);
_logger.LogInformation(MyLogEvents.TestItem, routeInfo);
return ControllerContext.MyDisplayRouteInfo();
}
MyLogEvents.TestItem
es el identificador del evento. MyLogEvents
forma parte de la aplicación de ejemplo y se muestra en la sección Log event ID (id. de evento de registro).
El paquete NuGet Rick.Docs.Samples.RouteInfo proporciona MyDisplayRouteInfo y ToCtxString. Los métodos muestran la información de ruta de Controller
y Razor Page
.
El siguiente código crea los registros Information
y Warning
:
[HttpGet("{id}")]
public async Task<ActionResult<TodoItemDTO>> GetTodoItem(long id)
{
_logger.LogInformation(MyLogEvents.GetItem, "Getting item {Id}", id);
var todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null)
{
_logger.LogWarning(MyLogEvents.GetItemNotFound, "Get({Id}) NOT FOUND", id);
return NotFound();
}
return ItemToDTO(todoItem);
}
En el código anterior, el primer parámetro de Log{LOG LEVEL}
, MyLogEvents.GetItem
, es el identificador de evento de registro. El segundo parámetro es una plantilla de mensaje con marcadores de posición para los valores de argumento proporcionados por el resto de parámetros de método. Los parámetros de método se explican detalladamente en la sección Plantilla de mensaje más adelante en este documento.
Llame al método Log{LOG LEVEL}
apropiado para controlar la cantidad de salida de registro que se escribe en un determinado medio de almacenamiento. Por ejemplo:
- En producción:
- El registro en los niveles
Trace
,Debug
oInformation
genera un gran volumen de mensajes de registro detallados. Para controlar los costos y no superar los límites de almacenamiento de datos, registre los mensajes de nivelTrace
,Debug
oInformation
en un almacén de datos de alto volumen y bajo costo. Considere la posibilidad de limitarTrace
,Debug
oInformation
a categorías específicas. - El registro entre los niveles
Warning
yCritical
debe generar pocos mensajes de registro.- Los costos y los límites de almacenamiento no suelen ser un problema.
- Cuantos menos registros haya, mayor será la flexibilidad a la hora de elegir el almacén de datos.
- El registro en los niveles
- En desarrollo:
- Establézcalo en
Warning
. - Agregue los mensajes
Trace
,Debug
oInformation
al solucionar problemas. Para limitar la salida, establezcaTrace
,Debug
oInformation
solo para las categorías que se están investigando.
- Establézcalo en
ASP.NET Core escribe registros de eventos de marco. Por ejemplo, tomemos la salida del registro de:
- Una aplicación de Razor Pages creada con las plantillas de ASP.NET Core.
- Registro establecido en
Logging:Console:LogLevel:Microsoft:Information
. - Navegación a la página Privacy:
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
Request starting HTTP/2 GET https://localhost:5001/Privacy
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
Executing endpoint '/Privacy'
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[3]
Route matched with {page = "/Privacy"}. Executing page /Privacy
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[101]
Executing handler method DefaultRP.Pages.PrivacyModel.OnGet - ModelState is Valid
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[102]
Executed handler method OnGet, returned result .
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[103]
Executing an implicit handler method - ModelState is Valid
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[104]
Executed an implicit handler method, returned result Microsoft.AspNetCore.Mvc.RazorPages.PageResult.
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[4]
Executed page /Privacy in 74.5188ms
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
Executed endpoint '/Privacy'
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
Request finished in 149.3023ms 200 text/html; charset=utf-8
El código JSON siguiente establece Logging:Console:LogLevel:Microsoft:Information
:
{
"Logging": { // Default, all providers.
"LogLevel": {
"Microsoft": "Warning"
},
"Console": { // Console provider.
"LogLevel": {
"Microsoft": "Information"
}
}
}
}
Id. de evento del registro
Cada registro se puede especificar un id. de evento. La aplicación de ejemplo usa la clase MyLogEvents
para definir los identificadores de evento:
public class MyLogEvents
{
public const int GenerateItems = 1000;
public const int ListItems = 1001;
public const int GetItem = 1002;
public const int InsertItem = 1003;
public const int UpdateItem = 1004;
public const int DeleteItem = 1005;
public const int TestItem = 3000;
public const int GetItemNotFound = 4000;
public const int UpdateItemNotFound = 4001;
}
[HttpGet("{id}")]
public async Task<ActionResult<TodoItemDTO>> GetTodoItem(long id)
{
_logger.LogInformation(MyLogEvents.GetItem, "Getting item {Id}", id);
var todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null)
{
_logger.LogWarning(MyLogEvents.GetItemNotFound, "Get({Id}) NOT FOUND", id);
return NotFound();
}
return ItemToDTO(todoItem);
}
Un id. de evento asocia un conjunto de eventos. Por ejemplo, todos los registros relacionados con la presentación de una lista de elementos en una página podrían ser 1001.
El proveedor de registro puede almacenar el id. de evento en un campo de identificador, en el mensaje de registro o no almacenarlo. El proveedor de depuración no muestra los identificadores de evento. El proveedor de consola muestra los identificadores de evento entre corchetes después de la categoría:
info: TodoApi.Controllers.TodoItemsController[1002]
Getting item 1
warn: TodoApi.Controllers.TodoItemsController[4000]
Get(1) NOT FOUND
Algunos proveedores de registro almacenan el identificador de evento en un campo, lo que permite filtrar por el id.
Plantilla de mensaje de registro
Cada API de registro usa una plantilla de mensaje. La plantilla de mensaje puede contener marcadores de posición para los que se proporcionan argumentos. Use los nombres de los marcadores de posición, no números.
[HttpGet("{id}")]
public async Task<ActionResult<TodoItemDTO>> GetTodoItem(long id)
{
_logger.LogInformation(MyLogEvents.GetItem, "Getting item {Id}", id);
var todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null)
{
_logger.LogWarning(MyLogEvents.GetItemNotFound, "Get({Id}) NOT FOUND", id);
return NotFound();
}
return ItemToDTO(todoItem);
}
El orden de los parámetros, no sus nombres de marcador de posición, determina qué parámetros se usan para proporcionar valores de marcador de posición en los mensajes de registro. En el código siguiente, los nombres de parámetro están fuera de la secuencia en los marcadores de posición de la plantilla de mensaje:
var apples = 1;
var pears = 2;
var bananas = 3;
_logger.LogInformation("Parameters: {Pears}, {Bananas}, {Apples}", apples, pears, bananas);
Sin embargo, los parámetros se asignan a los marcadores de posición en el orden: apples
, pears
, bananas
. El mensaje de registro refleja el orden de los parámetros:
Parameters: 1, 2, 3
Este enfoque permite a los proveedores de registro implementar registro semántico o estructurado. Los propios argumentos se pasan al sistema de registro, no solo a la plantilla de mensaje con formato. Esto permite a los proveedores de registro almacenar los valores de parámetro como campos. Por ejemplo, tomemos el siguiente método de registrador:
_logger.LogInformation("Getting item {Id} at {RequestTime}", id, DateTime.Now);
Por ejemplo, al registrar en Azure Table Storage:
- Cada entidad de Azure Table puede tener propiedades
ID
yRequestTime
. - Las tablas con propiedades simplifican las consultas en los datos registrados. Por ejemplo, una consulta puede buscar todos los registros dentro de un intervalo
RequestTime
determinado sin necesidad de analizar el tiempo de espera del mensaje de texto.
Registro de excepciones
Los métodos de registrador tienen sobrecargas que toman un parámetro de excepción:
[HttpGet("{id}")]
public IActionResult TestExp(int id)
{
var routeInfo = ControllerContext.ToCtxString(id);
_logger.LogInformation(MyLogEvents.TestItem, routeInfo);
try
{
if (id == 3)
{
throw new Exception("Test exception");
}
}
catch (Exception ex)
{
_logger.LogWarning(MyLogEvents.GetItemNotFound, ex, "TestExp({Id})", id);
return NotFound();
}
return ControllerContext.MyDisplayRouteInfo();
}
El paquete NuGet Rick.Docs.Samples.RouteInfo proporciona MyDisplayRouteInfo y ToCtxString. Los métodos muestran la información de ruta de Controller
y Razor Page
.
El registro de excepciones es específico del proveedor.
Nivel de registro predeterminado
Si no se establece el nivel de registro predeterminado, su valor será Information
.
Por ejemplo, considere la siguiente aplicación web:
- Creada con las plantillas de aplicación web de ASP.NET.
appsettings.json
yappsettings.Development.json
se eliminaron o se les cambió el nombre.
Con la configuración anterior, al navegar a la página de privacidad o de inicio, se generan muchos mensajes de Trace
, Debug
y Information
con Microsoft
en el nombre de la categoría.
El código siguiente establece el nivel de registro predeterminado cuando este no se establece en la configuración:
var builder = WebApplication.CreateBuilder();
builder.Logging.SetMinimumLevel(LogLevel.Warning);
En general, los niveles de registro se deben especificar en la configuración y no en el código.
Función de filtro
Se invoca una función de filtro para todos los proveedores y las categorías que no tienen reglas asignadas mediante configuración o código:
var builder = WebApplication.CreateBuilder();
builder.Logging.AddFilter((provider, category, logLevel) =>
{
if (provider.Contains("ConsoleLoggerProvider")
&& category.Contains("Controller")
&& logLevel >= LogLevel.Information)
{
return true;
}
else if (provider.Contains("ConsoleLoggerProvider")
&& category.Contains("Microsoft")
&& logLevel >= LogLevel.Information)
{
return true;
}
else
{
return false;
}
});
El código anterior muestra los registros de la consola cuando la categoría contiene Controller
o Microsoft
y el nivel de registro es Information
o superior.
En general, los niveles de registro se deben especificar en la configuración y no en el código.
Categorías de ASP.NET Core
En la tabla siguiente se incluyen algunas categorías usadas por ASP.NET Core.
Category | Notas |
---|---|
Microsoft.AspNetCore |
Diagnósticos generales de ASP.NET Core. |
Microsoft.AspNetCore.DataProtection |
Qué claves se tuvieron en cuenta, encontraron y usaron. |
Microsoft.AspNetCore.HostFiltering |
Hosts permitidos. |
Microsoft.AspNetCore.Hosting |
Cuánto tiempo tardaron en completarse las solicitudes HTTP y a qué hora comenzaron. Qué ensamblados de inicio de hospedaje se cargaron. |
Microsoft.AspNetCore.Mvc |
Diagnósticos de MVC y Razor. Enlace de modelos, ejecución de filtros, compilación de vistas y selección de acciones. |
Microsoft.AspNetCore.Routing |
Información de coincidencia de ruta. |
Microsoft.AspNetCore.Server |
Inicio y detención de conexión y mantener las respuestas activas. Información de certificado HTTPS. |
Microsoft.AspNetCore.StaticFiles |
Archivos servidos. |
Para ver más categorías en la ventana de la consola, establezca appsettings.Development.json
en lo siguiente:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Trace",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}
Para obtener una lista de categorías de Entity Framework, consulte Categorías de mensajes de EF.
Ámbitos de registro
Un ámbito puede agrupar un conjunto de operaciones lógicas. Esta agrupación se puede utilizar para adjuntar los mismos datos para cada registro que se crea como parte de un conjunto. Por ejemplo, cada registro creado como parte del procesamiento de una transacción puede incluir el identificador de dicha transacción.
Un ámbito:
- es un tipo IDisposable devuelto por el método BeginScope;
- se mantiene hasta que se elimina.
Los siguientes proveedores admiten ámbitos:
Use un ámbito encapsulando las llamadas de registrador en un bloque using
:
[HttpGet("{id}")]
public async Task<ActionResult<TodoItemDTO>> GetTodoItem(long id)
{
TodoItem todoItem;
var transactionId = Guid.NewGuid().ToString();
using (_logger.BeginScope(new List<KeyValuePair<string, object>>
{
new KeyValuePair<string, object>("TransactionId", transactionId),
}))
{
_logger.LogInformation(MyLogEvents.GetItem, "Getting item {Id}", id);
todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null)
{
_logger.LogWarning(MyLogEvents.GetItemNotFound,
"Get({Id}) NOT FOUND", id);
return NotFound();
}
}
return ItemToDTO(todoItem);
}
Proveedores de registro integrados
ASP.NET Core incluye los siguientes proveedores de registro como parte del marco compartido:
Microsoft envía los siguientes proveedores de registro, pero no como parte del marco compartido. Deben instalarse como NuGet adicional.
ASP.NET Core no incluye un proveedor de registro para escribir registros en archivos. Para escribir registros en archivos desde una aplicación ASP.NET Core, considere la posibilidad de usar un proveedor de registro de terceros.
Para obtener información sobre stdout
y depurar el registro con el módulo ASP.NET Core, consulte Solución de problemas de ASP.NET Core en Azure App Service e IIS y Módulo ASP.NET Core (ANCM) para IIS.
Consola
El proveedor Console
registra la salida en la consola. Para obtener más información sobre cómo ver los registros de Console
en desarrollo, consulte Registro de la salida de dotnet run y Visual Studio.
Depuración
El proveedor Debug
escribe la salida del registro mediante la clase System.Diagnostics.Debug. Las llamadas a System.Diagnostics.Debug.WriteLine
escriben en el proveedor Debug
.
En Linux, la ubicación del registro del proveedor Debug
depende de la distribución y puede ser una de las siguientes:
/var/log/message
/var/log/syslog
Origen de eventos
El proveedor EventSource
escribe en un origen de eventos multiplataforma con el nombre Microsoft-Extensions-Logging
. En Windows, el proveedor utiliza ETW.
herramientas dotnet-trace
La herramienta de dotnet-trace
es una herramienta global de CLI multiplataforma que permite la recopilación de seguimientos de .NET Core de un proceso en ejecución. La herramienta recopila datos del proveedor Microsoft.Extensions.Logging.EventSource mediante un LoggingEventSource.
Para conocer las instrucciones de instalación, vea dotnet-trace
.
Use la herramienta de dotnet-trace
para recopilar un seguimiento de una aplicación:
Ejecute la aplicación con el comando
dotnet run
.Determine el identificador del proceso (PID) de la aplicación .NET Core:
dotnet-trace ps
Busque el PID del proceso que tenga el mismo nombre que el ensamblado de la aplicación.
Ejecute el comando
dotnet-trace
.Sintaxis general del comando:
dotnet-trace collect -p {PID} --providers Microsoft-Extensions-Logging:{Keyword}:{Provider Level} :FilterSpecs=\" {Logger Category 1}:{Category Level 1}; {Logger Category 2}:{Category Level 2}; ... {Logger Category N}:{Category Level N}\"
Al usar un shell de comandos de PowerShell, incluya el valor
--providers
entre comillas simples ('
):dotnet-trace collect -p {PID} --providers 'Microsoft-Extensions-Logging:{Keyword}:{Provider Level} :FilterSpecs=\" {Logger Category 1}:{Category Level 1}; {Logger Category 2}:{Category Level 2}; ... {Logger Category N}:{Category Level N}\"'
En plataformas que no sean Windows, agregue la opción
-f speedscope
para cambiar el formato del archivo de seguimiento de salida aspeedscope
.En la tabla siguiente se define la palabra clave:
Palabra clave Descripción 1 Registre los eventos meta sobre el elemento LoggingEventSource
. No registre eventos deILogger
.2 Activa el evento Message
cuando se llama aILogger.Log()
. Proporciona la información mediante programación (sin formato).4 Activa el evento FormatMessage
cuando se llama aILogger.Log()
. Proporciona la versión de cadena con formato de la información.8 Activa el evento MessageJson
cuando se llama aILogger.Log()
. Proporciona una representación JSON de los argumentos.En la tabla siguiente se enumeran los niveles de proveedor:
Nivel de proveedor Descripción 0 LogAlways
1 Critical
2 Error
3 Warning
4 Informational
5 Verbose
El análisis de un nivel de categoría puede ser una cadena o un número:
Valor con nombre de categoría Valor numérico Trace
0 Debug
1 Information
2 Warning
3 Error
4 Critical
5 Nivel de proveedor y nivel de categoría:
- Están en orden inverso.
- Las constantes de cadena no son todas idénticas.
Si no se especifica ningún
FilterSpecs
, la implementaciónEventSourceLogger
intenta convertir el nivel de proveedor en un nivel de categoría y lo aplica a todas las categorías.Nivel de proveedor Nivel de categoría Verbose
(5)Debug
(1)Informational
(4)Information
(2)Warning
(3)Warning
(3)Error
(2)Error
(4)Critical
(1)Critical
(5)Si se proporciona
FilterSpecs
, cualquier categoría incluida en la lista usa el nivel de categoría codificado allí, todas las demás categorías se filtran.En los ejemplos siguientes se da por supuesto:
- Una aplicación está en ejecución y llamando a
logger.LogDebug("12345")
. - El identificador de proceso (PID) se ha establecido a través de
set PID=12345
, donde12345
es el PID real.
Observe el comando siguiente:
dotnet-trace collect -p %PID% --providers Microsoft-Extensions-Logging:4:5
El comando anterior:
- Captura los mensajes de depuración.
- No aplica un
FilterSpecs
. - Especifica el nivel 5 que asigna la categoría Depurar.
Observe el comando siguiente:
dotnet-trace collect -p %PID% --providers Microsoft-Extensions-Logging:4:5:\"FilterSpecs=*:5\"
El comando anterior:
- No captura mensajes de depuración porque el nivel de categoría 5 es
Critical
. - Proporciona un
FilterSpecs
.
El comando siguiente captura los mensajes de depuración porque el nivel de categoría 1 especifica
Debug
.dotnet-trace collect -p %PID% --providers Microsoft-Extensions-Logging:4:5:\"FilterSpecs=*:1\"
El comando siguiente captura los mensajes de depuración porque la categoría especifica
Debug
.dotnet-trace collect -p %PID% --providers Microsoft-Extensions-Logging:4:5:\"FilterSpecs=*:Debug\"
Las entradas
FilterSpecs
de{Logger Category}
y{Category Level}
representan condiciones de filtrado de registros adicionales. Separe las entradasFilterSpecs
con el carácter de punto y coma;
.Ejemplo de uso de un shell de comandos de Windows:
dotnet-trace collect -p %PID% --providers Microsoft-Extensions-Logging:4:2:FilterSpecs=\"Microsoft.AspNetCore.Hosting*:4\"
El comando anterior activa lo siguiente:
- Registrador de origen del evento para generar cadenas con formato (
4
) de los errores (2
). - Registro
Microsoft.AspNetCore.Hosting
en el nivel de registroInformational
(4
).
Detenga las herramientas
dotnet-trace
presionando la tecla Entrar o Ctrl+C.El seguimiento se guarda con el nombre
trace.nettrace
en la carpeta en la que se ejecuta el comandodotnet-trace
.Abra el seguimiento con Perfview. Abra el archivo
trace.nettrace
y explore los eventos de seguimiento.
Si la aplicación no compila el host con WebApplication.CreateBuilder, agregue el proveedor de origen del evento a la configuración de registro de la aplicación.
Para más información, consulte:
- Seguimiento de la utilidad de análisis de rendimiento (
dotnet-trace
) (documentación de .NET Core) - Seguimiento de la utilidad de análisis de rendimiento (
dotnet-trace
) (documentación del repositorio de GitHub sobre diagnóstico y dotnet) - LoggingEventSource
- EventLevel
- Perfview: es útil para ver los seguimientos del origen de eventos.
Perfview
Use la utilidad PerfView para recopilar y ver los registros. Hay otras herramientas para ver los registros ETW, pero PerfView proporciona la mejor experiencia para trabajar con los eventos ETW emitidos por ASP.NET Core.
Para configurar PerfView para la recopilación de eventos registrados por este proveedor, agregue la cadena *Microsoft-Extensions-Logging
a la lista Proveedores adicionales. No olvide el símbolo *
al principio de la cadena.
Registro de eventos de Windows
El proveedor EventLog
envía la salida del registro al Registro de eventos de Windows. A diferencia de otros proveedores, el proveedor EventLog
no hereda la configuración de no proveedor predeterminada. Si no se especifican valores de registro de EventLog
, el valor predeterminado será LogLevel.Warning.
Para registrar eventos inferiores a LogLevel.Warning, establezca el nivel de registro de forma explícita. En el ejemplo siguiente se establece el nivel de registro predeterminado del registro de eventos en LogLevel.Information:
"Logging": {
"EventLog": {
"LogLevel": {
"Default": "Information"
}
}
}
Las sobrecargas AddEventLog pueden pasar en EventLogSettings. Si es null
o no se especifica, se usa la siguiente configuración predeterminada:
LogName
: "Application"SourceName
: ".NET Runtime"MachineName
: se usa el nombre del equipo local.
En el código siguiente se cambia el valor predeterminado de SourceName
(".NET Runtime"
) por MyLogs
:
var builder = WebApplication.CreateBuilder();
builder.Logging.AddEventLog(eventLogSettings =>
{
eventLogSettings.SourceName = "MyLogs";
});
Azure App Service
El paquete de proveedor Microsoft.Extensions.Logging.AzureAppServices
escribe los registros en archivos de texto en el sistema de archivos de una aplicación de Azure App Service y en Blob Storage en una cuenta de Azure Storage.
El paquete del proveedor no se incluye en el marco compartido. Para usar el proveedor, agregue el paquete del proveedor al proyecto.
Para configurar las opciones de proveedor, use AzureFileLoggerOptions y AzureBlobLoggerOptions, tal y como se muestra en el ejemplo siguiente:
using Microsoft.Extensions.Logging.AzureAppServices;
var builder = WebApplication.CreateBuilder();
builder.Logging.AddAzureWebAppDiagnostics();
builder.Services.Configure<AzureFileLoggerOptions>(options =>
{
options.FileName = "azure-diagnostics-";
options.FileSizeLimit = 50 * 1024;
options.RetainedFileCountLimit = 5;
});
builder.Services.Configure<AzureBlobLoggerOptions>(options =>
{
options.BlobName = "log.txt";
});
Cuando se implementa en Azure App Service, la aplicación usa la configuración de la sección Registros de App Service de la página App Service de Azure Portal. Cuando se actualiza la configuración siguiente, los cambios se aplican de inmediato sin necesidad de reiniciar ni de volver a implementar la aplicación.
- Registro de la aplicación (sistema de archivos)
- Registro de la aplicación (blob)
La ubicación predeterminada de los archivos de registro está en la carpeta D:\\home\\LogFiles\\Application
y el nombre de archivo predeterminado es diagnostics-yyyymmdd.txt
. El límite de tamaño de archivo predeterminado es 10 MB, y el número máximo predeterminado de archivos que se conservan es 2. El nombre predeterminado del blob es {app-name}{timestamp}/yyyy/mm/dd/hh/{guid}-applicationLog.txt
.
El proveedor solo realiza registros cuando el proyecto se ejecuta en el entorno de Azure.
Secuencias de registro de Azure
El streaming de registro de Azure permiten ver la actividad de registro en tiempo real desde:
- El servidor de aplicaciones
- El servidor web
- Error del seguimiento de solicitudes
Para configurar las secuencias de registro de Azure:
- Desplácese a la página Registros de App Service desde la página del portal de la aplicación.
- Establezca Registro de la aplicación (sistema de archivos) en Activado.
- Elija el Nivel de registro. Esta configuración solo se aplica al streaming de registro de Azure.
Desplácese a la página Secuencia de registro para ver los registros. Los mensajes que se registran lo hacen con la interfaz ILogger
.
Azure Application Insights
El paquete de proveedor Microsoft.Extensions.Logging.ApplicationInsights
escribe registros en Azure Application Insights. Application Insights es un servicio que supervisa una aplicación web y proporciona herramientas para consultar y analizar los datos de telemetría. Si usa este proveedor, puede consultar y analizar los registros mediante las herramientas de Application Insights.
El proveedor de registro se incluye como dependencia de Microsoft.ApplicationInsights.AspNetCore
, que es el paquete que proporciona toda la telemetría disponible para ASP.NET Core. Si usa este paquete, no tiene que instalar el proveedor de paquete.
El paquete Microsoft.ApplicationInsights.Web
es para ASP.NET 4.x, no ASP.NET Core.
Para obtener más información, vea los siguientes recursos:
- Información general de Application Insights
- Application Insights para aplicaciones de ASP.NET Core: comience aquí si quiere implementar la variedad completa de telemetría de Application Insights junto con el registro.
- ApplicationInsightsLoggerProvider para los registros de .NET Core ILogger: comience aquí si quiere implementar el proveedor de registro sin el resto de la telemetría de Application Insights.
- Adaptadores de registro de Application Insights
- Tutorial interactivo Instalación, configuración e inicialización del SDK de Application Insights.
Proveedores de registro de terceros
Plataformas de registro de terceros que funcionan con ASP.NET Core:
- elmah.io (repositorio de GitHub)
- Gelf (repositorio de GitHub)
- JSNLog (repositorio de GitHub)
- KissLog.net (repositorio de GitHub)
- Log4Net (repositorio de GitHub)
- NLog (repositorio de GitHub)
- PLogger (repositorio de GitHub)
- Sentry (repositorio de GitHub)
- Serilog (repositorio de GitHub)
- Stackdriver (repositorio de GitHub)
Algunas plataformas de terceros pueden realizar registro semántico, también conocido como registro estructurado.
El uso de una plataforma de terceros es similar al uso de uno de los proveedores integrados:
- Agregue un paquete NuGet al proyecto.
- Llame a un método de extensión
ILoggerFactory
proporcionado por el marco de registro.
Para más información, vea la documentación de cada proveedor. Microsoft no admite los proveedores de registro de terceros.
No hay métodos de registrador asincrónicos
El registro debe ser tan rápido que no merezca la pena el costo de rendimiento del código asincrónico. Si el almacén de datos de registro es lento, no escriba directamente en él. Considere la posibilidad de escribir primero los mensajes de registro en un almacén rápido y, después, moverlos al almacén lento. Por ejemplo, al iniciar sesión en SQL Server, no lo haga directamente en un método Log
, ya que los métodos Log
son sincrónicos. En su lugar, agregue sincrónicamente mensajes de registro a una cola en memoria y haga que un trabajo en segundo plano extraiga los mensajes de la cola para realizar el trabajo asincrónico de insertar datos en SQL Server. Para obtener más información, vea Instrucciones sobre cómo registrar en una cola de mensajes los almacenes de datos lentos (dotnet/AspNetCore.Docs #11801).
Cambio de los niveles de registro en una aplicación en ejecución
La API de registro no incluye un escenario que permita cambiar los niveles de registro mientras se ejecuta una aplicación. No obstante, algunos proveedores de configuración pueden volver a cargar la configuración, lo que tiene efecto inmediato en la configuración del registro. Por ejemplo, el Proveedor de configuración de archivo vuelve a cargar la configuración de registro de forma predeterminada. Si se cambia la configuración en el código mientras se ejecuta una aplicación, la aplicación puede llamar a IConfigurationRoot.Reload para actualizar la configuración de registro de la aplicación.
ILogger e ILoggerFactory
Las implementaciones y las interfaces de ILogger<TCategoryName> y ILoggerFactory se incluyen en el SDK de .NET Core. También están disponibles en los siguientes paquetes NuGet:
- Las interfaces están en
Microsoft.Extensions.Logging.Abstractions
. - Las implementaciones predeterminadas están en
Microsoft.Extensions.Logging
.
Aplicación de reglas de filtro en el código
El método preferido para establecer las reglas de filtro de registro es mediante la Configuración.
En el siguiente ejemplo se muestra cómo registrar reglas de filtro en el código:
using Microsoft.Extensions.Logging.Console;
using Microsoft.Extensions.Logging.Debug;
var builder = WebApplication.CreateBuilder();
builder.Logging.AddFilter("System", LogLevel.Debug);
builder.Logging.AddFilter<DebugLoggerProvider>("Microsoft", LogLevel.Information);
builder.Logging.AddFilter<ConsoleLoggerProvider>("Microsoft", LogLevel.Trace);
logging.AddFilter("System", LogLevel.Debug)
especifica la categoría System
y el nivel de registro Debug
. El filtro se aplica a todos los proveedores porque no se ha configurado un proveedor específico.
AddFilter<DebugLoggerProvider>("Microsoft", LogLevel.Information)
especifica:
- El proveedor de registro
Debug
. - Nivel de registro
Information
y superiores. - Todas las categorías que empiezan con
"Microsoft"
.
Registre automáticamente el ámbito con SpanId
, TraceId
, ParentId
, Baggage
y Tags
.
Las bibliotecas de registro crean implícitamente un objeto de ámbito con SpanId
, TraceId
, ParentId
,Baggage
y Tags
. Este comportamiento se configura a través de ActivityTrackingOptions.
var builder = WebApplication.CreateBuilder(args);
builder.Logging.AddSimpleConsole(options =>
{
options.IncludeScopes = true;
});
builder.Logging.Configure(options =>
{
options.ActivityTrackingOptions = ActivityTrackingOptions.SpanId
| ActivityTrackingOptions.TraceId
| ActivityTrackingOptions.ParentId
| ActivityTrackingOptions.Baggage
| ActivityTrackingOptions.Tags;
});
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
Si se establece el encabezado de solicitud HTTP traceparent
, ParentId
en el ámbito del registro muestra el W3C parent-id
desde el encabezado traceparent
enlazado y SpanId
en el ámbito de registro muestra el parent-id
actualizado para el siguiente paso o intervalo fuera de enlace. Para obtener más información, vea Mutación del campo de seguimiento primario.
Creación de un registrador personalizado
Para obtener más información, consulte Implementación de un proveedor de registro personalizado en .NET.
Recursos adicionales
- Mejora del rendimiento del registro con generadores de origen
- Detrás de
[LogProperties]
y el nuevo generador de origen de registro de telemetría - Origen Microsoft.Extensions.Logging en GitHub
- Vea o descargue el código de ejemplo (cómo descargarlo).
- Registro de alto rendimiento
- Los errores de registro deben crearse en el repositorio
dotnet/runtime
de GitHub. - Registro de Blazor en ASP.NET Core
Por Kirk Larkin, Juergen Gutsch y Rick Anderson
En este tema describe el registro en .NET tal y como se aplica a las aplicaciones de ASP.NET Core. Para obtener información detallada sobre el registro en .NET, vea Registro en .NET. Para obtener más información sobre el registro en aplicaciones Blazor, consulte Registro de Blazor en ASP.NET Core.
Vea o descargue el código de ejemplo (cómo descargarlo).
Proveedores de registro
Los proveedores de registro almacenan los registros, a excepción del proveedor Console
, que los muestra. Por ejemplo, el proveedor de Azure Application Insights almacena los registros en Azure Application Insights. Se pueden habilitar varios proveedores.
Las plantillas de aplicación web de ASP.NET Core predeterminadas:
- usan el host genérico;
- llaman a CreateDefaultBuilder, que agrega los siguientes proveedores de registro:
- Consola
- Depurar
- EventSource
- EventLog: Solo Windows
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
En el código anterior se muestra la clase Program
creada con las plantillas de aplicación web de ASP.NET Core. En las siguientes secciones se proporcionan ejemplos basados en las plantillas de aplicación web de ASP.NET Core, que usan el host genérico. Las aplicaciones de consola que no son de host se explican más adelante en este documento.
Para invalidar el conjunto predeterminado de proveedores de registro agregados por Host.CreateDefaultBuilder
, llame a ClearProviders
y agregue los proveedores de registro necesarios. Por ejemplo, el código siguiente:
- Llama a ClearProviders para quitar todas las instancias de ILoggerProvider del generador.
- Agrega el proveedor de registro Console.
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureLogging(logging =>
{
logging.ClearProviders();
logging.AddConsole();
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
Para otros proveedores, vea:
Creación de registros
Para crear registros, use un objeto ILogger<TCategoryName> desde la inserción de dependencias (DI):
En el ejemplo siguiente:
- Crea un registrador,
ILogger<AboutModel>
, que utiliza una categoría de registro del nombre completo del tipoAboutModel
. La categoría de registro es una cadena que está asociada con cada registro. - Llama a LogInformation para realizar el registro en el nivel de
Information
. El nivel de registro indica la gravedad del evento registrado.
public class AboutModel : PageModel
{
private readonly ILogger _logger;
public AboutModel(ILogger<AboutModel> logger)
{
_logger = logger;
}
public string Message { get; set; }
public void OnGet()
{
Message = $"About page visited at {DateTime.UtcNow.ToLongTimeString()}";
_logger.LogInformation(Message);
}
}
Los niveles y las categorías se explican con más detalle posteriormente en este artículo.
Para obtener información sobre Blazor, consulte Registro de Blazor en ASP.NET Core.
Creación de registros en Main y Startup muestra cómo crear registros en Main
y Startup
.
registro
La configuración de registros suele proporcionarla la sección Logging
de los archivos appsettings.{Environment}.json
. El siguiente archivo appsettings.Development.json
se genera mediante las plantillas de aplicación web de ASP.NET Core:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}
En el código JSON anterior:
- Se especifican las categorías
"Default"
,"Microsoft"
y"Microsoft.Hosting.Lifetime"
. - La categoría
"Microsoft"
se aplica a todas las categorías que comienzan por"Microsoft"
. Por ejemplo, esta configuración se aplica a la categoría"Microsoft.AspNetCore.Routing.EndpointMiddleware"
. - La categoría
"Microsoft"
registra en el nivel de registroWarning
y superiores. - La categoría
"Microsoft.Hosting.Lifetime"
es más específica que la categoría"Microsoft"
, por lo que la categoría"Microsoft.Hosting.Lifetime"
registra en el nivel de registro "Information" y superiores. - No se especifica un proveedor de registro específico, por lo que
LogLevel
se aplica a todos los proveedores de registro habilitados, excepto Windows EventLog.
La propiedad Logging
puede tener LogLevel y registrar propiedades del proveedor de registro. LogLevel
especifica el nivel mínimo que se va a registrar para las categorías seleccionadas. En el código JSON anterior, se especifican los niveles de registro Information
y Warning
. LogLevel
indica la gravedad del registro y los valores están entre 0 y 6:
Trace
= 0, Debug
= 1, Information
= 2, Warning
= 3, Error
= 4, Critical
= 5 y None
= 6.
Cuando se especifica LogLevel
, el registro está habilitado para los mensajes tanto en el nivel especificado como en los superiores. En el código JSON anterior, se registra la categoría Default
para Information
y los niveles posteriores. Por ejemplo, se registran los mensajes Information
, Warning
, Error
y Critical
. Si no se especifica LogLevel
, el nivel predeterminado del registro es Information
. Para obtener más información, consulte Niveles de registro.
Una propiedad de proveedor puede especificar una propiedad de LogLevel
. LogLevel
en un proveedor especifica los niveles que se van a registrar para ese proveedor, e invalida la configuración de registro que no es de proveedor. Fíjese en el siguiente archivo appsettings.json
:
{
"Logging": {
"LogLevel": { // All providers, LogLevel applies to all the enabled providers.
"Default": "Error", // Default logging, Error and higher.
"Microsoft": "Warning" // All Microsoft* categories, Warning and higher.
},
"Debug": { // Debug provider.
"LogLevel": {
"Default": "Information", // Overrides preceding LogLevel:Default setting.
"Microsoft.Hosting": "Trace" // Debug:Microsoft.Hosting category.
}
},
"EventSource": { // EventSource provider
"LogLevel": {
"Default": "Warning" // All categories of EventSource provider.
}
}
}
}
La configuración de Logging.{providername}.LogLevel
invalida la configuración de Logging.LogLevel
. En el código JSON anterior, el nivel de registro predeterminado del proveedor de Debug
se establece en Information
:
Logging:Debug:LogLevel:Default:Information
La configuración anterior especifica el nivel de registro Information
para cada categoría de Logging:Debug:
, excepto Microsoft.Hosting
. Cuando se muestra una categoría específica, esa categoría invalida la categoría predeterminada. En el código JSON anterior, las categorías de Logging:Debug:LogLevel
"Microsoft.Hosting"
y "Default"
invalidan la configuración de Logging:LogLevel
Se puede especificar el nivel de registro mínimo para:
- Proveedores específicos: Por ejemplo,
Logging:EventSource:LogLevel:Default:Information
. - Categorías específicas: Por ejemplo,
Logging:LogLevel:Microsoft:Warning
. - Todos los proveedores y todas las categorías:
Logging:LogLevel:Default:Warning
Los registros situados por debajo del nivel mínimo no hacen lo siguiente:
- no se pasan proveedor;
- no se registran ni se muestran.
Para suprimir todos los registros, especifique LogLevel.None. LogLevel.None
tiene un valor de 6, que es mayor que LogLevel.Critical
(5).
Si un proveedor admite ámbitos de registro, IncludeScopes
indica si están habilitados. Para obtener más información, consulte Ámbitos de registro.
El siguiente archivo appsettings.json
contiene todos los proveedores habilitados de forma predeterminada:
{
"Logging": {
"LogLevel": { // No provider, LogLevel applies to all the enabled providers.
"Default": "Error",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Warning"
},
"Debug": { // Debug provider.
"LogLevel": {
"Default": "Information" // Overrides preceding LogLevel:Default setting.
}
},
"Console": {
"IncludeScopes": true,
"LogLevel": {
"Microsoft.AspNetCore.Mvc.Razor.Internal": "Warning",
"Microsoft.AspNetCore.Mvc.Razor.Razor": "Debug",
"Microsoft.AspNetCore.Mvc.Razor": "Error",
"Default": "Information"
}
},
"EventSource": {
"LogLevel": {
"Microsoft": "Information"
}
},
"EventLog": {
"LogLevel": {
"Microsoft": "Information"
}
},
"AzureAppServicesFile": {
"IncludeScopes": true,
"LogLevel": {
"Default": "Warning"
}
},
"AzureAppServicesBlob": {
"IncludeScopes": true,
"LogLevel": {
"Microsoft": "Information"
}
},
"ApplicationInsights": {
"LogLevel": {
"Default": "Information"
}
}
}
}
En el ejemplo anterior:
- Las categorías y los niveles no son valores sugeridos. El objetivo del ejemplo es mostrar todos los proveedores predeterminados.
- La configuración de
Logging.{providername}.LogLevel
invalida la configuración deLogging.LogLevel
. Por ejemplo, el nivel deDebug.LogLevel.Default
invalida el nivel deLogLevel.Default
. - Se usa cada alias de proveedor predeterminado. Cada proveedor define un alias que se puede utilizar en la configuración en lugar del nombre de tipo completo. Los alias de proveedores integrados son los siguientes:
- Consola
- Depurar
- EventSource
- EventLog
- AzureAppServicesFile
- AzureAppServicesBlob
- ApplicationInsights
Establecimiento del nivel de registro mediante la línea de comandos, las variables de entorno y otra configuración
El nivel de registro se puede establecer con cualquiera de los proveedores de configuración.
El separador :
no funciona con claves jerárquicas de variables de entorno en todas las plataformas. __
, el carácter de subrayado doble, tiene las siguientes características:
- Es compatible con todas las plataformas. Por ejemplo, el separador
:
no es compatible con Bash, pero__
sí. - Se reemplaza automáticamente por un signo
:
.
Los siguientes comandos:
- establecen la clave de entorno
Logging:LogLevel:Microsoft
en un valor deInformation
en Windows; - prueban la configuración cuando use una aplicación creada con las plantillas de aplicación web de ASP.NET Core. El comando
dotnet run
debe ejecutarse en el directorio del proyecto después de usarset
.
set Logging__LogLevel__Microsoft=Information
dotnet run
La configuración del entorno anterior:
- solo se establece en procesos iniciados desde la ventana de comandos en la que se establecieron;
- no podrá ser leída por los exploradores que se inician con Visual Studio.
El siguiente comando setx también establece la clave y el valor de entorno en Windows. A diferencia de set
, la configuración de setx
se conserva. El modificador /M
establece la variable en el entorno del sistema. Si no se usa /M
, se establece una variable de entorno de usuario.
setx Logging__LogLevel__Microsoft Information /M
Fíjese en el siguiente archivo appsettings.json
:
"Logging": {
"Console": {
"LogLevel": {
"Microsoft.Hosting.Lifetime": "Trace"
}
}
}
El comando siguiente establece la configuración anterior en el entorno:
setx Logging__Console__LogLevel__Microsoft.Hosting.Lifetime Trace /M
En Azure App Service, seleccione Nueva configuración de la aplicación en la página Configuración > Configuración. Los ajustes de configuración de Azure App Service:
- Se cifran en reposo y se transmiten a través de un canal cifrado.
- Se exponen como variables de entorno.
Para más información, consulte Aplicaciones de Azure: Invalidación de la configuración de la aplicación mediante Azure Portal.
Para obtener más información sobre cómo establecer los valores de configuración de ASP.NET Core mediante variables de entorno, vea Variables de entorno. Para obtener información sobre el uso de otros orígenes de configuración, como la línea de comandos, Azure Key Vault, Azure App Configuration, otros formatos de archivo, etc., vea Configuración en ASP.NET Core.
Cómo se aplican las reglas de filtro
Cuando se crea un objeto ILogger<TCategoryName>, el objeto ILoggerFactory selecciona una sola regla por proveedor para aplicar a ese registrador. Todos los mensajes escritos por una instancia ILogger
se filtran según las reglas seleccionadas. De las reglas disponibles, se selecciona la más específica para cada par de categoría y proveedor.
Cuando se crea un ILogger
para una categoría determinada, se usa el algoritmo siguiente para cada proveedor:
- Se seleccionan todas las reglas que coinciden con el proveedor o su alias. Si no se encuentra ninguna coincidencia, se seleccionan todas las reglas con un proveedor vacío.
- Del resultado del paso anterior, se seleccionan las reglas con el prefijo de categoría coincidente más largo. Si no se encuentra ninguna coincidencia, se seleccionan todas las reglas que no especifican una categoría.
- Si se seleccionan varias reglas, se toma la última.
- Si no se selecciona ninguna regla, se usa
MinimumLevel
.
Registro de la salida de dotnet run y Visual Studio
Se muestran los registros creados con los proveedores de registro predeterminados:
- En Visual Studio
- En la ventana de salida de Debug al depurar.
- En la ventana de ASP.NET Core Web Server.
- En la ventana de la consola cuando la aplicación se ejecuta con
dotnet run
.
Los registros que comienzan por categorías de "Microsoft" pertenecen al código de marco de ASP.NET Core. ASP.NET Core y el código de la aplicación usan la misma API y los mismos proveedores de registro.
Categoría de registro
Cuando se crea un objeto ILogger
, se especifica una categoría. Esa categoría se incluye con cada mensaje de registro creado por esa instancia de ILogger
. La cadena de categoría es arbitraria, pero la convención es usar el nombre de clase. Por ejemplo, en un controlador, el nombre podría ser "TodoApi.Controllers.TodoController"
. Las aplicaciones web de ASP.NET Core usan ILogger<T>
para obtener automáticamente una instancia de ILogger
que utiliza el nombre de tipo completo de T
como la categoría:
public class PrivacyModel : PageModel
{
private readonly ILogger<PrivacyModel> _logger;
public PrivacyModel(ILogger<PrivacyModel> logger)
{
_logger = logger;
}
public void OnGet()
{
_logger.LogInformation("GET Pages.PrivacyModel called.");
}
}
Para especificar explícitamente la categoría, llame a ILoggerFactory.CreateLogger
:
public class ContactModel : PageModel
{
private readonly ILogger _logger;
public ContactModel(ILoggerFactory logger)
{
_logger = logger.CreateLogger("TodoApi.Pages.ContactModel.MyCategory");
}
public void OnGet()
{
_logger.LogInformation("GET Pages.ContactModel called.");
}
La llamada a CreateLogger
con un nombre fijo puede ser útil cuando se usa en varios métodos, por lo que los eventos se pueden organizar por categoría.
ILogger<T>
es equivale a llamar a CreateLogger
con el nombre de tipo completo de T
.
Nivel de registro
En la tabla siguiente se enumeran los valores de LogLevel, el método de extensión Log{LogLevel}
oportuno y el uso sugerido:
LogLevel | Valor | Método | Descripción |
---|---|---|---|
Seguimiento | 0 | LogTrace | Contienen los mensajes más detallados. Estos mensajes pueden contener datos confidenciales de la aplicación. Están deshabilitados de forma predeterminada y no se deben habilitar en un entorno de producción. |
Depurar | 1 | LogDebug | Para depuración y desarrollo. Debido al elevado volumen, tenga precaución cuando lo use en producción. |
Información | 2 | LogInformation | Realiza el seguimiento del flujo general de la aplicación. Puede tener un valor a largo plazo. |
Advertencia | 3 | LogWarning | Para eventos anómalos o inesperados. Normalmente incluye errores o estados que no provocan un error en la aplicación. |
Error | 4 | LogError | Para los errores y excepciones que no se pueden controlar. Estos mensajes indican un error en la operación o solicitud actual, no un error de toda la aplicación. |
Critical) (Crítico) | 5 | LogCritical | Para los errores que requieren atención inmediata. Ejemplos: escenarios de pérdida de datos, espacio en disco insuficiente. |
Ninguno | 6 | Especifica que una categoría de registro no debe escribir ningún mensaje. |
En la tabla anterior, LogLevel
aparece de menor a mayor gravedad.
El primer parámetro del método Log, LogLevel, indica la gravedad del registro. En lugar de llamar a Log(LogLevel, ...)
, la mayoría de los desarrolladores llaman a los métodos de extensión Log{LogLevel}. Los métodos de extensión Log{LogLevel}
llaman al método Log y especifican el LogLevel. Por ejemplo, las dos llamadas de registro siguientes son funcionalmente equivalentes y generan el mismo registro:
[HttpGet]
public IActionResult Test1(int id)
{
var routeInfo = ControllerContext.ToCtxString(id);
_logger.Log(LogLevel.Information, MyLogEvents.TestItem, routeInfo);
_logger.LogInformation(MyLogEvents.TestItem, routeInfo);
return ControllerContext.MyDisplayRouteInfo();
}
MyLogEvents.TestItem
es el identificador del evento. MyLogEvents
forma parte de la aplicación de ejemplo y se muestra en la sección Log event ID (id. de evento de registro).
El paquete NuGet Rick.Docs.Samples.RouteInfo proporciona MyDisplayRouteInfo y ToCtxString. Los métodos muestran la información de ruta de Controller
y Razor Page
.
El siguiente código crea los registros Information
y Warning
:
[HttpGet("{id}")]
public async Task<ActionResult<TodoItemDTO>> GetTodoItem(long id)
{
_logger.LogInformation(MyLogEvents.GetItem, "Getting item {Id}", id);
var todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null)
{
_logger.LogWarning(MyLogEvents.GetItemNotFound, "Get({Id}) NOT FOUND", id);
return NotFound();
}
return ItemToDTO(todoItem);
}
En el código anterior, el primer parámetro de Log{LogLevel}
, MyLogEvents.GetItem
, es el identificador de evento de registro. El segundo parámetro es una plantilla de mensaje con marcadores de posición para los valores de argumento proporcionados por el resto de parámetros de método. Los parámetros de método se explican detalladamente en la sección Plantilla de mensaje más adelante en este documento.
Llame al método Log{LogLevel}
apropiado para controlar la cantidad de salida de registro que se escribe en un determinado medio de almacenamiento. Por ejemplo:
- En producción:
- El registro en los niveles
Trace
oInformation
genera un gran volumen de mensajes de registro detallados. Para controlar los costos y no superar los límites de almacenamiento de datos, registre los mensajes de nivelTrace
aInformation
en un almacén de datos de alto volumen y bajo costo. Considere la posibilidad de limitarTrace
yInformation
a categorías específicas. - El registro entre los niveles
Warning
yCritical
debe generar pocos mensajes de registro.- Los costos y los límites de almacenamiento no suelen ser un problema.
- Cuantos menos registros haya, mayor será la flexibilidad a la hora de elegir el almacén de datos.
- El registro en los niveles
- En desarrollo:
- Establézcalo en
Warning
. - Agregue los mensajes
Trace
oInformation
al solucionar problemas. Para limitar la salida, establezcaTrace
oInformation
solo para las categorías que se están investigando.
- Establézcalo en
ASP.NET Core escribe registros de eventos de marco. Por ejemplo, tomemos la salida del registro de:
- Una aplicación de Razor Pages creada con las plantillas de ASP.NET Core.
- Registro establecido en
Logging:Console:LogLevel:Microsoft:Information
. - Navegación a la página Privacy:
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
Request starting HTTP/2 GET https://localhost:5001/Privacy
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
Executing endpoint '/Privacy'
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[3]
Route matched with {page = "/Privacy"}. Executing page /Privacy
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[101]
Executing handler method DefaultRP.Pages.PrivacyModel.OnGet - ModelState is Valid
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[102]
Executed handler method OnGet, returned result .
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[103]
Executing an implicit handler method - ModelState is Valid
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[104]
Executed an implicit handler method, returned result Microsoft.AspNetCore.Mvc.RazorPages.PageResult.
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[4]
Executed page /Privacy in 74.5188ms
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
Executed endpoint '/Privacy'
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
Request finished in 149.3023ms 200 text/html; charset=utf-8
El código JSON siguiente establece Logging:Console:LogLevel:Microsoft:Information
:
{
"Logging": { // Default, all providers.
"LogLevel": {
"Microsoft": "Warning"
},
"Console": { // Console provider.
"LogLevel": {
"Microsoft": "Information"
}
}
}
}
Id. de evento del registro
Cada registro se puede especificar un id. de evento. La aplicación de ejemplo usa la clase MyLogEvents
para definir los identificadores de evento:
public class MyLogEvents
{
public const int GenerateItems = 1000;
public const int ListItems = 1001;
public const int GetItem = 1002;
public const int InsertItem = 1003;
public const int UpdateItem = 1004;
public const int DeleteItem = 1005;
public const int TestItem = 3000;
public const int GetItemNotFound = 4000;
public const int UpdateItemNotFound = 4001;
}
[HttpGet("{id}")]
public async Task<ActionResult<TodoItemDTO>> GetTodoItem(long id)
{
_logger.LogInformation(MyLogEvents.GetItem, "Getting item {Id}", id);
var todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null)
{
_logger.LogWarning(MyLogEvents.GetItemNotFound, "Get({Id}) NOT FOUND", id);
return NotFound();
}
return ItemToDTO(todoItem);
}
Un id. de evento asocia un conjunto de eventos. Por ejemplo, todos los registros relacionados con la presentación de una lista de elementos en una página podrían ser 1001.
El proveedor de registro puede almacenar el id. de evento en un campo de identificador, en el mensaje de registro o no almacenarlo. El proveedor de depuración no muestra los identificadores de evento. El proveedor de consola muestra los identificadores de evento entre corchetes después de la categoría:
info: TodoApi.Controllers.TodoItemsController[1002]
Getting item 1
warn: TodoApi.Controllers.TodoItemsController[4000]
Get(1) NOT FOUND
Algunos proveedores de registro almacenan el identificador de evento en un campo, lo que permite filtrar por el id.
Plantilla de mensaje de registro
Cada API de registro usa una plantilla de mensaje. La plantilla de mensaje puede contener marcadores de posición para los que se proporcionan argumentos. Use los nombres de los marcadores de posición, no números.
[HttpGet("{id}")]
public async Task<ActionResult<TodoItemDTO>> GetTodoItem(long id)
{
_logger.LogInformation(MyLogEvents.GetItem, "Getting item {Id}", id);
var todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null)
{
_logger.LogWarning(MyLogEvents.GetItemNotFound, "Get({Id}) NOT FOUND", id);
return NotFound();
}
return ItemToDTO(todoItem);
}
El orden de los parámetros, no sus nombres de marcador de posición, determina qué parámetros se usan para proporcionar valores de marcador de posición en los mensajes de registro. En el código siguiente, los nombres de parámetro están fuera de la secuencia en los marcadores de posición de la plantilla de mensaje:
var apples = 1;
var pears = 2;
var bananas = 3;
_logger.LogInformation("Parameters: {pears}, {bananas}, {apples}", apples, pears, bananas);
Sin embargo, los parámetros se asignan a los marcadores de posición en el orden: apples
, pears
, bananas
. El mensaje de registro refleja el orden de los parámetros:
Parameters: 1, 2, 3
Este enfoque permite a los proveedores de registro implementar registro semántico o estructurado. Los propios argumentos se pasan al sistema de registro, no solo a la plantilla de mensaje con formato. Esto permite a los proveedores de registro almacenar los valores de parámetro como campos. Por ejemplo, tomemos el siguiente método de registrador:
_logger.LogInformation("Getting item {Id} at {RequestTime}", id, DateTime.Now);
Por ejemplo, al registrar en Azure Table Storage:
- Cada entidad de Azure Table puede tener propiedades
ID
yRequestTime
. - Las tablas con propiedades simplifican las consultas en los datos registrados. Por ejemplo, una consulta puede buscar todos los registros dentro de un intervalo
RequestTime
determinado sin necesidad de analizar el tiempo de espera del mensaje de texto.
Registro de excepciones
Los métodos de registrador tienen sobrecargas que toman un parámetro de excepción:
[HttpGet("{id}")]
public IActionResult TestExp(int id)
{
var routeInfo = ControllerContext.ToCtxString(id);
_logger.LogInformation(MyLogEvents.TestItem, routeInfo);
try
{
if (id == 3)
{
throw new Exception("Test exception");
}
}
catch (Exception ex)
{
_logger.LogWarning(MyLogEvents.GetItemNotFound, ex, "TestExp({Id})", id);
return NotFound();
}
return ControllerContext.MyDisplayRouteInfo();
}
El paquete NuGet Rick.Docs.Samples.RouteInfo proporciona MyDisplayRouteInfo y ToCtxString. Los métodos muestran la información de ruta de Controller
y Razor Page
.
El registro de excepciones es específico del proveedor.
Nivel de registro predeterminado
Si no se establece el nivel de registro predeterminado, su valor será Information
.
Por ejemplo, considere la siguiente aplicación web:
- Creada con las plantillas de aplicación web de ASP.NET.
appsettings.json
yappsettings.Development.json
se eliminaron o se les cambió el nombre.
Con la configuración anterior, al navegar a la página de privacidad o de inicio, se generan muchos mensajes de Trace
, Debug
y Information
con Microsoft
en el nombre de la categoría.
El código siguiente establece el nivel de registro predeterminado cuando este no se establece en la configuración:
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureLogging(logging => logging.SetMinimumLevel(LogLevel.Warning))
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
En general, los niveles de registro se deben especificar en la configuración y no en el código.
Función de filtro
Se invoca una función de filtro para todos los proveedores y las categorías que no tienen reglas asignadas mediante configuración o código:
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureLogging(logging =>
{
logging.AddFilter((provider, category, logLevel) =>
{
if (provider.Contains("ConsoleLoggerProvider")
&& category.Contains("Controller")
&& logLevel >= LogLevel.Information)
{
return true;
}
else if (provider.Contains("ConsoleLoggerProvider")
&& category.Contains("Microsoft")
&& logLevel >= LogLevel.Information)
{
return true;
}
else
{
return false;
}
});
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
El código anterior muestra los registros de la consola cuando la categoría contiene Controller
o Microsoft
y el nivel de registro es Information
o superior.
En general, los niveles de registro se deben especificar en la configuración y no en el código.
Categorías EF Core y ASP.NET Core
La tabla siguiente conti9ene algunas categorías usadas por ASP.NET Core y Entity Framework Core, con notas sobre los registros:
Categoría | Notas |
---|---|
Microsoft.AspNetCore | Diagnósticos generales de ASP.NET Core. |
Microsoft.AspNetCore.DataProtection | Qué claves se tuvieron en cuenta, encontraron y usaron. |
Microsoft.AspNetCore.HostFiltering | Hosts permitidos. |
Microsoft.AspNetCore.Hosting | Cuánto tiempo tardaron en completarse las solicitudes HTTP y a qué hora comenzaron. Qué ensamblados de inicio de hospedaje se cargaron. |
Microsoft.AspNetCore.Mvc | Diagnósticos de MVC y Razor. Enlace de modelos, ejecución de filtros, compilación de vistas y selección de acciones. |
Microsoft.AspNetCore.Routing | Información de coincidencia de ruta. |
Microsoft.AspNetCore.Server | Inicio y detención de conexión y mantener las respuestas activas. Información de certificado HTTPS. |
Microsoft.AspNetCore.StaticFiles | Archivos servidos. |
Microsoft.EntityFrameworkCore | Diagnósticos generales de Entity Framework Core. Actividad y la configuración de bases de datos, detección de cambios y migraciones. |
Para ver más categorías en la ventana de la consola, establezca appsettings.Development.json
en lo siguiente:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Trace",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}
Ámbitos de registro
Un ámbito puede agrupar un conjunto de operaciones lógicas. Esta agrupación se puede utilizar para adjuntar los mismos datos para cada registro que se crea como parte de un conjunto. Por ejemplo, cada registro creado como parte del procesamiento de una transacción puede incluir el identificador de dicha transacción.
Un ámbito:
- es un tipo IDisposable devuelto por el método BeginScope;
- se mantiene hasta que se elimina.
Los siguientes proveedores admiten ámbitos:
Use un ámbito encapsulando las llamadas de registrador en un bloque using
:
[HttpGet("{id}")]
public async Task<ActionResult<TodoItemDTO>> GetTodoItem(long id)
{
TodoItem todoItem;
var transactionId = Guid.NewGuid().ToString();
using (_logger.BeginScope(new List<KeyValuePair<string, object>>
{
new KeyValuePair<string, object>("TransactionId", transactionId),
}))
{
_logger.LogInformation(MyLogEvents.GetItem, "Getting item {Id}", id);
todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null)
{
_logger.LogWarning(MyLogEvents.GetItemNotFound,
"Get({Id}) NOT FOUND", id);
return NotFound();
}
}
return ItemToDTO(todoItem);
}
Proveedores de registro integrados
ASP.NET Core incluye los siguientes proveedores de registro como parte del marco compartido:
Microsoft envía los siguientes proveedores de registro, pero no como parte del marco compartido. Deben instalarse como NuGet adicional.
ASP.NET Core no incluye un proveedor de registro para escribir registros en archivos. Para escribir registros en archivos desde una aplicación ASP.NET Core, considere la posibilidad de usar un proveedor de registro de terceros.
Para obtener información sobre stdout
y depurar el registro con el módulo ASP.NET Core, consulte Solución de problemas de ASP.NET Core en Azure App Service e IIS y Módulo ASP.NET Core (ANCM) para IIS.
Consola
El proveedor Console
registra la salida en la consola. Para obtener más información sobre cómo ver los registros de Console
en desarrollo, consulte Registro de la salida de dotnet run y Visual Studio.
Depuración
El proveedor Debug
escribe la salida del registro mediante la clase System.Diagnostics.Debug. Las llamadas a System.Diagnostics.Debug.WriteLine
escriben en el proveedor Debug
.
En Linux, la ubicación del registro del proveedor Debug
depende de la distribución y puede ser una de las siguientes:
- /var/log/message
- /var/log/syslog
Origen de eventos
El proveedor EventSource
escribe en un origen de eventos multiplataforma con el nombre Microsoft-Extensions-Logging
. En Windows, el proveedor utiliza ETW.
herramienta de seguimiento de dotnet
La herramienta de seguimiento de dotnet es una herramienta global de CLI multiplataforma que permite la recopilación de seguimientos de .NET Core de un proceso en ejecución. La herramienta recopila datos del proveedor Microsoft.Extensions.Logging.EventSource mediante un LoggingEventSource.
Vea dotnet-trace para obtener instrucciones de instalación.
Use la herramienta de seguimiento de dotnet para recopilar un seguimiento de una aplicación:
Ejecute la aplicación con el comando
dotnet run
.Determine el identificador del proceso (PID) de la aplicación .NET Core:
dotnet trace ps
Busque el PID del proceso que tenga el mismo nombre que el ensamblado de la aplicación.
Ejecute el comando
dotnet trace
.Sintaxis general del comando:
dotnet trace collect -p {PID} --providers Microsoft-Extensions-Logging:{Keyword}:{Provider Level} :FilterSpecs=\" {Logger Category 1}:{Category Level 1}; {Logger Category 2}:{Category Level 2}; ... {Logger Category N}:{Category Level N}\"
Al usar un shell de comandos de PowerShell, incluya el valor
--providers
entre comillas simples ('
):dotnet trace collect -p {PID} --providers 'Microsoft-Extensions-Logging:{Keyword}:{Provider Level} :FilterSpecs=\" {Logger Category 1}:{Category Level 1}; {Logger Category 2}:{Category Level 2}; ... {Logger Category N}:{Category Level N}\"'
En plataformas que no sean Windows, agregue la opción
-f speedscope
para cambiar el formato del archivo de seguimiento de salida aspeedscope
.En la tabla siguiente se define la palabra clave:
Palabra clave Descripción 1 Registre los eventos meta sobre el elemento LoggingEventSource
. No registre eventos deILogger
.2 Activa el evento Message
cuando se llama aILogger.Log()
. Proporciona la información mediante programación (sin formato).4 Activa el evento FormatMessage
cuando se llama aILogger.Log()
. Proporciona la versión de cadena con formato de la información.8 Activa el evento MessageJson
cuando se llama aILogger.Log()
. Proporciona una representación JSON de los argumentos.En la tabla siguiente se enumeran los niveles de proveedor:
Nivel de proveedor Descripción 0 LogAlways
1 Critical
2 Error
3 Warning
4 Informational
5 Verbose
El análisis de un nivel de categoría puede ser una cadena o un número:
Valor con nombre de categoría Valor numérico Trace
0 Debug
1 Information
2 Warning
3 Error
4 Critical
5 Nivel de proveedor y nivel de categoría:
- Están en orden inverso.
- Las constantes de cadena no son todas idénticas.
Si no se especifica ningún
FilterSpecs
, la implementaciónEventSourceLogger
intenta convertir el nivel de proveedor en un nivel de categoría y lo aplica a todas las categorías.Nivel de proveedor Nivel de categoría Verbose
(5)Debug
(1)Informational
(4)Information
(2)Warning
(3)Warning
(3)Error
(2)Error
(4)Critical
(1)Critical
(5)Si se proporciona
FilterSpecs
, cualquier categoría incluida en la lista usa el nivel de categoría codificado allí, todas las demás categorías se filtran.En los ejemplos siguientes se da por supuesto:
- Una aplicación está en ejecución y llamando a
logger.LogDebug("12345")
. - El identificador de proceso (PID) se ha establecido a través de
set PID=12345
, donde12345
es el PID real.
Observe el comando siguiente:
dotnet trace collect -p %PID% --providers Microsoft-Extensions-Logging:4:5
El comando anterior:
- Captura los mensajes de depuración.
- No aplica un
FilterSpecs
. - Especifica el nivel 5 que asigna la categoría Depurar.
Observe el comando siguiente:
dotnet trace collect -p %PID% --providers Microsoft-Extensions-Logging:4:5:\"FilterSpecs=*:5\"
El comando anterior:
- No captura mensajes de depuración porque el nivel de categoría 5 es
Critical
. - Proporciona un
FilterSpecs
.
El comando siguiente captura los mensajes de depuración porque el nivel de categoría 1 especifica
Debug
.dotnet trace collect -p %PID% --providers Microsoft-Extensions-Logging:4:5:\"FilterSpecs=*:1\"
El comando siguiente captura los mensajes de depuración porque la categoría especifica
Debug
.dotnet trace collect -p %PID% --providers Microsoft-Extensions-Logging:4:5:\"FilterSpecs=*:Debug\"
Las entradas
FilterSpecs
de{Logger Category}
y{Category Level}
representan condiciones de filtrado de registros adicionales. Separe las entradasFilterSpecs
con el carácter de punto y coma;
.Ejemplo de uso de un shell de comandos de Windows:
dotnet trace collect -p %PID% --providers Microsoft-Extensions-Logging:4:2:FilterSpecs=\"Microsoft.AspNetCore.Hosting*:4\"
El comando anterior activa lo siguiente:
- Registrador de origen del evento para generar cadenas con formato (
4
) de los errores (2
). - Registro
Microsoft.AspNetCore.Hosting
en el nivel de registroInformational
(4
).
Presione la tecla Entrar o Ctrl + C para detener las herramientas de seguimiento de dotnet.
El seguimiento se guarda con el nombre trace.nettrace en la carpeta en la que se ejecuta el comando
dotnet trace
.Abra el seguimiento con Perfview. Abra el archivo trace.nettrace y explore los eventos de seguimiento.
Si la aplicación no compila el host con CreateDefaultBuilder
, agregue el proveedor de origen del evento a la configuración de registro de la aplicación.
Para obtener más información, consulte:
- Seguimiento de la utilidad de análisis de rendimiento (dotnet-trace) (documentación de .NET Core)
- Seguimiento de la utilidad de análisis de rendimiento (dotnet-trace) (documentación del repositorio de GitHub sobre diagnóstico y dotnet)
- Clase LoggingEventSource (Explorador de API de .NET)
- EventLevel
- Origen de referencia de LoggingEventSource (3.0): Para obtener el origen de referencia de otra versión, cambie la rama a
release/{Version}
, donde{Version}
corresponde a la versión de ASP.NET Core deseada. - Perfview: es útil para ver los seguimientos del origen de eventos.
Perfview
Use la utilidad PerfView para recopilar y ver los registros. Hay otras herramientas para ver los registros ETW, pero PerfView proporciona la mejor experiencia para trabajar con los eventos ETW emitidos por ASP.NET Core.
Para configurar PerfView para la recopilación de eventos registrados por este proveedor, agregue la cadena *Microsoft-Extensions-Logging
a la lista Proveedores adicionales. No olvide el símbolo *
al principio de la cadena.
Registro de eventos de Windows
El proveedor EventLog
envía la salida del registro al Registro de eventos de Windows. A diferencia de otros proveedores, el proveedor EventLog
no hereda la configuración de no proveedor predeterminada. Si no se especifican valores de registro de EventLog
, el valor predeterminado será LogLevel.Warning.
Para registrar eventos inferiores a LogLevel.Warning, establezca el nivel de registro de forma explícita. En el ejemplo siguiente se establece el nivel de registro predeterminado del registro de eventos en LogLevel.Information:
"Logging": {
"EventLog": {
"LogLevel": {
"Default": "Information"
}
}
}
Las sobrecargas de AddEventLog pueden pasar EventLogSettings. Si es null
o no se especifica, se usa la siguiente configuración predeterminada:
LogName
: "Application"SourceName
: ".NET Runtime"MachineName
: se usa el nombre del equipo local.
En el código siguiente se cambia el valor predeterminado de SourceName
(".NET Runtime"
) por MyLogs
:
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureLogging(logging =>
{
logging.AddEventLog(eventLogSettings =>
{
eventLogSettings.SourceName = "MyLogs";
});
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
Azure App Service
El paquete de proveedor Microsoft.Extensions.Logging.AzureAppServices escribe los registros en archivos de texto en el sistema de archivos de una aplicación de Azure App Service y en Blob Storage en una cuenta de Azure Storage.
El paquete del proveedor no se incluye en el marco compartido. Para usar el proveedor, agregue el paquete del proveedor al proyecto.
Para configurar las opciones de proveedor, use AzureFileLoggerOptions y AzureBlobLoggerOptions, tal y como se muestra en el ejemplo siguiente:
public class Scopes
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureLogging(logging => logging.AddAzureWebAppDiagnostics())
.ConfigureServices(serviceCollection => serviceCollection
.Configure<AzureFileLoggerOptions>(options =>
{
options.FileName = "azure-diagnostics-";
options.FileSizeLimit = 50 * 1024;
options.RetainedFileCountLimit = 5;
})
.Configure<AzureBlobLoggerOptions>(options =>
{
options.BlobName = "log.txt";
}))
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}
Cuando se implementa en Azure App Service, la aplicación usa la configuración de la sección Registros de App Service de la página App Service de Azure Portal. Cuando se actualiza la configuración siguiente, los cambios se aplican de inmediato sin necesidad de reiniciar ni de volver a implementar la aplicación.
- Registro de la aplicación (sistema de archivos)
- Registro de la aplicación (blob)
La ubicación predeterminada de los archivos de registro es la carpeta D:\home\LogFiles\Application y el nombre de archivo predeterminado es diagnostics-yyyymmdd.txt. El límite de tamaño de archivo predeterminado es 10 MB, y el número máximo predeterminado de archivos que se conservan es 2. El nombre de blob predeterminado es {nombre-de-la-aplicación}{marca de tiempo}/aaaa/mm/dd/hh/{guid}-applicationLog.txt.
El proveedor solo realiza registros cuando el proyecto se ejecuta en el entorno de Azure.
Secuencias de registro de Azure
El streaming de registro de Azure permiten ver la actividad de registro en tiempo real desde:
- El servidor de aplicaciones
- El servidor web
- Error del seguimiento de solicitudes
Para configurar las secuencias de registro de Azure:
- Desplácese a la página Registros de App Service desde la página del portal de la aplicación.
- Establezca Registro de la aplicación (sistema de archivos) en Activado.
- Elija el Nivel de registro. Esta configuración solo se aplica al streaming de registro de Azure.
Desplácese a la página Secuencia de registro para ver los registros. Los mensajes que se registran lo hacen con la interfaz ILogger
.
Azure Application Insights
El paquete de proveedor Microsoft.Extensions.Logging.ApplicationInsights escribe los registros en Azure Application Insights. Application Insights es un servicio que supervisa una aplicación web y proporciona herramientas para consultar y analizar los datos de telemetría. Si usa este proveedor, puede consultar y analizar los registros mediante las herramientas de Application Insights.
El proveedor de registro se incluye como dependencia de Microsoft.ApplicationInsights.AspNetCore, que es el paquete que proporciona toda la telemetría disponible para ASP.NET Core. Si usa este paquete, no tiene que instalar el proveedor de paquete.
El paquete Microsoft.ApplicationInsights.Web es para ASP.NET 4.x, no para ASP.NET Core.
Para obtener más información, vea los siguientes recursos:
- Información general de Application Insights
- Application Insights para aplicaciones de ASP.NET Core: comience aquí si quiere implementar la variedad completa de telemetría de Application Insights junto con el registro.
- ApplicationInsightsLoggerProvider para los registros de .NET Core ILogger: comience aquí si quiere implementar el proveedor de registro sin el resto de la telemetría de Application Insights.
- Adaptadores de registro de Application Insights
- Tutorial interactivo Instalación, configuración e inicialización del SDK de Application Insights.
Proveedores de registro de terceros
Plataformas de registro de terceros que funcionan con ASP.NET Core:
- elmah.io (repositorio de GitHub)
- Gelf (repositorio de GitHub)
- JSNLog (repositorio de GitHub)
- KissLog.net (repositorio de GitHub)
- Log4Net (repositorio de GitHub)
- NLog (repositorio de GitHub)
- PLogger (repositorio de GitHub)
- Sentry (repositorio de GitHub)
- Serilog (repositorio de GitHub)
- Stackdriver (repositorio de GitHub)
Algunas plataformas de terceros pueden realizar registro semántico, también conocido como registro estructurado.
El uso de una plataforma de terceros es similar al uso de uno de los proveedores integrados:
- Agregue un paquete NuGet al proyecto.
- Llame a un método de extensión
ILoggerFactory
proporcionado por el marco de registro.
Para más información, vea la documentación de cada proveedor. Microsoft no admite los proveedores de registro de terceros.
Aplicación de consola que no es de host
Para ver un ejemplo de cómo usar el host genérico en una aplicación de consola que no sea web, vea el archivo Program.cs
de la aplicación de ejemplo de tareas en segundo plano (Tareas en segundo plano con servicios hospedados en ASP.NET Core).
El código de registro para las aplicaciones sin un host genérico es distinto en la forma en que se agregan los proveedores y se crean los registradores.
Proveedores de registro
En una aplicación de consola que no sea de host, llame al método de extensión Add{provider name}
del proveedor al crear un elemento LoggerFactory
:
class Program
{
static void Main(string[] args)
{
using var loggerFactory = LoggerFactory.Create(builder =>
{
builder
.AddFilter("Microsoft", LogLevel.Warning)
.AddFilter("System", LogLevel.Warning)
.AddFilter("LoggingConsoleApp.Program", LogLevel.Debug)
.AddConsole()
.AddEventLog();
});
ILogger logger = loggerFactory.CreateLogger<Program>();
logger.LogInformation("Example log message");
}
}
Creación de registros
Para crear registros, use un objeto de ILogger<TCategoryName>. Use LoggerFactory
para crear ILogger
.
En el ejemplo siguiente, se crea un registrador con LoggingConsoleApp.Program
como la categoría.
class Program
{
static void Main(string[] args)
{
using var loggerFactory = LoggerFactory.Create(builder =>
{
builder
.AddFilter("Microsoft", LogLevel.Warning)
.AddFilter("System", LogLevel.Warning)
.AddFilter("LoggingConsoleApp.Program", LogLevel.Debug)
.AddConsole()
.AddEventLog();
});
ILogger logger = loggerFactory.CreateLogger<Program>();
logger.LogInformation("Example log message");
}
}
En el ejemplo siguiente, el registrador se usa para crear registros con nivel de Information
. El nivel de registro indica la gravedad del evento registrado.
class Program
{
static void Main(string[] args)
{
using var loggerFactory = LoggerFactory.Create(builder =>
{
builder
.AddFilter("Microsoft", LogLevel.Warning)
.AddFilter("System", LogLevel.Warning)
.AddFilter("LoggingConsoleApp.Program", LogLevel.Debug)
.AddConsole()
.AddEventLog();
});
ILogger logger = loggerFactory.CreateLogger<Program>();
logger.LogInformation("Example log message");
}
}
Los niveles y las categorías se explican con más detalle en este documento.
Registro durante la construcción del host
No se admite directamente el registro durante la construcción del host. Sin embargo, se puede usar un registrador independiente. En el ejemplo siguiente, se usa un registrador Serilog para registrarse en CreateHostBuilder
. AddSerilog
usa la configuración estática especificada en Log.Logger
:
using System;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args)
{
var builtConfig = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddCommandLine(args)
.Build();
Log.Logger = new LoggerConfiguration()
.WriteTo.Console()
.WriteTo.File(builtConfig["Logging:FilePath"])
.CreateLogger();
try
{
return Host.CreateDefaultBuilder(args)
.ConfigureServices((context, services) =>
{
services.AddRazorPages();
})
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.AddConfiguration(builtConfig);
})
.ConfigureLogging(logging =>
{
logging.AddSerilog();
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
catch (Exception ex)
{
Log.Fatal(ex, "Host builder error");
throw;
}
finally
{
Log.CloseAndFlush();
}
}
}
Configuración de un servicio que dependa de ILogger
La inserción del constructor de un registrador en Startup
funciona en versiones anteriores de ASP.NET Core, ya que se crea un contenedor de inserción de dependencias independiente para el host de web. Para conocer por qué solo se crea un contenedor para el host genérico, vea el anuncio de cambios importantes.
Para configurar un servicio que dependa de ILogger<T>
, use la inserción de constructores o proporcione un método Factory. Usar un Factory Method es la opción recomendada si no tiene otra alternativa. Por ejemplo, tomemos un servicio que necesita una instancia de ILogger<T>
proporcionada por DI:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddRazorPages();
services.AddSingleton<IMyService>((container) =>
{
var logger = container.GetRequiredService<ILogger<MyService>>();
return new MyService() { Logger = logger };
});
}
El código resaltado anterior es un elemento Func<T,TResult> que se ejecuta la primera vez que el contenedor de inserción de dependencias necesita crear una instancia de MyService
. Puede acceder a cualquiera de los servicios registrados de esta forma.
Creación de registros en Main
El código siguiente registra en Main
mediante la obtención de una instancia de ILogger
de inserción de dependencias después de compilar el host:
public static void Main(string[] args)
{
var host = CreateHostBuilder(args).Build();
var logger = host.Services.GetRequiredService<ILogger<Program>>();
logger.LogInformation("Host created.");
host.Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
Creación de registros durante el inicio
El código siguiente escribe registros en Startup.Configure
:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env,
ILogger<Startup> logger)
{
if (env.IsDevelopment())
{
logger.LogInformation("In Development.");
app.UseDeveloperExceptionPage();
}
else
{
logger.LogInformation("Not Development.");
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapRazorPages();
});
}
No se admite la escritura de registros antes de la finalización del contenedor de inserción de dependencias configurado en el método Startup.ConfigureServices
:
- No se admite la inyección del registrador en el constructor
Startup
. - No se admite la inyección del registrador en la signatura del método
Startup.ConfigureServices
.
El motivo de esta restricción es que los registros dependen de la inserción de dependencias y de la configuración, que a su vez depende de la inserción de dependencias. El contenedor de inserción de dependencias no se configura hasta que finaliza ConfigureServices
.
Para obtener información sobre la configuración de un servicio que depende de ILogger<T>
o sobre el motivo de que la inserción de constructor de un registrador en Startup
funcionase en versiones anteriores, vea Configuración de un servicio que depende de ILogger
No hay métodos de registrador asincrónicos
El registro debe ser tan rápido que no merezca la pena el costo de rendimiento del código asincrónico. Si el almacén de datos de registro es lento, no escriba directamente en él. Considere la posibilidad de escribir primero los mensajes de registro en un almacén rápido y, después, moverlos al almacén lento. Por ejemplo, al iniciar sesión en SQL Server, no lo haga directamente en un método Log
, ya que los métodos Log
son sincrónicos. En su lugar, agregue sincrónicamente mensajes de registro a una cola en memoria y haga que un trabajo en segundo plano extraiga los mensajes de la cola para realizar el trabajo asincrónico de insertar datos en SQL Server. Para obtener más información, vea este problema de GitHub.
Cambio de los niveles de registro en una aplicación en ejecución
La API de registro no incluye un escenario que permita cambiar los niveles de registro mientras se ejecuta una aplicación. No obstante, algunos proveedores de configuración pueden volver a cargar la configuración, lo que tiene efecto inmediato en la configuración del registro. Por ejemplo, el Proveedor de configuración de archivo vuelve a cargar la configuración de registro de forma predeterminada. Si se cambia la configuración en el código mientras se ejecuta una aplicación, la aplicación puede llamar a IConfigurationRoot.Reload para actualizar la configuración de registro de la aplicación.
ILogger e ILoggerFactory
Las implementaciones y las interfaces de ILogger<TCategoryName> y ILoggerFactory se incluyen en el SDK de .NET Core. También están disponibles en los siguientes paquetes NuGet:
- Las interfaces están en Microsoft.Extensions.Logging.Abstractions.
- Las implementaciones predeterminadas se encuentran en Microsoft.Extensions.Logging.
Aplicación de reglas de filtro en el código
El método preferido para establecer las reglas de filtro de registro es mediante la Configuración.
En el siguiente ejemplo se muestra cómo registrar reglas de filtro en el código:
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureLogging(logging =>
logging.AddFilter("System", LogLevel.Debug)
.AddFilter<DebugLoggerProvider>("Microsoft", LogLevel.Information)
.AddFilter<ConsoleLoggerProvider>("Microsoft", LogLevel.Trace))
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
logging.AddFilter("System", LogLevel.Debug)
especifica la categoría System
y el nivel de registro Debug
. El filtro se aplica a todos los proveedores porque no se ha configurado un proveedor específico.
AddFilter<DebugLoggerProvider>("Microsoft", LogLevel.Information)
especifica:
- El proveedor de registro
Debug
. - Nivel de registro
Information
y superiores. - Todas las categorías que empiezan con
"Microsoft"
.
Registro automático del ámbito con SpanId, TraceId y ParentId
Las bibliotecas de registro crean implícitamente un objeto de ámbito con SpanId
, TraceId
y ParentId
. Este comportamiento se configura a través de ActivityTrackingOptions.
var loggerFactory = LoggerFactory.Create(logging =>
{
logging.Configure(options =>
{
options.ActivityTrackingOptions = ActivityTrackingOptions.SpanId
| ActivityTrackingOptions.TraceId
| ActivityTrackingOptions.ParentId;
}).AddSimpleConsole(options =>
{
options.IncludeScopes = true;
});
});
Si se establece el encabezado de solicitud HTTP traceparent
, ParentId
en el ámbito del registro muestra el W3C parent-id
desde el encabezado traceparent
enlazado y SpanId
en el ámbito de registro muestra el parent-id
actualizado para el siguiente paso o intervalo fuera de enlace. Para obtener más información, vea Mutación del campo de seguimiento primario.
Creación de un registrador personalizado
Para obtener más información, consulte Implementación de un proveedor de registro personalizado en .NET.
Recursos adicionales
- Registro de alto rendimiento
- Los errores de registro deben crearse en el repositorio github.com/dotnet/runtime/.
- Registro de Blazor en ASP.NET Core