.NET Core中使用NLog按等級過濾寫入控制台、文件、數據庫記錄日志


項目中日志是比較常見的一個功能模塊,在開發階段和運維階段我們可以根據日志排查項目出現的問題,同時可以為項目運營階段提供業務數據分析。所以日志是項目中不可或缺的功能模塊,項目中一般會根據項目需要開發偏向業務的日志模塊,而本博客主要介紹第三方日志框架NLog。通過引入NLog日志框架,項目中可以快速的實現基本的日志模塊,大大的提高了開發效率。

NuGet引入安裝包

添加NLog和NLog.Web.AspNetCore安裝包

Install-Package NLog -Version 4.7.4 

Install-Package NLog.Web.AspNetCore -Version 4.9.3

NLog.config

網站根目錄下新建NLog.config配置文件,記得右擊該文件“屬性”,復制到輸出目錄:“始終復制”

 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" throwExceptions="false" internalLogLevel="Off" internalLogFile="NlogRecords.log">
  <!--Nlog內部日志記錄為Off關閉。除非糾錯,不可以設為Trace否則速度很慢,起碼Debug以上-->
  <extensions>
    <add assembly="NLog.Web.AspNetCore" />
  </extensions>
  <targets>
    <!--通過數據庫記錄日志 配置
    dbProvider請選擇mysql或是sqlserver,同時注意連接字符串,需要安裝對應的sql數據提供程序
    MYSQL:
    dbProvider="MySql.Data.MySqlClient.MySqlConnection, MySql.Data"
    connectionString="server=localhost;database=BaseMIS;user=root;password=123456"
    MSSQL:
    dbProvider="Microsoft.Data.SqlClient.SqlConnection, Microsoft.Data.SqlClient"
    connectionString="Server=127.0.0.1;Database=BaseMIS;User ID=sa;Password=123456"
    -->
    <target name="log_database" xsi:type="Database" dbProvider="MySql.Data.MySqlClient.MySqlConnection, MySql.Data" connectionString="server=localhost;port=3306;User Id=root;password=wuzhd123456!;Database=testnlog;pooling=true;character set=utf8;Connection Timeout=160">
      <commandText>
        INSERT INTO TblLogrecords 
        (LogDate,LogLevel,LogType,Logger,Message,MachineName,MachineIp,NetRequestMethod
        ,NetRequestUrl,NetUserIsauthenticated,NetUserAuthtype,NetUserIdentity,Exception)
        VALUES
        (@LogDate,@LogLevel,@LogType,@Logger,@Message,@MachineName,@MachineIp,@NetRequestMethod
        ,@NetRequestUrl,@NetUserIsauthenticated,@NetUserAuthtype,@NetUserIdentity,@Exception);
      </commandText>
      <parameter name="@LogDate" layout="${date}" />
      <parameter name="@LogLevel" layout="${level}" />
      <parameter name="@LogType" layout="${event-properties:item=LogType}" />
      <parameter name="@Logger" layout="${logger}" />
      <parameter name="@Message" layout="${message}" />
      <parameter name="@MachineName" layout="${machinename}" />
      <parameter name="@MachineIp" layout="${aspnet-request-ip}" />
      <parameter name="@NetRequestMethod" layout="${aspnet-request-method}" />
      <parameter name="@NetRequestUrl" layout="${aspnet-request-url}" />
      <parameter name="@NetUserIsauthenticated" layout="${aspnet-user-isauthenticated}" />
      <parameter name="@NetUserAuthtype" layout="${aspnet-user-authtype}" />
      <parameter name="@NetUserIdentity" layout="${aspnet-user-identity}" />
      <parameter name="@Exception" layout="${exception:tostring}" />
    </target>
    <target name="log_file" xsi:type="File" fileName="${basedir}/logs/${shortdate}.log" layout="${longdate} | ${level:uppercase=false} | ${message} ${onexception:${exception:format=tostring} ${newline} ${stacktrace} ${newline}" />
    <!--ColoredConsole彩色控制台 xsi:type="Console"是指定輸出到普通控制台-->
    <target name="log_console" xsi:type="ColoredConsole" useDefaultRowHighlightingRules="true" layout="${longdate}|${level}|${logger}|${message} ${exception}">
      <highlight-row condition="level == LogLevel.Trace" foregroundColor="DarkGray" />
      <highlight-row condition="level == LogLevel.Debug" foregroundColor="Gray" />
      <highlight-row condition="level == LogLevel.Info" foregroundColor="White" />
      <highlight-row condition="level == LogLevel.Warn" foregroundColor="Yellow" />
      <highlight-row condition="level == LogLevel.Error" foregroundColor="Red" />
      <highlight-row condition="level == LogLevel.Fatal" foregroundColor="Magenta" backgroundColor="White" />
    </target>
  </targets>
  <rules>
    <!--跳過所有級別的Microsoft組件的日志記錄-->
    <!--<logger name="Microsoft.*" maxlevel="Info" final="true" />-->
    <!-- BlackHole without writeTo -->
    <!--只通過數據庫記錄日志,這里的*,如果給了name名字,代碼里用日志記錄的時候,取logger需要把name當做參數-->
    <logger name="*" minlevel="Info" writeTo="log_database" />
    <logger name="*" minlevel="Trace" writeTo="log_console" />
    <logger name="*" minlevel="Warn" writeTo="log_file" />
  </rules>
</nlog>

 

說明

  • nlog根節點:
    • autoReload屬性,true時,如果NLog.config文件有變動,會自動應用新配置(但是會有延遲,過幾秒才會應用起來)
    • internalLogLevel屬性,設定后,輸出的是NLog內部自己的日志記錄,如果遇到NLog異常/配置文件沒配好,可以把Off改為Trace或Debug來查看NlogRecords.log里的內容
    • internalLogFile屬性,可以設定路徑,例如默認的c:\temp\nlog-internal.log
  • 新增了extensions節點,因為引用了NLog.Web.AspNetCore
  • targets節點中是各種記錄方式的配置
  • 第一個target節點,可以看到name是log_database,這里的name和下方logger中writeTo屬性對應
    • xsi:type="Database",就是寫入數據庫了
    • dbProvider屬性是數據庫適配器,MySQL是MySql.Data.MySqlClient.MySqlConnection, MySql.Data
    • connectionString即連接字符串了
    • commandText子節點是插入數據庫時insert語句,可以看到我這里是寫入到TblLogrecords表,表結構下文會展示出來
    • parameter子節點是insert語句的各個參數:
      • 有個name="@LogType"參數,layout="${event-properties:item=LogType}",表示@LogType參數的值從event-properties中的LogType中取
      • 其余參數均是NLog自帶的內容,aspnet-開頭的是NLog.Web.AspNetCore包中提供的方法
  • 第二個target節點,可以看到name是log_file,這里的name和下方logger中writeTo屬性對應
    • xsi:type="File",即寫入到文件
    • fileName屬性是文件名,這里是寫入到當前目錄下的logs文件夾,並且按日期歸檔
    • layout屬性是寫入日志的格式
    • rules應用規則,給三種target限定了三種等級:
      • 首先寫入控制台最小等級為Trace,這樣我們在調試時,任何日志我們都能在控制台看到
      • 寫入數據庫的最小等級為Info,這樣並不是所以日志都寫入數據庫,僅當日志等級大於等於Info時才寫入
      • 當發生一些警告、致命錯誤時,必須以文件形式記錄下來,所以寫入文件的最小等級為Warn
      • 以上是我自己的配置,可以自行配置等級

 

網站項目應用NLog服務

 在CreateHostBuilder方法內,追加使用NLog服務以及配置

.ConfigureLogging(logging =>
                {
                    logging.ClearProviders();
                    logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace);
                }).UseNLog();  // NLog: 依賴注入Nlog;

在Main方法中初始化配置

var host = CreateWebHostBuilder(args).Build();
            Logger logger = LogManager.GetCurrentClassLogger();
            try
            {
                logger.Trace("網站啟動中...");
                using (IServiceScope scope = host.Services.CreateScope())
                {
                    IConfiguration configuration = scope.ServiceProvider.GetRequiredService<IConfiguration>();
                    //獲取到appsettings.json中的連接字符串
                    string sqlString = configuration.GetSection("Connection:MySql").Value;
                    //確保NLog.config中連接字符串與appsettings.json中同步
                    NLogUtil.EnsureNlogConfig("NLog.config", sqlString);
                    logger.Trace("初始化數據庫");
                    //用於查看彩色控制台樣式,以及日志等級過濾
                    logger.Trace("Test For Trace");
                    logger.Debug("Test For Debug");
                    logger.Info("Test For Info");
                    logger.Warn("Test For Warn");
                    logger.Error("Test For Error");
                    logger.Fatal("Test For Fatal");
                }
                //throw new Exception("測試異常");//for test

                //其他項目啟動時需要做的事情
                //code
                logger.Trace("網站啟動完成");
                host.Run();
            }
            catch (Exception ex)
            {
                logger.Fatal(ex, "網站啟動失敗");
                throw;
            }

 

NLogUtil類 EnsureNlogConfig 驗證是否與appsettings.json同步

/// <summary>
        /// 確保NLog配置文件sql連接字符串正確
        /// </summary>
        /// <param name="nlogPath"></param>
        /// <param name="sqlConnectionStr"></param>
        public static void EnsureNlogConfig(string nlogPath, string sqlConnectionStr)
        {
            XDocument xd = XDocument.Load(nlogPath);
            if (xd.Root.Elements().FirstOrDefault(a => a.Name.LocalName == "targets")
                is XElement targetsNode && targetsNode != null &&
                targetsNode.Elements().FirstOrDefault(a => a.Name.LocalName == "target" && a.Attribute("name").Value == "log_database")
                is XElement targetNode && targetNode != null)
            {
                if (!targetNode.Attribute("connectionString").Value.Equals(sqlConnectionStr))//不一致則修改
                {
                    //這里暫時沒有考慮dbProvider的變動
                    targetNode.Attribute("connectionString").Value = sqlConnectionStr;
                    xd.Save(nlogPath);
                    //編輯后重新載入配置文件(不依靠NLog自己的autoReload,有延遲)
                    LogManager.Configuration = new XmlLoggingConfiguration(nlogPath);
                }
            }
        }

 

測試查看效果

控制台:

 

 文件:

 

 數據庫:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM