巧用ActionFilterAttribute實現(xiàn)API日志的記錄
作者:conan5566
使用Func 委托實現(xiàn)API日志的記錄,這次我們使用另外一種方式,F(xiàn)ilter來記錄輸入輸出日志。
本文轉載自微信公眾號「UP技術控」,作者conan5566。轉載本文請聯(lián)系UP技術控公眾號。
背景
上回提到開發(fā)web api的時候,一般是需要記錄api的輸入輸出信息,方便后續(xù)排查問題;使用的是委托的形式進行記錄日志。
使用Func
這次我們使用另外一種方式,F(xiàn)ilter來記錄輸入輸出日志。
實現(xiàn)方式
1、首先在進入action的時候,定義OnActionExecuting。
- public override void OnActionExecuting(ActionExecutingContext context)
- {
- base.OnActionExecuting(context);
- // 后續(xù)添加了獲取請求的請求體,如果在實際項目中不需要刪除即可
- long contentLen = context.HttpContext.Request.ContentLength == null ? 0 : context.HttpContext.Request.ContentLength.Value;
- if (contentLen > 0)
- {
- // 讀取請求體中所有內(nèi)容
- System.IO.Stream stream = context.HttpContext.Request.Body;
- if (context.HttpContext.Request.Method == "POST")
- {
- stream.Position = 0;
- }
- byte[] buffer = new byte[contentLen];
- stream.Read(buffer, 0, buffer.Length);
- // 轉化為字符串
- RequestBody = System.Text.Encoding.UTF8.GetString(buffer);
- }
- ActionArguments = Newtonsoft.Json.JsonConvert.SerializeObject(context.ActionArguments);
- Stopwatch = new Stopwatch();
- Stopwatch.Start();
- }
2、定義Stopwatch ,計算方法的耗時。
- private string ActionArguments { get; set; }
- /// <summary>
- /// 請求體中的所有值
- /// </summary>
- private string RequestBody { get; set; }
- private Stopwatch Stopwatch { get; set; }
3、結束的時候,把信息打印出來OnActionExecuted。
- public override void OnActionExecuted(ActionExecutedContext context)
- {
- base.OnActionExecuted(context);
- Stopwatch.Stop();
- string url = context.HttpContext.Request.Host + context.HttpContext.Request.Path + context.HttpContext.Request.QueryString;
- string method = context.HttpContext.Request.Method;
- string controller = context.Controller.ToString();
- string action = context.ActionDescriptor.DisplayName;
- string token = "";
- if (context.HttpContext.Request != null && context.HttpContext.Request.Headers != null && context.HttpContext.Request.Headers["Authorization"].Count > 0)
- {
- token = context.HttpContext.Request.Headers["Authorization"];
- }
- string qs = ActionArguments;
- dynamic result = context?.Result?.GetType()?.Name == "EmptyResult" ? new { Value = "無返回結果" } : context?.Result as dynamic;
- string res = "在返回結果前發(fā)生了異常";
- try
- {
- if (result != null)
- {
- res = Newtonsoft.Json.JsonConvert.SerializeObject(result.Value);
- }
- }
- catch (System.Exception)
- {
- res = "日志未獲取到結果,返回的數(shù)據(jù)無法序列化";
- }
- NLogger.Info(
- $"地址:{url} \n " +
- $"controller:{controller} \n " +
- $"action:{action} \n " +
- $"token:{token} \n " +
- $"方式:{method} \n " +
- $"請求體:{RequestBody} \n " +
- $"參數(shù):{qs}\n " +
- $"結果:{res}\n " +
- $"耗時:{Stopwatch.Elapsed.TotalMilliseconds} 毫秒(指控制器內(nèi)對應方法執(zhí)行完畢的時間)");
- }
4、控制器調(diào)用LogAttribute。
- /// <summary>
- ///
- /// </summary>
- [Produces("application/json")]
- [LogAttribute]
- [CustomExceptionFilterAttribute]
- public class DefaultController : Controller
- {
- }
完整代碼
- using CompanyName.ProjectName.Core;
- using Microsoft.AspNetCore.Mvc.Filters;
- using System.Diagnostics;
- namespace CompanyName.ProjectName.HttpApi.Host.Code
- {
- /// <summary>
- /// 攔截器
- /// </summary>
- public class LogAttribute : ActionFilterAttribute
- {
- private string ActionArguments { get; set; }
- /// <summary>
- /// 請求體中的所有值
- /// </summary>
- private string RequestBody { get; set; }
- private Stopwatch Stopwatch { get; set; }
- /// <summary>
- ///
- /// </summary>
- /// <param name="context"></param>
- public override void OnActionExecuting(ActionExecutingContext context)
- {
- base.OnActionExecuting(context);
- // 后續(xù)添加了獲取請求的請求體,如果在實際項目中不需要刪除即可
- long contentLen = context.HttpContext.Request.ContentLength == null ? 0 : context.HttpContext.Request.ContentLength.Value;
- if (contentLen > 0)
- {
- // 讀取請求體中所有內(nèi)容
- System.IO.Stream stream = context.HttpContext.Request.Body;
- if (context.HttpContext.Request.Method == "POST")
- {
- stream.Position = 0;
- }
- byte[] buffer = new byte[contentLen];
- stream.Read(buffer, 0, buffer.Length);
- // 轉化為字符串
- RequestBody = System.Text.Encoding.UTF8.GetString(buffer);
- }
- ActionArguments = Newtonsoft.Json.JsonConvert.SerializeObject(context.ActionArguments);
- Stopwatch = new Stopwatch();
- Stopwatch.Start();
- }
- /// <summary>
- ///
- /// </summary>
- /// <param name="context"></param>
- public override void OnActionExecuted(ActionExecutedContext context)
- {
- base.OnActionExecuted(context);
- Stopwatch.Stop();
- string url = context.HttpContext.Request.Host + context.HttpContext.Request.Path + context.HttpContext.Request.QueryString;
- string method = context.HttpContext.Request.Method;
- string controller = context.Controller.ToString();
- string action = context.ActionDescriptor.DisplayName;
- string token = "";
- if (context.HttpContext.Request != null && context.HttpContext.Request.Headers != null && context.HttpContext.Request.Headers["Authorization"].Count > 0)
- {
- token = context.HttpContext.Request.Headers["Authorization"];
- }
- string qs = ActionArguments;
- dynamic result = context?.Result?.GetType()?.Name == "EmptyResult" ? new { Value = "無返回結果" } : context?.Result as dynamic;
- string res = "在返回結果前發(fā)生了異常";
- try
- {
- if (result != null)
- {
- res = Newtonsoft.Json.JsonConvert.SerializeObject(result.Value);
- }
- }
- catch (System.Exception)
- {
- res = "日志未獲取到結果,返回的數(shù)據(jù)無法序列化";
- }
- NLogger.Info(
- $"地址:{url} \n " +
- $"controller:{controller} \n " +
- $"action:{action} \n " +
- $"token:{token} \n " +
- $"方式:{method} \n " +
- $"請求體:{RequestBody} \n " +
- $"參數(shù):{qs}\n " +
- $"結果:{res}\n " +
- $"耗時:{Stopwatch.Elapsed.TotalMilliseconds} 毫秒(指控制器內(nèi)對應方法執(zhí)行完畢的時間)");
- }
- }
- }
責任編輯:武曉燕
來源:
UP技術控