目錄
一、引入 NuGet 包
二、配置log4net.config??
三、編寫Log4net封裝類
四、編寫日志記錄類
五、AOP -- 攔截器 -- 封裝
六、案例編寫
七、結(jié)果展示
一、引入 NuGet 包
log4net?
Microsoft.Extensions.Logging.Log4Net.AspNetCore? ?
MySql.Data? ? ? ? ?----? MySQL數(shù)據(jù)庫需要
Newtonsoft.Json
Autofac
Autofac.Extensions.DependencyInjection
Autofac.Extras.DynamicProxy
二、配置log4net.config??
? ? 注:當前網(wǎng)上有兩種 log4net.config 配置文件, 一種是以<log4net>為根目錄, 另一種以<configuration> 為根目錄
<?xml version="1.0" encoding="utf-8"?>
<log4net>
<!--正常日志:::記錄正常日志-->
<!-- appender 定義日志輸出方式 將日志以回滾文件的形式寫到MySQL數(shù)據(jù)庫中。-->
<appender name="ADONetAppender" type="log4net.Appender.ADONetAppender">
<!-- 代表緩存大小,在沒達到緩存大小時,暫時不會存到數(shù)據(jù)庫中, -->
<!-- 當程序關(guān)閉之后,會將未插入的信息加入到數(shù)據(jù)庫中 -->
<bufferSize value="1" />
<!--引入《MySql.Data》包-->
<param name="ConnectionType" value="MySql.Data.MySqlClient.MySqlConnection, MySql.Data" />
<!--配置連接數(shù)據(jù)庫的字符串-->
<param name="ConnectionString" value="server=localhost;database=TTTTT;uid=root;pwd=123456;"/>
<!--配置MySQL的插入語句-->
<param name="CommandText" value="insert into log4net(log_datetime,log_thread,log_level,log_logger,log_message)
values(@log_datetime, @log_thread , @log_level, @log_logger, @log_message)" />
<param name="Parameter">
<param name="ParameterName" value="@log_datetime" />
<param name="DbType" value="DateTime" />
<param name="Layout" type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%d{yyyy'-'MM'-'dd HH':'mm':'ss}" />
</param>
</param>
<param name="Parameter">
<param name="ParameterName" value="@log_thread" />
<param name="DbType" value="String" />
<param name="Size" value="255" />
<param name="Layout" type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%t" />
</param>
</param>
<param name="Parameter">
<param name="ParameterName" value="@log_level" />
<param name="DbType" value="String" />
<param name="Size" value="255" />
<param name="Layout" type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%p" />
</param>
</param>
<param name="Parameter">
<param name="ParameterName" value="@log_logger" />
<param name="DbType" value="String" />
<param name="Size" value="255" />
<param name="Layout" type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%c" />
</param>
</param>
<param name="Parameter">
<param name="ParameterName" value="@log_message" />
<param name="DbType" value="String" />
<param name="Size" value="4000" />
<param name="Layout" type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%m" />
</param>
</param>
</appender>
<!--正常日志:::記錄正常日志-->
<!--按日期分割日志文件 一天一個-->
<!-- appender 定義日志輸出方式 將日志以回滾文件的形式寫到文件中。-->
<appender name="RollingFile" type="log4net.Appender.RollingFileAppender">
<!-- 定義中文編碼類型 UTF-8-->
<param name="Encoding" value="utf-8" />
<!--定義文件存放位置-->
<file value="Log\log_"/>
<!--是否追加到文件-->
<appendToFile value="true"/>
<!--記錄日志寫入文件時,不鎖定文本文件,防止多線程時不能寫Log,官方說線程非安全-->
<lockingModel type="log4net.Appender.FileAppender+MinimalLock"/>
<!--最多產(chǎn)生的日志文件數(shù),超過則只保留最新的n個。設(shè)定值value="-1"為不限文件數(shù)-->
<maxSizeRollBackups value="-1"/>
<!--按照何種方式產(chǎn)生多個日志文件(日期[Date],文件大小[Size],混合[Composite])-->
<rollingStyle value="Composite"/>
<datePattern value="yyyy\\yyyyMM\\yyyyMMdd'.txt'"/>
<!--是否只寫到一個文件中-->
<staticLogFileName value="false"/>
<!--每個文件的大小。只在混合方式與文件大小方式下使用。
超出大小后在所有文件名后自動增加正整數(shù)重新命名,數(shù)字最大的最早寫入。
可用的單位:KB|MB|GB。不要使用小數(shù),否則會一直寫入當前日志-->
<maximumFileSize value="100MB"/>
<!--計數(shù)類型為1,2,3…-->
<!--<param name="CountDirection" value="1"/>-->
<layout type="log4net.Layout.PatternLayout">
<!--輸出格式-樣例:
記錄時間:2022-08-24 17:59:31,172 線程ID:[4] 日志級別:INFO 當前類:Log4NetDemo.MainClass
日志描述:創(chuàng)建連接。-->
<conversionPattern value="記錄時間:%date 線程ID:[%thread] 日志級別:%-5level 當前類:%logger %newline日志描述:%message %newline %newline"/>
</layout>
</appender>
<!--錯誤日志:::記錄錯誤日志-->
<!--按日期分割日志文件 一天一個-->
<!-- appender 定義日志輸出方式 將日志以回滾文件的形式寫到文件中。-->
<appender name="ErrorAppender" type="log4net.Appender.RollingFileAppender">
<!-- 定義中文編碼類型 UTF-8-->
<param name="Encoding" value="utf-8" />
<!--定義文件存放位置-->
<file value="Log\error_"/>
<!--是否追加到文件-->
<appendToFile value="true"/>
<!--記錄日志寫入文件時,不鎖定文本文件,防止多線程時不能寫Log,官方說線程非安全-->
<lockingModel type="log4net.Appender.FileAppender+MinimalLock"/>
<!--最多產(chǎn)生的日志文件數(shù),超過則只保留最新的n個。設(shè)定值value="-1"為不限文件數(shù)-->
<maxSizeRollBackups value="-1"/>
<!--按照何種方式產(chǎn)生多個日志文件(日期[Date],文件大小[Size],混合[Composite])-->
<rollingStyle value="Composite"/>
<datePattern value="yyyy\\yyyyMM\\yyyyMMdd'.txt'"/>
<!--是否只寫到一個文件中-->
<staticLogFileName value="false"/>
<!--每個文件的大小。只在混合方式與文件大小方式下使用。
超出大小后在所有文件名后自動增加正整數(shù)重新命名,數(shù)字最大的最早寫入。
可用的單位:KB|MB|GB。不要使用小數(shù),否則會一直寫入當前日志-->
<maximumFileSize value="100MB"/>
<!-- layout 控制Appender的輸出格式,也可以是xml 一個Appender只能是一個layout-->
<layout type="log4net.Layout.PatternLayout">
<!--每條日志末尾的文字說明-->
<!--輸出格式 模板-->
<!-- <param name="ConversionPattern" value="記錄時間:%date 線程ID:[%thread] 日志級別:%-5level 記錄類:%logger
操作者ID:%property{Operator} 操作類型:%property{Action}%n 當前機器名:%property%n當前機器名及登錄用戶:%username %n
記錄位置:%location%n 消息描述:%property{Message}%n 異常:%exception%n 消息:%message%newline%n%n" />-->
<!--樣例:2008-03-26 13:42:32,111 [10] INFO Log4NetDemo.MainClass [(null)] - info-->
<!--<conversionPattern value="%newline %n記錄時間:%date %n線程ID:[%thread] %n日志級別: %-5level %n錯誤描述:%message%newline %n"/>-->
<conversionPattern value="%n==========
%n【日志級別】%-5level
%n【記錄時間】%date
%n【執(zhí)行時間】[%r]毫秒
%n【錯誤位置】%logger 屬性[%property{NDC}]
%n【錯誤描述】%message
%n【錯誤詳情】%newline"/>
</layout>
<filter type="log4net.Filter.LevelRangeFilter,log4net">
<levelMin value="ERROR" />
<levelMax value="FATAL" />
</filter>
</appender>
<!--DEBUG:::記錄DEBUG日志-->
<!--按日期分割日志文件 一天一個-->
<!-- appender 定義日志輸出方式 將日志以回滾文件的形式寫到文件中。-->
<appender name="DebugAppender" type="log4net.Appender.RollingFileAppender">
<!-- 定義中文編碼類型 UTF-8-->
<param name="Encoding" value="utf-8" />
<!--定義文件存放位置-->
<file value="Log\debug_"/>
<!--是否追加到文件-->
<appendToFile value="true"/>
<!--記錄日志寫入文件時,不鎖定文本文件,防止多線程時不能寫Log,官方說線程非安全-->
<lockingModel type="log4net.Appender.FileAppender+MinimalLock"/>
<!--最多產(chǎn)生的日志文件數(shù),超過則只保留最新的n個。設(shè)定值value="-1"為不限文件數(shù)-->
<maxSizeRollBackups value="-1"/>
<!--按照何種方式產(chǎn)生多個日志文件(日期[Date],文件大小[Size],混合[Composite])-->
<rollingStyle value="Composite"/>
<datePattern value="yyyy\\yyyyMM\\yyyyMMdd'.txt'"/>
<!--是否只寫到一個文件中-->
<staticLogFileName value="false"/>
<!--每個文件的大小。只在混合方式與文件大小方式下使用。
超出大小后在所有文件名后自動增加正整數(shù)重新命名,數(shù)字最大的最早寫入。
可用的單位:KB|MB|GB。不要使用小數(shù),否則會一直寫入當前日志-->
<maximumFileSize value="100MB"/>
<!-- layout 控制Appender的輸出格式,也可以是xml 一個Appender只能是一個layout-->
<layout type="log4net.Layout.PatternLayout">
<!--輸出格式-樣例:
記錄時間:2022-08-24 17:59:31,172 線程ID:[4] 日志級別:INFO 當前類:Log4NetDemo.MainClass
日志描述:創(chuàng)建連接。-->
<conversionPattern value="記錄時間:%date 線程ID:[%thread] 日志級別:%-5level 當前類:%logger %newline日志描述:%message %newline %newline"/>
</layout>
<filter type="log4net.Filter.LevelRangeFilter,log4net">
<levelMin value="DEBUG" />
<levelMax value="WARN" />
</filter>
</appender>
<root>
<!--日志等級:OFF > FATAL > ERROR > WARN > INFO > DEBUG > ALL-->
<level value="ALL" />
<appender-ref ref="ADONetAppender" />
<appender-ref ref="RollingFile" />
<appender-ref ref="ErrorAppender" />
<appender-ref ref="DebugAppender" />
</root>
</log4net>
三、編寫Log4net封裝類
public static class CustomLog4netExt
{
public static void AddLog4netExt(this WebApplicationBuilder builder)
{
// 添加 Log4net 配置文件
builder.Logging.AddLog4Net("log4net.config");
// log錯誤日志配置
builder.Services.AddControllers(options =>
{
options.SuppressAsyncSuffixInActionNames = false;
options.Filters.Add(typeof(GlobalExceptionsFilter));
});
}
}
四、編寫日志記錄類
全局報錯監(jiān)測類
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
namespace Log4Test.Log4;
/// <summary>
/// 全局異常錯誤日志
/// </summary>
public class GlobalExceptionsFilter : IExceptionFilter
{
private readonly IWebHostEnvironment _env;
private readonly ILogger<GlobalExceptionsFilter> _logger;
public GlobalExceptionsFilter(IWebHostEnvironment env, ILogger<GlobalExceptionsFilter> logger)
{
_env = env;
_logger = logger;
}
public void OnException(ExceptionContext context)
{
var json = new JsonErrorResponse();
json.Message = context.Exception.Message;//錯誤信息
if (_env.IsDevelopment())
{
json.DevelopmentMessage = context.Exception.StackTrace;//堆棧信息
}
context.Result = new InternalServerErrorObjectResult(json);
//采用log4net 進行錯誤日志記錄
_logger.LogError(WriteLog(json.Message, context.Exception));
}
/// <summary>
/// 自定義返回格式
/// </summary>
/// <param name="throwMsg"></param>
/// <param name="ex"></param>
/// <returns></returns>
public string WriteLog(string throwMsg, Exception ex)
{
return string.Format("【自定義錯誤】:{0} \r\n" +
"【異常類型】:{1} \r\n" +
"【異常信息】:{2} \r\n" +
"【堆棧調(diào)用】:{3}",
new object[] {
throwMsg,
ex.GetType().Name,
ex.Message,
ex.StackTrace
});
}
}
public class InternalServerErrorObjectResult : ObjectResult
{
public InternalServerErrorObjectResult(object value) : base(value)
{
StatusCode = StatusCodes.Status500InternalServerError;
}
}
//返回錯誤信息
public class JsonErrorResponse
{
/// <summary>
/// 生產(chǎn)環(huán)境的消息
/// </summary>
public string Message { get; set; }
/// <summary>
/// 開發(fā)環(huán)境的消息
/// </summary>
public string DevelopmentMessage { get; set; }
}
日常方法監(jiān)測類
using Castle.DynamicProxy;
using Newtonsoft.Json;
namespace LOG.Test;
/// <summary>
/// 自定義 方法攔截器
/// </summary>
public class CustomInterceptor : IInterceptor
{
private readonly ILogger<CustomInterceptor> _logger;
public CustomInterceptor(ILogger<CustomInterceptor> logger)
{
_logger = logger;
}
public void Intercept(IInvocation invocation)
{
string result = $"開始執(zhí)行-->\n方法名: {invocation.Method.Name}\n";
foreach (var item in invocation.Arguments)
{
result += $"入?yún)?--{JsonConvert.SerializeObject(item)}\n";
}
_logger.LogInformation(result);
invocation.Proceed();
_logger.LogInformation($"結(jié)束執(zhí)行-->\n方法名: {invocation.Method.Name}\n" +
$"返回結(jié)果---{JsonConvert.SerializeObject(invocation.ReturnValue)}\n");
}
}
五、AOP -- 攔截器 -- 封裝
using Autofac;
using Autofac.Extensions.DependencyInjection;
using Autofac.Extras.DynamicProxy;
namespace LOG.Test;
public static class CustomAOPExt
{
public static void AddAOPExt(this WebApplicationBuilder builder)
{
builder.Host
.UseServiceProviderFactory(new AutofacServiceProviderFactory()) // 工廠替換,把Autofac整合進來
.ConfigureContainer<ContainerBuilder>(containerBuilder =>
{
// 依賴注入
containerBuilder.RegisterType<CustomInterceptor>();
containerBuilder.RegisterType<Student>().As<IStudent>().EnableClassInterceptors(); // 開啟類攔截器
//containerBuilder.RegisterType<Student>().As<IStudent>().EnableInterfaceInterceptors(); // 開啟接口攔截器
});
}
}
六、案例編寫
// 在Program.cs 中
// 添加 lg4net 擴展
builder.AddLog4netExt();
// 添加 AOP 擴展
builder.AddAOPExt();
創(chuàng)建 Student 和 IStudent? 測試類和接口
?創(chuàng)建 一個 控制器
七、結(jié)果展示
文章來源:http://www.zghlxwxcb.cn/news/detail-625226.html
?文章來源地址http://www.zghlxwxcb.cn/news/detail-625226.html
如有錯誤,煩請批評指正
到了這里,關(guān)于.Net6 Web Core API --- AOP -- log4net 封裝 -- MySQL -- txt的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!