Ведение журналов ASP.NET Core Blazor

Примечание.

Это не последняя версия этой статьи. В текущем выпуске см . версию .NET 8 этой статьи.

Внимание

Эта информация относится к предварительному выпуску продукта, который может быть существенно изменен до его коммерческого выпуска. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.

В текущем выпуске см . версию .NET 8 этой статьи.

В этой статье объясняется Blazor ведение журнала приложений, включая конфигурацию и запись сообщений журнала из Razor компонентов.

Настройка

Конфигурацию ведения журнала можно загрузить из файлов параметров приложения. Дополнительные сведения см. в статье Конфигурация ASP.NET Core Blazor.

На уровнях журналов по умолчанию и без настройки дополнительных поставщиков ведения журнала:

Если приложение настроено в файле проекта для использования неявных пространств имен (<ImplicitUsings>enable</ImplicitUsings>), директива using для Microsoft.Extensions.Logging или любого API в классе LoggerExtensions не требуется для поддержки завершений или создания приложений API Visual Studio IntelliSense. Если неявные пространства имен не включены, компоненты Razor должны явно определить директивы @using для пространств имен ведения журналов, которые не импортируются через файл _Imports.razor.

Уровни журнала

Уровни журналов соответствуют уровням журналов ASP.NET Core, которые перечислены в документации LogLevelпо API.

Ведение журнала компонентов Razor

Директива using для Microsoft.Extensions.Logging обеспечивает поддержку завершения IntelliSense для таких интерфейсов API, как LogWarning и LogError.

Следующий пример:

  • Добавляет объект ILogger (ILogger<Counter1>) для создания средства ведения журнала. Категория журнала представляет собой полное имя типа компонента — Counter.
  • Вызывает метод LogWarning для ведения журналов на уровне 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++;
    }
}

Приведенный ниже пример демонстрирует ведение журнала с помощью ILoggerFactory в компонентах.

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++;
    }
}

Ведение журнала на стороне сервера

Общие рекомендации по ведению журнала ASP.NET Core см. в разделе "Ведение журнала" в .NET Core и ASP.NET Core.

Ведение журнала на стороне клиента

Не каждая функция ведения журнала ASP.NET Core поддерживается на стороне клиента. Например, клиентские компоненты не имеют доступа к файловой системе или сети клиента, поэтому запись журналов в физическое или сетевое хранилище клиента невозможна. При использовании сторонней службы ведения журналов, предназначенной для работы с одностраничными приложениями, следуйте инструкциям в руководстве по безопасности службы. Помните, что все части данных, включая ключи или секреты, хранящиеся на стороне клиента, небезопасны и могут быть легко обнаружены вредоносными пользователями.

В зависимости от версий платформы и функций ведения журнала реализация ведения журнала может потребовать добавления пространства имен в Microsoft.Extensions.LoggingProgram файл:

using Microsoft.Extensions.Logging;

Настройте ведение журнала в клиентских приложениях с WebAssemblyHostBuilder.Logging помощью свойства. Свойство Logging имеет тип ILoggingBuilder, поэтому поддерживаются методы расширения ILoggingBuilder.

Чтобы задать минимальный уровень ведения журнала, вызовите LoggingBuilderExtensions.SetMinimumLevel построитель узлов в Program файле с LogLevelпомощью . В следующем примере значение минимального уровня ведения журнала устанавливается равным Warning:

builder.Logging.SetMinimumLevel(LogLevel.Warning);

Войдите в файл на стороне Program клиента

Ведение журнала поддерживается в клиентских приложениях после WebAssemblyHostBuilder создания с помощью внутреннего поставщика средства ведения журнала консоли платформы (WebAssemblyConsoleLoggerProvider (ссылочный источник)).

В файле 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();

Выходные данные консоли средств разработчика:

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

Примечание.

По ссылкам в документации на справочные материалы по .NET обычно загружается ветвь репозитория по умолчанию, которая представляет текущую разработку для следующего выпуска .NET. Чтобы выбрать тег для определенного выпуска, используйте раскрывающийся список Switch branches or tags (Переключение ветвей или тегов). Дополнительные сведения см. в статье Выбор тега версии исходного кода ASP.NET Core (dotnet/AspNetCore.Docs #26205).

Категория журнала на стороне клиента

Поддерживаются категории журналов .

В следующем примере показано, как использовать категории журналов с компонентом Counter приложения, созданного из шаблона проекта Blazor.

В методе IncrementCount компонента Counter приложения (Counter.razor), которое внедряет ILoggerFactory как LoggerFactory:

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

Выходные данные консоли средств разработчика:

warn: CustomCategory[0]
Someone has clicked me!

Идентификатор события журнала на стороне клиента

Поддерживается идентификатор события журнала.

В следующем примере показано, как использовать идентификаторы событий журналов с компонентом Counter приложения, созданного из шаблона проекта Blazor.

LogEvent.cs:

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

В методе IncrementCount компонента Counter приложения (Counter.razor):

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

Выходные данные консоли средств разработчика:

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

Шаблон сообщения журнала на стороне клиента

Поддерживаются шаблоны сообщений журнала:

В следующем примере показано, как использовать шаблоны сообщений журналов с компонентом Counter приложения, созданного из шаблона проекта Blazor.

В методе IncrementCount компонента Counter приложения (Counter.razor):

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

Выходные данные консоли средств разработчика:

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

Параметры исключения журнала на стороне клиента

Поддерживаются параметры исключения журналов .

В следующем примере показано, как использовать параметры исключений журналов с компонентом Counter приложения, созданного из шаблона проекта Blazor.

В методе IncrementCount компонента Counter приложения (Counter.razor):

currentCount++;

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

Выходные данные консоли средств разработчика:

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

Функция фильтрации на стороне клиента

Поддерживаются функции фильтрации.

В следующем примере показано, как использовать фильтры с компонентом Counter приложения, созданного из шаблона проекта Blazor.

В файле Program:

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

В методе IncrementCount компонента Counter приложения (Counter.razor), которое внедряет ILoggerFactory как 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!");

В выходных данных консоли средств разработчика фильтр разрешает только ведение журнала для категории CustomCategory2 и сообщения уровня журнала Information:

info: CustomCategory2[0]
Someone has clicked me!

Приложение также может настроить фильтрацию журналов для определенных пространств имен. Например, задайте уровень Trace журнала в Program файле:

builder.Logging.SetMinimumLevel(LogLevel.Trace);

Как правило, на уровне журнала Trace выходные данные консоли средств разработчика на уровне Подробный включают сообщения журнала Microsoft.AspNetCore.Components.RenderTree, такие как:

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

Program В файле сообщения журнала, относящиеся к Microsoft.AspNetCore.Components.RenderTree отключению, можно отключить с помощью одного из следующих подходов:

  • 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)
        ));
    

После добавления одного из предыдущих фильтров в приложение выходные данные консоли на уровне Подробный не включают сообщения журнала от API Microsoft.AspNetCore.Components.RenderTree.

Поставщик пользовательского средства ведения журнала на стороне клиента

В примере в этом разделе демонстрируется пользовательский поставщик средства ведения журнала для дальнейшей настройки.

Добавьте в приложение ссылку на пакет Microsoft.Extensions.Logging.Configuration.

Примечание.

Рекомендации по добавлению пакетов в приложения .NET см. в разделе Способы установки пакетов NuGet в статье Рабочий процесс использования пакета (документация по NuGet). Проверьте правильность версий пакета на сайте NuGet.org.

Добавьте следующую настраиваемую конфигурацию средства ведения журнала. Конфигурация создает словарь LogLevels, который задает пользовательский формат журнала для трех уровней ведения журнала: Information, Warning и Error. LogFormatenum используется для описания коротких (LogFormat.Short) и длинных (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
    }
}

Добавьте в приложение следующее пользовательское средство ведения журнала. CustomLogger выводит пользовательские форматы журнала с учетом значений logLevel, определенных в предыдущей конфигурации 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;
            }
        }
    }
}

Добавьте в приложение следующее пользовательское средство ведения журнала. CustomLoggerProvider использует методику на основе Options для настройки средства ведения журнала с помощью встроенных компонентов настройки ведения журнала. Например, приложение может устанавливать или изменять форматы журналов с помощью файла appsettings.json, не требуя изменений в коде пользовательского средства ведения журнала, как показано в конце этого раздела.

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();
    }
}

Добавьте следующие расширения пользовательского средства ведения журнала.

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;
    }
}

Program В файле построителя узлов очистите существующего поставщика, вызвав ClearProviders и добавьте настраиваемый поставщик ведения журнала:

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

Следующий компонент CustomLoggerExample:

  • Сообщение отладки не регистрируется в журнале.
  • Информационное сообщение вносится в журнал в коротком формате (LogFormat.Short).
  • Предупреждение регистрируется в журнале в коротком формате (LogFormat.Short).
  • Сообщение об ошибке регистрируется в длинном формате (LogFormat.Long).
  • Сообщение трассировки не вносится в журнал.

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.");
    }
}

Следующие выходные данные отображаются в консоли средств разработчика в браузере при нажатии на кнопку Log Messages. Записи журнала отражают соответствующие форматы, применяемые пользовательским средством ведения журнала (клиентское приложение называется 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.

При изучении предыдущего примера становится очевидным, что установка форматов строк журнала с помощью словаря в CustomLoggerConfiguration не является обязательной. Форматы линий, применяемые пользовательским средством ведения журнала (CustomLogger), могут быть применены путем простой проверки logLevel в методе Log. Назначение формата журнала с помощью конфигурации выполняется для того, чтобы разработчик мог легко изменить формат журнала с помощью конфигурации приложения, как показано в следующем примере.

В клиентском приложении добавьте или обновите appsettings.json файл, чтобы включить конфигурацию ведения журнала. Задайте формат журнала Long для всех трех уровней ведения журнала:

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

Обратите внимание, что в предыдущем примере запись для конфигурации пользовательского средства ведения журнала имеет значение CustomLog, которое было применено к пользовательскому поставщику средства ведения журнала (CustomLoggerProvider) в качестве псевдонима с [ProviderAlias("CustomLog")]. Конфигурация ведения журнала может быть применена с именем CustomLoggerProvider вместо CustomLog, но использование псевдонима CustomLog более удобно для пользователя.

Program В файле используется конфигурация ведения журнала. Добавьте следующий код:

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

Вызов LoggingBuilderConfigurationExtensions.AddConfiguration можно разместить до или после добавления пользовательского поставщика средства ведения журнала.

Снова запустите приложение. Выберите кнопку Log Messages. Обратите внимание, что конфигурация ведения журнала применяется из файла appsettings.json. Все три записи журнала находятся в формате long (LogFormat.Long) (клиентское приложение называется 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.

Клиентские журналы область

Средство ведения журнала средств разработчика не поддерживает область журналов. Однако области журнала поддерживает пользовательское средство ведения журнала. Неподдерживаемый пример, который можно продолжить разработку в соответствии с вашими потребностями, см BlazorWebAssemblyScopesLogger . в примере приложения в Blazor репозитории примеров GitHub (как скачать).

В примере приложения используется стандартный синтаксис ведения журнала BeginScope ASP.NET Core для обозначения областей зарегистрированных сообщений. В следующем примере служба Logger — это ILogger<CustomLoggerExample>, который внедряется в компонент приложения CustomLoggerExample (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.");
        }
    }
}

Выходные данные:

[ 3: информация ] {CLASS} — INFO: ОДИН область. => L1 blazor.webassembly.js:1:35542
[ 3: информация ] {CLASS} — INFO: ДВА область. => L1 => L2 blazor.webassembly.js:1:35542
[ 3: информация ] {CLASS} — INFO: ТРИ область. => L1 => L2 => L3

Заполнитель {CLASS} в предыдущем примере .BlazorWebAssemblyScopesLogger.Pages.CustomLoggerExample

Ведение журнала предварительно подготовленных компонентов

Предварительно созданные компоненты дважды выполняют код инициализации компонентов. Ведение журнала выполняется на стороне сервера при первом выполнении кода инициализации и на стороне клиента при втором выполнении кода инициализации. В зависимости от цели ведения журнала при инициализации, проверяйте журналы на стороне сервера и (или) на стороне клиента.

SignalR ведение журнала клиентов с помощью SignalR построителя клиентов

Этот раздел относится к приложениям на стороне сервера.

В Blazor конфигурации запуска скрипта передайте объект конфигурации, вызывающий configureSignalRconfigureLogging уровень журнала.

configureLogging Для значения уровня журнала передайте аргумент в виде строки или целочисленного уровня журнала, показанного в следующей таблице.

LogLevel Параметр строки Целочисленный параметр
Trace trace 0
Debug debug 1
Information information 2
Warning warning 3
Error error 4
Critical critical 5
None none 6

Пример 1. Задайте Information уровень журнала строковым значением.

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>

В предыдущем примере {BLAZOR SCRIPT} заполнитель — это путь к скрипту Blazor и имя файла. Сведения о расположении скрипта см. в разделе ASP.NET Структура проекта CoreBlazor.

Пример 2. Задайте Information уровень журнала целым значением.

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>

В предыдущем примере {BLAZOR SCRIPT} заполнитель — это путь к скрипту Blazor и имя файла. Сведения о расположении скрипта см. в разделе ASP.NET Структура проекта CoreBlazor.

Примечание.

Использование целого числа для указания уровня ведения журнала в примере 2, часто называемого волшебным числом или магической константой, считается плохой практикой кодирования, так как целое число не четко определяет уровень ведения журнала при просмотре исходного кода. Если минимизация байтов, передаваемых в браузер, является приоритетом, использование целого числа может быть оправдано (рекомендуется удалить комментарий в таких случаях).

Дополнительные сведения о запуске () см. в Blazor разделе ASP.NET Запуск CoreBlazor.Blazor.start()

SignalR ведение журнала клиентов с конфигурацией приложения

Настройте конфигурацию параметров приложения, как описано в ASP.NET конфигурации CoreBlazor. Поместите файлы параметров приложения в wwwroot файл, содержащий Logging:LogLevel:HubConnection параметр приложения.

Примечание.

В качестве альтернативы использованию параметров приложения можно передать LogLevel в качестве аргумента LoggingBuilderExtensions.SetMinimumLevel при создании подключения концентратора в компоненте Razor . Однако случайное развертывание приложения в рабочей среде размещения с подробным ведением журнала может привести к штрафу производительности. Мы рекомендуем использовать параметры приложения для задания уровня журнала.

Logging:LogLevel:HubConnection Укажите параметр приложения в файле по умолчанию appsettings.json и в Development файле параметров приложения среды. Используйте типичный менее подробный уровень журнала по умолчанию, например LogLevel.Warning. Значение параметров приложения по умолчанию — это то, что используется в Staging средах, Production если файлы параметров приложения для этих сред отсутствуют. Используйте подробный уровень журнала в Development файле параметров приложения среды, например 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"
    }
  }
}

Внимание

Конфигурация в предыдущих файлах параметров приложения используется приложением только в том случае, если следует руководство в конфигурации ASP.NET CoreBlazor.

В верхней части Razor файла компонента (.razor):

  • Вставьте ILoggerProvider, чтобы добавить WebAssemblyConsoleLogger к регистраторам, передаваемым в HubConnectionBuilder. В отличие от традиционных ConsoleLogger, WebAssemblyConsoleLogger является оболочкой для API-интерфейсов ведения журнала, характерных для браузера (например, console.log). Использование WebAssemblyConsoleLogger делает возможным ведение журнала в Mono внутри контекста браузера.
  • IConfiguration Внедрение параметра приложения для чтенияLogging:LogLevel:HubConnection.

Примечание.

WebAssemblyConsoleLogger является внутренней оболочкой и не поддерживается для непосредственного использования в коде разработчика.

@inject ILoggerProvider LoggerProvider
@inject IConfiguration Config

Примечание.

Следующий пример основан на демонстрации в руководствеBlazorSignalR. Дополнительные сведения см. в руководстве.

В методе компонента OnInitializedAsync используйте для HubConnectionBuilderExtensions.ConfigureLogging добавления поставщика ведения журнала и задания минимального уровня журнала из конфигурации:

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();
}

Примечание.

В предыдущем примере Navigation используется внедренный NavigationManagerобъект.

Дополнительные сведения о настройке среды приложения см. в ASP.NET основных Blazor средах.

Ведение журнала проверки подлинности на стороне клиента

Сообщения проверки подлинности журналов Blazor на LogLevel.DebugLogLevel.Trace уровне журнала с конфигурацией ведения журнала в параметрах приложения или с помощью фильтра Microsoft.AspNetCore.Components.WebAssembly.Authentication журнала в Program файле.

Используйте любой из следующих подходов:

  • В файле параметров приложения (например, wwwroot/appsettings.Development.json):

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

    Дополнительные сведения о настройке клиентского приложения для чтения файлов параметров приложения см. в ASP.NET конфигурации CoreBlazor.

  • С помощью фильтра журналов в следующем примере:

    • Активирует ведение журнала для Debug конфигурации сборки с помощью директивы препроцессора C#.
    • Blazor Регистрирует сообщения проверки подлинности на Debug уровне журнала.
    #if DEBUG
        builder.Logging.AddFilter(
            "Microsoft.AspNetCore.Components.WebAssembly.Authentication", 
            LogLevel.Debug);
    #endif
    

Примечание.

RazorКомпоненты, отображаемые только в журнале клиента, записываются в консоль средств разработчика браузера на стороне клиента.

Дополнительные ресурсы