NLog를 사용하여 로그

페이지 생성 날짜 :

환경

비주얼 스튜디오
  • 비주얼 스튜디오 2019
ASP.NET 코어
  • 5.0 (MVC, 면도기 페이지)

처음에

NLog를 사용하면 설정에 따라 파일, 이메일 및 데이터베이스에 로그를 출력할 수 있습니다.

NLog ASP.NET 코어의 표준 로깅 시스템에 통합될 ASP.NET. 기본 로거를 사용하는 동안 설정에 따라 로그를 출력할 수 있습니다.

로그 수준 에 대해

Microsoft 로그와 NLog는 6단계로 나뉘며 출력 수준은 거의 동일합니다.

레벨 마이크로 소프트NLog
0 자취 자취
1 디버그 디버그
2 정보 정보
3 경고 경고하다
4 오류 오류
5 비판적인 치명적인
(6) (없음) (꺼져)

레벨이 높을수록 로그가 더 중요하고 로그 출력 제약 조건에 관계없이 작성될 가능성이 높아지립니다.

로깅 지침

NLog 패키지 배포

ASP.NET 코어 프로젝트를 만들었으며 패키지를 추가합니다.

프로젝트에 대한 종속성을 마우스 오른쪽 단추로 클릭하고 NuGet 패키지 관리관리를 선택합니다.

검색 탭을 클릭하고 검색 필드에 NLog를 입력하여 NLog 관련 패키지를 표시합니다.

NLog를 선택한 다음 최신 안정적인 버전을 선택한 설치 단추를 클릭합니다.

확인을 클릭합니다.

또한 NLog.Web.AspNetCore를 설치합니다.

패키지가 프로젝트에 추가되었습니다.

nlog.config 추가

NLog 로그의 출력 정의인 nlog.config를 프로젝트에 추가합니다. 내용은 XML 형식으로 되어 있으므로 XML 파일로 만들었습니다. 파일 이름은 nlog.config(소문자)여야 합니다.

다음과 같이 파일을 만듭니다. 자세한 설정은 나중에 설명합니다.

<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      autoReload="true"
      internalLogLevel="Info"
      throwConfigExceptions="true"
      internalLogFile="${basedir}/internal-nlog-AspNetCore.txt">

  <!-- ログの出力レイアウトを変数 layoutDefine で定義 -->
  <variable name="layoutDefine"
            value="${longdate} [${event-properties:item=EventId_Id:whenEmpty=0}][${level:padding=-5}] ${message} ${exception:format=tostring} (${callsite:includeNamespace=false:fileName=true:includeSourcePath=false})" />

  <!-- 書き込むターゲット -->
  <targets>
    <!-- Visual Studio の出力 (デバッグ) に書き込みます -->
    <target xsi:type="Trace" name="TraceOutput" rawWrite="true" layout="${layoutDefine}" />

    <!-- 基本的な詳細を含むすべてのログメッセージのファイルターゲット -->
    <target xsi:type="File" name="FileOutput" fileName="${aspnet-appbasepath}/Log-${shortdate}.log" layout="${layoutDefine}" />

    <!-- Docker / Visual Studio の起動検出を改善するためにライフタイムメッセージをホストするためのコンソールターゲット  -->
    <target xsi:type="Console" name="LifetimeConsole" layout="${level:truncate=4}\: ${logger}[0]${newline}      ${message}${exception:format=tostring}" />
  </targets>

  <!-- ロガー名からターゲットにマップするルール -->
  <rules>
    <!-- Microsoft からのものを含むすべてのログ -->
    <logger name="*" writeTo="TraceOutput" />

    <!-- 起動の検出を高速化するために、ホスティングライフタイムメッセージをコンソールターゲットに出力します。Microsoft.Hosting.Lifetime はここより下の定義には出力しません -->
    <logger name="Microsoft.Hosting.Lifetime" minlevel="Info" writeTo="LifetimeConsole" final="true" />

    <!-- 重要でない Microsoft ログをスキップして、自分のログのみをログに記録する。システムが出す Warning 以上のログ以外はここより下の定義には出力されません -->
    <logger name="Microsoft.*" maxlevel="Info" final="true" />
    <logger name="System.Net.Http.*" maxlevel="Info" final="true" />

    <!-- 上記で除外したもの以外をファイルに出力 -->
    <logger name="*" writeTo="FileOutput" />
  </rules>
</nlog>

nlog.config의 속성이 작업 빌드로 설정되어 있는지 확인: 콘텐츠, 출력 디렉터리로 복사: 새 경우 복사.

appsetting.json 편집

기본적으로 nlog.config를 설정하는 방법에 관계없이 Information 이러한 수준만 출력됩니다. 로깅은 appsetting.json에도 의존하기 때문입니다.

appsetting.json을 열고 Logging.LogLevel.Default 값을 로 Trace 변경합니다. NLog를 사용하는 경우 NLog 측의 레벨을 조정할 수 있으므로 appsetting.json을 설정하여 거의 모든 레벨을 출력할 수 Trace 있습니다.

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

또한 개발 중, 앱 설정. Development.json 설정이 로드되므로 변경도 됩니다.

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

NLog를 위한 프로그램 준비

NLog 메커니즘에 로그인할 수 있도록 프로그램을 추가합니다.

프로그램 파일을 .cs 열고 다음과 같이 수정합니다.

using NLog.Web;  // 追加

// 省略

public class Program
{
  public static void Main(string[] args)
  {
    var logger = NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
    try
    {
      CreateHostBuilder(args).Build().Run();
    }
    catch (Exception exception)
    {
      // NLog:セットアップエラーをキャッチ
      logger.Error(exception, "例外のためにプログラムを停止しました。");
      throw;
    }
    finally
    {
      // アプリケーションを終了する前に、内部タイマー/スレッドをフラッシュして停止するようにしてください
      // (Linux でのセグメンテーション違反を回避してください)
      NLog.LogManager.Shutdown();
    }
  }

  public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
      .ConfigureWebHostDefaults(webBuilder =>
      {
        webBuilder.UseStartup<Startup>();
      })
      .ConfigureLogging(logging =>
      {
        logging.ClearProviders();                 // NLog 以外で設定された Provider の無効化.
        logging.SetMinimumLevel(LogLevel.Trace);  // 最小ログレベルの設定
      })
      .UseNLog();  // NLog:依存性注入のための NLog のセットアップ
}

로깅

MVC 프로젝트의 HomeComtroller 경우 Razor 페이지의 경우 IndexModel ILogger<IndexModel> logger 생성자에게 전달되었습니다. 또한 개인 필드에 설정되어 _logger 있으므로 로그하는 데 사용할 수 있습니다.

다음은 Razor 페이지에서 출력한 예이지만 MVC는 동일한 코드로 출력할 수 있습니다.

// 省略

public class IndexModel : PageModel
{
  private readonly ILogger<IndexModel> _logger;
  
  public IndexModel(ILogger<IndexModel> logger)
  {
    _logger = logger;
    
    _logger.LogTrace("Trace で出力します。");
    _logger.LogDebug("Debug で出力します。");
    _logger.LogInformation("Information で出力します。");
    _logger.LogWarning("Warning で出力します。");
    _logger.LogError("Error で出力します。");
    _logger.LogCritical("Critical で出力します。");
    
    _logger.LogInformation(1, "EventID ありで出力します。");
  }
  
  public void OnGet()
  {
    _logger.LogInformation("ページを表示するタイミングでログを出力します。");
  }
}

디버깅 할 때 프로젝트의 폴더에서 로그 파일을 만들 수 있다고 생각합니다.

파일의 내용을 확인하여 로그를 확인할 수 있습니다.

샘플 nlog.config 해설

나는 순서대로 설명하고 있지만, 나는 덜 중요한 부분을 설명하지 않습니다.

<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      autoReload="true"
      internalLogLevel="Info"
      throwConfigExceptions="true"
      internalLogFile="${basedir}/internal-nlog-AspNetCore.txt">

NLog 자체에 대한 로그 출력 설정과 같은 매개 변수가 있습니다.

internalLogFile 로그의 대상이 됩니다. 예를 들어 로그 자체의 출력에 오류가 있는 경우 유용할 수 있습니다. ${basedir} 프로그램의 실행 폴더를 나타냅니다.

internalLogLevel NLog 로그의 출력 수준입니다. Off 이 경우 출력이 전혀 되지 않습니다.

<!-- ログの出力レイアウトを変数 layoutDefine で定義 -->
<variable name="layoutDefine"
          value="${longdate} [${event-properties:item=EventId_Id:whenEmpty=0}][${level:padding=-5}] ${message} ${exception:format=tostring} (${callsite:includeNamespace=false:fileName=true:includeSourcePath=false})" />

변수는 로그의 내용이 출력될 레이아웃으로 설정됩니다. 이후 대상에 직접 입력할 수 있지만 동일한 레이아웃의 배수를 지정하면 한 변수에서 쉽게 관리할 수 있습니다.

레이아웃에 지정할 수 있는 매개 변수를 보려면 공식 웹 사이트를 참조하는 것이 좋습니다.

참조를 위해 여기에 지정된 매개 변수는 다음 형식으로 출력됩니다.

매개 변수 출력 콘텐츠
롱데이트 "2021-03-17 11:46:36.5034" 등의 날짜 및 시간 분
이벤트 속성 프로그램에서 지정한 로그 출력의 이벤트 ID 등을 표시합니다.
수준 추적 및 오류와 같은 수준
메시지 프로그램 로깅에 지정된 메시지
예외 프로그램 로깅에서 예외를 통과하면 어떻게 해야 합니까?
콜사이트 로깅 위치, 파일 이름 등

출력 예제

2021-03-17 11:46:37.3537 [0][Info ] ページを表示するタイミングでログを出力します。  (IndexModel.OnGet(Index.cshtml.cs:26))
<!-- 書き込むターゲット -->
<targets>
  <!-- Visual Studio の出力 (デバッグ) に書き込みます -->
  <target xsi:type="Trace" name="TraceOutput" rawWrite="true" layout="${layoutDefine}" />

  <!-- 基本的な詳細を含むすべてのログメッセージのファイルターゲット -->
  <target xsi:type="File" name="FileOutput" fileName="${aspnet-appbasepath}/Log-${shortdate}.log" layout="${layoutDefine}" />

  <!-- Docker / Visual Studio の起動検出を改善するためにライフタイムメッセージをホストするためのコンソールターゲット  -->
  <target xsi:type="Console" name="LifetimeConsole" layout="${level:truncate=4}\: ${logger}[0]${newline}      ${message}${exception:format=tostring}" />
</targets>

대상을 출력하도록 지정합니다. 여러 번 지정할 수 있습니다.

첫 번째 xsi:type="Trace" 지정하고 로그가 Visual Studio 출력 창에 인쇄됩니다. 주로 디버깅 실행에 사용할 수 있습니다.

두 번째는 xsi:type="File" 지정된 경로의 파일에 지정하고 로그됩니다. ${shortdate} 경로에 지정한 경우 로그 시 로그 날짜 파일에 로그를 쓸 수 있습니다. 또한 ${aspnet-appbasepath} 웹 프로젝트의 루트 폴더를 지정합니다. 그러나 작동 할 때 프로그램 교체 및 보안을 위해 웹 디렉터리 외부에 로그 파일을 출력하는 것이 좋습니다.

세 번째가 xsi:type="Console" 지정되어 콘솔 앱의 콘솔에 표시할 수 있습니다. ASP.NET 코어 자체는 콘솔 앱이 아니지만 상태를 콘솔에 표시할 수 있으므로 Docker 및 Azure와 같은 환경에서도 사용할 수 있습니다. 이것은 NLog 공식 웹 사이트의 설명입니다.

<!-- ロガー名からターゲットにマップするルール -->
<rules>
  <!-- Microsoft からのものを含むすべてのログ -->
  <logger name="*" writeTo="TraceOutput" />

  <!-- 起動の検出を高速化するために、ホスティングライフタイムメッセージをコンソールターゲットに出力します。Microsoft.Hosting.Lifetime はここより下の定義には出力しません -->
  <logger name="Microsoft.Hosting.Lifetime" minlevel="Info" writeTo="LifetimeConsole" final="true" />

  <!-- 重要でない Microsoft ログをスキップして、自分のログのみをログに記録する。システムが出す Warning 以上のログ以外はここより下の定義には出力されません -->
  <logger name="Microsoft.*" maxlevel="Info" final="true" />
  <logger name="System.Net.Http.*" maxlevel="Info" final="true" />

  <!-- 上記で除外したもの以外をファイルに出力 -->
  <logger name="*" writeTo="FileOutput" />
</rules>

여기서 출력할 레벨과 로그 유형을 지정합니다. 이 설명은 위에서 위로 적용됩니다.

첫 번째는 name="*" 레벨을 지정하는 동안 레벨을 지정하기 때문에 대상에 모든 로그를 writeTo 출력하는 것입니다. target 이 값은 개체 TraceOutput 스튜디오 출력에 표시되므로 에 지정된 것입니다.

두 번째는 Microsoft.Hosting.Lifetime 라이브러리의 로그 출력에 writeTo (コンソール) 출력됩니다. 콘솔 라이프타임 연결은 Azure 및 Docker와 같은 콘솔에서 확인할 수 있습니다. minlevel="Info" 지정하고 Trace Debug 기록되지 않기 때문입니다. 또한 후속 정의는 관련 로그를 출력하지 final="true" Microsoft.Hosting.Lifetime 않습니다.

세 번째는 name="Microsoft.*" name="System.Net.Http.*" final="true" 로깅을 지정하고 로그하도록 지정하여 로깅을 중지하는 것입니다. name *와일드카드로, Microsoft System.Net.Http 모든 관련 라이브러리를 의미합니다. 하지만 여기서 그만두는 maxlevel="Info" Trace Debug Information 것은 WArning Error [ 로그 또한 후속 Critical 정의에서 출력됩니다.

네 번째는 final="true" 위에서 중지된 로그 이외의 파일로 출력됩니다.

아카이브 로그

또한 하나의 주 로그 파일만 있는 각 날짜에 대해 별도의 폴더에 이전 로그 파일을 보관하는 방법도 있습니다.

예를 들어:

<target xsi:type="File"
        name="FileOutput"
        fileName="${aspnet-appbasepath}/Log.log"
        archiveNumbering="Date"
        archiveEvery="Day"
        archiveFileName="${aspnet-appbasepath}/Archive/Log_{#}.log"
        archiveDateFormat="yyyy-MM-dd"
        maxArchiveFiles="7"
        layout="${layoutDefine}" />

여기에 사용되는 매개 변수는 다음을 의미합니다.

매개 변수 설명
아카이브 번호 매기기 날짜는 날짜별로 아카이브 파일을 만듭니다.
아카이브 모든 하루는 매일 보관하는 데 사용됩니다. "월", "시간", "일요일"등을 지정하는 방법도 있습니다.
아카이브파일네임 보관하는 경로입니다. {#} 아카이브별로 변경됩니다.
아카이브데이트포맷 파일 이름의 날짜별 아카이브 날짜 형식입니다.
maxArchive파일 보관할 파일 수를 지정합니다.

비날짜 메서드를 보관하는 방법도 있습니다. 자세한 내용은 공식 웹 사이트를 참조하십시오.

실행하면 다음과 같습니다.

로그당 이메일 보내기

NLog를 사용하면 로깅 할 때 전자 메일을 보낼 수도 있습니다. 그러나 디버그 로그와 같은 이메일을 보내면 전송하기가 너무 많아집니다. 오류 및 치명적과 같은 제한된 로그 수준만 타겟팅하는 것이 좋습니다. 또한, 오버 전송으로 인한 메일 서버 차단 과 같은 고장의 위험을 피하기 위해, 로그 전용 이메일 계정을 지정하는 것이 좋습니다.

다음은 구성의 예입니다. 실제로 메일을 보내려면 사용하려는 SMTP 서버를 따르십시오.

<targets>
  <target xsi:type="Mail"
          name="SendMail"
          smtpServer="SMTP Server Name"
          smtpPort="25"
          subject="XXXX システムでエラーが発生しました"
          from="aaaa@example.com"
          to="bbbb@example.com"
          enableSsl="False"
          smtpAuthentication="None"
          smtpUserName=""
          smtpPassword=""
          layout="${layoutDefine}"/>
</targets>

<rules>
  <logger name="*" minlevel="Error" writeTo="SendMail" />
</rules>

데이터베이스에 로그 쓰기

NLog는 데이터베이스에 로그를 쓸 수도 있습니다. 다음은 예이므로 자세한 내용은 공식 웹 사이트를 참조하십시오.

이 섹션에서는 다른 서버에서 SQL Server에 쓰는 단계를 설명합니다.

먼저 대상 SQL Server에 로깅할 테이블을 만듭니다. 작성할 값을 선택할 수 있으므로 로그로 필요한 것을 열로 정의합니다.

다음은 테이블 생성 SQL의 예입니다.

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Log](
  [Id] [int] IDENTITY(1,1) NOT NULL,
  [Application] [nvarchar](50) NOT NULL,
  [Logged] [datetime] NOT NULL,
  [Level] [nvarchar](50) NOT NULL,
  [User] [nvarchar](250) NOT NULL,
  [Message] [nvarchar](max) NOT NULL,
  [Logger] [nvarchar](250) NULL,
  [Callsite] [nvarchar](max) NULL,
  [Exception] [nvarchar](max) NULL,
  CONSTRAINT [PK_dbo.Log] PRIMARY KEY CLUSTERED 
(
  [Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO

데이터베이스 처리에는 데이터베이스 클라이언트 System.Data.SqlClient 라이브러리가 필요합니다. NuGet에서 설치해 보겠습니다.

appsettings.json에 데이터베이스 정보를 씁니다. nlog.config를 사용하면 appsettings.json에서 정보를 로드할 수 있습니다. 설정은 미정이므로 실제 데이터베이스에 따라 설정하십시오. 키 이름은 임의이지만 nlog.config에서 사용됩니다.

{
  "": "省略",

  "NlogConnection": {
    "DbHost": "ServerName\\SQLEXPRESS",
    "Database": "TestDatabase",
    "User": "UserName",
    "Password": "********"
  }
}

nlog.config를 다음과 같이 설정합니다.

<targets>
  <target xsi:type="Database"
          name="DatabaseOutput"
          dbProvider="sqlserver"
          dbHost="${configsetting:name=NlogConnection.DbHost}"
          dbDatabase="${configsetting:name=NlogConnection.Database}"
          dbUserName="${configsetting:name=NlogConnection.User}"
          dbPassword="${configsetting:name=NlogConnection.Password}">
    <commandText>
      insert into dbo.Log (
        Application, Logged, [Level], [User], Message, Logger, CallSite, Exception
      ) values (
        @Application, @Logged, @Level, @User, @Message, @Logger, @Callsite, @Exception
      );
    </commandText>
    <parameter name="@application" layout="XXXX System" />
    <parameter name="@logged" layout="${date}" />
    <parameter name="@level" layout="${level}" />
    <parameter name="@user" layout="${aspnet-user-identity}" />
    <parameter name="@message" layout="${message}" />
    <parameter name="@logger" layout="${logger}" />
    <parameter name="@callSite" layout="${callsite:filename=true}" />
    <parameter name="@exception" layout="${exception:tostring}" />
  </target>
</targets>

<rules>
  <logger name="*" writeTo="DatabaseOutput" />
</rules>

실행할 오류가 없는 경우 다음과 같이 작성됩니다.

그건 그렇고.cs 프로그램 .cs 메서드와 같은 초기 단계에서 데이터베이스에 로그를 작성하려고 시도하는 CreateHostBuilder 것이 실패할 수 있습니다.

RequestServices에서 로거를 얻고 로그

새 컨트롤러 또는 페이지 모델을 만들 때마다 생성자에 추가하는 것은 지루할 수 ILogger 있습니다. 또는. RequestServices

public void OnGet()
{
  // RequestServices から ILogger を取得する
  var logger = (ILogger<IndexModel>)HttpContext.RequestServices.GetService(typeof(ILogger<IndexModel>));

  logger.LogInformation("ページを表示するタイミングでログを出力します。");
}

사용자 고유의 컨트롤러 또는 페이지 모델을 지정하는 것도 번거로울 경우 확장 메서드 또는 기본 클래스를 만들 수 있습니다.

public static class AspNetExtention
{
  /// <summary>
  /// ロガーを取得する拡張メソッドです。
  /// </summary>
  public static ILogger<T> GetLogger<T>(this T self) where T : PageModel
    => (ILogger<T>)self.HttpContext.RequestServices.GetService(typeof(ILogger<T>));

  // MVC の場合
  //public static ILogger<T> GetLogger<T>(this T self) where T : Controller
  //  => (ILogger<T>)self.HttpContext.RequestServices.GetService(typeof(ILogger<T>));
}

서비스 케이스 사용

public void OnGet()
{
  // RequestServices から ILogger を取得する (this. は必要)
  var logger = this.GetLogger();

  logger.LogInformation("ページを表示するタイミングでログを出力します。");
}