ASP.NET Core Blazor 日志记录

注意

此版本不是本文的最新版本。 有关当前版本,请参阅本文.NET 9 版本。

警告

此版本的 ASP.NET Core 不再受支持。 有关详细信息,请参阅 .NET 和 .NET Core 支持策略。 对于当前版本,请参阅此文的 .NET 8 版本

重要

此信息与预发布产品相关,相应产品在商业发布之前可能会进行重大修改。 Microsoft 对此处提供的信息不提供任何明示或暗示的保证。

有关当前版本,请参阅本文.NET 9 版本。

本文介绍 Blazor 应用日志记录,包括配置以及如何从 Razor 组件写入日志消息。

配置

可以从应用设置文件中加载日志记录配置。 有关详细信息,请参阅 ASP.NET Core Blazor 配置

在默认日志级别,无需配置额外的日志记录提供程序:

当应用在项目文件中配置为使用隐式命名空间 (<ImplicitUsings>enable</ImplicitUsings>) 时,不需要 Microsoft.Extensions.Loggingusing 指令或 LoggerExtensions 类中的任何 API 来支持 API Visual Studio IntelliSense 完成或生成应用。 如果没有启用隐式命名空间,Razor 组件必须明确定义 @using 指令,用于记录不是通过 _Imports.razor 文件导入的命名空间。

日志级别

日志级别符合 ASP.NET Core 应用日志级别,具体信息列在 LogLevel 处的 API 文档中。

Razor 组件日志记录

要支持对 API 使用 IntelliSense 补全功能(例如 LogWarningLogError),需具备 Microsoft.Extensions.Loggingusing 指令。

如下示例中:

  • 注入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

<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

<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 日志记录的所有功能都在客户端侧受支持。 例如,客户端组件无法访问客户端的文件系统或网络,因此无法将日志写入客户端的物理或网络存储。 使用旨在用于单页应用 (SPA) 的第三方日志记录服务时,请遵循该服务的安全指南。 请记住,每段数据(包括存储在客户端中的密钥或机密)都是不安全的,并且很容易被恶意用户发现

根据框架版本和日志记录功能,日志记录实现可能需要将 Microsoft.Extensions.Logging 的命名空间添加到 Program 文件:

using Microsoft.Extensions.Logging;

使用 WebAssemblyHostBuilder.Logging 属性在客户端侧应用中配置日志记录。 Logging 属性的类型为 ILoggingBuilder,因此支持 ILoggingBuilder 的扩展方法。

若要设置最低日志记录级别,请通过 LogLevelProgram 文件中的主机生成器上调用 LoggingBuilderExtensions.SetMinimumLevel。 以下示例将最低日志级别设置为 Warning

builder.Logging.SetMinimumLevel(LogLevel.Warning);

登录客户端侧 Program 文件

使用框架的内部控制台记录器提供程序(WebAssemblyConsoleLoggerProvider(引用源))生成 WebAssemblyHostBuilder 后,将支持在客户端侧应用中进行日志记录。

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 版本的当前开发。 若要为特定版本选择标记,请使用“切换分支或标记”下拉列表。 有关详细信息,请参阅如何选择 ASP.NET Core 源代码的版本标记 (dotnet/AspNetCore.Docs #26205)

客户端侧日志类别

支持日志类别

以下示例展示了如何在从 Blazor 项目模板创建的应用的 Counter 组件中使用日志类别。

在将 ILoggerFactory 作为 LoggerFactory 注入的应用的 Counter 组件 (Counter.razor) 的 IncrementCount 方法中:

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

开发人员工具控制台输出以下内容:

warn: CustomCategory[0]
Someone has clicked me!

客户端侧日志事件 ID

支持日志事件 ID

以下示例展示了如何在从 Blazor 项目模板创建的应用的 Counter 组件中使用日志事件 ID。

LogEvent.cs:

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

在应用的 Counter 组件 (Counter.razor) 的 IncrementCount 方法中:

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!

客户端侧日志消息模板

支持日志消息模板

以下示例展示了如何在从 Blazor 项目模板创建的应用的 Counter 组件中使用日志消息模板。

在应用的 Counter 组件 (Counter.razor) 的 IncrementCount 方法中:

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

开发人员工具控制台输出以下内容:

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

客户端侧日志异常参数

支持日志异常参数

以下示例展示了如何在从 Blazor 项目模板创建的应用的 Counter 组件中使用日志异常参数。

在应用的 Counter 组件 (Counter.razor) 的 IncrementCount 方法中:

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

客户端侧筛选函数

支持筛选函数

以下示例展示了如何在从 Blazor 项目模板创建的应用的 Counter 组件中使用筛选器。

Program 文件中:

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

在将 ILoggerFactory 作为 LoggerFactory 注入的应用的 Counter 组件 (Counter.razor) 的 IncrementCount 方法中:

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!

该应用还可以为特定命名空间配置日志筛选。 例如,在 Program 文件中将日志级别设置为 Trace

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

将上述任一筛选器添加到应用后,详细级别的控制台输出不会显示来自 Microsoft.AspNetCore.Components.RenderTree API 的日志记录消息。

客户端侧自定义记录器提供程序

本部分中的示例演示了用于进一步自定义的自定义记录器提供程序。

Microsoft.Extensions.Logging.Configuration 包添加对应用的包引用。

注意

有关将包添加到 .NET 应用的指南,请参阅包使用工作流(NuGet 文档)中“安装和管理包”下的文章。 在 NuGet.org 中确认正确的包版本。

添加以下自定义记录器配置。 该配置建立一个 LogLevels 字典,该字典设置以下三个日志级别的自定义日志格式:InformationWarningErrorLogFormatenum 用于描述短 (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 根据上述 CustomLoggerConfiguration 配置中定义的 logLevel 值输出自定义日志格式。

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 中的字典设置日志行格式显然不是必要。 只需在 Log 方法中检查 logLevel,即可应用自定义记录器 (CustomLogger) 应用的行格式。 通过配置分配日志格式的目的是让开发人员可以通过应用配置轻松更改日志格式,如以下示例所示。

在客户端侧应用中,添加或更新 appsettings.json 文件以包括日志记录配置。 将这三个日志级别的日志格式设置为 Long

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

请注意,在上一示例中,自定义记录器配置的条目是 CustomLog,它是作为 [ProviderAlias("CustomLog")] 的别名应用于自定义记录器提供程序 (CustomLoggerProvider) 的。 日志记录配置可能应用了 CustomLoggerProvider 名称而不是 CustomLog,但使用别名 CustomLog 更加易记。

Program 文件中,使用日志记录配置。 添加以下代码:

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

可以在添加自定义记录器提供程序之前或之后调用 LoggingBuilderConfigurationExtensions.AddConfiguration

再次运行应用。 选择 Log Messages 按钮。 请注意,日志记录配置是通过 appsettings.json 文件应用的。 所有三个日志条目都采用长 (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.

客户端侧日志范围

开发人员工具控制台记录器不支持日志作用域。 但是,自定义记录器可以支持日志作用域。 有关进一步开发不受支持的示例以满足需求,请参阅 Blazor 示例 GitHub 存储库下载方法)中的 BlazorWebAssemblyScopesLogger 示例应用。

示例应用使用标准 ASP.NET Core BeginScope 日志记录语法来指示记录的消息的作用域。 以下示例中的 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: Information ] {CLASS} - INFO: ONE scope. => L1 blazor.webassembly.js:1:35542
[ 3: Information ] {CLASS} - INFO: TWO scopes. => L1 => L2 blazor.webassembly.js:1:35542
[ 3: Information ] {CLASS} - INFO: THREE scopes. => L1 => L2 => L3

前面的示例中的 {CLASS} 占位符为 BlazorWebAssemblyScopesLogger.Pages.CustomLoggerExample

预呈现的组件日志记录

预呈现的组件执行组件初始化代码两次。 日志记录的第一次初始化代码执行位于服务器端,第二次初始化代码执行位于客户端。 根据初始化期间日志记录的目标,检查服务器端和/或客户端日志。

使用 SignalR 客户端生成器进行 SignalR 客户端日志记录

本部分适用于服务器端应用。

在 Blazor 脚本启动配置中,传入使用日志级别调用 configureLoggingconfigureSignalR 配置对象。

对于 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 Web App:

<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 Core Blazor 项目结构

示例 2:使用整数值设置 Information 日志级别。

Blazor Web App:

<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 Core Blazor 项目结构

注意

在示例 2 中使用整数指定日志记录级别(通常称为幻数或 magic 常量)被视为一种糟糕的编码做法,因为该整数在查看源代码时无法清楚地识别日志记录级别。 如果首要任务是尽量减少传输到浏览器的字节数,则使用整数可能是合理的(在这种情况下,请考虑删除注释)。

有关 Blazor 启动 (Blazor.start()) 的详细信息,请参阅 ASP.NET Core Blazor 启动

使用应用配置的 SignalR 客户端日志记录

按照 ASP.NET Core Blazor 配置中所述设置应用设置配置。 将包含 Logging:LogLevel:HubConnection 应用设置的应用设置文件置于 wwwroot 中。

注意

作为使用应用设置的替代方法,当在 Razor 组件中创建中心连接时,可以将 LogLevel 作为参数传递给 LoggingBuilderExtensions.SetMinimumLevel。 但是,意外将应用部署到具有详细日志记录的生产托管环境可能会导致性能损失。 建议使用应用设置来设置日志级别。

在默认 appsettings.json 文件和 Development 环境应用设置文件中提供 Logging:LogLevel:HubConnection 应用设置。 使用典型的不太详细的日志级别作为默认值,例如 LogLevel.Warning。 默认应用设置值是在 StagingProduction 环境中使用的值(如果不存在这些环境的应用设置文件)。 在 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 Core Blazor 配置中的指导时,应用才会使用上述应用设置文件中的配置。

在 Razor 组件文件 (.razor) 顶部:

  • 注入 ILoggerProvider,将 WebAssemblyConsoleLogger 添加到传递给 HubConnectionBuilder 的日志记录提供程序。 与 ConsoleLoggerProvider 不同,WebAssemblyConsoleLogger 是特定于浏览器的日志记录 API(例如,console.log)的包装器。 使用 WebAssemblyConsoleLogger 可以在浏览器上下文内的 Mono 中进行日志记录。
  • 注入 IConfiguration 以读取 Logging:LogLevel:HubConnection 应用设置。

注意

WebAssemblyConsoleLogger内部包装器,不支持在开发人员代码中直接使用。

@inject ILoggerProvider LoggerProvider
@inject IConfiguration Config

说明

以下示例基于结合使用 SignalR 和 Blazor 教程中的演示。 有关更多详细信息,请参阅教程。

在组件的 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 Core Blazor 环境

客户端侧身份验证日志记录

使用应用设置中的日志记录配置或使用 Program 文件中的 Microsoft.AspNetCore.Components.WebAssembly.Authentication 的日志筛选器,在 LogLevel.DebugLogLevel.Trace 日志记录级别记录 Blazor 身份验证消息。

请使用下述任一方法:

  • 在应用程序设置文件中(例如 wwwroot/appsettings.Development.json):

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

    如需详细了解如何配置客户端应用以读取应用设置文件,请参阅 ASP.NET Core Blazor 配置

  • 通过使用日志筛选器,以下示例:

    • 使用 C# 预处理器指令激活 Debug 生成配置的日志记录。
    • Debug 日志级别记录 Blazor 身份验证消息。
    #if DEBUG
        builder.Logging.AddFilter(
            "Microsoft.AspNetCore.Components.WebAssembly.Authentication", 
            LogLevel.Debug);
    #endif
    

说明

客户端上呈现的 Razor 组件仅记录到客户端侧浏览器开发人员工具控制台。

其他资源