Registro em log no ASP.NET Core Blazor

Observação

Esta não é a versão mais recente deste artigo. Para informações sobre a versão vigente, confira a Versão do .NET 8 deste artigo.

Importante

Essas informações relacionam-se ao produto de pré-lançamento, que poderá ser substancialmente modificado antes do lançamento comercial. A Microsoft não oferece nenhuma garantia, explícita ou implícita, quanto às informações fornecidas aqui.

Para informações sobre a versão vigente, confira a Versão do .NET 8 deste artigo.

Este artigo explica o registro em log de aplicativos Blazor, incluindo a configuração e como gravar mensagens de log de componentes Razor.

Configuração

A configuração de registro em log pode ser carregada dos arquivos de configurações do aplicativo. Para obter mais informações, consulte Configuração no ASP.NET Core Blazor.

Em níveis de log padrão e sem configurar provedores de log adicionais:

Quando o aplicativo é configurado no arquivo de projeto para usar namespaces implícitos (<ImplicitUsings>enable</ImplicitUsings>), uma diretiva using para Microsoft.Extensions.Logging ou qualquer API na classe LoggerExtensions não é necessária para dar suporte a conclusões ou criação de aplicativos do Visual Studio IntelliSense de API. Se os namespaces implícitos não estiverem habilitados, os componentes Razor devem definir diretivas @using explicitamente para registrar namespaces que não são importados por meio do arquivo _Imports.razor.

Níveis de log

Os níveis de log estão em conformidade com os níveis de log do aplicativo ASP.NET Core, que estão listados na documentação da API em LogLevel.

Registro em log de componente Razor

A diretiva using para Microsoft.Extensions.Logging é exigida para dar suporte a conclusões do IntelliSense para APIs, como LogWarning e LogError.

O exemplo a seguir:

  • Insere um objeto ILogger (ILogger<Counter1>) para criar um agente. A categoria do log é o nome totalmente qualificado do tipo do componente Counter.
  • Chama LogWarning para registrar em log no nível Warning.

Counter1.razor:

@page "/counter-1"
@inject ILogger<Counter1> Logger

<PageTitle>Counter 1</PageTitle>

<h1>Counter 1</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
    private int currentCount = 0;

    private void IncrementCount()
    {
        Logger.LogWarning("Someone has clicked me!");

        currentCount++;
    }
}
@page "/counter-1"
@inject ILogger<Counter1> Logger

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
    private int currentCount = 0;

    private void IncrementCount()
    {
        Logger.LogWarning("Someone has clicked me!");

        currentCount++;
    }
}
@page "/counter-1"
@inject ILogger<Counter1> Logger

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
    private int currentCount = 0;

    private void IncrementCount()
    {
        Logger.LogWarning("Someone has clicked me!");

        currentCount++;
    }
}
@page "/counter-1"
@using Microsoft.Extensions.Logging
@inject ILogger<Counter1> Logger

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
    private int currentCount = 0;

    private void IncrementCount()
    {
        Logger.LogWarning("Someone has clicked me!");

        currentCount++;
    }
}
@page "/counter-1"
@using Microsoft.Extensions.Logging
@inject ILogger<Counter1> Logger

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
    private int currentCount = 0;

    private void IncrementCount()
    {
        Logger.LogWarning("Someone has clicked me!");

        currentCount++;
    }
}

O exemplo a seguir mostra o registro em log com um ILoggerFactory em componentes.

Counter2.razor:

@page "/counter-2"
@inject ILoggerFactory LoggerFactory

<PageTitle>Counter 2</PageTitle>

<h1>Counter 2</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
    private int currentCount = 0;

    private void IncrementCount()
    {
        var logger = LoggerFactory.CreateLogger<Counter2>();
        logger.LogWarning("Someone has clicked me!");

        currentCount++;
    }
}
@page "/counter-2"
@inject ILoggerFactory LoggerFactory

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
    private int currentCount = 0;

    private void IncrementCount()
    {
        var logger = LoggerFactory.CreateLogger<Counter2>();
        logger.LogWarning("Someone has clicked me!");

        currentCount++;
    }
}
@page "/counter-2"
@inject ILoggerFactory LoggerFactory

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
    private int currentCount = 0;

    private void IncrementCount()
    {
        var logger = LoggerFactory.CreateLogger<Counter2>();
        logger.LogWarning("Someone has clicked me!");

        currentCount++;
    }
}
@page "/counter-2"
@using Microsoft.Extensions.Logging
@inject ILoggerFactory LoggerFactory

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
    private int currentCount = 0;

    private void IncrementCount()
    {
        var logger = LoggerFactory.CreateLogger<Counter2>();
        logger.LogWarning("Someone has clicked me!");

        currentCount++;
    }
}
@page "/counter-2"
@using Microsoft.Extensions.Logging
@inject ILoggerFactory LoggerFactory

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
    private int currentCount = 0;

    private void IncrementCount()
    {
        var logger = LoggerFactory.CreateLogger<Counter2>();
        logger.LogWarning("Someone has clicked me!");

        currentCount++;
    }
}

Registro em log no lado do servidor

Para obter as diretrizes gerais do registro em log do ASP.NET Core, confira Registro em log no .NET Core e no ASP.NET Core.

Registro em log no lado do cliente

Nem todos os recursos do registro em log ASP.NET Core são suportados no lado do cliente. Por exemplo, os componentes do lado do cliente não têm acesso ao sistema de arquivos ou à rede do cliente, portanto, não é possível gravar logs no armazenamento físico ou de rede do cliente. Ao usar um serviço de registro de log de terceiros desenvolvido para funcionar com aplicativos de página única (SPAs), siga as diretrizes de segurança do serviço. Lembre-se de que todos os dados, incluindo chaves ou segredos armazenados no lado do cliente, são inseguros e podem ser facilmente descobertos por usuários mal-intencionados.

Dependendo da versão da estrutura e dos recursos de registro em log, as implementações de registro em log podem exigir a adição do namespace para Microsoft.Extensions.Logging ao arquivo Program:

using Microsoft.Extensions.Logging;

Configure o registro em log nos aplicativos do lado do cliente com a propriedade WebAssemblyHostBuilder.Logging. A propriedade Logging é do tipo ILoggingBuilder, portanto, os métodos de extensão de ILoggingBuilder têm suporte.

Para definir o nível mínimo de registro em log, chame LoggingBuilderExtensions.SetMinimumLevel no criador de host no arquivo Program com LogLevel. O exemplo a seguir define o nível de log mínimo como Warning:

builder.Logging.SetMinimumLevel(LogLevel.Warning);

Registro no arquivo Program do lado do cliente

O registro em log é suportado em aplicativos do lado do cliente depois que o WebAssemblyHostBuilder é criado utilizando o provedor do agente de registro do console interno da estrutura (WebAssemblyConsoleLoggerProvider (fonte de referência)).

No arquivo Program:

var host = builder.Build();

var logger = host.Services.GetRequiredService<ILoggerFactory>()
    .CreateLogger<Program>();

logger.LogInformation("Logged after the app is built in the Program file.");

await host.RunAsync();

Saída do console de ferramentas do desenvolvedor:

info: Program[0]
Logged after the app is built in the Program file.

Observação

Os links de documentação para a fonte de referência do .NET geralmente carregam o branch padrão do repositório, que representa o desenvolvimento atual da próxima versão do .NET. Para selecionar uma marca para uma versão específica, use a lista suspensa para Alternar branches ou marcas. Para saber mais, confira Como selecionar uma marca de versão do código-fonte do ASP.NET Core (dotnet/AspNetCore.Docs #26205).

Categoria de log do lado do cliente

As categorias de logs são suportadas.

O exemplo a seguir mostra como usar categorias de log com o componente Counter de um aplicativo criado a partir de um modelo de projeto Blazor.

No método IncrementCount do componente Counter do aplicativo (Counter.razor) que insere um ILoggerFactory como LoggerFactory:

var logger = LoggerFactory.CreateLogger("CustomCategory");
logger.LogWarning("Someone has clicked me!");

Saída do console de ferramentas do desenvolvedor:

warn: CustomCategory[0]
Someone has clicked me!

ID do evento de log do lado do cliente

A ID do evento de log é suportada.

O exemplo a seguir mostra como usar IDs de evento de log com o componente Counter de um aplicativo criado a partir de um modelo de projeto Blazor.

LogEvent.cs:

public class LogEvent
{
    public const int Event1 = 1000;
    public const int Event2 = 1001;
}

No método IncrementCount do componente Counter do aplicativo (Counter.razor):

logger.LogInformation(LogEvent.Event1, "Someone has clicked me!");
logger.LogWarning(LogEvent.Event2, "Someone has clicked me!");

Saída do console de ferramentas do desenvolvedor:

info: BlazorSample.Pages.Counter[1000]
Someone has clicked me!
warn: BlazorSample.Pages.Counter[1001]
Someone has clicked me!

Modelo de mensagens de log do lado do cliente

Modelos de mensagens de log são suportados:

O exemplo a seguir mostra como usar modelos de mensagem de log com o componente Counter de um aplicativo criado a partir de um modelo de projeto Blazor.

No método IncrementCount do componente Counter do aplicativo (Counter.razor):

logger.LogInformation("Someone clicked me at {CurrentDT}!", DateTime.UtcNow);

Saída do console de ferramentas do desenvolvedor:

info: BlazorSample.Pages.Counter[0]
Someone clicked me at 04/21/2022 12:15:57!

Parâmetros de exceção de registro em log do lado do cliente

Os parâmetros de exceção do registro em log são suportados.

O exemplo a seguir mostra como usar parâmetros de exceção de log com o componente Counter de um aplicativo criado a partir de um modelo de projeto Blazor.

No método IncrementCount do componente Counter do aplicativo (Counter.razor):

currentCount++;

try
{
    if (currentCount == 3)
    {
        currentCount = 4;
        throw new OperationCanceledException("Skip 3");
    }
}
catch (Exception ex)
{
    logger.LogWarning(ex, "Exception (currentCount: {Count})!", currentCount);
}

Saída do console de ferramentas do desenvolvedor:

warn: BlazorSample.Pages.Counter[0]
Exception (currentCount: 4)!
System.OperationCanceledException: Skip 3
at BlazorSample.Pages.Counter.IncrementCount() in C:UsersAlabaDesktopBlazorSamplePagesCounter.razor:line 28

Função de filtro no lado do cliente

Funções de filtro são suportadas.

O exemplo a seguir mostra como usar um filtro com o componente Counter de um aplicativo criado a partir de um modelo de projeto Blazor.

No arquivo Program:

builder.Logging.AddFilter((provider, category, logLevel) =>
    category.Equals("CustomCategory2") && logLevel == LogLevel.Information);

No método IncrementCount do componente Counter do aplicativo (Counter.razor) que insere um ILoggerFactory como LoggerFactory:

var logger1 = LoggerFactory.CreateLogger("CustomCategory1");
logger1.LogInformation("Someone has clicked me!");

var logger2 = LoggerFactory.CreateLogger("CustomCategory1");
logger2.LogWarning("Someone has clicked me!");

var logger3 = LoggerFactory.CreateLogger("CustomCategory2");
logger3.LogInformation("Someone has clicked me!");

var logger4 = LoggerFactory.CreateLogger("CustomCategory2");
logger4.LogWarning("Someone has clicked me!");

Na saída do console das ferramentas de desenvolvedor, o filtro somente permite o registro em log para a categoria CustomCategory2 e a mensagem de nível de log Information:

info: CustomCategory2[0]
Someone has clicked me!

O aplicativo também pode configurar a filtragem de log para namespaces específicos. Por exemplo, defina o nível de log como Trace no arquivo Program:

builder.Logging.SetMinimumLevel(LogLevel.Trace);

Normalmente, no nível do log Trace, a saída de console de ferramentas do desenvolvedor no nível Detalhado inclui mensagens de log Microsoft.AspNetCore.Components.RenderTree, da seguinte forma:

dbug: Microsoft.AspNetCore.Components.RenderTree.Renderer[3]
Rendering component 14 of type Microsoft.AspNetCore.Components.Web.HeadOutlet

No arquivo Program, as mensagens do registro em log específicas para Microsoft.AspNetCore.Components.RenderTree podem ser desabilitadas usando ou das seguintes abordagens:

  • builder.Logging.AddFilter("Microsoft.AspNetCore.Components.RenderTree.*", LogLevel.None);
    
  • builder.Services.PostConfigure<LoggerFilterOptions>(options =>
        options.Rules.Add(
            new LoggerFilterRule(null, 
                                 "Microsoft.AspNetCore.Components.RenderTree.*", 
                                 LogLevel.None, 
                                 null)
        ));
    

Depois que qualquer um dos filtros anteriores é adicionado ao aplicativo, a saída do console no nível Detalhado não mostra mensagens de registro em log da API Microsoft.AspNetCore.Components.RenderTree.

Provedor do agente personalizado no lado do cliente

O exemplo nesta seção demonstra um provedor de agente personalizado para personalização adicional.

Adicione uma referência de pacote ao aplicativo para o pacote Microsoft.Extensions.Logging.Configuration.

Observação

Para obter diretrizes sobre como adicionar pacotes a aplicativos .NET, consulte os artigos em Instalar e gerenciar pacotes no Fluxo de trabalho de consumo de pacotes (documentação do NuGet). Confirme as versões corretas de pacote em NuGet.org.

Adicione a seguinte configuração de agente personalizado. A configuração estabelece um dicionário LogLevels que define um formato de log personalizado para três níveis de log: Information, Warninge Error. Um LogFormatenum é usado para descrever formatos curtos (LogFormat.Short) e longos (LogFormat.Long).

CustomLoggerConfiguration.cs:

using Microsoft.Extensions.Logging;

public class CustomLoggerConfiguration
{
    public int EventId { get; set; }

    public Dictionary<LogLevel, LogFormat> LogLevels { get; set; } = 
        new()
        {
            [LogLevel.Information] = LogFormat.Short,
            [LogLevel.Warning] = LogFormat.Short,
            [LogLevel.Error] = LogFormat.Long
        };

    public enum LogFormat
    {
        Short,
        Long
    }
}

Adicione o seguinte agente personalizado ao aplicativo. O CustomLogger gera formatos de log personalizados com base nos valores logLevel definidos na configuração anterior CustomLoggerConfiguration.

using Microsoft.Extensions.Logging;
using static CustomLoggerConfiguration;

public sealed class CustomLogger : ILogger
{
    private readonly string name;
    private readonly Func<CustomLoggerConfiguration> getCurrentConfig;

    public CustomLogger(
        string name,
        Func<CustomLoggerConfiguration> getCurrentConfig) =>
        (this.name, this.getCurrentConfig) = (name, getCurrentConfig);

    public IDisposable BeginScope<TState>(TState state) => default!;

    public bool IsEnabled(LogLevel logLevel) =>
        getCurrentConfig().LogLevels.ContainsKey(logLevel);

    public void Log<TState>(
        LogLevel logLevel,
        EventId eventId,
        TState state,
        Exception? exception,
        Func<TState, Exception?, string> formatter)
    {
        if (!IsEnabled(logLevel))
        {
            return;
        }

        CustomLoggerConfiguration config = getCurrentConfig();

        if (config.EventId == 0 || config.EventId == eventId.Id)
        {
            switch (config.LogLevels[logLevel])
            {
                case LogFormat.Short:
                    Console.WriteLine($"{name}: {formatter(state, exception)}");
                    break;
                case LogFormat.Long:
                    Console.WriteLine($"[{eventId.Id, 2}: {logLevel, -12}] {name} - {formatter(state, exception)}");
                    break;
                default:
                    // No-op
                    break;
            }
        }
    }
}

Adicione o seguinte provedor personalizado ao aplicativo. CustomLoggerProvider adota uma abordagem baseada em Options para configurar o agente por meio de recursos internos de configuração de log. Por exemplo, o aplicativo pode definir ou alterar formatos de log por meio de um arquivo appsettings.json sem exigir alterações de código no agente personalizado, o que é mostrado no final desta seção.

CustomLoggerProvider.cs:

using System.Collections.Concurrent;
using Microsoft.Extensions.Options;

[ProviderAlias("CustomLog")]
public sealed class CustomLoggerProvider : ILoggerProvider
{
    private readonly IDisposable onChangeToken;
    private CustomLoggerConfiguration config;
    private readonly ConcurrentDictionary<string, CustomLogger> loggers =
        new(StringComparer.OrdinalIgnoreCase);

    public CustomLoggerProvider(
        IOptionsMonitor<CustomLoggerConfiguration> config)
    {
        this.config = config.CurrentValue;
        onChangeToken = config.OnChange(updatedConfig => this.config = updatedConfig);
    }

    public ILogger CreateLogger(string categoryName) =>
        loggers.GetOrAdd(categoryName, name => new CustomLogger(name, GetCurrentConfig));

    private CustomLoggerConfiguration GetCurrentConfig() => config;

    public void Dispose()
    {
        loggers.Clear();
        onChangeToken.Dispose();
    }
}

Adicione a seguinte extensão de agente personalizado.

CustomLoggerExtensions.cs:

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Configuration;

public static class CustomLoggerExtensions
{
    public static ILoggingBuilder AddCustomLogger(
        this ILoggingBuilder builder)
    {
        builder.AddConfiguration();

        builder.Services.TryAddEnumerable(
            ServiceDescriptor.Singleton<ILoggerProvider, CustomLoggerProvider>());

        LoggerProviderOptions.RegisterProviderOptions
            <CustomLoggerConfiguration, CustomLoggerProvider>(builder.Services);

        return builder;
    }
}

No arquivo Program do criador de host, limpe o provedor existente chamando ClearProviders e adicione o provedor de registro em log personalizado:

builder.Logging.ClearProviders().AddCustomLogger();

No seguinte componente CustomLoggerExample:

  • A mensagem de depuração não está registrada.
  • A mensagem de informações é registrada no formato curto (LogFormat.Short).
  • A mensagem de aviso é registrada no formato curto (LogFormat.Short).
  • A mensagem de erro é registrada no formato longo (LogFormat.Long).
  • A mensagem de rastreamento não é registrada.

CustomLoggerExample.razor:

@page "/custom-logger-example"
@inject ILogger<CustomLoggerExample> Logger

<p>
    <button @onclick="LogMessages">Log Messages</button>
</p>

@code{
    private void LogMessages()
    {
        Logger.LogDebug(1, "This is a debug message.");
        Logger.LogInformation(3, "This is an information message.");
        Logger.LogWarning(5, "This is a warning message.");
        Logger.LogError(7, "This is an error message.");
        Logger.LogTrace(5!, "This is a trace message.");
    }
}
@page "/custom-logger-example"
@using Microsoft.Extensions.Logging
@inject ILogger<CustomLoggerExample> Logger

<p>
    <button @onclick="LogMessages">Log Messages</button>
</p>

@code{
    private void LogMessages()
    {
        Logger.LogDebug(1, "This is a debug message.");
        Logger.LogInformation(3, "This is an information message.");
        Logger.LogWarning(5, "This is a warning message.");
        Logger.LogError(7, "This is an error message.");
        Logger.LogTrace(5!, "This is a trace message.");
    }
}

A saída a seguir é visualizada no console de ferramentas para desenvolvedores do navegador quando é selecionado o botão Log Messages. As entradas de log refletem os formatos apropriados aplicados pelo agente personalizado (o aplicativo cliente é chamado LoggingTest):

LoggingTest.Pages.CustomLoggerExample: This is an information message.
LoggingTest.Pages.CustomLoggerExample: This is a warning message.
[ 7: Error ] LoggingTest.Pages.CustomLoggerExample - This is an error message.

A partir de uma verificação casual do exemplo anterior, fica claro que a configuração dos formatos de linha de log por meio do dicionário em CustomLoggerConfiguration não é estritamente necessária. Os formatos de linha aplicados pelo agente personalizado (CustomLogger) poderiam ser aplicados apenas pela verificação de logLevel no método Log. A finalidade de atribuir o formato de log por meio da configuração é que o desenvolvedor pode alterar o formato de log facilmente por meio da configuração do aplicativo, como mostra o exemplo a seguir.

No aplicativo do lado do cliente, adicione ou atualize o arquivo appsettings.json para incluir a configuração do registro em log. Defina o formato de log Long para todos os três níveis de log:

{
  "Logging": {
    "CustomLog": {
      "LogLevels": {
        "Information": "Long",
        "Warning": "Long",
        "Error": "Long"
      }
    }
  }
}

No exemplo anterior, observe que a entrada para a configuração do agente personalizado é CustomLog, que foi aplicada ao provedor de agente personalizado (CustomLoggerProvider) como um alias com [ProviderAlias("CustomLog")]. A configuração de log poderia ter sido aplicada com o nome CustomLoggerProvider em vez de CustomLog, mas o uso do alias CustomLog é mais amigável.

No arquivo Program, consuma a configuração do registro em log. Adicione o seguinte código:

builder.Logging.AddConfiguration(
    builder.Configuration.GetSection("Logging"));

A chamada para LoggingBuilderConfigurationExtensions.AddConfiguration pode ser colocada antes ou depois de adicionar o provedor de agente personalizado.

Execute o aplicativo novamente. Selecione o botão Log Messages. Observe que a configuração de log é aplicada ao arquivo appsettings.json. Todas as três entradas de log estão no formato longo (LogFormat.Long) (o aplicativo cliente tem o nome LoggingTest):

[ 3: Information ] LoggingTest.Pages.CustomLoggerExample - This is an information message.
[ 5: Warning ] LoggingTest.Pages.CustomLoggerExample - This is a warning message.
[ 7: Error ] LoggingTest.Pages.CustomLoggerExample - This is an error message.

Escopos de log do lado do cliente

O agente de registro do console das ferramentas do desenvolvedor não tem suporte para escopos de logs . No entanto, um agente personalizado pode ser compatível com escopos de log. Para obter um exemplo sem suporte que pode ser desenvolvido para atender às suas necessidades, consulte o aplicativo de amostra no BlazorWebAssemblyScopesLoggerBlazorrepositório GitHub de amostras (como baixar).

O aplicativo de exemplo usa a sintaxe de log padrão ASP.NET Core BeginScope para indicar escopos para mensagens registradas. O serviço Logger no exemplo a seguir é um ILogger<CustomLoggerExample>, que é inserido no componente CustomLoggerExample do aplicativo (CustomLoggerExample.razor).

using (Logger.BeginScope("L1"))
{
    Logger.LogInformation(3, "INFO: ONE scope.");
}

using (Logger.BeginScope("L1"))
{
    using (Logger.BeginScope("L2"))
    {
        Logger.LogInformation(3, "INFO: TWO scopes.");
    }
}

using (Logger.BeginScope("L1"))
{
    using (Logger.BeginScope("L2"))
    {
        using (Logger.BeginScope("L3"))
        {
            Logger.LogInformation(3, "INFO: THREE scopes.");
        }
    }
}

Saída:

[ 3: Informações ] {CLASS} - INFO: UM escopo. => L1 blazor.webassembly.js:1:35542
[ 3: Informações ] {CLASS} - INFO: DOIS escopos. => L1 => L2 blazor.webassembly.js:1:35542
[ 3: Informações ] {CLASS} - INFO: TRÊS escopos. => L1 => L2 => L3

O espaço reservado {CLASS} no exemplo anterior é BlazorWebAssemblyScopesLogger.Pages.CustomLoggerExample.

Registro em log de componentes pré-renderizados

Os componentes pré-renderizados executam o código de inicialização do componente duas vezes. O registro em log ocorre por parte do servidor na primeira execução do código de inicialização e por parte do cliente na segunda execução do código de inicialização. Dependendo da meta de registro em log durante a inicialização, verifique os logs por parte do servidor e por parte do cliente ou em ambos.

Registro em log do cliente SignalR com o criador de clientes SignalR

Esta seção se aplica a aplicativos do lado do servidor.

Na configuração de início do script Blazor, passe o objeto de configuração configureSignalR que chama configureLogging com o nível de log.

Para o valor de nível de log configureLogging, aprove o argumento como o nível de log de cadeia de caracteres ou inteiro mostrado na tabela a seguir.

LogLevel Configuração de cadeia de caracteres Configuração de valor inteiro
Trace trace 0
Debug debug 1
Information information 2
Warning warning 3
Error error 4
Critical critical 5
None none 6

Exemplo 1: defina o nível de log Information com um valor de cadeia de caracteres.

Aplicativo Web Blazor:

<script src="{BLAZOR SCRIPT}" autostart="false"></script>
<script>
  Blazor.start({
    circuit: {
      configureSignalR: function (builder) {
        builder.configureLogging("information");
      }
    }
  });
</script>

Blazor Server:

<script src="{BLAZOR SCRIPT}" autostart="false"></script>
<script>
  Blazor.start({
    configureSignalR: function (builder) {
      builder.configureLogging("information");
    }
  });
</script>

No exemplo anterior, o espaço reservado {BLAZOR SCRIPT} é o caminho de script Blazor e o nome do arquivo. Para obter a localização do script, confira a estrutura do projeto ASP.NET Core Blazor.

Exemplo 2: defina o nível de log Information com um valor inteiro.

Aplicativo Web Blazor:

<script src="{BLAZOR SCRIPT}" autostart="false"></script>
<script>
  Blazor.start({
    circuit: {
      configureSignalR: function (builder) {
        builder.configureLogging(2); // LogLevel.Information
      }
    }
  });
</script>

Blazor Server:

<script src="{BLAZOR SCRIPT}" autostart="false"></script>
<script>
  Blazor.start({
    configureSignalR: function (builder) {
      builder.configureLogging(2); // LogLevel.Information
    }
  });
</script>

No exemplo anterior, o espaço reservado {BLAZOR SCRIPT} é o caminho de script Blazor e o nome do arquivo. Para obter a localização do script, confira a estrutura do projeto ASP.NET Core Blazor.

Observação

Usar um inteiro para especificar o nível de registro em log no Exemplo 2, geralmente conhecido como um número mágico ou constante mágica, é considerado uma prática de codificação ruim porque o inteiro não identifica claramente o nível de registro em log ao exibir o código-fonte. Se minimizar os bytes transferidos para o navegador for uma prioridade, o uso de um inteiro poderá ser justificado (considere remover o comentário nesses casos).

Para obter mais informações sobre a inicialização de Blazor (Blazor.start()), consulte Inicialização de no ASP.NET CoreBlazor.

O registro em log do cliente SignalR com a configuração do aplicativo

Defina a configuração das definições do aplicativo conforme descrito em ASP.NET Core Blazor configuração. Coloque arquivos de configurações de aplicativo no wwwroot que contêm uma configuração de aplicativo Logging:LogLevel:HubConnection.

Observação

Como alternativa ao uso de configurações de aplicativo, você pode aprovar o LogLevel como o argumento para LoggingBuilderExtensions.SetMinimumLevel quando a conexão de hub é criada em um componente Razor. No entanto, a implantação acidental do aplicativo em um ambiente de hospedagem de produção com log detalhado pode resultar em uma penalidade de desempenho. É recomendável usar as configurações do aplicativo para definir o nível de log.

Forneça uma configuração de aplicativo Logging:LogLevel:HubConnection no arquivo padrão appsettings.json e no arquivo de configurações do aplicativo de ambiente Development. Use um nível de log menos detalhado típico para o padrão, como LogLevel.Warning. O valor de configurações de aplicativo padrão é o que é usado em ambientes Staging e Production se nenhum arquivo de configurações de aplicativo para esses ambientes estiver presente. Use um nível de log detalhado no arquivo de configurações do aplicativo de ambiente Development, como LogLevel.Trace.

wwwroot/appsettings.json:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning",
      "HubConnection": "Warning"
    }
  }
}

wwwroot/appsettings.Development.json:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning",
      "HubConnection": "Trace"
    }
  }
}

Importante

É usada a configuração nos arquivos de configurações de aplicativo anteriores somente pelo aplicativo se as diretrizes na configuraçãoBlazor de ASP.NET Core forem seguidas.

Na parte superior do arquivo de componente Razor(.razor):

  • Insira um ILoggerProvider para adicionar um WebAssemblyConsoleLogger aos provedores de log aprovados para HubConnectionBuilder. Diferente do ConsoleLogger tradicional, WebAssemblyConsoleLogger é um wrapper próximo de APIs de log específicas do navegador (por exemplo, console.log). O uso de WebAssemblyConsoleLogger permite o registro em log no Mono em um contexto de navegador.
  • Insira um IConfiguration para ler a configuração do aplicativo Logging:LogLevel:HubConnection.

Observação

WebAssemblyConsoleLogger é interno e não é compatível com o uso direto no código do desenvolvedor.

@inject ILoggerProvider LoggerProvider
@inject IConfiguration Config

Observação

O exemplo a seguir é baseado na demonstração do tutorial SignalR com Blazor. Para saber mais, consulte o tutorial.

No OnInitializedAsyncmétodo do componente, use HubConnectionBuilderExtensions.ConfigureLogging para adicionar o provedor de log e definir o nível mínimo de log da configuração:

protected override async Task OnInitializedAsync()
{
    hubConnection = new HubConnectionBuilder()
        .WithUrl(Navigation.ToAbsoluteUri("/chathub"))
        .ConfigureLogging(builder => 
        {
            builder.AddProvider(LoggerProvider);
            builder.SetMinimumLevel(
                Config.GetValue<LogLevel>("Logging:LogLevel:HubConnection"));
        })
        .Build();

    hubConnection.On<string, string>("ReceiveMessage", (user, message) => ...

    await hubConnection.StartAsync();
}

Observação

No exemplo anterior, Navigation é um NavigationManager inserido.

Para obter mais informações sobre como definir o ambiente do aplicativo, confira ASP.NET Core Blazor ambientes.

Registro em log de autenticação no lado do cliente

Registre as mensagens de autenticação Blazor nos níveis de registro LogLevel.Debug ou LogLevel.Trace com uma configuração de logs nas configurações do aplicativo ou utilizando um filtro de log para Microsoft.AspNetCore.Components.WebAssembly.Authentication no arquivo Program.

Use qualquer uma das seguintes abordagens:

  • Em um arquivo de configurações do aplicativo (por exemplo, wwwroot/appsettings.Development.json):

    "Logging": {
      "LogLevel": {
        "Microsoft.AspNetCore.Components.WebAssembly.Authentication": "Debug"
      }
    }
    

    Para obter mais informações sobre como fazer para configurar um aplicativo do lado do cliente para a leitura de arquivos de configurações de aplicativos, consulte ASP.NET Core Blazor configuração.

  • Usando um filtro de log, o seguinte exemplo:

    • Ativa o registro em log para a configuração de compilação Debug usando uma diretiva de pré-processador C#.
    • Registra em log mensagens de autenticação Blazor no nível do log Debug.
    #if DEBUG
        builder.Logging.AddFilter(
            "Microsoft.AspNetCore.Components.WebAssembly.Authentication", 
            LogLevel.Debug);
    #endif
    

Observação

Os componentes Razor renderizados no cliente só registram no console das ferramentas de desenvolvedor do navegador do lado do cliente.

Recursos adicionais