השתמש ביומן הרישום של NLog

תאריך יצירת דף :

בסביבה

סטודיו חזותי
  • סטודיו ויזואלי 2019
הליבה ASP.NET
  • 5.0 (MVC, דף גילוח)

בהתחלה

NLog מאפשר לך ליצור פלט של יומני רישום לקבצים, הודעות דואר אלקטרוני ומסדי נתונים בהתאם להגדרות שלך.

NLog ASP.NET ישולבו במערכת הרישום הסטנדרטית של הליבה. ניתן ליצור פלט של יומני רישום בהתאם להגדרות בעת שימוש ביומן ברירת המחדל.

אודות רמות יומן רישום

יומני רישום של Microsoft ו- NLogs מחולקים לשישה שלבים, ורמות הפלט זהות בערך:

רמה מיקרוסופטNLog
0 מעקב מעקב
1 איתור באגים איתור באגים
2 מידע מידע
3 אזהרה להזהיר
4 שגיאה שגיאה
5 קריטי קטלני
(6) (ללא) לא) (כבוי)

ככל שהרמה גבוהה יותר, כך יומן הרישום חשוב יותר, וסביר יותר שהוא ייכתב ללא קשר לאילוצי פלט יומן הרישום.

הוראות רישום

פריסת חבילת NLog

ASP.NET שיצרת פרוייקט ליבה, הוסף חבילה.

לחץ באמצעות לחצן העכבר הימני על יחסי תלות עבור הפרוייקט ובחר נהל חבילות NuGet.

לחץ על הכרטיסיה עיון והקלד NLog בשדה החיפוש כדי להציג חבילות הקשורות ל- NLog.

בחר NLog ולאחר מכן לחץ על לחצן ההתקנה כאשר הגירסה היציבה העדכנית ביותר נבחרה.

לחץ על אישור.

התקן גם את NLog.web.AspNetCore.

החבילה נוספה לפרוייקט.

הוסף nlog.config

הוסף לפרוייקט את nlog.config, הגדרת הפלט של יומן הרישום של NLog. התוכן הוא בתבנית 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 מוגדרים כפעולה לבניית: תוכן, העתק לספריית הפלט: העתק אם חדש.

עריכת אפליקציותing.json

כברירת מחדל, ללא קשר לאופן הגדרת nlog.config, Information רק רמות אלה הן פלט. הסיבה לכך היא שרישום גם מסתמך על appsetting.json.

פתח את appsetting.json Logging.LogLevel.Default ושנה את הערך Trace ל- . אם אתה משתמש ב- NLog, באפשרותך להתאים את הרמה בצד NLog, כך שתוכל ליצור פלט כמעט בכל הרמות Trace על-ידי הגדרת appsetting.json.

{
  "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 , עבור דפי תער, 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"
מאפייני אירוע הצגת מזהה האירוע וכו' של פלט יומן הרישום שצוין על-ידי התוכנית
רמת רמות כגון מעקב ושגיאה
ההודעה הודעה שצוינה ברישום תוכניות
חריגה מה קורה אם אתה מעביר חריג ברישום תוכניות
אתר שיחות מיקום רישום, שם קובץ וכו'.

דוגמה לפלט

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 Core עצמו אינו יישום מסוף, אך ניתן להשתמש בו גם בסביבות כגון 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 מופיע בפלט Visual Studio.

השני הוא Microsoft.Hosting.Lifetime פלט לפלט יומן הרישום writeTo (コンソール) בספריה. ניתן לבדוק שיוכי ConsoleLifetime במסופים כגון תכלת הרקיע ו- 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}" />

משמעות הפרמטרים המשמשים כאן היא:

תיאור פרמטר
מספור בארכיון Date יוצר קובץ ארכיון לפי תאריך.
אחסן בארכיוןכל אחד היום משמש לארכיון על בסיס יומי. יש גם דרכים לציין "חודש", "שעה", "יום ראשון" וכו '.
שם קובץ ארכיון נתיב לארכיון ל. {#} שינויים על בסיס ארכיון אחר ארכיון.
עיצוב עיצוב בארכיון תבנית תאריך ארכיון תאריך לפי תאריך של שם הקובץ.
קבצי ארכיון מרביים ציון מספר הקבצים שיש לאחסן בארכיון.

קיימות גם דרכים לאחסן בארכיון שיטות שאינן תאריכים. לקבלת מידע נוסף, עיין באתר הרשמי.

כאשר הוא מוצא להורג, הוא נראה כך:

שליחת הודעות דואר אלקטרוני לכל יומן רישום

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 בשרת אחר.

תחילה, צור טבלה לרישום בשרת SQL המשמש כיעד. מאחר שבאפשרותך לבחור את הערך לכתיבה, הגדר את מה שאתה צריך כיומן רישום כעמודה.

להלן דוגמה ליצירת 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("ページを表示するタイミングでログを出力します。");
}