.NET Core 및 ASP.NET Core의 로깅

작성자: Kirk Larkin, Juergen GutschRick Anderson

.NET Core는 다양한 기본 제공 및 타사 로깅 공급자에서 작동하는 로깅 API를 지원합니다. 이 문서에서는 기본 제공 공급자를 이용하여 로깅 API를 사용하는 방법을 보여줍니다.

이 문서에 사용된 대부분의 코드 예제는 ASP.NET Core 앱에서 가져온 것입니다. 해당 코드 조각의 로깅 관련 부분은 제네릭 호스트를 사용하는 모든 .NET Core 앱에 적용됩니다. ASP.NET Core 웹앱 템플릿은 제네릭 호스트를 사용합니다.

예제 코드 살펴보기 및 다운로드 (다운로드 방법)

로깅 공급자

로그를 표시하는 Console 공급자를 제외하고 로깅 공급자는 로그를 저장합니다. 예를 들어 Azure Application Insights 공급자는 Azure Application Insights의 로그를 저장합니다. 여러 공급자를 사용하도록 설정할 수 있습니다.

기본 ASP.NET Core 웹앱 템플릿은 다음과 같습니다.

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

위의 코드는 ASP.NET Core 웹앱 템플릿을 사용하여 만든 Program 클래스를 보여 줍니다. 다음 몇 개 섹션에서는 제네릭 호스트를 사용하는 ASP.NET Core 웹앱 템플릿을 기반으로 하는 샘플을 제공합니다. 비호스트 콘솔 앱은 문서의 뒷부분에 설명되어 있습니다.

Host.CreateDefaultBuilder로 추가된 로깅 공급자의 기본 세트를 재정의하려면 ClearProviders를 호출하고 필요한 로깅 공급자를 추가합니다. 예를 들어, 다음 코드는

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureLogging(logging =>
        {
            logging.ClearProviders();
            logging.AddConsole();
        })
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
        });

추가 공급자는 다음을 참조하세요.

로그 만들기

로그를 만들려면 DI(종속성 주입)에서 ILogger<TCategoryName> 개체를 사용합니다.

다음 예제가 하는 일:

  • 형식이 AboutModel인 정규화된 이름의 로그 ‘범주’를 사용하는 ILogger<AboutModel> 로거를 만듭니다. 로그 범주는 각 로그와 연결된 문자열입니다.
  • LogInformation을 호출하여 Information 수준에 로그합니다. 로그 수준은 기록된 이벤트의 심각도를 나타냅니다.
public class AboutModel : PageModel
{
    private readonly ILogger _logger;

    public AboutModel(ILogger<AboutModel> logger)
    {
        _logger = logger;
    }
    public string Message { get; set; }

    public void OnGet()
    {
        Message = $"About page visited at {DateTime.UtcNow.ToLongTimeString()}";
        _logger.LogInformation(Message);
    }
}

수준범주는 이 문서의 뒷부분에 자세히 설명되어 있습니다.

Blazor에 대한 자세한 내용은 이 문서의 Blazor 및 Blazor WebAssembly에서 로그 만들기를 참조하세요.

Main 및 Startup에서 로그 만들기에서는 MainStartup에서 로그를 만드는 방법을 보여 줍니다.

로깅 구성

로깅 구성은 일반적으로 appsettings.{Environment} .json 파일의 Logging 섹션에서 제공됩니다. 다음 appsettings.Development.json 파일은 ASP.NET Core 웹앱 템플릿으로 생성되었습니다.

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  }
}

앞의 JSON에서:

  • "Default", "Microsoft""Microsoft.Hosting.Lifetime" 범주가 지정되었습니다.
  • "Microsoft" 범주는 "Microsoft"로 시작하는 모든 범주에 적용됩니다. 예를 들어 이 설정은 "Microsoft.AspNetCore.Routing.EndpointMiddleware" 범주에 적용됩니다.
  • "Microsoft" 범주는 로그 수준 Warning 이상에 로그됩니다.
  • "Microsoft.Hosting.Lifetime" 범주는 "Microsoft" 범주보다 구체적이므로 "Microsoft.Hosting.Lifetime" 범주는 로그 수준 “정보” 이상에 로그됩니다.
  • 특정 로그 공급자를 지정하지 않았으므로 LogLevelWindows EventLog를 제외하고 사용하도록 설정한 모든 로깅 공급자에 적용됩니다.

Logging 속성은 LogLevel 및 로그 공급자 속성을 포함할 수 있습니다. LogLevel 속성은 선택한 범주에 대해 로그할 최소 수준을 지정합니다. 위의 JSON에서는 InformationWarning 로그 수준을 지정했습니다. LogLevel 로그의 심각도를 나타내며 0에서 6 사이의 범위입니다.

Trace = 0, Debug = 1, Information = 2, Warning = 3, Error = 4, Critical = 5 및 None = 6

LogLevel을 지정하면 지정된 수준 이상의 메시지에 대해 로깅을 사용하도록 설정됩니다. 위의 JSON에서 Default 범주는 Information 이상에 대해 로그됩니다. 예를 들어 Information, Warning, ErrorCritical 메시지가 로그됩니다. LogLevel 지정하지 않으면 로깅은 Information 수준으로 기본 설정됩니다. 자세한 내용은 로그 수준을 참조하세요.

공급자 속성에서 LogLevel 속성을 지정할 수 있습니다. 공급자 아래의 LogLevel은 해당 공급자에 대해 로그할 수준을 지정하고 공급자 이외의 로그 설정을 재정의합니다. 다음 appsettings.json 파일을 고려하세요.

{
  "Logging": {
    "LogLevel": { // All providers, LogLevel applies to all the enabled providers.
      "Default": "Error", // Default logging, Error and higher.
      "Microsoft": "Warning" // All Microsoft* categories, Warning and higher.
    },
    "Debug": { // Debug provider.
      "LogLevel": {
        "Default": "Information", // Overrides preceding LogLevel:Default setting.
        "Microsoft.Hosting": "Trace" // Debug:Microsoft.Hosting category.
      }
    },
    "EventSource": { // EventSource provider
      "LogLevel": {
        "Default": "Warning" // All categories of EventSource provider.
      }
    }
  }
}

Logging.{providername}.LogLevel의 설정은 Logging.LogLevel의 설정을 재정의합니다. 위의 JSON에서는 Debug 공급자의 기본 로그 수준이 Information로 설정되었습니다.

Logging:Debug:LogLevel:Default:Information

위 설정은 Microsoft.Hosting을 제외하고 모든 Logging:Debug: 범주에 대해 Information 로그 수준을 지정합니다. 특정 범주를 나열하면 특정 범주로 기본 범주가 재정의됩니다. 위의 JSON에서 Logging:Debug:LogLevel 범주 "Microsoft.Hosting""Default"Logging:LogLevel의 설정을 재정의합니다.

최소 로그 수준은 다음에 대해 지정할 수 있습니다.

  • 특정 공급자: 예를 들면 Logging:EventSource:LogLevel:Default:Information과 같습니다.
  • 특정 범주: 예를 들면 Logging:LogLevel:Microsoft:Warning과 같습니다.
  • 모든 공급자와 모든 범주: Logging:LogLevel:Default:Warning

최소 수준 이하의 모든 로그는 다음과 같이 되지 않습니다.

  • 공급자에 전달됩니다.
  • 로그되거나 표시됩니다.

모든 로그를 표시하지 않으려면 LogLevel.None을 지정합니다. LogLevel.None의 값은 LogLevel.Critical(5)보다 높은 6입니다.

공급자가 로그 범위를 지원하는 경우 IncludeScopes는 사용 가능 여부를 나타냅니다. 자세한 내용은 로그 범위를 참조하세요.

다음 appsettings.json 파일에는 기본적으로 사용하도록 설정되는 모든 공급자가 포함되어 있습니다.

{
  "Logging": {
    "LogLevel": { // No provider, LogLevel applies to all the enabled providers.
      "Default": "Error",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Warning"
    },
    "Debug": { // Debug provider.
      "LogLevel": {
        "Default": "Information" // Overrides preceding LogLevel:Default setting.
      }
    },
    "Console": {
      "IncludeScopes": true,
      "LogLevel": {
        "Microsoft.AspNetCore.Mvc.Razor.Internal": "Warning",
        "Microsoft.AspNetCore.Mvc.Razor.Razor": "Debug",
        "Microsoft.AspNetCore.Mvc.Razor": "Error",
        "Default": "Information"
      }
    },
    "EventSource": {
      "LogLevel": {
        "Microsoft": "Information"
      }
    },
    "EventLog": {
      "LogLevel": {
        "Microsoft": "Information"
      }
    },
    "AzureAppServicesFile": {
      "IncludeScopes": true,
      "LogLevel": {
        "Default": "Warning"
      }
    },
    "AzureAppServicesBlob": {
      "IncludeScopes": true,
      "LogLevel": {
        "Microsoft": "Information"
      }
    },
    "ApplicationInsights": {
      "LogLevel": {
        "Default": "Information"
      }
    }
  }
}

앞의 예제에서:

  • 범주 및 수준은 제안된 값이 아닙니다. 기본 공급자를 모두 표시하기 위해 제공되는 샘플입니다.
  • Logging.{providername}.LogLevel의 설정은 Logging.LogLevel의 설정을 재정의합니다. 예를 들어 Debug.LogLevel.Default 수준은 LogLevel.Default수준을 재정의합니다.
  • 각 기본 공급자 ‘별칭’을 사용합니다. 각 공급자는 정규화된 형식 이름 대신 구성에서 사용할 수 있는 별칭을 정의합니다. 기본 제공 공급자 별칭은 다음과 같습니다.
    • Console
    • Debug
    • EventSource
    • EventLog
    • AzureAppServicesFile
    • AzureAppServicesBlob
    • ApplicationInsights

명령줄, 환경 변수 및 기타 구성으로 로그 수준 설정

로그 수준은 구성 공급자 중 하나로 설정할 수 있습니다.

: 구분 기호는 모든 플랫폼의 환경 변수 계층적 키에서 작동하지 않습니다. 이중 밑줄 __은 다음과 같습니다.

  • 모든 플랫폼에서 지원됩니다. 예를 들어 : 구분 기호는 Bash에서 지원되지 않지만 __은 지원됩니다.
  • 자동으로 :으로 대체

다음 명령은,

  • Windows에서 환경 키 Logging:LogLevel:MicrosoftInformation 값으로 설정합니다.
  • ASP.NET Core 웹 애플리케이션 템플릿을 사용하여 만든 앱을 사용할 때 설정을 테스트합니다. dotnet run 명령은 set을 사용한 후 프로젝트 디렉터리에서 실행해야 합니다.
set Logging__LogLevel__Microsoft=Information
dotnet run

위의 환경 설정은,

  • 설정된 명령 창에서 시작된 프로세스에서만 설정됩니다.
  • Visual Studio에서 시작된 브라우저에서는 읽을 수 없습니다.

다음 setx 명령은 Windows에서 환경 키 및 값도 설정합니다. set와 달리, setx 설정은 유지됩니다. /M 스위치는 시스템 환경에서 변수를 설정합니다. /M을 사용하지 않으면 사용자 환경 변수가 설정됩니다.

setx Logging__LogLevel__Microsoft=Information /M

Azure App Service설정 > 구성 페이지에서 새 애플리케이션 설정을 선택합니다. Azure App Service 애플리케이션 설정은,

  • 미사용 시 암호화되고 암호화된 채널을 통해 전송됩니다.
  • 환경 변수로 노출됩니다.

자세한 내용은 Azure 앱: Azure Portal을 사용하여 앱 구성 재정의 편을 참조하세요.

환경 변수를 사용하여 ASP.NET Core 구성 값을 설정하는 방법에 대한 자세한 내용은 환경 변수를 참조하세요. 명령줄, Azure Key Vault, Azure App Configuration, 기타 파일 형식 등을 포함하여 다른 구성 원본을 사용하는 방법에 대한 자세한 내용은 ASP.NET Core의 구성를 참조하세요.

필터링 규칙 적용 방식

ILogger<TCategoryName> 개체를 만들 때 ILoggerFactory 개체는 공급자마다 해당 로거에 적용할 단일 규칙을 선택합니다. ILogger 인스턴스에서 작성된 모든 메시지는 선택한 규칙에 따라 필터링됩니다. 사용 가능한 규칙 중에서 각 공급자 및 범주 쌍과 가장 관련이 많은 규칙이 선택됩니다.

지정된 범주에 대한 ILogger가 생성되면 다음 알고리즘이 각 공급자에 사용됩니다.

  • 공급자 또는 공급자의 별칭과 일치하는 모든 규칙을 선택합니다. 일치하는 규칙이 없는 경우 빈 공급자가 있는 모든 규칙을 선택합니다.
  • 앞 단계의 결과에서 일치하는 범주 접두사가 가장 긴 규칙을 선택합니다. 일치하는 규칙이 없는 경우 범주를 지정하지 않는 규칙을 모두 선택합니다.
  • 여러 규칙을 선택하는 경우 마지막 규칙을 사용합니다.
  • 규칙을 선택하지 않는 경우 MinimumLevel을 사용합니다.

dotnet run 및 Visual Studio의 로깅 출력

기본 로깅 공급자를 사용하여 만든 로그는 다음과 같이 표시됩니다.

  • Visual Studio
    • 디버그할 때 디버그 출력 창에 표시됨
    • ASP.NET Core 웹 서버 창에 표시됨
  • dotnet run을 사용하여 앱을 실행할 때 콘솔 창에 표시됨

“Microsoft” 범주로 시작하는 로그는 ASP.NET Core 프레임워크 코드에서 온 것입니다. ASP.NET Core 및 애플리케이션 코드는 동일한 로깅 API와 공급자를 사용합니다.

로그 범주

ILogger 개체가 생성되면 ‘범주’가 지정됩니다. 해당 범주는 ILogger의 해당 인스턴스에서 만든 각 로그 메시지에 포함됩니다. 범주 문자열은 임의로 지정되지만 규칙은 클래스 이름을 사용하는 것입니다. 예를 들어 컨트롤러에서 이름은 "TodoApi.Controllers.TodoController"일 수 있습니다. ASP.NET Core 웹앱은 ILogger<T>를 사용하여 T의 정규화된 형식 이름을 범주로 사용하는 ILogger 인스턴스를 자동으로 가져옵니다.

public class PrivacyModel : PageModel
{
    private readonly ILogger<PrivacyModel> _logger;

    public PrivacyModel(ILogger<PrivacyModel> logger)
    {
        _logger = logger;
    }

    public void OnGet()
    {
        _logger.LogInformation("GET Pages.PrivacyModel called.");
    }
}

범주를 명시적으로 지정하려면 ILoggerFactory.CreateLogger를 호출합니다.

public class ContactModel : PageModel
{
    private readonly ILogger _logger;

    public ContactModel(ILoggerFactory logger)
    {
        _logger = logger.CreateLogger("MyCategory");
    }

    public void OnGet()
    {
        _logger.LogInformation("GET Pages.ContactModel called.");
    }

ILogger<T>T의 정규화된 형식 이름으로 CreateLogger를 호출하는 것과 동일합니다.

로그 수준

다음 표에서는 LogLevel 값, 편리한 Log{LogLevel} 확장 메서드 및 추천 사용법을 설명합니다.

LogLevel 메서드 Description
추적 0 LogTrace 가장 자세한 메시지를 포함합니다. 해당 메시지는 중요한 앱 데이터를 포함할 수 있습니다. 해당 메시지는 기본적으로 사용하지 않도록 설정되며 프로덕션에서 사용하도록 설정하면 안 됩니다.
디버그 1 LogDebug 디버깅 및 개발을 위한 수준입니다. 너무 많으므로 프로덕션에서는 주의해서 사용합니다.
정보 2 LogInformation 앱의 일반적인 흐름을 추적합니다. 장기적인 값이 있을 수 있습니다.
경고 3 LogWarning 비정상적이거나 예기치 않은 이벤트를 위한 수준입니다. 일반적으로 앱의 오류를 발생시키지 않는 오류 또는 조건을 포함합니다.
오류 4 LogError 처리할 수 없는 오류 및 예외를 위한 수준입니다. 해당 메시지는 전체 앱 오류가 아닌 현재 작업 또는 요청의 오류를 의미합니다.
심각 5 LogCritical 즉각적인 대응이 필요한 오류를 위한 수준입니다. 예: 데이터 손실 시나리오, 디스크 공간 부족.
없음 6 로깅 범주에서 메시지를 쓰지 않도록 지정합니다.

위의 표에서는 LogLevel이 심각도가 낮은 것에서 높은 것 순으로 표시됩니다.

Log 메서드의 첫 번째 매개 변수인 LogLevel은 로그의 심각도를 나타냅니다. 대부분의 개발자는 Log(LogLevel, ...) 대신 Log{LogLevel} 확장 메서드를 호출합니다. Log{LogLevel} 확장 메서드는 Log 메서드를 호출하고 LogLevel을 지정합니다. 예를 들어 다음 두 로깅 호출은 기능이 동일하며 같은 로그를 생성합니다.

[HttpGet]
public IActionResult Test1(int id)
{
    var routeInfo = ControllerContext.ToCtxString(id);

    _logger.Log(LogLevel.Information, MyLogEvents.TestItem, routeInfo);
    _logger.LogInformation(MyLogEvents.TestItem, routeInfo);

    return ControllerContext.MyDisplayRouteInfo();
}

MyLogEvents.TestItem은 이벤트 ID입니다. MyLogEvents는 샘플 앱의 일부이며 로그 이벤트 ID 섹션에 표시됩니다.

MyDisplayRouteInfo 및 ToCtxStringRick.Docs.Samples.RouteInfo NuGet 패키지가 제공합니다. 이 메서드는 Controller 경로 정보를 표시합니다.

다음 코드는 InformationWarning 로그를 만듭니다.

[HttpGet("{id}")]
public async Task<ActionResult<TodoItemDTO>> GetTodoItem(long id)
{
    _logger.LogInformation(MyLogEvents.GetItem, "Getting item {Id}", id);

    var todoItem = await _context.TodoItems.FindAsync(id);

    if (todoItem == null)
    {
        _logger.LogWarning(MyLogEvents.GetItemNotFound, "Get({Id}) NOT FOUND", id);
        return NotFound();
    }

    return ItemToDTO(todoItem);
}

위의 코드에서 첫 번째 Log{LogLevel} 매개 변수 MyLogEvents.GetItem로그 이벤트 ID입니다. 두 번째 매개 변수는 나머지 메서드 매개 변수가 제공하는 인수 값에 대한 자리 표시자를 포함하고 있는 메시지 템플릿입니다. 메서드 매개 변수는 이 문서의 뒷부분에 있는 메시지 템플릿 섹션에 설명되어 있습니다.

적절한 Log{LogLevel} 메서드를 호출하여 특정 스토리지 매체에 기록되는 로그 출력의 양을 제어합니다. 예를 들어:

  • 프로덕션:
    • Trace 또는 Information 수준 로깅은 자세한 로그 메시지를 대량으로 생성합니다. 비용을 관리하고 데이터 스토리지 제한을 초과하지 않으려면 TraceInformation 수준 메시지를 대용량, 저비용 데이터 저장소에 로그합니다. TraceInformation을 특정 범주로 제한하는 것이 좋습니다.
    • Warning~Critical 수준의 로깅은 적은 로그 메시지를 생성합니다.
      • 비용과 스토리지 제한이 일반적으로 문제가 되지 않습니다.
      • 로그가 적으므로 데이터 저장소를 더 유연하게 선택할 수 있습니다.
  • 개발 중:
    • Warning로 설정합니다.
    • 문제를 해결할 때는 Trace 또는 Information 메시지를 추가합니다. 출력을 제한하려면 조사 중인 범주에 대해서만 Trace 또는 Information을 설정합니다.

ASP.NET Core는 프레임워크 이벤트에 대한 로그를 작성합니다. 예를 들어 다음의 로그 출력을 고려하세요.

  • ASP.NET Core 템플릿을 사용하여 만든 Razor Pages 앱
  • 로깅을 Logging:Console:LogLevel:Microsoft:Information으로 설정
  • 개인정보처리방침 페이지로 이동
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/2 GET https://localhost:5001/Privacy
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
      Executing endpoint '/Privacy'
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[3]
      Route matched with {page = "/Privacy"}. Executing page /Privacy
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[101]
      Executing handler method DefaultRP.Pages.PrivacyModel.OnGet - ModelState is Valid
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[102]
      Executed handler method OnGet, returned result .
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[103]
      Executing an implicit handler method - ModelState is Valid
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[104]
      Executed an implicit handler method, returned result Microsoft.AspNetCore.Mvc.RazorPages.PageResult.
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[4]
      Executed page /Privacy in 74.5188ms
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
      Executed endpoint '/Privacy'
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished in 149.3023ms 200 text/html; charset=utf-8

다음 JSON에서는 Logging:Console:LogLevel:Microsoft:Information을 설정합니다.

{
  "Logging": {      // Default, all providers.
    "LogLevel": {
      "Microsoft": "Warning"
    },
    "Console": { // Console provider.
      "LogLevel": {
        "Microsoft": "Information"
      }
    }
  }
}

로그 이벤트 ID

각 로그는 이벤트 ID를 지정할 수 있습니다. 샘플 앱에서는 MyLogEvents 클래스를 사용하여 이벤트 ID를 정의합니다.

public class MyLogEvents
{
    public const int GenerateItems = 1000;
    public const int ListItems     = 1001;
    public const int GetItem       = 1002;
    public const int InsertItem    = 1003;
    public const int UpdateItem    = 1004;
    public const int DeleteItem    = 1005;

    public const int TestItem      = 3000;

    public const int GetItemNotFound    = 4000;
    public const int UpdateItemNotFound = 4001;
}
[HttpGet("{id}")]
public async Task<ActionResult<TodoItemDTO>> GetTodoItem(long id)
{
    _logger.LogInformation(MyLogEvents.GetItem, "Getting item {Id}", id);

    var todoItem = await _context.TodoItems.FindAsync(id);

    if (todoItem == null)
    {
        _logger.LogWarning(MyLogEvents.GetItemNotFound, "Get({Id}) NOT FOUND", id);
        return NotFound();
    }

    return ItemToDTO(todoItem);
}

이벤트 ID는 이벤트 집합을 연결합니다. 예를 들어 페이지에서 항목 목록을 표시하는 것과 관련된 모든 로그는 1001일 수 있습니다.

로깅 공급자는 이벤트 ID를 ID 필드, 로그 메시지에 저장하거나 또는 전혀 저장하지 않을 수도 있습니다. 디버그 공급자는 이벤트 ID를 표시하지 않습니다. 콘솔 공급자는 범주 뒤에 대괄호로 이벤트 ID를 표시합니다.

info: TodoApi.Controllers.TodoItemsController[1002]
      Getting item 1
warn: TodoApi.Controllers.TodoItemsController[4000]
      Get(1) NOT FOUND

일부 로깅 공급자는 ID에 대한 필터링을 허용하는 필드에 이벤트 ID를 저장합니다.

로그 메시지 템플릿

각 로그 API는 메시지 템플릿을 사용합니다. 메시지 템플릿에는 인수가 제공되는 자리 표시자를 포함할 수 있습니다. 번호가 아닌 자리 표시자의 이름을 사용합니다.

[HttpGet("{id}")]
public async Task<ActionResult<TodoItemDTO>> GetTodoItem(long id)
{
    _logger.LogInformation(MyLogEvents.GetItem, "Getting item {Id}", id);

    var todoItem = await _context.TodoItems.FindAsync(id);

    if (todoItem == null)
    {
        _logger.LogWarning(MyLogEvents.GetItemNotFound, "Get({Id}) NOT FOUND", id);
        return NotFound();
    }

    return ItemToDTO(todoItem);
}

값을 제공하는 데 사용되는 매개 변수를 결정하는 것은 자리 표시자의 이름이 아닌 순서입니다. 다음 코드에서는 매개 변수 이름이 메시지 템플릿의 순서와 일치하지 않습니다.

string p1 = "param1";
string p2 = "param2";
_logger.LogInformation("Parameter values: {p2}, {p1}", p1, p2);

앞의 코드는 매개 변수 값을 순서대로 사용하여 로그 메시지를 만듭니다.

Parameter values: param1, param2

해당 접근 방식을 통해 로깅 공급자는 의미 체계 또는 구조적 로깅를 구현할 수 있습니다. 인수 자체는 서식이 지정된 메시지 템플릿뿐만 아니라 로깅 시스템에 전달됩니다. 따라서 로깅 공급자는 매개 변수 값을 필드로 저장할 수 있습니다. 예를 들어 다음 로거 메서드를 살펴보세요.

_logger.LogInformation("Getting item {Id} at {RequestTime}", id, DateTime.Now);

Azure Table Storage에 로그할 경우를 예로 듭니다.

  • 각 Azure Table 엔터티에는 IDRequestTime 속성이 있을 수 있습니다.
  • 속성이 있는 테이블은 로그된 데이터의 쿼리를 쉽게 합니다. 예를 들어 문자 메시지의 시간 초과를 구문 분석하지 않고도 특정 RequestTime 범위 내에 있는 모든 로그를 쿼리를 통해 찾을 수 있습니다.

예외 로그

로거 메서드에는 예외 매개 변수를 사용하는 오버로드가 있습니다.

[HttpGet("{id}")]
public IActionResult TestExp(int id)
{
    var routeInfo = ControllerContext.ToCtxString(id);
    _logger.LogInformation(MyLogEvents.TestItem, routeInfo);

    try
    {
        if (id == 3)
        {
            throw new Exception("Test exception");
        }
    }
    catch (Exception ex)
    {
        _logger.LogWarning(MyLogEvents.GetItemNotFound, ex, "TestExp({Id})", id);
        return NotFound();
    }

    return ControllerContext.MyDisplayRouteInfo();
}

MyDisplayRouteInfo 및 ToCtxStringRick.Docs.Samples.RouteInfo NuGet 패키지가 제공합니다. 이 메서드는 Controller 경로 정보를 표시합니다.

예외 로깅은 공급자별로 다릅니다.

기본 로그 수준

기본 로그 수준을 설정하지 않으면 기본 로그 수준 값은 Information입니다.

예를 들어 다음 웹앱을 고려하세요.

  • ASP.NET 웹앱 템플릿을 사용하여 만들었습니다.
  • appsettings.jsonappsettings.Development.json을 삭제하거나 이름을 변경했습니다.

이전 설정을 사용하여 개인정보처리방침이나 홈페이지로 이동하면 범주 이름에 Microsoft가 포함된 Trace, DebugInformation 메시지가 많이 생성됩니다.

다음 코드에서는 구성에 기본 로그 수준이 설정되어 있지 않은 경우 기본 로그 수준을 설정합니다.

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureLogging(logging => logging.SetMinimumLevel(LogLevel.Warning))
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

일반적으로 로그 수준은 코드에서가 아니라 구성에서 지정해야 합니다.

필터 함수

필터 함수는 구성 또는 코드를 통해 규칙이 할당되지 않은 모든 공급자와 범주에 대해 호출됩니다.

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureLogging(logging =>
            {
                logging.AddFilter((provider, category, logLevel) =>
                {
                    if (provider.Contains("ConsoleLoggerProvider")
                        && category.Contains("Controller")
                        && logLevel >= LogLevel.Information)
                    {
                        return true;
                    }
                    else if (provider.Contains("ConsoleLoggerProvider")
                        && category.Contains("Microsoft")
                        && logLevel >= LogLevel.Information)
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                });
            })
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

앞의 코드는 범주에 Controller 또는 Microsoft가 포함되어 있고 로그 수준이 Information 이상인 경우 콘솔 로그를 표시합니다.

일반적으로 로그 수준은 코드에서가 아니라 구성에서 지정해야 합니다.

ASP.NET Core 및 EF Core 범주

다음 표에는 ASP.NET Core 및 Entity Framework Core에서 사용되는 몇 가지 범주와 로그에 관한 참고 사항이 나와 있습니다.

범주 참고
Microsoft.AspNetCore 일반 ASP.NET Core 진단.
Microsoft.AspNetCore.DataProtection 고려되고, 발견되고, 사용된 키.
Microsoft.AspNetCore.HostFiltering 허용되는 호스트.
Microsoft.AspNetCore.Hosting HTTP 요청을 완료하는 데 걸린 시간과 시작 시간. 로드된 호스팅 시작 어셈블리.
Microsoft.AspNetCore.Mvc MVC 및 Razor 진단. 모델 바인딩, 필터 실행, 뷰 컴파일 작업 선택.
Microsoft.AspNetCore.Routing 경로 일치 정보.
Microsoft.AspNetCore.Server 연결 시작, 중지 및 활성 응답 유지. HTTPS 인증서 정보.
Microsoft.AspNetCore.StaticFiles 제공된 파일.
Microsoft.EntityFrameworkCore 일반 Entity Framework Core 진단. 데이터베이스 작업 및 구성, 변경 내용 검색, 마이그레이션.

콘솔 창에서 더 많은 범주를 보려면 appsettings.Development.json을 다음으로 설정합니다.

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Trace",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  }
}

로그 범위

범위는 논리적 작업 집합을 그룹화할 수 있습니다. 이 그룹화는 집합의 일부로 생성된 각 로그에 동일한 데이터를 연결하는 데 사용될 수 있습니다. 예를 들어 트랜잭션 처리의 일부로 생성되는 모든 로그에는 트랜잭션 ID가 포함될 수 있습니다.

범위:

  • BeginScope 메서드에서 반환하는 IDisposable 형식입니다.
  • 삭제될 때까지 유지됩니다.

범위를 지원하는 공급자는 다음과 같습니다.

using 블록에 로거 호출을 래핑하여 범위를 사용합니다.

[HttpGet("{id}")]
public async Task<ActionResult<TodoItemDTO>> GetTodoItem(long id)
{
    TodoItem todoItem;

    using (_logger.BeginScope("using block message"))
    {
        _logger.LogInformation(MyLogEvents.GetItem, "Getting item {Id}", id);

        todoItem = await _context.TodoItems.FindAsync(id);

        if (todoItem == null)
        {
            _logger.LogWarning(MyLogEvents.GetItemNotFound, 
                "Get({Id}) NOT FOUND", id);
            return NotFound();
        }
    }

    return ItemToDTO(todoItem);
}

다음 JSON은 콘솔 공급자에 대해 범위를 사용하도록 설정합니다.

{
  "Logging": {
    "Debug": {
      "LogLevel": {
        "Default": "Information"
      }
    },
    "Console": {
      "IncludeScopes": true, // Required to use Scopes.
      "LogLevel": {
        "Microsoft": "Warning",
        "Default": "Information"
      }
    },
    "LogLevel": {
      "Default": "Debug"
    }
  }
}

다음은 콘솔 공급자에 대한 범위를 사용하도록 설정하는 코드입니다.

일반적으로 로깅은 코드에서가 아니라 구성에서 지정해야 합니다.

기본 로깅 공급자

ASP.NET Core에는 다음과 같은 로깅 공급자가 있습니다.

ASP.NET Core 모듈을 사용한 stdout 및 디버그 로깅에 대한 자세한 내용은 및 Azure App Service 및 IIS에서 ASP.NET Core 문제 해결ASP.NET Core 모듈을 참조하세요.

Console

Console 공급자는 콘솔에 출력을 로그합니다. 개발 중인 Console 로그를 보는 방법에 대한 자세한 내용은 dotnet run 및 Visual Studio의 로깅 출력을 참조하세요.

디버그

Debug 공급자는 System.Diagnostics.Debug 클래스를 사용하여 로그 출력을 기록합니다. System.Diagnostics.Debug.WriteLine을 호출하여 Debug 공급자에 기록합니다.

Linux에서 Debug 공급자 로그 위치는 배포판마다 다르며 다음 중 하나일 수 있습니다.

  • /var/log/message
  • /var/log/syslog

이벤트 원본

EventSource 공급자는 이름이 Microsoft-Extensions-Logging인 플랫폼 간 이벤트 원본에 기록합니다. Windows에서 공급자는 ETW를 사용합니다.

dotnet 추적 도구

dotnet 추적 도구는 실행 중인 프로세스의 .NET Core 추적을 수집할 수 있도록 하는 플랫폼 간 CLI 전역 도구입니다. 이 도구는 LoggingEventSource를 사용하여 Microsoft.Extensions.Logging.EventSource 공급자 데이터를 수집합니다.

설치 지침은 dotnet-trace를 참조하세요.

Dotnet 추적 도구를 사용하여 앱에서 추적을 수집합니다.

  1. dotnet run 명령으로 앱을 실행합니다.

  2. .NET Core 앱의 PID(프로세스 식별자)를 확인합니다.

    앱의 어셈블리와 동일한 이름의 프로세스에 대한 PID를 찾습니다.

  3. dotnet trace 명령을 실행합니다.

    일반 명령 구문:

    dotnet trace collect -p {PID} 
        --providers Microsoft-Extensions-Logging:{Keyword}:{Event Level}
            :FilterSpecs=\"
                {Logger Category 1}:{Event Level 1};
                {Logger Category 2}:{Event Level 2};
                ...
                {Logger Category N}:{Event Level N}\"
    

    PowerShell 명령 셸을 사용하는 경우 --providers 값을 작은따옴표(')로 묶습니다.

    dotnet trace collect -p {PID} 
        --providers 'Microsoft-Extensions-Logging:{Keyword}:{Event Level}
            :FilterSpecs=\"
                {Logger Category 1}:{Event Level 1};
                {Logger Category 2}:{Event Level 2};
                ...
                {Logger Category N}:{Event Level N}\"'
    

    Windows가 아닌 플랫폼에서는 출력 추적 파일의 형식을 speedscope로 변경하는 -f speedscope 옵션을 추가합니다.

    키워드 Description
    1 LoggingEventSource에 대한 로그 메타 이벤트입니다. ILogger)에서 이벤트를 기록하지 않습니다.
    2 ILogger.Log()가 호출될 때 Message 이벤트 설정을 켭니다. 서식 지정되지 않은 프로그래밍 방식으로 정보를 제공합니다.
    4 ILogger.Log()가 호출될 때 FormatMessage 이벤트 설정을 켭니다. 서식 지정된 문자열 버전의 정보를 제공합니다.
    8 ILogger.Log()가 호출될 때 MessageJson 이벤트 설정을 켭니다. 인수의 JSON 표현을 제공합니다.
    이벤트 수준 설명
    0 LogAlways
    1 Critical
    2 Error
    3 Warning
    4 Informational
    5 Verbose

    FilterSpecs``{Logger Category}{Event Level}에 대한 항목은 추가 로그 필터링 조건을 나타냅니다. FilterSpecs 항목을 세미콜론(;)으로 구분합니다.

    Windows 명령 셸을 사용하는 예(--providers 값에 작은따옴표를 사용하지 않음):

    dotnet trace collect -p {PID} --providers Microsoft-Extensions-Logging:4:2:FilterSpecs=\"Microsoft.AspNetCore.Hosting*:4\"
    

    이전 명령은 다음과 같이 활성화됩니다.

    • (2) 오류에 대해 형식이 지정된 문자열(4)을 생성하는 이벤트 원본 로거입니다.
    • Informational 로깅 수준에서 Microsoft.AspNetCore.Hosting 로깅(4).
  4. Enter 키 또는 Ctrl + C를 눌러 dotnet 추적 도구를 중지합니다.

    추적은 dotnet trace 명령이 실행되는 폴더에 trace.nettrace 이름으로 저장됩니다.

  5. Perfview를 사용하여 추적을 엽니다. trace.nettrace 파일을 열고 추적 이벤트를 탐색합니다.

앱이 CreateDefaultBuilder를 사용하여 호스트를 빌드하지 않는 경우 이벤트 원본 공급자를 앱의 로깅 구성에 추가합니다.

자세한 내용은 다음을 참조하세요.

Perfview

PerfView 유틸리티를 사용하여 로그를 수집하고 볼 수 있습니다. ETW 로그를 보는 다른 도구도 있지만, PerfView는 ASP.NET Core에서 내보내는 ETW 이벤트를 처리하기에 가장 좋은 환경을 제공합니다.

이 공급자가 기록한 이벤트를 수집하도록 PerfView를 구성하려면 추가 공급자 목록에 *Microsoft-Extensions-Logging 문자열을 추가합니다. 문자열의 시작 부분에 *를 누락하지 마세요.

Windows EventLog

EventLog 공급자는 로그 출력을 Windows 이벤트 로그에 보냅니다. 다른 공급자와 달리 EventLog 공급자는 기본 비공급자 설정을 상속하지 않습니다. EventLog 로그 설정을 지정하지 않으면 LogLevel.Warning으로 기본 설정됩니다.

LogLevel.Warning 수준보다 낮은 이벤트를 기록하려면 로그 수준을 명시적으로 설정합니다. 다음 예제에서는 이벤트 로그 기본 로그 수준을 LogLevel.Information으로 설정합니다.

"Logging": {
  "EventLog": {
    "LogLevel": {
      "Default": "Information"
    }
  }
}

AddEventLog 오버로드EventLogSettings를 전달할 수 있습니다. null이거나 지정하지 않으면 다음 기본 설정이 사용됩니다.

  • LogName: “Application”
  • SourceName: “.NET Runtime”
  • MachineName: 로컬 머신 이름이 사용됩니다.

다음 코드에서는 SourceName을 기본값 ".NET Runtime"에서 MyLogs로 변경합니다.

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureLogging(logging =>
            {
                logging.AddEventLog(eventLogSettings =>
                {
                    eventLogSettings.SourceName = "MyLogs"; 
                });
            })
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

Azure App Service

Microsoft.Extensions.Logging.AzureAppServices 공급자 패키지는 Azure App Service 앱의 파일 시스템과 Azure Storage 계정의 Blob 스토리지에 텍스트 파일을 기록합니다.

이 공급자 패키지는 공유 프레임워크에 포함되어 있지 않습니다. 이 공급자를 사용하려면 프로젝트에 공급자 패키지를 추가합니다.

공급자 설정을 구성하려면 다음 예제와 같이 AzureFileLoggerOptionsAzureBlobLoggerOptions를 사용합니다.

public class Scopes
{
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureLogging(logging => logging.AddAzureWebAppDiagnostics())
                .ConfigureServices(serviceCollection => serviceCollection
                    .Configure<AzureFileLoggerOptions>(options =>
                    {
                        options.FileName = "azure-diagnostics-";
                        options.FileSizeLimit = 50 * 1024;
                        options.RetainedFileCountLimit = 5;
                    })
                    .Configure<AzureBlobLoggerOptions>(options =>
                    {
                        options.BlobName = "log.txt";
                    }))
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
    }
}

Azure App Service에 배포하는 경우 앱은 Azure Portal에서 App Service 페이지에 있는 App Service 로그 섹션의 설정을 사용합니다. 다음 설정이 업데이트되면 앱을 다시 시작하거나 재배포하지 않아도 변경 내용이 즉시 적용됩니다.

  • 애플리케이션 로깅(파일 시스템)
  • 애플리케이션 로깅(Blob)

로그 파일의 기본 위치는 D:\home\LogFiles\Application 폴더이며, 기본 파일 이름은 diagnostics-yyyymmdd.txt입니다. 기본 파일 크기 제한은 10MB이고, 보존되는 기본 최대 파일 수는 2입니다. 기본 BLOB 이름은 {app-name}{timestamp}/yyyy/mm/dd/hh/{guid}-applicationLog.txt입니다.

이 공급자는 프로젝트가 Azure 환경에서 실행되는 경우에만 로그합니다.

Azure 로그 스트리밍

Azure 로그 스트리밍을 통해 다음에서 로그 활동을 실시간으로 볼 수 있습니다.

  • 앱 서버
  • 웹 서버
  • 실패한 요청 추적

Azure 로그 스트리밍을 구성하려면:

  • 앱의 포털 페이지에서 App Service 로그 페이지로 이동합니다.
  • 애플리케이션 로깅(파일 시스템)On으로 설정합니다.
  • 로그 수준을 선택합니다. 이 설정은 Azure 로그 스트리밍에만 적용됩니다.

로그 스트림 페이지로 이동하여 로그를 봅니다. 로드되는 메시지는 ILogger 인터페이스를 사용하여 로그됩니다.

Azure Application Insights

Microsoft.Extensions.Logging.ApplicationInsights 공급자 패키지는 Azure Application Insights에 로그를 기록합니다. Application Insights는 웹앱을 모니터링하고 원격 분석 데이터를 쿼리 및 분석하기 위한 도구를 제공하는 서비스입니다. 이 공급자를 사용하는 경우 Application Insights 도구를 사용하여 로그를 쿼리 및 분석할 수 있습니다.

로깅 공급자는 ASP.NET Core에 대한 모든 사용 가능한 원격 분석을 제공하는 패키지인 Microsoft.ApplicationInsights.AspNetCore의 종속성으로 포함됩니다. 이 패키지를 사용하는 경우 공급자 패키지를 설치할 필요가 없습니다.

Microsoft.ApplicationInsights.Web 패키지는 ASP.NET Core가 아니라 ASP.NET 4.x용입니다.

자세한 내용은 다음 자료를 참조하세요.

타사 로깅 공급자

ASP.NET Core와 호환되는 타사 로깅 프레임워크는 다음과 같습니다.

일부 타사 프레임워크는 구조적 로깅이라고 하는 의미 체계 로깅을 수행할 수 있습니다.

타사 프레임워크를 사용하는 방법은 다음과 같이 기본 공급자 중 하나를 사용하는 방법과 비슷합니다.

  1. 프로젝트에 NuGet 패키지를 추가합니다.
  2. 로깅 프레임워크에서 제공하는 ILoggerFactory 확장 메서드를 호출합니다.

자세한 내용은 각 공급자의 설명서를 참조하세요. 타사 로깅 공급자는 Microsoft에서 지원되지 않습니다.

비호스트 콘솔 앱

비 웹 콘솔 앱에서 일반 호스트를 사용하는 방법에 대한 사례는 백그라운드 작업 샘플 앱(ASP.NET Core에서 호스팅되는 서비스를 사용하는 백그라운드 작업)의 Program.cs 파일을 참조하세요.

제네릭 호스트를 사용하지 않는 앱의 로깅 코드는 공급자 추가로거 생성 방식에 따라 달라집니다.

로깅 공급자

비 호스트 콘솔 앱에서는 LoggerFactory를 만드는 동안 공급자의 Add{provider name} 확장 메서드를 호출합니다.

class Program
{
    static void Main(string[] args)
    {
        using var loggerFactory = LoggerFactory.Create(builder =>
        {
            builder
                .AddFilter("Microsoft", LogLevel.Warning)
                .AddFilter("System", LogLevel.Warning)
                .AddFilter("LoggingConsoleApp.Program", LogLevel.Debug)
                .AddConsole()
                .AddEventLog();
        });
        ILogger logger = loggerFactory.CreateLogger<Program>();
        logger.LogInformation("Example log message");
    }
}

로그 만들기

로그를 만들려면 ILogger<TCategoryName> 개체를 사용합니다. LoggerFactory를 사용하여 ILogger를 만듭니다.

다음 예제에서는 LoggingConsoleApp.Program을 범주로 사용하여 로거를 만듭니다.

class Program
{
    static void Main(string[] args)
    {
        using var loggerFactory = LoggerFactory.Create(builder =>
        {
            builder
                .AddFilter("Microsoft", LogLevel.Warning)
                .AddFilter("System", LogLevel.Warning)
                .AddFilter("LoggingConsoleApp.Program", LogLevel.Debug)
                .AddConsole()
                .AddEventLog();
        });
        ILogger logger = loggerFactory.CreateLogger<Program>();
        logger.LogInformation("Example log message");
    }
}

다음의 ASP.NET Core 예제에서 로거는 Information을 수준으로 사용하여 로그를 만드는 데 사용됩니다. 로그 수준은 기록된 이벤트의 심각도를 나타냅니다.

class Program
{
    static void Main(string[] args)
    {
        using var loggerFactory = LoggerFactory.Create(builder =>
        {
            builder
                .AddFilter("Microsoft", LogLevel.Warning)
                .AddFilter("System", LogLevel.Warning)
                .AddFilter("LoggingConsoleApp.Program", LogLevel.Debug)
                .AddConsole()
                .AddEventLog();
        });
        ILogger logger = loggerFactory.CreateLogger<Program>();
        logger.LogInformation("Example log message");
    }
}

수준범주는 이 문서에 자세히 설명되어 있습니다.

호스트 생성 중 로깅

호스트 생성 중 로깅은 직접 지원되지 않습니다. 그러나 별도의 로거를 사용할 수 있습니다. 다음 예에서는 Serilog 로거를 사용하여 CreateHostBuilder에 로그인합니다. AddSerilog에서 Log.Logger에 지정된 정적 구성을 사용합니다.

using System;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args)
    {
        var builtConfig = new ConfigurationBuilder()
            .AddJsonFile("appsettings.json")
            .AddCommandLine(args)
            .Build();

        Log.Logger = new LoggerConfiguration()
            .WriteTo.Console()
            .WriteTo.File(builtConfig["Logging:FilePath"])
            .CreateLogger();

        try
        {
            return Host.CreateDefaultBuilder(args)
                .ConfigureServices((context, services) =>
                {
                    services.AddRazorPages();
                })
                .ConfigureAppConfiguration((hostingContext, config) =>
                {
                    config.AddConfiguration(builtConfig);
                })
                .ConfigureLogging(logging =>
                {   
                    logging.AddSerilog();
                })
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
        }
        catch (Exception ex)
        {
            Log.Fatal(ex, "Host builder error");

            throw;
        }
        finally
        {
            Log.CloseAndFlush();
        }
    }
}

ILogger에 종속되는 서비스 구성

이전 버전의 ASP.NET Core에서는 Startup에 대한 로거의 생성자 주입이 작동하는데, 이는 웹 호스트에 대한 별도의 DI 컨테이너가 생성되기 때문입니다. 제네릭 호스트에 대해 하나의 컨테이너만 생성되는 이유에 대한 자세한 내용은 호환성이 손상되는 변경 공지를 참조하세요.

ILogger<T>에 종속되는 서비스를 구성하려면 생성자 주입을 사용하거나 팩터리 메서드를 제공합니다. 팩터리 메서드 접근 방식은 다른 옵션이 없는 경우에만 권장됩니다. 예를 들어 DI에서 제공하는 ILogger<T> 인스턴스가 필요한 서비스를 살펴보겠습니다.

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();
    services.AddRazorPages();

    services.AddSingleton<IMyService>((container) =>
    {
        var logger = container.GetRequiredService<ILogger<MyService>>();
        return new MyService() { Logger = logger };
    });
}

위에 강조 표시된 코드는 DI 컨테이너가 MyService의 인스턴스를 처음 생성해야 할 때 실행되는 Func입니다. 이러한 방식으로 등록된 서비스에 액세스할 수 있습니다.

Main에서 로그 만들기

다음 코드는 호스트를 빌드한 후 DI에서 ILogger 인스턴스를 가져와 Main에 로그합니다.

public static void Main(string[] args)
{
    var host = CreateHostBuilder(args).Build();

    var logger = host.Services.GetRequiredService<ILogger<Program>>();
    logger.LogInformation("Host created.");

    host.Run();
}

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
        });

시작 시 로그 만들기

다음 코드는 Startup.Configure에 로그를 작성합니다.

public void Configure(IApplicationBuilder app, IWebHostEnvironment env,
                      ILogger<Startup> logger)
{
    if (env.IsDevelopment())
    {
        logger.LogInformation("In Development.");
        app.UseDeveloperExceptionPage();
    }
    else
    {
        logger.LogInformation("Not Development.");
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }

    app.UseHttpsRedirection();
    app.UseStaticFiles();

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
        endpoints.MapRazorPages();
    });
}

Startup.ConfigureServices 메서드에서 DI 컨테이너 설정이 완료되기 전에 로그를 작성하는 작업은 지원되지 않습니다.

  • Startup 생성자에 대한 로거 주입은 지원되지 않습니다.
  • Startup.ConfigureServices 메서드 시그니처에 대한 로거 주입은 지원되지 않습니다.

이러한 제한의 이유는 로깅이 DI와 구성에 종속되며, 이는 결국 DI에 종속되기 때문입니다. DI 컨테이너는 ConfigureServices가 완료될 때까지 설정되지 않습니다.

ILogger<T>에 종속되는 서비스를 구성하는 방법이나 Startup로 로거의 생성자 주입이 이전 버전에서 작동한 이유에 대한 자세한 내용은 ILogger에 종속되는 서비스 구성을 참조하세요.

비동기 로거 메서드 미지원

로깅은 매우 빨라서 비동기 코드의 성능 비용을 들일 필요가 없습니다. 로깅 데이터 저장소가 느린 경우 직접 작성하지 마세요. 로그 메시지를 처음에 빠른 저장소에 작성한 다음, 나중에 느린 저장소로 이동하는 것이 좋습니다. 예를 들어 SQL Server에 로그하는 경우 Log 메서드는 동기식이므로 Log 메서드에서 직접 로그하지 마세요. 대신 동기적으로 로그 메시지를 메모리 내 큐에 추가하고 백그라운드 작업자가 큐에서 메시지를 풀하여 SQL Server에 대해 비동기 데이터 푸시 작업을 수행하도록 합니다. 자세한 내용은 GitHub 이슈를 참조하세요.

실행 중인 앱에서 로그 수준 변경

로깅 API는 앱이 실행되는 동안 로그 수준을 변경하는 시나리오를 포함하지 않습니다. 그러나 일부 구성 공급자는 구성을 다시 로드할 수 있으며 이는 로깅 구성에 대한 즉각적인 영향을 줍니다. 예를 들어 파일 구성 공급자는 기본적으로 로깅 구성을 다시 로드합니다. 앱이 실행되는 동안 코드에서 구성이 변경되면 앱 IConfigurationRoot.Reload를 호출하여 앱의 로깅 구성을 업데이트할 수 있습니다.

ILogger 및 ILoggerFactory

ILogger<TCategoryName>ILoggerFactory 인터페이스와 구현은 .NET Core SDK에 포함되어 있습니다. 또한 다음 NuGet 패키지에서도 사용할 수 있습니다.

코드에서 로그 필터 규칙 적용

로그 필터 규칙을 설정하는 기본 방법은 구성을 사용하는 것입니다.

다음 예제는 코드에서 필터 규칙을 등록하는 방법을 보여줍니다.

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureLogging(logging =>
               logging.AddFilter("System", LogLevel.Debug)
                  .AddFilter<DebugLoggerProvider>("Microsoft", LogLevel.Information)
                  .AddFilter<ConsoleLoggerProvider>("Microsoft", LogLevel.Trace))
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

logging.AddFilter("System", LogLevel.Debug)System범주 및 로그 수준Debug을 지정합니다. 특정 공급자를 구성하지 않았으므로 필터가 모든 공급자에 적용됩니다.

AddFilter<DebugLoggerProvider>("Microsoft", LogLevel.Information)은 다음을 지정합니다.

  • Debug 로깅 공급자
  • 로그 수준 Information 이상
  • "Microsoft"로 시작하는 모든 범주

사용자 지정 로거 만들기

사용자 지정 로거를 추가하려면 ILoggerFactory를 사용하여 ILoggerProvider를 추가합니다.

public void Configure(
    IApplicationBuilder app,
    IWebHostEnvironment env,
    ILoggerFactory loggerFactory)
{
    loggerFactory.AddProvider(new CustomLoggerProvider(new CustomLoggerConfiguration()));

ILoggerProvider는 하나 이상의 ILogger 인스턴스를 만듭니다. ILogger 인스턴스는 프레임워크에서 정보를 로그하는 데 사용됩니다.

샘플 사용자 지정 로거 구성

샘플:

  • 이벤트 ID 및 로그 수준으로 로그 콘솔의 색을 설정하는 기본적인 샘플로 설계되었습니다. 로거는 일반적으로 이벤트 ID로 변경되지 않으며 로그 수준에 국한되지 않습니다.
  • 다음 구성 유형을 사용하여 로그 수준 및 이벤트 ID에 따라 다른 색의 콘솔 항목을 만듭니다.
public class ColorConsoleLoggerConfiguration
{
    public LogLevel LogLevel { get; set; } = LogLevel.Warning;
    public int EventId { get; set; } = 0;
    public ConsoleColor Color { get; set; } = ConsoleColor.Yellow;
}

위의 코드는 기본 수준을 Warning으로 설정하고 색을 Yellow로 설정합니다. EventId를 0으로 설정하면 모든 이벤트를 로그합니다.

사용자 지정 로거 만들기

ILogger 구현 범주 이름은 일반적으로 로깅 원본입니다. 예를 들어 다음은 로거를 만드는 형식입니다.

public class ColorConsoleLogger : ILogger
{
    private readonly string _name;
    private readonly ColorConsoleLoggerConfiguration _config;

    public ColorConsoleLogger(string name, ColorConsoleLoggerConfiguration config)
    {
        _name = name;
        _config = config;
    }

    public IDisposable BeginScope<TState>(TState state)
    {
        return null;
    }

    public bool IsEnabled(LogLevel logLevel)
    {
        return logLevel == _config.LogLevel;
    }

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

        if (_config.EventId == 0 || _config.EventId == eventId.Id)
        {
            var color = Console.ForegroundColor;
            Console.ForegroundColor = _config.Color;
            Console.WriteLine($"{logLevel} - {eventId.Id} " +
                              $"- {_name} - {formatter(state, exception)}");
            Console.ForegroundColor = color;
        }
    }
}

위의 코드는

  • 범주 이름별로 로거 인스턴스를 만듭니다.
  • IsEnabled에서 logLevel == _config.LogLevel을 확인하므로 각 logLevel에 고유한 로거가 있습니다. 일반적으로 모든 상위 로그 수준에 대해서도 로거를 사용하도록 설정해야 합니다.
public bool IsEnabled(LogLevel logLevel)
{
    return logLevel >= _config.LogLevel;
}

사용자 지정 LoggerProvider 만들기

LoggerProvider는 로거 인스턴스를 만드는 클래스입니다. 범주별로 로거 인스턴스를 만들 필요가 없을 수도 있지만, NLog 또는 log4net와 같은 일부 로거에 적합합니다. 이렇게 하면 필요한 경우 범주별로 다른 로깅 출력 대상을 선택할 수도 있습니다.

public class ColorConsoleLoggerProvider : ILoggerProvider
{
    private readonly ColorConsoleLoggerConfiguration _config;
    private readonly ConcurrentDictionary<string, ColorConsoleLogger> _loggers = new ConcurrentDictionary<string, ColorConsoleLogger>();

    public ColorConsoleLoggerProvider(ColorConsoleLoggerConfiguration config)
    {
        _config = config;
    }

    public ILogger CreateLogger(string categoryName)
    {
        return _loggers.GetOrAdd(categoryName, name => new ColorConsoleLogger(name, _config));
    }

    public void Dispose()
    {
        _loggers.Clear();
    }
}

위의 코드에서 CreateLogger는 범주 이름별로 ColorConsoleLogger의 단일 인스턴스를 만들어 ConcurrentDictionary<TKey,TValue>에 저장합니다.

사용자 지정 로거의 사용 및 등록

Startup.Configure에 로거를 등록합니다.

public void Configure(IApplicationBuilder app, IWebHostEnvironment env, 
                      ILoggerFactory loggerFactory)
{
    // Default registration.
    loggerFactory.AddProvider(new ColorConsoleLoggerProvider(
                              new ColorConsoleLoggerConfiguration
    {
        LogLevel = LogLevel.Error,
        Color = ConsoleColor.Red
    }));

    // Custom registration with default values.
    loggerFactory.AddColorConsoleLogger();

    // Custom registration with a new configuration instance.
    loggerFactory.AddColorConsoleLogger(new ColorConsoleLoggerConfiguration
    {
        LogLevel = LogLevel.Debug,
        Color = ConsoleColor.Gray
    });

    // Custom registration with a configuration object.
    loggerFactory.AddColorConsoleLogger(c =>
    {
        c.LogLevel = LogLevel.Information;
        c.Color = ConsoleColor.Blue;
    });

    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
        app.UseHsts();
    }
    app.UseHttpsRedirection();
    app.UseStaticFiles();

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllerRoute(
            name: "default",
            pattern: "{controller=Home}/{action=Index}/{id?}");
    });
}

앞의 코드에서는 ILoggerFactory를 위한 확장 메서드를 하나 이상 제공합니다.

public static class ColorConsoleLoggerExtensions
{
    public static ILoggerFactory AddColorConsoleLogger(
                                      this ILoggerFactory loggerFactory, 
                                      ColorConsoleLoggerConfiguration config)
    {
        loggerFactory.AddProvider(new ColorConsoleLoggerProvider(config));
        return loggerFactory;
    }
    public static ILoggerFactory AddColorConsoleLogger(
                                      this ILoggerFactory loggerFactory)
    {
        var config = new ColorConsoleLoggerConfiguration();
        return loggerFactory.AddColorConsoleLogger(config);
    }
    public static ILoggerFactory AddColorConsoleLogger(
                                    this ILoggerFactory loggerFactory, 
                                    Action<ColorConsoleLoggerConfiguration> configure)
    {
        var config = new ColorConsoleLoggerConfiguration();
        configure(config);
        return loggerFactory.AddColorConsoleLogger(config);
    }
}

추가 자료

작성자: Tom DykstraSteve Smith

.NET Core는 다양한 기본 제공 및 타사 로깅 공급자에서 작동하는 로깅 API를 지원합니다. 이 문서에서는 기본 제공 공급자를 이용하여 로깅 API를 사용하는 방법을 보여줍니다.

예제 코드 살펴보기 및 다운로드 (다운로드 방법)

공급자 추가

로깅 공급자는 로그를 표시하거나 저장합니다. 예를 들어 콘솔 공급자는 콘솔에 로그를 표시하고 Azure Application Insights 공급자는 로그를 Azure Application Insights에 저장합니다. 여러 공급자를 추가하여 로그를 여러 대상으로 보낼 수 있습니다.

공급자를 추가하려면 Program.cs에서 공급자의 Add{provider name} 확장 메서드를 호출합니다.

public static void Main(string[] args)
{
    var webHost = new WebHostBuilder()
        .UseKestrel()
        .UseContentRoot(Directory.GetCurrentDirectory())
        .ConfigureAppConfiguration((hostingContext, config) =>
        {
            var env = hostingContext.HostingEnvironment;
            config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                  .AddJsonFile($"appsettings.{env.EnvironmentName}.json", 
                      optional: true, reloadOnChange: true);
            config.AddEnvironmentVariables();
        })
        .ConfigureLogging((hostingContext, logging) =>
        {
            // Requires `using Microsoft.Extensions.Logging;`
            logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
            logging.AddConsole();
            logging.AddDebug();
            logging.AddEventSourceLogger();
        })
        .UseStartup<Startup>()
        .Build();

    webHost.Run();
}

앞의 코드는 Microsoft.Extensions.LoggingMicrosoft.Extensions.Configuration에 대한 참조를 요구합니다.

기본 프로젝트 템플릿은 다음과 같은 로깅 공급자를 추가하는 CreateDefaultBuilder를 호출합니다.

  • Console
  • 디버그
  • EventSource(ASP.NET Core 2.2부터 시작)
public static void Main(string[] args)
{
    CreateWebHostBuilder(args).Build().Run();
}

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>();

CreateDefaultBuilder를 사용하는 경우 기본 제공자를 사용자가 선택한 대로 바꿀 수 있습니다. ClearProviders를 호출하고 원하는 공급자를 추가합니다.

public static void Main(string[] args)
{
    var host = CreateWebHostBuilder(args).Build();

    var todoRepository = host.Services.GetRequiredService<ITodoRepository>();
    todoRepository.Add(new Core.Model.TodoItem() { Name = "Feed the dog" });
    todoRepository.Add(new Core.Model.TodoItem() { Name = "Walk the dog" });

    var logger = host.Services.GetRequiredService<ILogger<Program>>();
    logger.LogInformation("Seeded the database.");

    host.Run();
}

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .ConfigureLogging(logging =>
        {
            logging.ClearProviders();
            logging.AddConsole();
        });

문서의 뒷부분에 나오는 기본 제공 로깅 공급자타사 로깅 공급자에서 더 자세히 알아봅니다.

로그 만들기

로그를 만들려면 ILogger<TCategoryName> 개체를 사용합니다. 웹앱 또는 호스트되는 서비스에서는 DI(종속성 주입)로부터 ILogger를 가져옵니다. 비 호스트 콘솔 앱에서는 LoggerFactory를 사용하여 ILogger를 만듭니다.

다음 ASP.NET Core 예제는 TodoApiSample.Pages.AboutModel을 범주로 사용하여 로거를 만듭니다. 로그 범주는 각 로그와 연결된 문자열입니다. DI에서 제공한 ILogger<T> 인스턴스는 T 형식의 정규화된 이름을 범주로 가진 로그를 만듭니다.

public class AboutModel : PageModel
{
    private readonly ILogger _logger;

    public AboutModel(ILogger<AboutModel> logger)
    {
        _logger = logger;
    }

다음의 ASP.NET Core 및 콘솔 앱 예제에서 로거는 Information을 수준으로 사용하여 로그를 만드는 데 사용됩니다. 로그 수준은 기록된 이벤트의 심각도를 나타냅니다.

public void OnGet()
{
    Message = $"About page visited at {DateTime.UtcNow.ToLongTimeString()}";
    _logger.LogInformation("Message displayed: {Message}", Message);
}

수준범주는 이 문서의 뒷부분에 자세히 설명되어 있습니다.

시작 시 로그 만들기

Startup 클래스에서 로그를 작성하려면 생성자 시그니처에 ILogger 매개 변수를 포함합니다.

public class Startup
{
    private readonly ILogger _logger;

    public Startup(IConfiguration configuration, ILogger<Startup> logger)
    {
        Configuration = configuration;
        _logger = logger;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc()
            .SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

        // Add our repository type
        services.AddSingleton<ITodoRepository, TodoRepository>();
        _logger.LogInformation("Added TodoRepository to services");
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            _logger.LogInformation("In Development environment");
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Error");
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseStaticFiles();
        app.UseCookiePolicy();

        app.UseMvc();
    }
}

Program 클래스에서 로그 만들기

Program 클래스에 로그를 작성하려면 DI에서 ILogger 인스턴스를 가져옵니다.

public static void Main(string[] args)
{
    var host = CreateWebHostBuilder(args).Build();

    var todoRepository = host.Services.GetRequiredService<ITodoRepository>();
    todoRepository.Add(new Core.Model.TodoItem() { Name = "Feed the dog" });
    todoRepository.Add(new Core.Model.TodoItem() { Name = "Walk the dog" });

    var logger = host.Services.GetRequiredService<ILogger<Program>>();
    logger.LogInformation("Seeded the database.");

    host.Run();
}

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .ConfigureLogging(logging =>
        {
            logging.ClearProviders();
            logging.AddConsole();
        });

호스트 생성 중 로깅은 직접 지원되지 않습니다. 그러나 별도의 로거를 사용할 수 있습니다. 다음 예에서는 Serilog 로거를 사용하여 CreateWebHostBuilder에 로그인합니다. AddSerilog에서 Log.Logger에 지정된 정적 구성을 사용합니다.

using System;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;

public class Program
{
    public static void Main(string[] args)
    {
        CreateWebHostBuilder(args).Build().Run();
    }

    public static IWebHostBuilder CreateWebHostBuilder(string[] args)
    {
        var builtConfig = new ConfigurationBuilder()
            .AddJsonFile("appsettings.json")
            .AddCommandLine(args)
            .Build();

        Log.Logger = new LoggerConfiguration()
            .WriteTo.Console()
            .WriteTo.File(builtConfig["Logging:FilePath"])
            .CreateLogger();

        try
        {
            return WebHost.CreateDefaultBuilder(args)
                .ConfigureServices((context, services) =>
                {
                    services.AddMvc();
                })
                .ConfigureAppConfiguration((hostingContext, config) =>
                {
                    config.AddConfiguration(builtConfig);
                })
                .ConfigureLogging(logging =>
                {
                    logging.AddSerilog();
                })
                .UseStartup<Startup>();
        }
        catch (Exception ex)
        {
            Log.Fatal(ex, "Host builder error");

            throw;
        }
        finally
        {
            Log.CloseAndFlush();
        }
    }
}

비동기 로거 메서드 미지원

로깅은 매우 빨라서 비동기 코드의 성능 비용을 들일 필요가 없습니다. 로깅 데이터 저장소가 느린 경우 직접 작성하지 마세요. 로그 메시지를 처음에 빠른 저장소에 작성한 다음, 나중에 느린 저장소로 이동하는 것이 좋습니다. 예를 들어 SQL Server에 로그하는 경우 Log 메서드는 동기식이므로 Log 메서드에서 직접 로그하지는 않습니다. 대신 동기적으로 로그 메시지를 메모리 내 큐에 추가하고 백그라운드 작업자가 큐에서 메시지를 풀하여 SQL Server에 대해 비동기 데이터 푸시 작업을 수행하도록 합니다. 자세한 내용은 GitHub 이슈를 참조하세요.

Configuration

로깅 공급자 구성은 하나 이상의 구성 공급자에서 제공합니다.

  • 파일 형식(INI, JSON 및 XML).
  • 명령줄 인수.
  • 환경 변수.
  • 메모리 내 .NET 개체.
  • 암호화되지 않은 암호 관리자 저장소.
  • 암호화된 사용자 저장소(예:Azure Key Vault).
  • 사용자 지정 공급자(설치 또는 생성된).

예를 들어 로깅 구성은 일반적으로 앱 설정 파일의 Logging 섹션에서 제공됩니다. 다음 예제에서는 일반적인 appsettings.Development.json 파일의 콘텐츠를 보여줍니다.

{
  "Logging": {
    "LogLevel": {
      "Default": "Debug",
      "System": "Information",
      "Microsoft": "Information"
    },
    "Console":
    {
      "IncludeScopes": true
    }
  }
}

Logging 속성은 LogLevel 및 로그 공급자 속성을 포함할 수 있습니다(Console이 나타나 있습니다).

Logging 아래의 LogLevel 속성은 선택한 범주에 대해 로그할 최소 수준을 지정합니다. 이 예제에서는 SystemMicrosoft 범주는 Information 수준으로 로그되고 다른 모든 범주는 Debug 수준으로 로그됩니다.

Logging 아래의 다른 속성은 로깅 공급자를 지정합니다. 이 예제는 콘솔 공급자에 대한 것입니다. 공급자가 로그 범위를 지원하는 경우 IncludeScopes는 사용 가능 여부를 나타냅니다. 공급자 속성(예: 예제에서 Console)은 LogLevel 속성을 지정할 수도 있습니다. 공급자 아래의 LogLevel은 해당 공급자에 대한 로그 수준을 지정합니다.

수준이 Logging.{providername}.LogLevel에 지정된 경우 Logging.LogLevel에 설정된 모든 수준을 재정의합니다. 예를 들어, 다음과 같은 JSON을 가정해 봅시다.

{
  "Logging": {      // Default, all providers.
    "LogLevel": {
      "Microsoft": "Warning"
    },
    "Console": { // Console provider.
      "LogLevel": {
        "Microsoft": "Information"
      }
    }
  }
}

위의 JSON에서 Console 공급자 설정은 이전(기본) 로그 수준을 재정의합니다.

로깅 API는 앱이 실행되는 동안 로그 수준을 변경하는 시나리오를 포함하지 않습니다. 그러나 일부 구성 공급자는 구성을 다시 로드할 수 있으며 이는 로깅 구성에 대한 즉각적인 영향을 줍니다. 예를 들어 파일 구성 공급자는 설정 파일을 읽기 위해 CreateDefaultBuilder에 의해 추가되며 기본적으로 로깅 구성을 다시 로드합니다. 앱이 실행되는 동안 코드에서 구성이 변경되면 앱 IConfigurationRoot.Reload를 호출하여 앱의 로깅 구성을 업데이트할 수 있습니다.

구성 공급자 구현에 대한 자세한 내용은 ASP.NET Core의 구성를 참조하세요.

샘플 로깅 출력

이전 섹션에 나와 있는 샘플 코드를 사용하면 명령줄에서 앱을 실행할 때 콘솔에 로그가 표시됩니다. 다음은 콘솔 출력의 예입니다.

info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET http://localhost:5000/api/todo/0
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
      Executing action method TodoApi.Controllers.TodoController.GetById (TodoApi) with arguments (0) - ModelState is Valid
info: TodoApi.Controllers.TodoController[1002]
      Getting item 0
warn: TodoApi.Controllers.TodoController[4000]
      GetById(0) NOT FOUND
info: Microsoft.AspNetCore.Mvc.StatusCodeResult[1]
      Executing HttpStatusCodeResult, setting HTTP status code 404
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
      Executed action TodoApi.Controllers.TodoController.GetById (TodoApi) in 42.9286ms
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 148.889ms 404

위의 로그는 샘플 앱의 http://localhost:5000/api/todo/0에 HTTP Get 요청을 하여 생성되었습니다.

다음은 Visual Studio에서 샘플 앱을 실행할 때 디버그 창에 나타나는 것과 동일한 로그의 예입니다.

Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 GET http://localhost:53104/api/todo/0  
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executing action method TodoApi.Controllers.TodoController.GetById (TodoApi) with arguments (0) - ModelState is Valid
TodoApi.Controllers.TodoController:Information: Getting item 0
TodoApi.Controllers.TodoController:Warning: GetById(0) NOT FOUND
Microsoft.AspNetCore.Mvc.StatusCodeResult:Information: Executing HttpStatusCodeResult, setting HTTP status code 404
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executed action TodoApi.Controllers.TodoController.GetById (TodoApi) in 152.5657ms
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 316.3195ms 404

이전 섹션에 표시된 ILogger 호출을 통해 생성된 로그는 "TodoApi"로 시작합니다. "Microsoft" 범주로 시작하는 로그는 ASP.NET Core 프레임워크 코드에서 온 것입니다. ASP.NET Core 및 애플리케이션 코드는 동일한 로깅 API와 공급자를 사용합니다.

이 문서의 나머지 부분에서는 로깅에 대한 일부 세부 정보 및 옵션을 설명합니다.

NuGet 패키지

ILoggerILoggerFactory 인터페이스는 Microsoft.Extensions.Logging.Abstractions에 있으며, 두 인터페이스의 기본 구현은 Microsoft.Extensions.Logging에 있습니다.

로그 범주

ILogger 개체가 생성되면 개체에 대한 범주가 지정됩니다. 해당 범주는 ILogger의 해당 인스턴스에서 만든 각 로그 메시지에 포함됩니다. 범주는 임의의 문자열일 수 있지만 "TodoApi.Controllers.TodoController"와 같은 클래스 이름을 사용하는 것이 규칙입니다.

ILogger<T>를 사용하여 T의 정규화된 형식 이름을 범주로 사용하는 ILogger 인스턴스를 가져옵니다.

public class TodoController : Controller
{
    private readonly ITodoRepository _todoRepository;
    private readonly ILogger _logger;

    public TodoController(ITodoRepository todoRepository,
        ILogger<TodoController> logger)
    {
        _todoRepository = todoRepository;
        _logger = logger;
    }

범주를 명시적으로 지정하려면 ILoggerFactory.CreateLogger를 호출합니다.

public class TodoController : Controller
{
    private readonly ITodoRepository _todoRepository;
    private readonly ILogger _logger;

    public TodoController(ITodoRepository todoRepository,
        ILoggerFactory logger)
    {
        _todoRepository = todoRepository;
        _logger = logger.CreateLogger("TodoApiSample.Controllers.TodoController");
    }

ILogger<T>T의 정규화된 형식 이름으로 CreateLogger를 호출하는 것과 동일합니다.

로그 수준

모든 로그는 LogLevel 값을 지정합니다. 로그 수준은 심각도 또는 중요도를 나타냅니다. 예를 들어 메서드가 정상적으로 종료되면 Information 로그를 작성하고 메서드가 404 찾을 수 없음 상태 코드를 반환하면 Warning 로그를 작성할 수 있습니다.

다음 코드는 InformationWarning 로그를 만듭니다.

public IActionResult GetById(string id)
{
    _logger.LogInformation(LoggingEvents.GetItem, "Getting item {Id}", id);
    var item = _todoRepository.Find(id);
    if (item == null)
    {
        _logger.LogWarning(LoggingEvents.GetItemNotFound, "GetById({Id}) NOT FOUND", id);
        return NotFound();
    }
    return new ObjectResult(item);
}

위의 코드에서 MyLogEvents.GetItemMyLogEvents.GetItemNotFound 매개 변수는 로그 이벤트 ID입니다. 두 번째 매개 변수는 나머지 메서드 매개 변수가 제공하는 인수 값에 대한 자리 표시자를 포함하고 있는 메시지 템플릿입니다. 메서드 매개 변수는 이 문서의 로그 메시지 템플릿 섹션에 설명되어 있습니다.

메서드 이름에 수준을 포함하는 로그 메서드(예: LogInformationLogWarning)는 ILogger에 대한 확장 메서드입니다. 이 메서드들은 LogLevel 매개 변수를 사용하는 Log 메서드를 호출합니다. 이러한 확장 메서드 중 하나를 호출하는 대신 Log 메서드를 직접 호출할 수도 있지만, 구문이 비교적 복잡합니다. 자세한 내용은 ILogger로거 확장 소스 코드를 참조하세요.

ASP.NET Core는 다음과 같은 로그 수준을 정의하며, 여기에는 가장 낮은 심각도에서 가장 높은 심각도 순으로 정렬되어 있습니다.

  • Trace = 0

    일반적으로 디버깅에만 유용한 정보입니다. 이러한 메시지는 중요한 애플리케이션 데이터를 포함할 수 있으므로 프로덕션 환경에서 사용하면 안 됩니다. 기본적으로 사용하지 않도록 설정됩니다.

  • Debug = 1

    개발 및 디버깅에 유용할 수 있는 정보입니다. 예: Entering method Configure with flag set to true. 로그 볼륨이 크기 때문에 문제 해결 시에만 Debug 수준 로그를 프로덕션 환경에서 사용합니다.

  • Information = 2

    앱의 일반적인 흐름을 추적합니다. 이러한 로그는 일반적으로 장기적인 가치가 있습니다. 예: Request received for path /api/todo

  • Warning = 3

    앱의 흐름에서 비정상적이거나 예기치 않은 이벤트를 위한 수준입니다. 앱이 중지되지는 않지만 조사해야 하는 오류 또는 기타 조건이 여기에 포함될 수 있습니다. 처리된 예외는 Warning 로그 수준을 사용하는 일반적인 장소입니다. 예: FileNotFoundException for file quotes.txt.

  • Error = 4

    처리할 수 없는 오류 및 예외를 위한 수준입니다. 이러한 메시지는 전체 앱 오류가 아닌 현재 동작 또는 작업(예: 현재 HTTP 요청)의 오류를 의미합니다. 예제 로그 메시지: Cannot insert record due to duplicate key violation.

  • Critical = 5

    즉각적인 대응이 필요한 오류를 위한 수준입니다. 예: 데이터 손실 시나리오, 디스크 공간 부족.

로그 수준을 사용하여 특정 스토리지 매체 또는 디스플레이 창에 기록되는 로그 출력의 양을 제어합니다. 예를 들어:

  • 프로덕션:
    • Trace~Information 수준 로깅은 자세한 로그 메시지를 대량으로 생성합니다. 비용을 관리하고 데이터 저장소 제한을 초과하지 않으려면 Trace~Information 수준 메시지를 대용량, 저비용 데이터 저장소에 기록합니다.
    • Warning~Critical 수준 로깅에서 생성되는 로그 메시지는 일반적으로 수량 및 용량이 더 적습니다. 따라서 비용 및 스토리지 제한은 대개의 경우 문제가 되지 않으므로 데이터 스토리지를 유연하게 선택할 수 있습니다.
  • 개발 중:
    • Warning~Critical 메시지를 콘솔에 기록합니다.
    • 문제 해결 시 Trace~Information 메시지를 추가합니다.

이 문서의 뒷부분에 나오는 로그 필터링 섹션에서는 공급자가 처리하는 로그 수준을 제어하는 방법을 설명합니다.

ASP.NET Core는 프레임워크 이벤트에 대한 로그를 작성합니다. 이 문서 앞부분에 나온 로그 예제는 Information 수준 미만 로그를 제외했기 때문에 Debug 또는 Trace 수준 로그가 생성되지 않습니다. 다음은 Debug 로그를 표시하도록 구성된 샘플 앱을 실행하여 생성된 콘솔 로그의 예입니다.

info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET http://localhost:62555/api/todo/0
dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
      Request successfully matched the route with name 'GetTodo' and template 'api/Todo/{id}'.
dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
      Action 'TodoApi.Controllers.TodoController.Update (TodoApi)' with id '089d59b6-92ec-472d-b552-cc613dfd625d' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
      Action 'TodoApi.Controllers.TodoController.Delete (TodoApi)' with id 'f3476abe-4bd9-4ad3-9261-3ead09607366' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
      Executing action TodoApi.Controllers.TodoController.GetById (TodoApi)
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
      Executing action method TodoApi.Controllers.TodoController.GetById (TodoApi) with arguments (0) - ModelState is Valid
info: TodoApi.Controllers.TodoController[1002]
      Getting item 0
warn: TodoApi.Controllers.TodoController[4000]
      GetById(0) NOT FOUND
dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
      Executed action method TodoApi.Controllers.TodoController.GetById (TodoApi), returned result Microsoft.AspNetCore.Mvc.NotFoundResult.
info: Microsoft.AspNetCore.Mvc.StatusCodeResult[1]
      Executing HttpStatusCodeResult, setting HTTP status code 404
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
      Executed action TodoApi.Controllers.TodoController.GetById (TodoApi) in 0.8788ms
dbug: Microsoft.AspNetCore.Server.Kestrel[9]
      Connection id "0HL6L7NEFF2QD" completed keep alive response.
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 2.7286ms 404

로그 이벤트 ID

각 로그는 이벤트 ID를 지정할 수 있습니다. 샘플 앱은 로컬에 정의된 LoggingEvents 클래스를 사용하여 이 작업을 수행합니다.

public IActionResult GetById(string id)
{
    _logger.LogInformation(LoggingEvents.GetItem, "Getting item {Id}", id);
    var item = _todoRepository.Find(id);
    if (item == null)
    {
        _logger.LogWarning(LoggingEvents.GetItemNotFound, "GetById({Id}) NOT FOUND", id);
        return NotFound();
    }
    return new ObjectResult(item);
}
public class LoggingEvents
{
    public const int GenerateItems = 1000;
    public const int ListItems = 1001;
    public const int GetItem = 1002;
    public const int InsertItem = 1003;
    public const int UpdateItem = 1004;
    public const int DeleteItem = 1005;

    public const int GetItemNotFound = 4000;
    public const int UpdateItemNotFound = 4001;
}

이벤트 ID는 이벤트 집합을 연결합니다. 예를 들어 페이지에서 항목 목록을 표시하는 것과 관련된 모든 로그는 1001일 수 있습니다.

로깅 공급자는 이벤트 ID를 ID 필드, 로그 메시지에 저장하거나 또는 전혀 저장하지 않을 수도 있습니다. 디버그 공급자는 이벤트 ID를 표시하지 않습니다. 콘솔 공급자는 범주 뒤에 대괄호로 이벤트 ID를 표시합니다.

info: TodoApi.Controllers.TodoController[1002]
      Getting item invalidid
warn: TodoApi.Controllers.TodoController[4000]
      GetById(invalidid) NOT FOUND

로그 메시지 템플릿

각 로그는 메시지 템플릿을 지정합니다. 메시지 템플릿에는 인수가 제공되는 자리 표시자를 포함할 수 있습니다. 번호가 아닌 자리 표시자의 이름을 사용합니다.

public IActionResult GetById(string id)
{
    _logger.LogInformation(LoggingEvents.GetItem, "Getting item {Id}", id);
    var item = _todoRepository.Find(id);
    if (item == null)
    {
        _logger.LogWarning(LoggingEvents.GetItemNotFound, "GetById({Id}) NOT FOUND", id);
        return NotFound();
    }
    return new ObjectResult(item);
}

값을 제공하는 데 사용되는 매개 변수를 결정하는 것은 자리 표시자의 이름이 아닌 순서입니다. 다음 코드에서는 매개 변수 이름이 메시지 템플릿 순서와 일치하지 않습니다.

string p1 = "parm1";
string p2 = "parm2";
_logger.LogInformation("Parameter values: {p2}, {p1}", p1, p2);

이 코드는 매개 변수 값을 순서대로 사용하여 로그 메시지를 만듭니다.

Parameter values: parm1, parm2

로깅 프레임워크는 로깅 공급자가 구조화된 로깅이라고도 하는 의미 체계 로깅을 구현할 수 있도록 이 방식으로 작동합니다. 인수 자체는 서식이 지정된 메시지 템플릿뿐만 아니라 로깅 시스템에 전달됩니다. 이 정보를 통해 로깅 공급자는 매개 변수 값을 필드로 저장할 수 있습니다. 예를 들어 로거 메서드 호출이 다음과 같다고 가정합니다.

_logger.LogInformation("Getting item {Id} at {RequestTime}", id, DateTime.Now);

Azure Table Storage에 로그를 보내는 경우 각 Azure Table 엔터티는 로그 데이터에 대한 쿼리를 간소화하는 IDRequestTime 속성을 가질 수 있습니다. 쿼리는 문자 메시지의 시간 초과를 구문 분석하지 않고 특정 RequestTime 범위 내의 모든 로그를 찾을 수 있습니다.

예외 로깅

로거 메서드는 다음 예제와 같이 예외를 전달할 수 있는 오버로드를 갖고 있습니다.

catch (Exception ex)
{
    _logger.LogWarning(LoggingEvents.GetItemNotFound, ex, "GetById({Id}) NOT FOUND", id);
    return NotFound();
}
return new ObjectResult(item);

공급자마다 다양한 방식으로 예외 정보를 처리합니다. 다음은 위에서 살펴본 코드의 디버그 공급자 출력의 예제입니다.

TodoApiSample.Controllers.TodoController: Warning: GetById(55) NOT FOUND

System.Exception: Item not found exception.
   at TodoApiSample.Controllers.TodoController.GetById(String id) in C:\TodoApiSample\Controllers\TodoController.cs:line 226

로그 필터링

특정 공급자 및 범주 또는 모든 공급자나 모든 범주의 최소 로그 수준을 지정할 수 있습니다. 최소 수준 미만인 로그는 해당 공급자에게 전달되지 않으므로 표시되거나 저장되지 않습니다.

모든 로그를 표시하지 않으려면 LogLevel.None을 최소 로그 수준으로 지정합니다. LogLevel.None의 정수 값은 LogLevel.Critical(5)보다 높은 6입니다.

구성에서 필터 규칙 만들기

프로젝트 템플릿 코드는 CreateDefaultBuilder를 호출하여 콘솔, 디버그 및 EventSource(ASP.NET Core 2.2 이상) 공급자에 대한 로깅을 설정합니다. 이 문서의 앞에서 설명한 것처럼 CreateDefaultBuilder 메서드는 Logging 섹션에서 구성을 조회하는 로깅을 설정합니다.

구성 데이터는 다음 예제와 같이 공급자 및 범주별로 최소 로그 수준을 지정합니다.

{
  "Logging": {
    "Debug": {
      "LogLevel": {
        "Default": "Information"
      }
    },
    "Console": {
      "IncludeScopes": false,
      "LogLevel": {
        "Microsoft.AspNetCore.Mvc.Razor.Internal": "Warning",
        "Microsoft.AspNetCore.Mvc.Razor.Razor": "Debug",
        "Microsoft.AspNetCore.Mvc.Razor": "Error",
        "Default": "Information"
      }
    },
    "LogLevel": {
      "Default": "Debug"
    }
  }
}

이 JSON은 6개의 필터 규칙을 만드는데, 하나는 디버그 공급자용이고, 4개는 콘솔 공급자용이고, 나머지 하나는 모든 공급자용입니다. ILogger 개체가 생성될 때 각 공급자에 대해 단일 규칙이 선택됩니다.

코드의 필터 규칙

다음 예제는 코드에서 필터 규칙을 등록하는 방법을 보여줍니다.

WebHost.CreateDefaultBuilder(args)
    .UseStartup<Startup>()
    .ConfigureLogging(logging =>
        logging.AddFilter("System", LogLevel.Debug)
               .AddFilter<DebugLoggerProvider>("Microsoft", LogLevel.Trace));

두 번째 AddFilter는 형식 이름을 사용하여 디버그 공급자를 지정합니다. 첫 번째 AddFilter는 공급자 형식을 지정하지 않으며, 따라서 모든 공급자에 적용됩니다.

필터링 규칙 적용 방식

이전 예제의 구성 데이터 및 AddFilter 코드는 다음 표에 표시된 규칙을 만듭니다. 처음 6개는 구성 예제로부터 비롯된 것이고 마지막 2개는 코드 예제로부터 비롯된 것입니다.

번호 공급자 다음으로 시작하는 범주... 최소 로그 수준
1 디버그 모든 범주 정보
2 Console Microsoft.AspNetCore.Mvc.Razor.Internal Warning
3 Console Microsoft.AspNetCore.Mvc.Razor.Razor 디버그
4 Console Microsoft.AspNetCore.Mvc.Razor Error
5 Console 모든 범주 정보
6 모든 공급자 모든 범주 디버그
7 모든 공급자 시스템 디버그
8 디버그 Microsoft Trace

ILogger 개체를 만들 때 ILoggerFactory 개체는 공급자마다 해당 로거에 적용할 단일 규칙을 선택합니다. ILogger 인스턴스에서 작성된 모든 메시지는 선택한 규칙에 따라 필터링됩니다. 사용 가능한 규칙 중에서 각 공급자 및 범주 쌍에 적용 가능한 가장 구체적인 규칙이 선택됩니다.

지정된 범주에 대한 ILogger가 생성되면 다음 알고리즘이 각 공급자에 사용됩니다.

  • 공급자 또는 공급자의 별칭과 일치하는 모든 규칙을 선택합니다. 일치하는 규칙이 없는 경우 빈 공급자가 있는 모든 규칙을 선택합니다.
  • 앞 단계의 결과에서 일치하는 범주 접두사가 가장 긴 규칙을 선택합니다. 일치하는 규칙이 없는 경우 범주를 지정하지 않는 규칙을 모두 선택합니다.
  • 여러 규칙을 선택하는 경우 마지막 규칙을 사용합니다.
  • 규칙을 선택하지 않는 경우 MinimumLevel을 사용합니다.

앞의 규칙 목록을 사용하여 “Microsoft.AspNetCore.Mvc.Razor.RazorViewEngine” 범주에 대한 ILogger 개체를 만든다고 가정합니다.

  • 디버그 공급자에게는 규칙 1, 6, 8이 적용됩니다. 규칙 8이 가장 구체적이므로 선택됩니다.
  • 콘솔 공급자에게는 규칙 3, 4, 5, 6이 적용됩니다. 규칙 3이 가장 구체적입니다.

결과 ILogger 인스턴스는 Trace 수준 이상의 로그를 디버그 공급자에게 보냅니다. Debug 수준 이상의 로그는 콘솔 공급자에게 전송됩니다.

공급자 별칭

각 공급자는 정규화된 형식 이름 대신 구성에서 사용할 수 있는 별칭을 정의합니다. 기본 공급자의 경우 다음 별칭을 사용합니다.

  • Console
  • Debug
  • EventSource
  • EventLog
  • TraceSource
  • AzureAppServicesFile
  • AzureAppServicesBlob
  • ApplicationInsights

기본 최소 수준

특정 공급자 및 범주에 대한 구성 또는 코드의 규칙이 적용되지 않는 경우에만 적용되는 최소 수준 설정이 있습니다. 다음 예제는 최소 수준을 설정하는 방법을 보여 줍니다.

WebHost.CreateDefaultBuilder(args)
    .UseStartup<Startup>()
    .ConfigureLogging(logging => logging.SetMinimumLevel(LogLevel.Warning));

최소 수준을 명시적으로 설정하지 않으면 TraceDebug 로그를 무시하는 Information이 기본값으로 설정됩니다.

필터 함수

필터 함수는 구성 또는 코드를 통해 규칙이 할당되지 않은 모든 공급자와 범주에 대해 호출됩니다. 함수의 코드는 공급자 형식, 범주 및 로그 수준에 액세스할 수 있습니다. 예를 들어:

WebHost.CreateDefaultBuilder(args)
    .UseStartup<Startup>()
    .ConfigureLogging(logBuilder =>
    {
        logBuilder.AddFilter((provider, category, logLevel) =>
        {
            if (provider == "Microsoft.Extensions.Logging.Console.ConsoleLoggerProvider" &&
                category == "TodoApiSample.Controllers.TodoController")
            {
                return false;
            }
            return true;
        });
    });

시스템 범주 및 수준

다음은 ASP.NET Core 및 Entity Framework Core에서 사용되는 몇 가지 범주로, 예상되는 로그에 대한 참고 사항입니다.

범주 참고
Microsoft.AspNetCore 일반 ASP.NET Core 진단.
Microsoft.AspNetCore.DataProtection 고려되고, 발견되고, 사용된 키.
Microsoft.AspNetCore.HostFiltering 허용되는 호스트.
Microsoft.AspNetCore.Hosting HTTP 요청을 완료하는 데 걸린 시간과 시작 시간. 로드된 호스팅 시작 어셈블리.
Microsoft.AspNetCore.Mvc MVC 및 Razor 진단. 모델 바인딩, 필터 실행, 뷰 컴파일 작업 선택.
Microsoft.AspNetCore.Routing 경로 일치 정보.
Microsoft.AspNetCore.Server 연결 시작, 중지 및 활성 응답 유지. HTTPS 인증서 정보.
Microsoft.AspNetCore.StaticFiles 제공된 파일.
Microsoft.EntityFrameworkCore 일반 Entity Framework Core 진단. 데이터베이스 작업 및 구성, 변경 내용 검색, 마이그레이션.

로그 범위

범위는 논리적 작업 집합을 그룹화할 수 있습니다. 이 그룹화는 집합의 일부로 생성된 각 로그에 동일한 데이터를 연결하는 데 사용될 수 있습니다. 예를 들어 트랜잭션 처리의 일부로 생성되는 모든 로그에는 트랜잭션 ID가 포함될 수 있습니다.

범위는 BeginScope 메서드에서 반환하는 IDisposable 형식이며 삭제될 때까지 유지됩니다. using 블록에 로거 호출을 래핑하여 범위를 사용합니다.

public IActionResult GetById(string id)
{
    TodoItem item;
    using (_logger.BeginScope("Message attached to logs created in the using block"))
    {
        _logger.LogInformation(LoggingEvents.GetItem, "Getting item {Id}", id);
        item = _todoRepository.Find(id);
        if (item == null)
        {
            _logger.LogWarning(LoggingEvents.GetItemNotFound, "GetById({Id}) NOT FOUND", id);
            return NotFound();
        }
    }
    return new ObjectResult(item);
}

다음은 콘솔 공급자에 대한 범위를 사용하도록 설정하는 코드입니다.

Program.cs:

.ConfigureLogging((hostingContext, logging) =>
{
    logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
    logging.AddConsole(options => options.IncludeScopes = true);
    logging.AddDebug();
})

참고

범위 기반 로깅을 사용하려면 IncludeScopes 콘솔 로거 옵션을 구성해야 합니다.

구성에 대한 자세한 내용은 구성 섹션을 참조하세요.

각 로그 메시지는 범위 정보를 포함합니다.

info: TodoApiSample.Controllers.TodoController[1002]
      => RequestId:0HKV9C49II9CK RequestPath:/api/todo/0 => TodoApiSample.Controllers.TodoController.GetById (TodoApi) => Message attached to logs created in the using block
      Getting item 0
warn: TodoApiSample.Controllers.TodoController[4000]
      => RequestId:0HKV9C49II9CK RequestPath:/api/todo/0 => TodoApiSample.Controllers.TodoController.GetById (TodoApi) => Message attached to logs created in the using block
      GetById(0) NOT FOUND

기본 로깅 공급자

ASP.NET Core는 다음 공급자를 제공합니다.

ASP.NET Core 모듈을 사용한 표준 출력(stdout) 및 디버그 로깅에 대한 자세한 내용은 Azure App Service 및 IIS에서 ASP.NET Core 문제 해결ASP.NET Core 모듈을 참조하세요.

콘솔 공급자

Microsoft.Extensions.Logging.Console 공급자 패키지는 콘솔에 로그 출력을 보냅니다.

logging.AddConsole();

콘솔 로깅 출력을 보려면 프로젝트 폴더에서 명령 프롬프트를 열고 다음 명령을 실행합니다.

dotnet run

디버그 공급자

Microsoft.Extensions.Logging.Debug 공급자 패키지는 System.Diagnostics.Debug 클래스(Debug.WriteLine 메서드 호출)를 사용하여 로그 출력을 씁니다.

Linux에서 이 공급자는 /var/log/message에 로그를 씁니다.

logging.AddDebug();

이벤트 원본 공급자

Microsoft.Extensions.Logging.EventSource 공급자 패키지는 Microsoft-Extensions-Logging 이름을 사용하여 플랫폼 간 이벤트 원본에 씁니다. Windows에서 공급자는 ETW를 사용합니다.

logging.AddEventSourceLogger();

호스트를 빌드하기 위해 CreateDefaultBuilder가 호출되면 이벤트 원본 공급자가 자동으로 추가됩니다.

PerfView 유틸리티를 사용하여 로그를 수집하고 볼 수 있습니다. ETW 로그를 보는 다른 도구도 있지만, PerfView는 ASP.NET Core에서 내보내는 ETW 이벤트를 처리하기에 가장 좋은 환경을 제공합니다.

이 공급자가 기록한 이벤트를 수집하도록 PerfView를 구성하려면 추가 공급자 목록에 *Microsoft-Extensions-Logging 문자열을 추가합니다. (문자열의 시작 부분에 별표를 누락하지 마세요.)

Perfview 추가 공급자

Windows EventLog 공급자

Microsoft.Extensions.Logging.EventLog 공급자 패키지는 Windows 이벤트 로그에 로그 출력을 보냅니다.

logging.AddEventLog();

AddEventLog 오버로드를 사용하여 EventLogSettings를 전달할 수 있습니다. null이거나 지정하지 않으면 다음 기본 설정이 사용됩니다.

  • LogName: “Application”
  • SourceName: “.NET Runtime”
  • MachineName: 로컬 머신 이름이 사용됩니다.

경고 수준 이상의 이벤트가 기록됩니다. 다음 예제에서는 이벤트 로그 기본 로그 수준을 LogLevel.Information으로 설정합니다.

"Logging": {
  "EventLog": {
    "LogLevel": {
      "Default": "Information"
    }
  }
}

TraceSource 공급자

Microsoft.Extensions.Logging.TraceSource 공급자 패키지는 TraceSource 라이브러리 및 공급자를 사용합니다.

logging.AddTraceSource(sourceSwitchName);

AddTraceSource 오버로드를 사용하여 원본 스위치 및 추적 수신기를 전달할 수 있습니다.

이 공급자를 사용하려면 앱이 .NET Framework(.NET Core가 아닌)에서 실행되어야 합니다. 공급자는 샘플 앱에 사용된 TextWriterTraceListener와 같은 다양한 수신기로 메시지를 라우팅할 수 있습니다.

Azure App Service 공급자

Microsoft.Extensions.Logging.AzureAppServices 공급자 패키지는 Azure App Service 앱의 파일 시스템과 Azure Storage 계정의 Blob 스토리지에 텍스트 파일을 기록합니다.

logging.AddAzureWebAppDiagnostics();

이 공급자 패키지는 Microsoft.AspNetCore.App 메타패키지에 포함되어 있지 않습니다. .NET Framework를 대상으로 지정하거나 Microsoft.AspNetCore.App 메타패키지를 참조하는 경우 공급자 패키지를 프로젝트에 추가합니다.

AddAzureWebAppDiagnostics 오버로드로 AzureAppServicesDiagnosticsSettings를 전달할 수 있습니다. 설정 개체는 로깅 출력 템플릿, BLOB 이름, 파일 크기 제한과 같은 기본 설정을 재정의할 수 있습니다. (출력 템플릿ILogger 메서드를 호출과 함께 제공되는 것 이외에 모든 로그에 적용되는 메시지 템플릿입니다.)

App Service 앱에 배포할 때 응용 프로그램은 Azure 포털 App Service 페이지의 App Service 로그 섹션에 있는 설정을 따릅니다. 다음 설정이 업데이트되면 앱을 다시 시작하거나 재배포하지 않아도 변경 내용이 즉시 적용됩니다.

  • 애플리케이션 로깅(파일 시스템)
  • 애플리케이션 로깅(Blob)

로그 파일의 기본 위치는 D:\home\LogFiles\Application 폴더이며, 기본 파일 이름은 diagnostics-yyyymmdd.txt입니다. 기본 파일 크기 제한은 10MB이고, 보존되는 기본 최대 파일 수는 2입니다. 기본 BLOB 이름은 {app-name}{timestamp}/yyyy/mm/dd/hh/{guid}-applicationLog.txt입니다.

공급자는 프로젝트가 Azure 환경에서 실행되는 경우에만 작동합니다. 프로젝트를 로컬로 실행하는 경우에는 아무 영향도 없습니다—로컬 파일 또는 로컬 개발 스토리지에 Blob을 기록하지 않습니다.

Azure 로그 스트리밍

Azure 로그 스트리밍을 통해 로그 작업을 실시간으로 볼 수 있습니다.

  • 앱 서버
  • 웹 서버
  • 실패한 요청 추적

Azure 로그 스트리밍을 구성하려면:

  • 앱의 포털 페이지에서 App Service 로그 페이지로 이동합니다.
  • 애플리케이션 로깅(파일 시스템)On으로 설정합니다.
  • 로그 수준을 선택합니다. 이 설정은 앱의 다른 로깅 공급자가 아닌 Azure 로그 스트리밍에만 적용됩니다.

로그 스트림 페이지로 이동하여 앱 메시지를 봅니다. 앱이 ILogger 인터페이스를 통해 기록한 것입니다.

Azure Application Insights 추적 로깅

Microsoft.Extensions.Logging.ApplicationInsights 공급자 패키지는 Azure Application Insights에 로그를 기록합니다. Application Insights는 웹앱을 모니터링하고 원격 분석 데이터를 쿼리 및 분석하기 위한 도구를 제공하는 서비스입니다. 이 공급자를 사용하는 경우 Application Insights 도구를 사용하여 로그를 쿼리 및 분석할 수 있습니다.

로깅 공급자는 ASP.NET Core에 대한 모든 사용 가능한 원격 분석을 제공하는 패키지인 Microsoft.ApplicationInsights.AspNetCore의 종속성으로 포함됩니다. 이 패키지를 사용하는 경우 공급자 패키지를 설치할 필요가 없습니다.

ASP.NET 4.x용으로 제공되는 Microsoft.ApplicationInsights.Web 패키지—를 사용하지 마세요.

자세한 내용은 다음 자료를 참조하세요.

타사 로깅 공급자

ASP.NET Core와 호환되는 타사 로깅 프레임워크는 다음과 같습니다.

일부 타사 프레임워크는 구조적 로깅이라고 하는 의미 체계 로깅을 수행할 수 있습니다.

타사 프레임워크를 사용하는 방법은 다음과 같이 기본 공급자 중 하나를 사용하는 방법과 비슷합니다.

  1. 프로젝트에 NuGet 패키지를 추가합니다.
  2. 로깅 프레임워크에서 제공하는 ILoggerFactory 확장 메서드를 호출합니다.

자세한 내용은 각 공급자의 설명서를 참조하세요. 타사 로깅 공급자는 Microsoft에서 지원되지 않습니다.

추가 자료