다음을 통해 공유


ASP.NET Core Blazor 로깅

참고 항목

이 문서의 최신 버전은 아닙니다. 현재 릴리스는 이 문서의 .NET 8 버전을 참조 하세요.

Warning

이 버전의 ASP.NET Core는 더 이상 지원되지 않습니다. 자세한 내용은 .NET 및 .NET Core 지원 정책을 참조 하세요. 현재 릴리스는 이 문서의 .NET 8 버전을 참조 하세요.

Important

이 정보는 상업적으로 출시되기 전에 실질적으로 수정될 수 있는 시험판 제품과 관련이 있습니다. Microsoft는 여기에 제공된 정보에 대해 어떠한 명시적, 또는 묵시적인 보증을 하지 않습니다.

현재 릴리스는 이 문서의 .NET 8 버전을 참조 하세요.

이 문서에서는 Blazor 구성 및 구성 요소에서 Razor 로그 메시지를 작성하는 방법을 포함하여 앱 로깅에 대해 설명합니다.

구성

로깅 구성은 앱 설정 파일에서 로드할 수 있습니다. 자세한 내용은 ASP.NET Core Blazor 구성을 참조하세요.

기본 로그 수준에서 추가 로깅 공급자를 구성하지 않고 다음을 수행합니다.

암시적 네임스페이스(<ImplicitUsings>enable</ImplicitUsings>)를 사용하도록 프로젝트 파일에서 앱이 구성된 경우, API Visual Studio IntelliSense 완성 또는 빌드 앱을 지원하기 위해 LoggerExtensions 클래스의 Microsoft.Extensions.Logging에 대한 using 지시문 또는 API가 필요하지 않습니다. 암시적 네임스페이스를 사용하도록 설정하지 않은 경우, Razor 구성 요소는 _Imports.razor 파일을 통해 가져오지 않는 네임스페이스를 로깅하기 위한 @using 지시문을 명시적으로 정의해야 합니다.

로그 수준

로그 수준은 API 설명서 LogLevel에 나열된 ASP.NET Core 앱 로그 수준을 준수합니다.

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에서 사용할 수 있는 확장 메서드를 지원합니다.

최소 로깅 수준을 설정하려면 파일LogLevel에서 호스트 작성 Program 기를 호출 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을 위한 현재 개발을 나타내는 리포지토리의 기본 분기를 로드합니다. 특정 릴리스를 위한 태그를 선택하려면 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!

앱은 특정 네임스페이스에 대한 로그 필터링을 구성할 수도 있습니다. 예를 들어 로그 수준을 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)
        ));
    

위의 필터 중 하나가 앱에 추가된 후에 자세한 정보 표시 수준의 콘솔 출력에 Microsoft.AspNetCore.Components.RenderTree API의 로깅 메시지가 표시되지 않습니다.

클라이언트 쪽 사용자 지정 로거 공급자

이 섹션의 예제에서는 추가 사용자 지정을 위한 사용자 지정 로거 공급자를 보여 줍니다.

Microsoft.Extensions.Logging.Configuration 패키지용 앱에 패키지 참조를 추가합니다.

참고 항목

.NET 앱에 패키지를 추가하는 방법에 대한 지침은 패키지 사용 워크플로에서 패키지 설치 및 관리의 문서(NuGet 설명서)를 참조하세요. NuGet.org에서 올바른 패키지 버전을 확인합니다.

다음 사용자 지정 로거 구성을 추가합니다. 구성은 세 가지 로그 수준(Information, Warning, Error)에 대한 사용자 지정 로그 형식을 설정하는 LogLevels 사전을 설정합니다. A LogFormat enum 는 짧은() 및 long(LogFormat.ShortLogFormat.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)가 적용한 줄 형식은 단순히 Log 메서드에서 logLevel을 확인하여 적용할 수 있습니다. 구성을 통해 로그 형식을 할당하는 목적은 다음 예제와 같이 개발자가 앱 구성을 통해 로그 형식을 쉽게 변경할 수 있다는 것입니다.

클라이언트 쪽 앱에서 로깅 구성을 appsettings.json 포함하도록 파일을 추가하거나 업데이트합니다. 세 가지 로그 수준 모두에 대해 로그 형식을 Long으로 설정합니다.

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

앞의 예제에서는 사용자 지정 로거 구성에 대한 항목이 CustomLog이며, 이 항목은 [ProviderAlias("CustomLog")]의 별칭으로 사용자 지정 로거 공급자(CustomLoggerProvider)에 적용된 것을 확인합니다. 로깅 구성이 CustomLog 대신 CustomLoggerProvider의 이름으로 적용되었을 수 있지만 별칭 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.

클라이언트 쪽 로그 범위

개발자 도구 콘솔 로거는 로그 범위를 지원하지 않습니다. 그러나 사용자 지정 로거는 로그 범위를 지원할 수 있습니다. 요구 사항에 맞게 추가로 개발할 수 있는 지원되지 않는 예제는 샘플 GitHub 리포지토리(다운로드 방법)의Blazor 샘플 앱을 참조 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: 정보 ] {CLASS} - INFO: ONE 범위입니다. => 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 configureSignalR 로그 수준으로 호출 configureLogging 하는 구성 개체를 전달합니다.

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에서 정수를 사용하여 매직 넘버 또는 매직 상수라고도 하는 로깅 수준을 지정하는 것은 소스 코드를 볼 때 정수가 로깅 수준을 명확하게 식별하지 못하기 때문에 부실한 코딩 사례로 간주됩니다. 브라우저로 전송되는 바이트를 최소화하는 것이 우선 순위인 경우 정수 사용이 정당화될 수 있습니다(이러한 경우 주석 제거 고려).

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

Important

이전 앱 설정 파일의 구성은 ASP.NET Core Blazor 구성의 지침을 따르는 경우에만 앱에서 사용됩니다.

Razor 구성 요소 파일(.razor)의 맨 위에 다음을 수행합니다.

  • ILoggerProvider를 삽입하여 HubConnectionBuilder로 전달된 로깅 공급자에 WebAssemblyConsoleLogger를 추가합니다. 와 ConsoleLoggerProviderWebAssemblyConsoleLogger 달리 브라우저별 로깅 API(예console.log: )에 대한 래퍼입니다. WebAssemblyConsoleLogger를 사용하면 브라우저 컨텍스트의 Mono 내에서 로깅을 수행할 수 있습니다.
  • IConfiguration를 삽입하여 Logging:LogLevel:HubConnection 앱 설정을 읽습니다.

참고 항목

WebAssemblyConsoleLogger내부용이며, 개발자 코드에서 직접 사용할 수 없습니다.

@inject ILoggerProvider LoggerProvider
@inject IConfiguration Config

참고 항목

다음 예제는 with 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 환경을 참조하세요.

클라이언트 쪽 인증 로깅

Blazor 앱 설정에서 LogLevel.Debug 로깅 구성을 사용하거나 LogLevel.Trace 파일의 로그 필터 Microsoft.AspNetCore.Components.WebAssembly.Authentication Program 를 사용하여 또는 로깅 수준에서 인증 메시지를 기록합니다.

다음 방식 중 하나를 사용합니다.

  • 앱 설정 파일에서(예: 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 클라이언트에서 렌더링된 구성 요소는 클라이언트 쪽 브라우저 개발자 도구 콘솔에만 로그됩니다.

추가 리소스