Günlüğe kaydetmek için NLog'yi kullanma

Sayfa oluşturma tarihi :

Ortam

Visual Studio
  • Visual Studio 2019
ASP.NET Çekirdek
  • 5.0 (MVC, Razor sayfası)

İlk başta

NLog, ayarlarınıza bağlı olarak dosyalara, e-postalara ve veritabanlarına günlüklerin çıktısını almanızı sağlar.

NLog ASP.NET core'un standart günlük sistemine dahil edilecektir. Varsayılan günlükçü kullanılırken günlükleri ayarlara göre çıkarmak mümkündür.

Günlük düzeyleri hakkında

Microsoft günlükleri ve NLog'lar altı aşamaya ayrılır ve çıktı düzeyleri kabaca aynıdır:

Düzey MicrosoftNLog
0 Izleme Izleme
1 Hata ayıklama Hata ayıklama
2 Bilgi Bilgi
3 Uyarı Uyarmak
4 Hata Hata
5 Kritik Ölümcül
(6) (Yok) (Kapalı)

Düzey ne kadar yüksekse, günlük o kadar önemlidir ve günlük çıktı kısıtlamalarına bakılmaksızın yazılması o kadar olasıdır.

Günlüğe kaydetme yönergeleri

NLog Paket Dağıtımı

ASP.NET bir Çekirdek projesi oluşturduysanız, bir paket ekleyin.

Projeniz için Bağımlılıklar'ı sağ tıklatın ve NuGet Paketlerini Yönet'i seçin.

Gözat sekmesini tıklatın ve NLog ile ilgili paketleri görüntülemek için arama alanına NLog yazın.

NLog'u seçin ve ardından en son kararlı sürümün seçili olduğu yükle düğmesini tıklatın.

Tamam'ı tıklatın.

Ayrıca NLog.Web.AspNetCore'u yükleyin.

Paket projeye eklendi.

nlog.config ekle

Projeye NLog günlüğünün çıktı tanımı olan nlog.config ekleyin. İçerik XML biçiminde, bu yüzden xml dosyası olarak oluşturdum. Dosya adı nlog.config (küçük harf) olmalıdır.

Dosyayı aşağıdaki gibi oluşturun: Ayrıntılı ayarlar daha sonra tartışılacaktır.

<?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 özelliklerinin Yapı Eylemi: İçerik, Çıktı Dizinine Kopyala: Yeniyse Kopyala olarak ayarlandığından emin olun.

Appsetting.json'ı düzenleme

Varsayılan olarak, nlog.config dosyasını nasıl ayarlarsanız ayarlayın, Information yalnızca bu düzeyler çıktıdır. Bunun nedeni, günlüğe kaydetmenin appsetting.json'a da dayanmasıdır.

appsetting.json adresini açın Logging.LogLevel.Default ve değeri ' olarak Trace değiştirin. NLog kullanıyorsanız, NLog tarafındaki düzeyi ayarlayabilirsiniz, böylece Trace appsetting.json'ı ayarlayarak hemen hemen tüm düzeylerin çıktısını alabilirsiniz.

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

Ayrıca, geliştirme sırasında, uygulamalar. Geliştirme.json ayarları yüklendi, bu yüzden onları da değiştiriyoruz.

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

NLog için program hazırlama

NLog mekanizmasında oturum açabilmeniz için bir program ekleyin.

.cs program dosyasını açın ve aşağıdaki gibi düzeltin:

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 のセットアップ
}

Günlüğü

MVC projeleri HomeComtroller için , Razor sayfaları için, IndexModel ILogger<IndexModel> logger oluşturucuya geçirilirdiniz. Ayrıca özel alanda da _logger ayarlanır, böylece günlüğe kaydetmek için kullanabilirsiniz.

Aşağıda Razor sayfasından çıktı örneği verilmiştir, ancak MVC aynı kodla çıktı alabilir.

// 省略

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("ページを表示するタイミングでログを出力します。");
  }
}

Hata ayıklarken, projenin klasöründe bir günlük dosyası yapılabileceğini düşünüyorum.

Dosyanın içeriğine bakarak günlüğü kontrol edebilirsiniz.

Örnek nlog.config yorumu

Sırayla açıklıyorum ama daha az önemli kısımları açıklamıyorum.

<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'un kendisi için günlük çıktı ayarları gibi parametreler vardır.

internalLogFile günlüğün hedefi olacaktır. Bu, örneğin günlüğün çıktısında bir hata varsa yararlı olabilir. ${basedir} programın yürütme klasörüne başvurur.

internalLogLevel NLog günlüğünün çıkış düzeyidir. Off eğer öyleyse, hiç çıkış olmayacaktır.

<!-- ログの出力レイアウトを変数 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})" />

Değişken, günlüğün içeriğinin hangi düzende çıktılanacağına ayarlanır. Daha sonraki hedeflere doğrudan yazabilirsiniz, ancak aynı düzenin katlarını belirtirseniz, bunları tek bir değişkende yönetmek daha kolaydır.

Düzende hangi parametrelerin belirtilebileceğini görmek için resmi web sitesine başvurmak daha iyidir.

Başvuru için, burada belirtilen parametreler aşağıdaki biçimde çıktıdır:

Parametre çıktı içeriği
uzun zaman "2021-03-17 11:46:36.5034" gibi tarih ve saat dakikaları
olay özellikleri Program tarafından belirtilen günlük çıktısının olay kimliği vb.
Düzey İzleme ve Hata gibi düzeyler
İleti Program günlüğünde belirtilen ileti
Özel durum Program günlüğünde özel durum geçirirseniz ne olur?
Callsite Günlük konumu, dosya adı vb.

Çıktı örneği

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>

Çıktı hedefi belirtir. Birden çok belirtilebilir.

İlki xsi:type="Trace" belirtir ve günlük Visual Studio çıktı penceresinde yazdırılır. Öncelikle hata ayıklama yürütme için kullanılabilir.

İkincisi, xsi:type="File" belirtilen yoldaki bir dosyayı belirtir ve günlüğe kaydeder. Yolda ${shortdate} belirtirseniz, günlüğü günlüğün tarihindeki dosyaya yazabilirsiniz. Ayrıca, ${aspnet-appbasepath} Web projesinin kök klasörünü de belirtir. Ancak, çalışırken, program değiştirme ve güvenlik için Günlük dosyalarını Web dizininin dışında çıkarmak daha iyidir.

Üçüncüsü xsi:type="Console" belirtilir ve konsol uygulamasında konsolda görüntülenebilir. ASP.NET Core'un kendisi bir konsol uygulaması değildir, ancak durum konsolda görüntülenebildiğinden Docker ve Azure gibi ortamlarda da kullanılabilir. Bu, NLog resmi web sitesindeki açıklamadır.

<!-- ロガー名からターゲットにマップするルール -->
<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>

Burada, hangi düzeyin ve ne tür günlüklerin nereye çıkart verileceğini belirtirsiniz. Bu açıklama yukarıdan üste uygulanır.

Birincisi, name="*" belirtilirken düzey belirtildiğinden, hedefe tüm günlüklerin writeTo çıktısını almaktır. Bu , target içinde belirtilendir, bu nedenle TraceOutput Visual Studio çıktısında görünür.

İkincisi, Microsoft.Hosting.Lifetime kitaplıktaki günlük çıktısına writeTo (コンソール) çıktıdır. ConsoleLifetime ilişkileri Azure ve Docker gibi konsollarda iade edilebilir. minlevel="Info" Trace Debug belirttiğinden ve günlüğe kaydedilmediğinden. Ayrıca, sonraki tanımlar ilgili günlüklerin çıktısını final="true" Microsoft.Hosting.Lifetime yapmaz.

Üçüncüsü, name="Microsoft.*" name="System.Net.Http.*" için ve final="true" günlükleri belirterek günlüğe kaydetmeyi durdurmaktır. name *bir joker karakterdir, bu da Microsoft System.Net.Http ilgili tüm kütüphaneleri ifade ettiği anlamına gelir. , ama burada dur maxlevel="Info" Trace , Debug Information çünkü WArning Error , günlüğü de sonraki Critical tanımlarda çıktıdır.

Dördüncüsü, final="true" yukarıda durdurulan günlük dışında bir dosyaya çıktıdır.

Günlükleri arşivle

Eski günlük dosyasını her tarih için ayrı bir klasörde yalnızca bir ana günlük dosyasıyla arşivleme yöntemi de vardır.

Örneğin:

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

Burada kullanılan parametreler şu anlama gelir:

Parametre açıklaması
arşivSayılama Tarih, tarihe göre bir arşiv dosyası oluşturur.
arşivEvery Gün günlük olarak arşivlemek için kullanılır. "Ay", "Saat", "Pazar" vb.
archiveFileAdı Arşivleme yolu. {#} arşiv bazında değişir.
arşivDateFormat Dosya adının tarihe göre arşiv tarihi biçimi.
maxArchiveFiles Kaç dosyanın arşivlenerek arşivlendiğini belirtir.

Tarih dışı yöntemleri arşivlemenin yolları da vardır. Daha fazla bilgi için resmi web sitesine bakın.

Yürütüldüğünde şöyle görünür:

Günlük başına e-posta gönderme

NLog ayrıca günlüğe kaydetme sırasında e-posta göndermenizi sağlar. Ancak, hata ayıklama günlüğü gibi bir e-posta gönderirseniz, göndermek çok fazla olur, Hata ve Önemli gibi yalnızca sınırlı günlük düzeylerini hedeflemek iyi bir fikirdir. Buna ek olarak, aşırı iletim nedeniyle posta sunucusunu engellemek gibi hata riskini önlemek için, Yalnızca günlük e-posta hesabı belirtmenizi öneririz.

Aşağıda bir yapılandırma örneği verilmiştir. Gerçekten posta göndermek istiyorsanız, kullanmak istediğiniz SMTP sunucusunu izleyin.

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

Günlükleri veritabanına yazma

NLog ayrıca veritabanına günlük yazabilir. Aşağıda bir örnek verilmiştir, bu nedenle ayrıntılar için lütfen resmi web sitesine bakın.

Bu bölümde, farklı bir sunucuda SQL Server'a yazma adımları açıklanmaktadır.

İlk olarak, hedef SQL Server'da oturum açmak için bir tablo oluşturun. Yazacak değeri seçebildiğinize göre, günlük olarak neye ihtiyacınız olduğunu sütun olarak tanımlayın.

Aşağıda tablo oluşturma SQL örneği verilmiştir.

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

Veritabanı işleme için bir veritabanı istemci kitaplığı System.Data.SqlClient gereklidir. NuGet'ten yükleyelim.

Veritabanı bilgilerini appsettings.json'a yazar. nlog.config, bilgileri appsettings.json dosyasına yüklemenizi sağlar. Ayarlar belirsizdir, bu yüzden lütfen bunları gerçek veritabanına göre ayarlayın. Anahtar adı rasgeledir, ancak nlog.config tarafından kullanılır.

{
  "": "省略",

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

nlog.config dosyasını aşağıdaki gibi ayarlayın:

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

Çalıştırılacak hata yoksa, aşağıdaki gibi yazılır:

Bu arada.cs program .cs yöntemleri gibi erken bir aşamada veritabanına günlük yazmaya çalışmanın başarısız CreateHostBuilder olabileceğini unutmayın.

RequestServices'ten günlükçüleri alma ve günlüğe kaydetme

Her yeni denetleyici veya sayfa modeli oluşturduğunuzda oluşturucuya eklemek sıkıcı ILogger olabilir. Alternatif olarak, RequestServices 'den alabilirsiniz.

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

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

Kendi denetleyicinizi veya sayfa modelinizi belirtmek de hantalsa, uzantı yöntemleri veya temel sınıflar oluşturabilirsiniz.

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

Kullanım örnekleri

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

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