項目一旦出現異常,記錄錯誤日誌就顯得尤為重要。今天我就分享在ASP.NET CORE中全局捕獲異常並記錄日誌的代碼,下面給出具體實現過程。
1、日誌實現類
/// <summary>
///
///
public class InitRepository
{
/// <summary>
///
///
public static ILoggerRepository LogRepository { get; set; }
}
/// <summary>
///
///
public class LogHelper
{
private static readonly ILog logerror = LogManager.GetLogger(InitRepository.LogRepository.Name, "logerror");
private static readonly ILog loginfo = LogManager.GetLogger(InitRepository.LogRepository.Name, "loginfo");
#region 全局異常錯誤記錄持久化
/// <summary>
/// 全局異常錯誤記錄持久化
///
/// <param>
/// <param>
public static void WriteError(string throwMsg, Exception ex)
{
string errorMsg = string.Format("\\r\\n[名稱]:{0}\\r\\n[方法]:{4}\\r\\n[類型]:{1}\\r\\n[信息]:{2}\\r\\n[堆棧]:{3}", new object[] { throwMsg,
ex.GetType().Name, ex.Message, ex.StackTrace.Trim(),ex.StackTrace.Split(" in ")[0].Replace("at","").Trim() });
errorMsg += "\\r\\n";
logerror.Error(errorMsg);
}
#endregion
#region 自定義操作記錄
/// <summary>
///
///
/// <param>
/// <param>
/// <param>
public static void WriteInfo(string name, string message, string method = "")
{
string errorMsg = string.Format("\\r\\n[名稱]:{0}", new object[] { name });
if (!string.IsNullOrWhiteSpace(message))
{
errorMsg += $"\\r\\n[方法]:{method} ";
}
errorMsg += $"\\r\\n[信息]:{message}";
errorMsg += "\\r\\n";
loginfo.Info(errorMsg);
}
public static void WriteInfo(string throwMsg, Exception ex)
{
string errorMsg = string.Format("\\r\\n[名稱]:{0}\\r\\n[方法]:{4}\\r\\n[類型]:{1}\\r\\n[信息]:{2}\\r\\n[堆棧]:{3}", new object[] { throwMsg,
ex.GetType().Name, ex.Message, ex.StackTrace.Trim(),ex.StackTrace.Split(" in ")[0].Replace("at","").Trim() });
errorMsg += "\\r\\n";
loginfo.Info(errorMsg);
}
#endregion
}
2、全局異常捕獲類
public class GlobalExceptions : IExceptionFilter
{
private readonly IHostEnvironment _env;
public GlobalExceptions(IHostEnvironment env)
{
_env = env;
}
public void OnException(ExceptionContext context)
{
var json = new JsonErrorResponse(); //這裡面是自定義的操作記錄日誌
json.Message = "內部服務器錯誤";
if (_env.IsDevelopment())
{
json.DevelopmentMessage = context.Exception.StackTrace;//堆棧信息
}
context.Result = new InternalServerErrorObjectResult(json);
//採用log4net 進行錯誤日誌記錄
LogHelper.WriteError(json.Message, context.Exception);
}
}
public class InternalServerErrorObjectResult : ObjectResult
{
public InternalServerErrorObjectResult(object value) : base(value)
{
StatusCode = StatusCodes.Status500InternalServerError;
}
}
public class JsonErrorResponse
{
/// <summary>
/// 生產環境的消息
///
public string Message { get; set; }
/// <summary>
/// 開發環境的消息
///
public string DevelopmentMessage { get; set; }
}
3、Startup註冊
public Startup(IConfiguration configuration)
{
Configuration = configuration;
repository = LogManager.CreateRepository("NetCoreRepository");
XmlConfigurator.Configure(repository, new FileInfo("log4net.config"));
Utils.InitRepository.LogRepository = repository;
}
4、配置log4net.config文件
<configuration>
<log4net>
<appender>
<layout>
<logger>
<level>
<appender-ref>
<appender>
<param>
<param>
<param>
<param>
<param>
<param>
<param>
<layout>
<conversionpattern>
<logger>
<level>
<appender-ref>
<appender>
<param>
<param>
<param>
<param>
<param>
<param>
<param>
<layout>
<conversionpattern>
<root>
<level>
<appender-ref>
<appender-ref>
<appender-ref>
5、異常測試
/// <summary>
/// 用戶登錄
///
/// <param>賬號
/// <param>密碼
/// <returns>
[HttpPost]
[Route("Login")]
public string Login(string userName , string password)
{
Utils.LogHelper.WriteInfo("用戶登錄", $"賬號:{userName},密碼:{password}", method + "." + System.Reflection.MethodBase.GetCurrentMethod().Name);
int a = 10;
int b = 0;
//測試除0異常
int c = a / b;
return "success";
}
6、錯誤展示
2020-02-16 23:21:04,719 [10] ERROR logerror [(null)] -
[名稱]:內部服務器錯誤
[方法]:Demo.WebAPI.Controllers.UserController.Login(String userName, String password)
[類型]:DivideByZeroException
[信息]:Attempted to divide by zero.
[堆棧]:at Demo.WebAPI.Controllers.UserController.Login(String userName, String password) in F:\\work2020\\Demo\\Demo.WebAPI\\Controllers\\UserController.cs:line 52
at lambda_method(Closure , Object , Object[] )
at Microsoft.Extensions.Internal.ObjectMethodExecutor.Execute(Object target, Object[] parameters)
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.SyncObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync()
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync()
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<invokenextexceptionfilterasync>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)/<invokenextexceptionfilterasync>