Treinamento
Módulo
Formatar dados alfanuméricos para apresentação em C# - Training
Explore métodos básicos em C# para formatar dados alfanuméricos.
Não há mais suporte para esse navegador.
Atualize o Microsoft Edge para aproveitar os recursos, o suporte técnico e as atualizações de segurança mais recentes.
O .NET dá suporte ao registro em log estruturado e de alto desempenho por meio da API ILogger para ajudar a monitorar o comportamento do aplicativo e diagnosticar problemas. Os logs poderão ser gravados em destinos diferentes se você configurar provedores de registro em log diferentes. Os provedores básicos de registro em log são integrados e também existem muitos provedores de terceiros disponíveis.
Este primeiro exemplo mostra as noções básicas, mas é adequado apenas para um aplicativo de console trivial. Este aplicativo de console de amostra depende dos seguintes pacotes NuGet:
Na próxima seção, você verá como aprimorar o código levando em conta a escala, o desempenho, a configuração e os padrões de programação típicos.
using Microsoft.Extensions.Logging;
using ILoggerFactory factory = LoggerFactory.Create(builder => builder.AddConsole());
ILogger logger = factory.CreateLogger("Program");
logger.LogInformation("Hello World! Logging is {Description}.", "fun");
No exemplo anterior:
ILoggerFactory
armazena toda a configuração que determina para onde as mensagens de log são enviadas. Nesse caso, você configura o provedor de registro em log do console para que as mensagens de log sejam gravadas no console.string
associada a cada mensagem registrada em log pelo objeto ILogger
. É usada para agrupar mensagens de log da mesma classe (ou categoria) ao pesquisar ou filtrar logs.Information
. O nível de log indica a gravidade do evento registrado em log e é usado para filtrar e deixar de fora as mensagens de log menos importantes. A entrada de registro também inclui um modelo de mensagem "Hello World! Logging is {Description}."
e um par de chave-valor Description = fun
. O nome da chave (ou espaço reservado) vem da palavra entre chaves no modelo e o valor vem do argumento de método restante.Este arquivo de projeto para este exemplo inclui dois pacotes NuGet:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="9.0.0" />
</ItemGroup>
</Project>
Dica
Todo o código-fonte do exemplo de log está disponível no Navegador de Exemplos para download. Para obter mais informações, confira Procurar exemplos de código: log no .NET.
Há várias alterações que você deve pensar em fazer no exemplo anterior ao registrar em log em um cenário menos trivial:
Se o seu aplicativo estiver usando Injeção de Dependência (DI) ou um host como o WebApplication ou um Host Genérico do ASP.NET, você deve usar objetos ILoggerFactory
e ILogger
de seus respectivos contêineres de DI em vez de criá-los diretamente. Para obter mais informações, confira Integração com DI e Hosts.
O registro em log da geração da origem do tempo de compilação costuma ser uma alternativa melhor do que os métodos de extensão do ILogger
, como LogInformation
. A geração da origem do registro em log oferece um melhor desempenho, uma digitação mais sólida e evita a propagação de constantes de string
em todos os seus métodos. A desvantagem é que usar essa técnica requer um pouco mais de código.
using Microsoft.Extensions.Logging;
internal partial class Program
{
static void Main(string[] args)
{
using ILoggerFactory factory = LoggerFactory.Create(builder => builder.AddConsole());
ILogger logger = factory.CreateLogger("Program");
LogStartupMessage(logger, "fun");
}
[LoggerMessage(Level = LogLevel.Information, Message = "Hello World! Logging is {Description}.")]
static partial void LogStartupMessage(ILogger logger, string description);
}
Type
para tornar essa nomenclatura fácil de fazer.using Microsoft.Extensions.Logging;
internal class Program
{
static void Main(string[] args)
{
using ILoggerFactory factory = LoggerFactory.Create(builder => builder.AddConsole());
ILogger logger = factory.CreateLogger<Program>();
logger.LogInformation("Hello World! Logging is {Description}.", "fun");
}
}
using Microsoft.Extensions.Logging;
using OpenTelemetry.Logs;
using ILoggerFactory factory = LoggerFactory.Create(builder =>
{
builder.AddOpenTelemetry(logging =>
{
logging.AddOtlpExporter();
});
});
ILogger logger = factory.CreateLogger("Program");
logger.LogInformation("Hello World! Logging is {Description}.", "fun");
Se o seu aplicativo estiver usando Injeção de Dependência (DI) ou um host como o WebApplication ou um Host Genérico do ASP.NET, você deve usar objetos ILoggerFactory
e ILogger
do contêiner de DI em vez de criá-los diretamente.
Esse exemplo obtém um objeto ILogger em um aplicativo hospedado usando APIs Mínimas do ASP.NET:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<ExampleHandler>();
var app = builder.Build();
var handler = app.Services.GetRequiredService<ExampleHandler>();
app.MapGet("/", handler.HandleRequest);
app.Run();
partial class ExampleHandler(ILogger<ExampleHandler> logger)
{
public string HandleRequest()
{
LogHandleRequest(logger);
return "Hello World";
}
[LoggerMessage(LogLevel.Information, "ExampleHandler.HandleRequest was called")]
public static partial void LogHandleRequest(ILogger logger);
}
No exemplo anterior:
ExampleHandler
e mapeou as solicitações da web recebidas para executar a função ExampleHandler.HandleRequest
.ILogger<ExampleHandler>
. ILogger<TCategoryName> deriva de ILogger e indica qual categoria o objeto ILogger
tem. O contêiner de DI localiza um ILogger
com a categoria correta e o fornece como o argumento do construtor. Se nenhum ILogger
com essa categoria já existir, o contêiner de DI o criará automaticamente a partir do ILoggerFactory
no provedor de serviços.logger
recebido no construtor foi usado para registrar em log na função HandleRequest
.Os construtores de host inicializam a configuração padrão e, em seguida, adicionam um objeto ILoggerFactory
configurado ao contêiner de DI do host quando o host é criado. Antes de o host ser criado, você pode ajustar a configuração de registro em log por meio de HostApplicationBuilder.Logging, WebApplicationBuilder.Logging ou APIs semelhantes em outros hosts. Os hosts também aplicam a configuração do registro em log das fontes de configuração padrão, como appsettings.json, e variáveis de ambiente. Para obter mais informações, confira Configuração no .NET.
Esse exemplo se expande a partir do anterior para personalizar o ILoggerFactory
fornecido pelo WebApplicationBuilder
. Adiciona o OpenTelemetry como um provedor de registro em log que transmite os logs por meio do Protocolo OpenTelemetry (OTLP):
var builder = WebApplication.CreateBuilder(args);
builder.Logging.AddOpenTelemetry(logging => logging.AddOtlpExporter());
builder.Services.AddSingleton<ExampleHandler>();
var app = builder.Build();
Se estiver usando um contêiner de DI sem um host, use AddLogging para configurar e adicionar um ILoggerFactory
ao contêiner.
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
// Add services to the container including logging
var services = new ServiceCollection();
services.AddLogging(builder => builder.AddConsole());
services.AddSingleton<ExampleService>();
IServiceProvider serviceProvider = services.BuildServiceProvider();
// Get the ExampleService object from the container
ExampleService service = serviceProvider.GetRequiredService<ExampleService>();
// Do some pretend work
service.DoSomeWork(10, 20);
class ExampleService(ILogger<ExampleService> logger)
{
public void DoSomeWork(int x, int y)
{
logger.LogInformation("DoSomeWork was called. x={X}, y={Y}", x, y);
}
}
No exemplo anterior:
ILoggerFactory
configurado para gravar no consoleExampleService
ao contêinerExampleService
do contêiner de DI que também criou automaticamente um ILogger<ExampleService>
a ser usado como o argumento do construtor.ExampleService.DoSomeWork
que usou o ILogger<ExampleService>
para registrar uma mensagem no console.A configuração do registro em log é definida no código ou por meio de fontes externas, como, por exemplo, arquivos de configuração e variáveis de ambiente. O uso da configuração externa é benéfico sempre que possível porque pode ser alterado sem ser preciso recompilar o aplicativo. No entanto, algumas tarefas, como definir provedores de registro em log, só podem ser configuradas a partir do código.
No caso de arquivos que usam um host, a configuração do registro em log geralmente é fornecida pela seção "Logging"
dos arquivos appsettings.{Environment}
.json. Para aplicativos que não usam um host, as fontes de configuração externas são configuradas explicitamente ou, alternativamente, configuradas no código.
O seguinte arquivo appsettings.Development.json é gerado pelos modelos do serviço .NET Worker:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}
No JSON anterior:
"Default"
, "Microsoft"
e "Microsoft.Hosting.Lifetime"
são especificadas."Default"
é aplicado a todas as categorias que não são especificadas de outra forma, efetivamente tornando todos os valores padrão para todas as categorias "Information"
. Você pode substituir esse comportamento especificando um valor para uma categoria."Microsoft"
se aplica a todas as categorias que começam com "Microsoft"
."Microsoft"
registra em log no nível de log Warning
e superior."Microsoft.Hosting.Lifetime"
é mais específica do que a "Microsoft"
, ou seja, a categoria "Microsoft.Hosting.Lifetime"
faz o registro em log no nível "Information"
e superiores.LogLevel
se aplica a todos os provedores de log habilitados, exceto por EventLog do Windows.A propriedade Logging
pode ter LogLevel e as propriedades do provedor de logs. A LogLevel
especifica o nível mínimo de log nas categorias selecionadas. No JSON anterior, os níveis de log Information
e Warning
são especificados. LogLevel
indica a severidade do log e varia de 0 a 6:
Trace
= 0, Debug
= 1, Information
= 2, Warning
= 3, Error
= 4, Critical
= 5 e None
= 6.
Quando um LogLevel
é especificado, o registro em log é habilitado para mensagens no nível especificado e superior. No JSON anterior, a categoria Default
é registrada para Information
e superior. Por exemplo, mensagens Information
, Warning
, Error
e Critical
são registradas em log. Se LogLevel
não for especificado, o registro em log usará o nível Information
como padrão. Para obter mais informações, confira Níveis de log.
Uma propriedade de provedor pode especificar uma propriedade LogLevel
. LogLevel
em um provedor especifica os níveis de log desse provedor e substitui as configurações de log que não são do provedor. Considere o seguinte arquivo appsettings.json:
{
"Logging": {
"LogLevel": {
"Default": "Error",
"Microsoft": "Warning"
},
"Debug": {
"LogLevel": {
"Default": "Information",
"Microsoft.Hosting": "Trace"
}
},
"EventSource": {
"LogLevel": {
"Default": "Warning"
}
}
}
}
As configurações em Logging.{ProviderName}.LogLevel
substituem as configurações em Logging.LogLevel
. No JSON anterior, o nível de log padrão do provedor Debug
é definido como Information
:
Logging:Debug:LogLevel:Default:Information
A configuração anterior especifica o nível de log Information
para todas as categorias de Logging:Debug:
, exceto a Microsoft.Hosting
. Quando uma categoria específica é listada, ela substitui a categoria padrão. No JSON anterior, as categorias "Microsoft.Hosting"
e "Default"
de Logging:Debug:LogLevel
substituem as configurações em Logging:LogLevel
O nível mínimo de log pode ser especificado para:
Logging:EventSource:LogLevel:Default:Information
Logging:LogLevel:Microsoft:Warning
Logging:LogLevel:Default:Warning
Todos os logs abaixo do nível mínimo não são:
Para suprimir todos os logs, especifique LogLevel.None. LogLevel.None
tem o valor 6, que é superior a LogLevel.Critical
(5).
Se um provedor oferecer suporte a escopos de log, IncludeScopes
indicará se eles estão habilitados. Para obter mais informações, confira Escopos de log
O seguinte arquivo appsettings.json contém as configurações de todos os provedores internos:
{
"Logging": {
"LogLevel": {
"Default": "Error",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Warning"
},
"Debug": {
"LogLevel": {
"Default": "Information"
}
},
"Console": {
"IncludeScopes": true,
"LogLevel": {
"Microsoft.Extensions.Hosting": "Warning",
"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"
}
}
}
}
Na amostra anterior:
Logging.{ProviderName}.LogLevel
substituem as configurações em Logging.LogLevel
. Por exemplo, o nível em Debug.LogLevel.Default
substitui o nível em LogLevel.Default
.Console
Debug
EventSource
EventLog
AzureAppServicesFile
AzureAppServicesBlob
ApplicationInsights
O nível de log pode ser definido por qualquer um dos provedores de configuração. Por exemplo, você pode criar uma variável de ambiente persistente chamada Logging:LogLevel:Microsoft
com o valor Information
.
Crie e atribua variáveis de ambiente persistentes, considerando o valor de nível de log.
:: Assigns the env var to the value
setx "Logging__LogLevel__Microsoft" "Information" /M
Em uma nova instância do prompt de comando, leia a variável de ambiente.
:: Prints the env var value
echo %Logging__LogLevel__Microsoft%
A configuração de ambiente anterior é mantida no ambiente. Para testar as configurações ao usar um aplicativo criado com os modelos do serviço .NET Worker, use o comando dotnet run
no diretório do projeto depois que a variável de ambiente for atribuída.
dotnet run
Dica
Depois de definir uma variável de ambiente, reinicie o IDE (ambiente de desenvolvimento integrado) para garantir que as variáveis de ambiente adicionadas recentemente estejam disponíveis.
Em Serviço de Aplicativo do Azure, selecione Nova configuração de aplicativo na página Configuração > Configurações. As configurações do aplicativo do Serviço de Aplicativo do Azure são:
Para obter mais informações de como definir valores de configuração do .NET usando variáveis de ambiente, confira variáveis de ambiente.
Para configurar o registro em log no código, use a API ILoggingBuilder. O recurso pode ser acessado a partir de diferentes locais:
ILoggerFactory
diretamente, configure-o em LoggerFactory.Create.Esse exemplo mostra como configurar o provedor de registro em log do console e diversos filtros.
using Microsoft.Extensions.Logging;
using var loggerFactory = LoggerFactory.Create(static builder =>
{
builder
.AddFilter("Microsoft", LogLevel.Warning)
.AddFilter("System", LogLevel.Warning)
.AddFilter("LoggingConsoleApp.Program", LogLevel.Debug)
.AddConsole();
});
ILogger logger = loggerFactory.CreateLogger<Program>();
logger.LogDebug("Hello {Target}", "Everyone");
No exemplo anterior, AddFilter é usado para ajustar o nível de log que é habilitado para várias categorias. O AddConsole é usado para adicionar o provedor de registro em log do console. Por padrão, os logs com nível de gravidade Debug
não são habilitados, mas como a configuração ajustou os filtros, a mensagem de depuração "Olá, todo mundo" é exibida no console.
Quando um objeto ILogger<TCategoryName> é criado, o objeto ILoggerFactory seleciona uma única regra por provedor para aplicar a esse agente. Todas as mensagens gravadas pela instância ILogger
são filtradas com base nas regras selecionadas. A regra mais específica possível para cada par de categoria e provedor é selecionada entre as regras disponíveis.
O algoritmo a seguir é usado para cada provedor quando um ILogger
é criado para uma determinada categoria:
Quando um objeto ILogger
é criado, uma categoria é especificada. Essa categoria é incluída em cada mensagem de log criada por essa instância de ILogger
. A cadeia de caracteres da categoria é arbitrária, mas a convenção é usar o nome de classe totalmente qualificado. Por exemplo, em um aplicativo com um serviço definido como o seguinte objeto, a categoria pode ser "Example.DefaultService"
:
namespace Example
{
public class DefaultService : IService
{
private readonly ILogger<DefaultService> _logger;
public DefaultService(ILogger<DefaultService> logger) =>
_logger = logger;
// ...
}
}
Se mais categorização for desejada, a convenção é usar um nome hierárquico anexando uma subcategoria ao nome de classe totalmente qualificado e especificar explicitamente a categoria usando LoggerFactory.CreateLogger:
namespace Example
{
public class DefaultService : IService
{
private readonly ILogger _logger;
public DefaultService(ILoggerFactory loggerFactory) =>
_logger = loggerFactory.CreateLogger("Example.DefaultService.CustomCategory");
// ...
}
}
A chamada de CreateLogger
com um nome fixo pode ser útil quando usada em várias classes/tipos para que os eventos possam ser organizados por categoria.
ILogger<T>
é equivalente a chamar CreateLogger
com o nome de tipo totalmente qualificado de T
.
A seguinte tabela lista os valores de LogLevel, o método de extensão de conveniência Log{LogLevel}
e o uso sugerido:
LogLevel | Valor | Método | Descrição |
---|---|---|---|
Trace | 0 | LogTrace | Contêm as mensagens mais detalhadas. Essas mensagens podem conter dados confidenciais do aplicativo. Essas mensagens são desabilitadas por padrão e não devem ser habilitadas em um ambiente de produção. |
Depurar | 1 | LogDebug | Para depuração e desenvolvimento. Use com cuidado em produção devido ao alto volume. |
Informações | 2 | LogInformation | Rastreia o fluxo geral do aplicativo. Pode ter um valor de longo prazo. |
Aviso | 3 | LogWarning | Para eventos anormais ou inesperados. Geralmente, inclui erros ou condições que não fazem com que o aplicativo falhe. |
Erro | 4 | LogError | Para erros e exceções que não podem ser manipulados. Essas mensagens indicam uma falha na operação ou na solicitação atual, não uma falha em todo o aplicativo. |
Crítico | 5 | LogCritical | Para falhas que exigem atenção imediata. Exemplos: cenários de perda de dados, espaço em disco insuficiente. |
Nenhum | 6 | Especifica que nenhuma mensagem deve ser gravada. |
Na tabela anterior, o LogLevel
é listado da severidade menor para a maior.
O primeiro parâmetro do método Log, LogLevel, indica a severidade do log. Em vez de chamar Log(LogLevel, ...)
, a maioria dos desenvolvedores chama os métodos de extensão Log{LogLevel}. Os métodos de extensão Log{LogLevel}
chamam o método Log
e especificam o LogLevel
. Por exemplo, estas duas chamadas de log são equivalentes em funcionalidades e produzem o mesmo log:
public void LogDetails()
{
var logMessage = "Details for log.";
_logger.Log(LogLevel.Information, AppLogEvents.Details, logMessage);
_logger.LogInformation(AppLogEvents.Details, logMessage);
}
AppLogEvents.Details
é a ID do evento e é representada implicitamente por um valor Int32 constante. AppLogEvents
é uma classe que expõe várias constantes de identificador nomeadas e é exibida na seção ID do evento de log.
O código a seguir cria os logs Information
e Warning
:
public async Task<T> GetAsync<T>(string id)
{
_logger.LogInformation(AppLogEvents.Read, "Reading value for {Id}", id);
var result = await _repository.GetAsync(id);
if (result is null)
{
_logger.LogWarning(AppLogEvents.ReadNotFound, "GetAsync({Id}) not found", id);
}
return result;
}
No código anterior, o primeiro Log{LogLevel}
parâmetro, AppLogEvents.Read
, é a ID do evento Log. O segundo parâmetro é um modelo de mensagem com espaços reservados para valores de argumento fornecidos pelos parâmetros de método restantes. Os parâmetros de método serão explicados na seção modelos de mensagem mais adiante neste artigo.
Configure o nível de log apropriado e chame os métodos Log{LogLevel}
corretos para controlar a quantidade de saída de log gravada em um determinado meio de armazenamento. Por exemplo:
Trace
ou Debug
produz um alto volume de mensagens de log detalhadas. Para controlar os custos e não exceder os limites de armazenamento de dados, registre mensagens nos níveis Trace
e Debug
em um armazenamento de dados de alto volume e baixo custo. Considere limitar Trace
e Debug
a categorias específicas.Warning
a Critical
deve produzir poucas mensagens de log.
Warning
.Trace
ou Debug
ao solucionar problemas. Para limitar a saída, defina Trace
ou Debug
somente para as categorias em investigação.O seguinte JSON define Logging:Console:LogLevel:Microsoft:Information
:
{
"Logging": {
"LogLevel": {
"Microsoft": "Warning"
},
"Console": {
"LogLevel": {
"Microsoft": "Information"
}
}
}
}
Cada log pode especificar um identificador de evento. EventId é uma estrutura com a propriedade Id
e a propriedade somente leitura opcional Name
. O código-fonte de exemplo usa a classe AppLogEvents
para definir IDs de evento:
using Microsoft.Extensions.Logging;
internal static class AppLogEvents
{
internal static EventId Create = new(1000, "Created");
internal static EventId Read = new(1001, "Read");
internal static EventId Update = new(1002, "Updated");
internal static EventId Delete = new(1003, "Deleted");
// These are also valid EventId instances, as there's
// an implicit conversion from int to an EventId
internal const int Details = 3000;
internal const int Error = 3001;
internal static EventId ReadNotFound = 4000;
internal static EventId UpdateNotFound = 4001;
// ...
}
Dica
Para obter mais informações de como converter um int
em um EventId
, confira Operador EventId.Implicit(Int32 to EventId).
Uma ID de evento associa um conjunto de eventos. Por exemplo, todos os logs relacionados à leitura de valores de um repositório podem ser 1001
.
O provedor de logs pode armazenar ou não a ID do evento em um campo de ID na mensagem de log. O provedor de Depuração não mostra IDs de eventos. O provedor de console mostra IDs de evento entre colchetes após a categoria:
info: Example.DefaultService.GetAsync[1001]
Reading value for a1b2c3
warn: Example.DefaultService.GetAsync[4000]
GetAsync(a1b2c3) not found
Alguns provedores de log armazenam a ID do evento em um campo, o que permite a filtragem na ID.
Cada API de log usa um modelo de mensagem. O modelo de mensagem pode conter espaços reservados para os quais são fornecidos argumentos. Use nomes para os espaços reservados, não números. A ordem dos espaços reservados e não de seus nomes, determina quais parâmetros serão usados para fornecer seus valores. No código a seguir, os nomes de parâmetro estão fora de sequência no modelo de mensagem:
string p1 = "param1";
string p2 = "param2";
_logger.LogInformation("Parameter values: {p2}, {p1}", p1, p2);
Esse código cria uma mensagem de log com os valores de parâmetro em sequência:
Parameter values: param1, param2
Observação
Esteja atento ao usar vários espaços reservados em um só modelo de mensagem, pois eles são baseados em ordinais. Os nomes não são usados para alinhar os argumentos aos espaços reservados.
Essa abordagem permite que os provedores de log implementem o log semântico ou estruturado. Os próprios argumentos são passados para o sistema de registro em log, não apenas o modelo de mensagem formatado. Essas informações permitem que os provedores de log armazenem os valores de parâmetro como campos. Considere o seguinte método de agente:
_logger.LogInformation("Getting item {Id} at {RunTime}", id, DateTime.Now);
Por exemplo, ao registrar em log no Armazenamento de Tabelas do Azure:
ID
e RunTime
.RunTime
sem precisar analisar o tempo limite da mensagem de texto.Os modelos de mensagem de log dão suporte à formatação de espaço reservado. Os modelos são livres para especificar qualquer formato válido para o argumento de tipo fornecido. Por exemplo, considere o seguinte modelo de mensagem Information
do agente:
_logger.LogInformation("Logged on {PlaceHolderName:MMMM dd, yyyy}", DateTimeOffset.UtcNow);
// Logged on January 06, 2022
No exemplo anterior, a instância de DateTimeOffset
é o tipo que corresponde a PlaceHolderName
no modelo de mensagem do agente. Esse nome pode ser qualquer coisa, pois os valores são baseados em ordinais. O formato MMMM dd, yyyy
é válido para o tipo DateTimeOffset
.
Para obter mais informações sobre a formatação de DateTime
e DateTimeOffset
, confira Cadeias de caracteres de formato de data e hora personalizadas.
Os exemplos a seguir mostram como formatar um modelo de mensagem usando a sintaxe de espaço reservado {}
. Além disso, um exemplo de escape da sintaxe de espaço reservado {}
é mostrado com a saída. Por fim, a interpolação de cadeia de caracteres com espaços reservados de modelo também é mostrada:
logger.LogInformation("Number: {Number}", 1); // Number: 1
logger.LogInformation("{{Number}}: {Number}", 3); // {Number}: 3
logger.LogInformation($"{{{{Number}}}}: {{Number}}", 5); // {Number}: 5
Dica
Os métodos do agente têm sobrecargas que usam um parâmetro de exceção:
public void Test(string id)
{
try
{
if (id is "none")
{
throw new Exception("Default Id detected.");
}
}
catch (Exception ex)
{
_logger.LogWarning(
AppLogEvents.Error, ex,
"Failed to process iteration: {Id}", id);
}
}
O log de exceções é específico do provedor.
Se o nível de log padrão não for definido, o valor do nível de log padrão será Information
.
Por exemplo, considere o seguinte aplicativo de serviço de trabalho:
Com a configuração anterior, o acesso à página de privacidade ou à home page gera várias mensagens Trace
, Debug
e Information
com Microsoft
no nome da categoria.
O seguinte código define o nível de log padrão quando ele não está definido na configuração:
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Logging.SetMinimumLevel(LogLevel.Warning);
using IHost host = builder.Build();
await host.RunAsync();
Uma função de filtro é invocada para todos os provedores e as categorias que não têm regras atribuídas por configuração ou no código:
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Logging.AddFilter((provider, category, logLevel) =>
{
return provider.Contains("ConsoleLoggerProvider")
&& (category.Contains("Example") || category.Contains("Microsoft"))
&& logLevel >= LogLevel.Information;
});
using IHost host = builder.Build();
await host.RunAsync();
O código anterior exibe logs de console quando a categoria contém Example
ou Microsoft
e o nível de log é Information
ou superior.
Um escopo agrupa um conjunto de operações lógicas. Esse agrupamento pode ser usado para anexar os mesmos dados para cada log criado como parte de um conjunto. Por exemplo, todo log criado como parte do processamento de uma transação pode incluir a ID da transação.
Um escopo:
Os seguintes provedores dão suporte a escopos:
Use um escopo por meio do encapsulamento de chamadas de agente em um bloco using
:
public async Task<T> GetAsync<T>(string id)
{
T result;
var transactionId = Guid.NewGuid().ToString();
using (_logger.BeginScope(new List<KeyValuePair<string, object>>
{
new KeyValuePair<string, object>("TransactionId", transactionId),
}))
{
_logger.LogInformation(
AppLogEvents.Read, "Reading value for {Id}", id);
var result = await _repository.GetAsync(id);
if (result is null)
{
_logger.LogWarning(
AppLogEvents.ReadNotFound, "GetAsync({Id}) not found", id);
}
}
return result;
}
O seguinte JSON habilita escopos para o provedor de console:
{
"Logging": {
"Debug": {
"LogLevel": {
"Default": "Information"
}
},
"Console": {
"IncludeScopes": true,
"LogLevel": {
"Microsoft": "Warning",
"Default": "Information"
}
},
"LogLevel": {
"Default": "Debug"
}
}
}
O código a seguir habilita os escopos para o provedor de console:
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Logging.ClearProviders();
builder.Logging.AddConsole(options => options.IncludeScopes = true);
using IHost host = builder.Build();
await host.RunAsync();
O seguinte código registra logs em Main
obtendo uma instância de ILogger
da DI após a criação do host:
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using IHost host = Host.CreateApplicationBuilder(args).Build();
var logger = host.Services.GetRequiredService<ILogger<Program>>();
logger.LogInformation("Host created.");
await host.RunAsync();
O código anterior depende de dois pacotes NuGet:
O arquivo de projeto seria semelhante ao seguinte:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="7.0.0" />
</ItemGroup>
</Project>
O registro em log deve ser tão rápido que não justifique o custo de desempenho de código assíncrono. Se o armazenamento de dados de log estiver lento, não grave as mensagens diretamente nele. Grave as mensagens de log em um armazenamento rápido primeiro e depois passe-as para um armazenamento lento. Por exemplo, se você estiver enviado logs ao SQL Server, não faça isso diretamente em um método Log
, pois os métodos Log
são síncronos. Em vez disso, adicione mensagens de log de forma síncrona a uma fila na memória e faça com que uma função de trabalho de plano de fundo efetue pull das mensagens para fora da fila para fazer o trabalho assíncrono de envio de dados por push para o SQL Server.
A API de Log não inclui um cenário para alterar os níveis de log enquanto um aplicativo está em execução. No entanto, alguns provedores de configuração conseguem recarregar a configuração, o que entra em vigor imediatamente na configuração de log. Por exemplo, o Provedor de Configuração de Arquivos recarrega a configuração de log por padrão. Se a configuração for alterada no código enquanto um aplicativo estiver em execução, o aplicativo poderá chamar IConfigurationRoot.Reload para atualizar a configuração de log do aplicativo.
As interfaces e implementações ILogger<TCategoryName> e ILoggerFactory estão inclusas na maioria dos SDKs do .NET como referência implícita de pacote. Elas também estão disponíveis explicitamente nos seguintes pacotes NuGet quando não são referenciadas implicitamente:
Para obter mais informações sobre qual SDK do .NET inclui referências implícitas de pacote, confira SDK do .NET: tabela para namespace implícito.
Comentários do .NET
O .NET é um projeto código aberto. Selecione um link para fornecer comentários:
Treinamento
Módulo
Formatar dados alfanuméricos para apresentação em C# - Training
Explore métodos básicos em C# para formatar dados alfanuméricos.