次の方法で共有


ASP.NET Core Blazor のログ

注意

これは、この記事の最新バージョンではありません。 現在のリリースについては、この記事の .NET 9 バージョンを参照してください。

警告

このバージョンの ASP.NET Core はサポート対象から除外されました。 詳細については、「.NET および .NET Core サポート ポリシー」を参照してください。 現在のリリースについては、この記事の .NET 8 バージョンを参照してください。

重要

この情報はリリース前の製品に関する事項であり、正式版がリリースされるまでに大幅に変更される可能性があります。 Microsoft はここに示されている情報について、明示か黙示かを問わず、一切保証しません。

現在のリリースについては、この記事の .NET 9 バージョンを参照してください。

この記事では、構成や Razor コンポーネントからログ メッセージを書き込む方法など、Blazor アプリのログについて説明します。

構成

ログの構成は、アプリの設定ファイルから読み込むことができます。 詳しくは、「ASP.NET Core Blazor の構成」をご覧ください。

既定のログ レベルで、追加のログ プロバイダーを構成しない場合:

  • サーバーでは、LogLevel.Information レベル以上の Development 環境のサーバー側 .NET コンソールに対してのみ、アプリによってログが記録されます。
  • クライアントでは、LogLevel.Information レベル以上のクライアント側ブラウザー開発者ツール コンソールに対してのみ、アプリによってログが記録されます。

プロジェクト ファイルで暗黙の名前空間 (<ImplicitUsings>enable</ImplicitUsings>) を使うようにアプリが構成されている場合、API Visual Studio IntelliSense の補完またはアプリのビルドをサポートするために Microsoft.Extensions.Logging または LoggerExtensions クラス内の任意の API の using ディレクティブは必要ありません。 暗黙的な名前空間が有効ではない場合、_Imports.razor ファイル経由でインポートされていないログの名前空間に対して、Razor コンポーネントで @using ディレクティブを明示的に定義する必要があります。

ログ レベル

ログ レベルは ASP.NET Core アプリのログ レベル (API ドキュメントの LogLevel に掲載) に準拠しています。

Razor コンポーネントのログ

LogWarningLogError など、API の IntelliSense 入力候補をサポートするには、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 の拡張メソッドがサポートされます。

最小ログ レベルを設定するには、Program ファイルのホスト ビルダーで、LogLevel を使用して 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.

Note

通常、.NET 参照ソースへのドキュメント リンクを使用すると、リポジトリの既定のブランチが読み込まれます。このブランチは、.NET の次回リリースに向けて行われている現在の開発を表します。 特定のリリースのタグを選択するには、[Switch branches or tags](ブランチまたはタグの切り替え) ドロップダウン リストを使います。 詳細については、「ASP.NET Core ソース コードのバージョン タグを選択する方法」 (dotnet/AspNetCore.Docs #26205) を参照してください。

クライアント側のログ カテゴリ

ログ カテゴリがサポートされています。

次の例は、Blazor プロジェクト テンプレートから作成されたアプリの Counter コンポーネントでログ カテゴリを使う方法を示しています。

ILoggerFactoryLoggerFactory として挿入するアプリの 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);

ILoggerFactoryLoggerFactory として挿入するアプリの 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 パッケージのアプリへのパッケージ参照を追加します。

Note

.NET アプリへのパッケージの追加に関するガイダンスについては、「パッケージ利用のワークフロー」 (NuGet ドキュメント) の "パッケージのインストールと管理" に関する記事を参照してください。 NuGet.org で正しいパッケージ バージョンを確認します。

次のカスタム ロガー構成を追加します。 この構成により、InformationWarningError の 3 つのログ レベルのカスタム ログ形式を設定する LogLevels 辞書が確立されます。 LogFormat enum は、短い (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 の辞書を使用してログ行の形式を設定することは、厳密には必要ないことが明らかです。 カスタム ロガー (CustomLogger) によって適用された行形式は、logLevelLog メソッドで確認するだけで適用できた可能性があります。 構成を使用してログ形式を割り当てる目的は、次の例に示すように、開発者がアプリ構成を使用してログ形式を簡単に変更できることです。

クライアント側アプリで、、ログ構成を含むように appsettings.json ファイルを追加または更新します。 次の 3 つのログ レベルのすべてについて、ログの形式を Long に設定します。

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

前の例では、カスタム ロガー構成のエントリが CustomLog であることに注目してください。これは、カスタム ロガー プロバイダー (CustomLoggerProvider) に [ProviderAlias("CustomLog")] の別名として適用されました。 ログの構成は、名前 CustomLog ではなく CustomLoggerProvider を使用して適用することができましたが、別名 CustomLog を使用する方がよりユーザー フレンドリです。

Program ファイルで、ログ構成を使用します。 次のコードを追加します。

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

LoggingBuilderConfigurationExtensions.AddConfiguration の呼び出しは、カスタム ロガー プロバイダーを追加する前または後に配置できます。

再度アプリを実行します。 Log Messages ボタンを選択します。 ログの構成が appsettings.json ファイルから適用されていることに注目してください。 3 つすべてのログ エントリは、長い (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 サービスは、アプリの CustomLoggerExample コンポーネント (CustomLoggerExample.razor) に挿入される ILogger<CustomLoggerExample> です。

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

Output:

[ 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 です。

プリレンダリングされたコンポーネントのログ

プリレンダリングされたコンポーネントは、コンポーネント初期化コードを 2 回実行します。 ログ記録は、初期化コードの最初の実行時にはサーバー側で、初期化コードの 2 回目の実行時にはクライアント側で行われます。 初期化時のログ記録の目的に応じて、サーバー側、クライアント側、またはその両方でログをチェックします。

SignalR クライアント ビルダーを使用した SignalR クライアントのログ

このセクションは、サーバー側アプリに適用されます。

Blazor スクリプトの開始構成で、ログ レベルを指定して configureLogging を呼び出す configureSignalR 構成オブジェクトを渡します。

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 プロジェクトの構造」を参照してください。

Note

例 2 のように整数を使ってログ レベルを指定することは ("マジック ナンバー" または "マジック定数" と呼ばれることがよくあります)、ソース コードを見たときに整数が示すログ レベルがはっきりわからないため、不適切なコーディング手法と考えられます。 ブラウザーに転送されるバイト数を最小限に抑えることが優先される場合は、整数を使うのが理にかなっている可能性があります (このような場合はコメントの削除を検討してください)。

Blazor の起動 (Blazor.start()) の詳細については、「ASP.NET Core Blazor の起動」をご覧ください。

アプリ構成を使用しした SignalR クライアントのログ

ASP.NET Core Blazor の構成」の説明に従って、アプリ設定の構成を設定します。 Logging:LogLevel:HubConnection アプリ設定を含むアプリ設定ファイルを wwwroot に配置します。

注意

アプリ設定を使用する代わりに、ハブ接続が Razor コンポーネントで作成されるときに、LogLevelLoggingBuilderExtensions.SetMinimumLevel の引数として渡すことができます。 ただし、詳細ログを含む運用レベルのホスティング環境にアプリを誤って配置すると、パフォーマンスが低下する可能性があります。 アプリ設定を使用してログ レベルを設定することをお勧めします。

既定の appsettings.json ファイルと Development 環境アプリ設定ファイルに Logging:LogLevel:HubConnection アプリ設定を指定します。 既定には、一般的な詳細度の低いログ レベル (LogLevel.Warning など) を使用します。 そのような環境のアプリ設定ファイルが存在しない場合、StagingProduction の環境で使用されるものが既定のアプリ設定値です。 LogLevel.Trace などの Development 環境アプリ設定ファイルでは、詳細ログ レベルを使用してください。

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 を挿入して、HubConnectionBuilder に渡されたログ プロバイダーに WebAssemblyConsoleLogger を追加します。 ConsoleLoggerProvider とは異なり、WebAssemblyConsoleLogger はブラウザー固有のログ API (例: console.log) のラッパーです。 WebAssemblyConsoleLogger を使用すると、ブラウザー コンテキスト内の Mono 内でログ記録できるようになります。
  • IConfiguration を挿入して Logging:LogLevel:HubConnection アプリ設定を読み取ります。

Note

WebAssemblyConsoleLoggerinternal であり、開発者コードで直接サポートされていません。

@inject ILoggerProvider LoggerProvider
@inject IConfiguration Config

メモ

次の例は、Blazor で SignalR を使用するチュートリアルのデモに基づいています。 詳細については、チュートリアルを参照してください。

コンポーネントの 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 にログ フィルターを使用して、Blazor 認証メッセージを LogLevel.Debug または LogLevel.Trace ログ レベルでログに記録します。

次の "いずれか" の方法を使用します。

  • アプリ設定ファイル (例: wwwroot/appsettings.Development.json):

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

    クライアント側アプリでアプリ設定ファイルの読み取りを構成する方法の詳細については、「ASP.NET Core Blazor の構成」をご覧ください。

  • ログ フィルターを使用する場合、次の例のようになります。

    #if DEBUG
        builder.Logging.AddFilter(
            "Microsoft.AspNetCore.Components.WebAssembly.Authentication", 
            LogLevel.Debug);
    #endif
    

メモ

クライアントにレンダリングされた Razor コンポーネントのログは、クライアント側のブラウザー開発者ツール コンソールに対してのみ記録されます。

その他の技術情報