Asp .Net Core 系列:Asp .Net Core 集成 NLog

簡介

NLog是一個基於.NET平臺編寫的日誌記錄類庫,它可以在應用程序中添加跟蹤調試代碼,以便在開發、測試和生產環境中對程序進行監控和故障排除。NLog具有簡單、靈活和易於配置的特點,支持在任何一種.NET語言中輸出帶有上下文的調試診斷信息,並能夠將這些信息發送到一個或多個輸出目標(target)中,如文件、數據庫、控制檯等。

NLog的API非常類似於log4net,但配置方式更加簡單,使用路由表(routing table)進行配置,使得配置文件易於閱讀和維護。此外,NLog還支持結構化日誌記錄,可以方便地記錄複雜的數據類型,如對象、集合等。它還提供了可擴展性,允許用戶編寫自定義目標或傳遞自定義值,以滿足特定的日誌記錄需求。

NLog支持多種平臺,包括.NET Framework、.NET Core、Xamarin、ASP.NET等,可以在各種應用程序中使用。同時,NLog還遵從BSD license,允許商業應用且完全開放源代碼,因此得到了廣泛的應用和支持。

NLog 支持結構化日誌 記錄和傳統日誌記錄。

NLog的重點是:高性能、易於使用、易於擴展和靈活配置

官網:https://nlog-project.org/

github:https://github.com/nlog/nlog/

配置文件說明:https://github.com/NLog/NLog/wiki/Configuration-file#

NLog配置文件說明

文件位置

啓動時,NLog 在各種文件中搜索其配置,如下所述。它加載找到的第一個 nlog 配置。當找到第一個 nlog 配置時,搜索結束。如果未找到配置,NLog 將不會執行任何日誌記錄。

對於獨立的 *.exe 應用程序,按如下方式搜索文件:

  • 標準應用程序配置文件 app.config(例如 applicationname.exe.config)
  • 應用程序目錄中的 applicationname.exe.nlog
  • 應用程序目錄中的 NLog.config
  • NLog.dll.nlog 位於 NLog.dll 所在目錄中(僅當 NLog 未安裝在 GAC 中時)

對於 ASP.NET 應用程序,按如下方式搜索文件:

  • 標準 Web 應用程序配置文件 web.config
  • web.nlog 與 web.config 位於同一目錄
  • 應用程序目錄中的 NLog.config
  • NLog.dll.nlog 位於 NLog.dll 所在目錄中(僅當 NLog 未安裝在 GAC 中時)

另請參閱顯式 NLog 配置加載(包括有關assetsXamarin Android 的 -folder 的詳細信息)

元素說明

您可以使用以下元素作爲 的子元素nlogtargetsrules在任何配置中都是必需的 其他是可選的,並且在高級場景中很有用。

  • targets– 定義日誌目標/輸出
  • rules– 定義日誌路由規則
  • extensions– 從 *.dll 文件加載 NLog 擴展
  • include– 包括外部配置文件
  • variable– 設置配置變量的值

Targets:定義日誌目標/輸出

<targets>
    <target name="f"
            xsi:type="File"
            fileName="${basedir}/logs/${shortdate}.log"
            layout="${longdate} ${uppercase:${level}} ${message}" 
            maxArchiveFiles="5"
            archiveAboveSize="10240"
            archiveEvery="Day"/>
</targets>0

Nlog允許用戶配置單個文件大小, 放置在內容過長效率過慢,配置了大小之後, Nlog會自動創建一個新的文件副本,插入新的日誌輸出。

maxArchiveFiles:允許生成的副本文件最大數量

archiveAboveSize:允許單個文件得最大容量

archiveEvery:按天生成

name:輸出目標的名稱,用於rules中路由規則writeTo指定

fileName:包含完整的生成文件的路徑和文件名

xsi:type:輸出類型如下

Chainsaw
ColoredConsole 
Console
Database
Debug
Debugger
EventLog
File
LogReceiverService
Mail
Memory
MethodCall
Network
NLogViewer
Null
OutputDebugString
PerfCounter
Trace
WebService

layout:用來規定輸出內容格式,語法“${屬性}”,可以把上下文信息插入到日誌中。

系統變量參考:https://nlog-project.org/config/?tab=layout-renderers

Rules– 定義日誌路由規則

路由順序會對日誌打印產生影響。路由匹配邏輯爲順序匹配。

日誌可以分不同級別進行輸出,日誌規則rules裏面可以控制輸出的日誌級別。不同級別的日誌代表日誌的重要程度,比如一些debug級別的日誌在生產環境就會被控制不輸出,以減少日誌文件的大小。

<rules>
    <logger name="*" minlevel="Debug" writeTo="file" />
</rules>name:記錄者的名字。
  • ame– 匹配記錄器對象的記錄器名稱 - 可能包含通配符(* 和 ?)
  • minlevel– 記錄的最低級別(與指定級別和上面的級別匹配)
  • maxlevel– 記錄的最大級別(與指定級別和下面的級別匹配)
  • level– 單級記錄
  • levels- 以逗號分隔的要記錄的級別列表
  • writeTo– 以逗號分隔的要寫入的目標列表
  • final– 最終規則匹配後不處理任何規則
  • enabled- 設置爲false禁用規則而不刪除它
  • ruleName- 允許使用 Configuration.FindRuleByName和進行規則查找的規則標識符Configuration.RemoveRuleByName。NLog 4.6.4 中引入
  • FinalMinLevel - 記錄器匹配將被限制爲以下規則的指定最低級別。NLog 5.0中引入

日誌級別有如下,自上而下,等級遞增。

  • Trace - 最常見的記錄信息,一般用於普通輸出
  • Debug - 同樣是記錄信息,不過出現的頻率要比Trace少一些,一般用來調試程序
  • Info - 信息類型的消息
  • Warn - 警告信息,一般用於比較重要的場合
  • Error - 錯誤信息
  • Fatal - 致命異常信息。一般來講,發生致命異常之後程序將無法繼續執行。

日誌過濾器:可以在路由當中, 爲每個路由配置自定義得日誌過濾器fliter,如下所示

<rules>
    <logger name="*" writeTo="file">
        <filters>
            <when condition="length('${message}') > 100" action="Ignore" />
            <when condition="equals('${logger}','MyApps.SomeClass')" action="Ignore" />
            <when condition="(level >= LogLevel.Debug and contains('${message}','PleaseDontLogThis'))" action="Ignore" />
            <when condition="not starts-with('${message}','PleaseLogThis')" action="Ignore" />
        </filters>
    </logger>
</rules>

Asp .Net Core 集成 NLog

參考:https://github.com/NLog/NLog/wiki/Getting-started-with-ASP.NET-Core-6

  1. 安裝 NLog.Web.AspNetCore 包

    在您的項目中,通過 NuGet 包管理器安裝 NLog.Web.AspNetCore 包。在 Visual Studio 中,您可以右鍵點擊項目 -> 選擇 "Manage NuGet Packages" -> 搜索 NLog.Web.AspNetCore -> 點擊 "Install"。

    或者通過命令行安裝:

    dotnet add package NLog.Web.AspNetCore
    
  2. 配置 NLog

    創建一個 nlog.config 文件在項目的根目錄下,並添加您的 NLog 配置。例如:

<?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="Info" internalLogFile="internal-nlog.txt">  

    <!-- 定義日誌輸出目標 -->  
    <targets>  
      <target xsi:type="File" name="file" fileName="${basedir}/logs/nlog.txt"  
              layout="${longdate} ${level:uppercase=true} ${message} ${exception}" />  
    </targets>  

    <!-- 定義日誌規則 -->  
    <rules>  
      <logger name="*" minlevel="Debug" writeTo="file" />  
    </rules>  
</nlog>
  1. 在 Program.cs 中配置 NLog

    // 添加 NLog  
    builder.Logging.ClearProviders();  
    //builder.Logging.SetMinimumLevel(LogLevel.Debug);  
    //NLogBuilder.ConfigureNLog("nlog.config");  
    builder.Host.UseNLog(); 
    
  2. 使用 NLog

    現在您可以在控制器、服務等中注入 ILogger 並使用它記錄日誌。NLog 將處理這些日誌並記錄到配置的目標中。

    using Microsoft.AspNetCore.Mvc;
    
    namespace NLogTest.Controllers
    {
        [ApiController]
        [Route("[controller]")]
        public class WeatherForecastController : ControllerBase
        {
            private readonly ILogger<WeatherForecastController> _logger;
    
            public WeatherForecastController(ILogger<WeatherForecastController> logger)
            {
                _logger = logger;
            }
    
            [HttpGet(Name = "GetWeatherForecast")]
            public IEnumerable<WeatherForecast> Get()
            {
                try
                {           
                    int a = 1 / int.Parse("0");
                    return null;
                }
                catch (Exception ex)
                {
                    _logger.LogDebug(ex, ex.Message);
                    _logger.LogTrace(ex, ex.Message);
                    _logger.LogInformation(ex, ex.Message);
                    _logger.LogWarning(ex, ex.Message);
                    _logger.LogError(ex, ex.Message);
                    return Enumerable.Empty<WeatherForecast>();
                }
            }
        }
    }
    
    

NLog 自定義全局變量

            app.Use(async (context, next) =>
            {
                GlobalDiagnosticsContext.Set("TenantId", 1);
                GlobalDiagnosticsContext.Set("CreateUserId", 111);
                await next();
            });

// 使用
${gdc:TenantId}

將日誌消息寫入MySQL數據庫

https://github.com/NLog/NLog/wiki/Database-target

安裝Nuget包

dotnet add package NLog.Database
dotnet add package MySql.Data

數據庫準備(MySQL)

create database mcode_log;
use mcode_log;
create table if not exists erp_log
(
    Id              bigint auto_increment comment '主鍵'
        primary key,
    TenantId        bigint       null comment '租戶Id',
    ApplicationName varchar(100) null comment '程序名稱',
    HostName        varchar(100) null comment '主機',
    Ip              varchar(100) null comment 'Ip地址',
    Message         text         null comment '信息',
    Level           varchar(50)  null comment '級別',
    ExceptionInfo   text         null comment '異常信息',
    CallInfo        text         null comment '調用信息',
    RequestMethod   varchar(20)  null comment '請求方法',
    RequestUrl      varchar(512) null comment '請求地址',
    RequestBody     text         null comment '請求主體',
    CreateTime      datetime     null comment '創建時間',
    CreateUserId    bigint       null comment '創建用戶',
    CreateUserName  varchar(50)  null comment '創建用戶名稱'
);

配置NLog

<?xml version="1.0" encoding="utf-8"?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      autoReload="true"
      throwExceptions="false" 
      throwConfigExceptions="true"
      internalLogLevel="warn"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
	<!--生產環境 throwExceptions 建議爲false -->
	<extensions>
		<add assembly="NLog.Web.AspNetCore"/>
		<add assembly="NLog.Database"/>
	</extensions>
	<!--internalLogFile="logfiles"-->
	<targets async="true">
		<!--屏幕打印消息-->
		<target name="console" xsi:type="ColoredConsole"
						layout="${newline}=======================================================================
                            ${newline} 【當前時間】: [${date:format=yyyy-MM-dd HH\:mm\:ss}]                           
                            ${newline} 【 級 別 】:[${level}]                            
                            ${newline} 【 調 用 】:[${callsite}] [${callsite-linenumber}] [${callsite-filename}] [${stacktrace}]                                                            
                            ${newline} 【 消 息 】:[${message}]   
                            ${newline} 【 異 常 】:[${exception:format=ToString}] [${threadname}] [${threadid}]
                            " />

		<!--VS輸出窗口-->
		<target name="debugger" xsi:type="Debugger"
						 layout="${newline}=======================================================================
                            ${newline} 【當前時間】: [${date:format=yyyy-MM-dd HH\:mm\:ss}]                           
                            ${newline} 【 級 別 】:[${level}]                            
                            ${newline} 【 調 用 】:[${callsite}] [${callsite-linenumber}] [${callsite-filename}] [${stacktrace}]                                                            
                            ${newline} 【 消 息 】:[${message}]   
                            ${newline} 【 異 常 】:[${exception:format=ToString}] [${threadname}] [${threadid}]
                            " />

		<!--保存至文件-->
		<target name="info" xsi:type="File" maxArchiveFiles="30"
						fileName="${basedir}/Logs/Info/${shortdate}.txt"
						 layout="${newline}=======================================================================
                             ${newline} 【當前時間】: [${date:format=yyyy-MM-dd HH\:mm\:ss}]                           
                            ${newline} 【 級 別 】:[${level}]                            
                            ${newline} 【 調 用 】:[${callsite}] [${callsite-linenumber}] [${callsite-filename}] [${stacktrace}]                                                            
                            ${newline} 【 消 息 】:[${message}]   
                            ${newline} 【 異 常 】:[${exception:format=ToString}] [${threadname}] [${threadid}]
                            " />

		<!--保存至文件-->
		<target name="error" xsi:type="File" maxArchiveFiles="30"
						fileName="${basedir}/Logs/Error/${shortdate}.txt"
						layout="${newline}=======================================================================
                            ${newline} 【當前時間】: [${date:format=yyyy-MM-dd HH\:mm\:ss}]                           
                            ${newline} 【 級 別 】:[${level}]                            
                            ${newline} 【 調 用 】:[${callsite}] [${callsite-linenumber}] [${callsite-filename}] [${stacktrace}]                                                            
                            ${newline} 【 消 息 】:[${message}]   
                            ${newline} 【 異 常 】:[${exception:format=ToString}] [${threadname}] [${threadid}]
                            " />
		<!--寫入數據庫-->
		<target xsi:type="Null" name="blackhole"/>
		<target name="database" xsi:type="Database"
			   dbProvider="MySql.Data.MySqlClient.MySqlConnection, MySql.Data"
			  connectionString="server=110.41.14.13;Database=mcode_log;user id=root;password=123456;SslMode=none">
		<!--<target name="database" xsi:type="Database"
			  dbProvider="MySqlConnector.MySqlConnection, MySqlConnector"
			  connectionString="server=127.0.0.1;Database=mcode_log;user id=root;password=123456;SslMode=none">-->
			<commandText>
				insert into erp_log (TenantId, ApplicationName, HostName, Ip, Message, Level, ExceptionInfo, CallInfo,
				RequestMethod, RequestUrl, RequestBody, CreateTime, CreateUserId, CreateUserName)
				values (@TenantId,@ApplicationName,@HostName,@Ip,@Message,@Level,@ExceptionInfo,@CallInfo,@RequestMethod,@RequestUrl,@RequestBody,@CreateTime,@CreateUserId,@CreateUserName);
			</commandText>
			<!--注意:對於非字符串,要指定dbType"-->
			<parameter name="@TenantId" layout="${gdc:TenantId}"  dbType="DbType.Int64" />
			<parameter name="@ApplicationName" layout="${gdc:ApplicationName}"   />
			<parameter name="@HostName" layout="${hostname}" />
			<parameter name="@Ip" layout="${gdc:Ip}" />
			<parameter name="@Message" layout="${message}" />
			<parameter name="@Level" layout="${level}" />
			<parameter name="@ExceptionInfo" layout="[${exception:format=ToString}] [${threadname}] [${threadid}]" />
			<parameter name="@CallInfo" layout="[${callsite}] [${callsite-linenumber}] [${callsite-filename}] [${stacktrace}]" />
			<parameter name="@RequestMethod" layout="${gdc:RequestMethod}" />
			<parameter name="@RequestUrl" layout="${gdc:RequestUrl}" />
			<parameter name="@RequestBody" layout="${gdc:RequestBody}" />
			<parameter name="@CreateTime" layout="${date}"  dbType="DbType.DateTime" />
			<parameter name="@CreateUserId" layout="${gdc:CreateUserId}" dbType="DbType.Int64" />
			<parameter name="@CreateUserName" layout="${gdc:CreateUserName}" />
		</target>
	</targets>

	<!--規則-->
	<rules>
		<logger name="*" minlevel="Warn" writeTo="console" />
		<logger name="NLogTest.*" minlevel="Debug"  writeTo="debugger" />
		<logger name="NLogTest.*" minlevel="Info" maxlevel="Info"  writeTo="info" />
		<logger name="*" minlevel="Warn" writeTo="error" />
		<logger name="NLogTest.*" minlevel="Warn" writeTo="database" />
	</rules>
</nlog>

image

image

其它數據庫

MySql and .NET Core

Install package: https://www.nuget.org/packages/MySql.Data/

dbProvider="MySql.Data.MySqlClient.MySqlConnection, MySql.Data"

or if using packages: https://www.nuget.org/packages/MySqlConnector/ and https://www.nuget.org/packages/MySqlConnector.Logging.NLog/

dbProvider="MySqlConnector.MySqlConnection, MySqlConnector"

System.Data.SQLite and .NET Core

Install package: https://www.nuget.org/packages/System.Data.SQLite

dbProvider="System.Data.SQLite.SQLiteConnection, System.Data.SQLite"

Microsoft.Data.SqlClient and .NET Core

Install package: https://www.nuget.org/packages/Microsoft.Data.SqlClient/

dbProvider="Microsoft.Data.SqlClient.SqlConnection, Microsoft.Data.SqlClient"

Microsoft.Data.Sqlite and .NET Core

Install package: https://www.nuget.org/packages/Microsoft.Data.SQLite/

dbProvider="Microsoft.Data.Sqlite.SqliteConnection, Microsoft.Data.Sqlite"

Npgsql and .NET core

Install package: https://www.nuget.org/packages/Npgsql/

dbProvider="Npgsql.NpgsqlConnection, Npgsql"

Oracle.ManagedDataAccess and .NET

dbProvider="Oracle.ManagedDataAccess.Client.OracleConnection, Oracle.ManagedDataAccess"

Mono.Data.Sqlite and .NET

dbProvider="Mono.Data.Sqlite.SqliteConnection, Mono.Data.Sqlite"

記錄故障排除

有時我們的應用程序不會向日志文件寫入任何內容,即使我們應該正確配置了日誌記錄。日誌未寫入的原因可能有很多。最常見的問題是權限問題,通常在 ASP.NET 進程中,其中aspnet_wp.exew3wp.exe進程可能沒有對我們要存儲日誌的目錄的寫訪問權限。

NLog 旨在吞掉日誌記錄可能導致的運行時異常。以下設置可以更改此行爲和/或重定向這些消息。

  • <nlog throwExceptions="true" />-throwExceptions在配置文件中添加該屬性會導致 NLog 停止屏蔽異常並將其傳遞給調用應用程序。該屬性在部署時非常有用,可以快速定位任何問題。至關重要的是,一旦應用程序正確配置throwExceptions"false"運行,就應立即進行配置,這樣意外的日誌記錄問題就不會導致應用程序掛起或崩潰。
  • <nlog throwConfigExceptions="true" /> - 類似於throwExceptions但僅與配置異常隔離。與此不同的是throwExceptions,啓用它並不危險,建議在生產環境中啓用,因爲在生產環境中,日誌記錄配置的初始設置成功至關重要。NLog 4.3 中引入。默認null(表示未配置,而是使用 的值throwExceptions
  • <nlog internalLogLevel="Trace|Debug|Info|Warn|Error|Fatal" />– 確定內部日誌級別。級別越高,內部日誌輸出越不詳細。當需要診斷日誌記錄問題時,輸出通常非常有幫助。有關設置輸出到文件或控制檯的選項,請參閱內部日誌記錄。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章