博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
巧用ActionFilterAttribute实现API日志的记录
阅读量:4035 次
发布时间:2019-05-24

本文共 6515 字,大约阅读时间需要 21 分钟。

背景

上回提到开发web api的时候,一般是需要记录api的输入输出信息,方便后续排查问题;使用的是委托的形式进行记录日志。

这次我们使用另外一种方式,Filter来记录输入输出日志。

实现方式

1、首先在进入action的时候,定义OnActionExecuting。

public override void OnActionExecuting(ActionExecutingContext context)        {            base.OnActionExecuting(context);            // 后续添加了获取请求的请求体,如果在实际项目中不需要删除即可            long contentLen = context.HttpContext.Request.ContentLength == null ? 0 : context.HttpContext.Request.ContentLength.Value;            if (contentLen > 0)            {                // 读取请求体中所有内容                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; }        ///         /// 请求体中的所有值        ///         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 = "在返回结果前发生了异常";            try            {                if (result != null)                {                    res = Newtonsoft.Json.JsonConvert.SerializeObject(result.Value);                }            }            catch (System.Exception)            {                res = "日志未获取到结果,返回的数据无法序列化";            }            NLogger.Info(                $"地址:{url} \n " +                  $"controller:{controller} \n " +                    $"action:{action} \n " +                      $"token:{token} \n " +                $"方式:{method} \n " +                $"请求体:{RequestBody} \n " +                $"参数:{qs}\n " +                $"结果:{res}\n " +                $"耗时:{Stopwatch.Elapsed.TotalMilliseconds} 毫秒(指控制器内对应方法执行完毕的时间)");        }

4、控制器调用LogAttribute。

///     ///    ///     [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{    ///     /// 拦截器    ///     public class LogAttribute : ActionFilterAttribute    {        private string ActionArguments { get; set; }        ///         /// 请求体中的所有值        ///         private string RequestBody { get; set; }        private Stopwatch Stopwatch { get; set; }        ///         ///        ///         ///         public override void OnActionExecuting(ActionExecutingContext context)        {            base.OnActionExecuting(context);            // 后续添加了获取请求的请求体,如果在实际项目中不需要删除即可            long contentLen = context.HttpContext.Request.ContentLength == null ? 0 : context.HttpContext.Request.ContentLength.Value;            if (contentLen > 0)            {                // 读取请求体中所有内容                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();        }        ///         ///        ///         ///         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 = "在返回结果前发生了异常";            try            {                if (result != null)                {                    res = Newtonsoft.Json.JsonConvert.SerializeObject(result.Value);                }            }            catch (System.Exception)            {                res = "日志未获取到结果,返回的数据无法序列化";            }            NLogger.Info(                $"地址:{url} \n " +                  $"controller:{controller} \n " +                    $"action:{action} \n " +                      $"token:{token} \n " +                $"方式:{method} \n " +                $"请求体:{RequestBody} \n " +                $"参数:{qs}\n " +                $"结果:{res}\n " +                $"耗时:{Stopwatch.Elapsed.TotalMilliseconds} 毫秒(指控制器内对应方法执行完毕的时间)");        }    }}

转载地址:http://qvudi.baihongyu.com/

你可能感兴趣的文章
慢慢欣赏linux vsftpd的使用
查看>>
慢慢欣赏linux 思考中的问题
查看>>
慢慢欣赏linux switch_to学习
查看>>
慢慢欣赏linux CPU占用率和负载
查看>>
设计模式学习
查看>>
慢慢欣赏linux seq_file
查看>>
慢慢欣赏linux 设备树device tree
查看>>
慢慢欣赏linux HZ与时钟中断频率的关联
查看>>
慢慢欣赏linux 文件黑洞和文件空洞
查看>>
慢慢欣赏linux 截断文件
查看>>
慢慢欣赏linux 数据类型
查看>>
中断学习之timer_interrupt powerpc实现
查看>>
慢慢欣赏linux 死锁检测
查看>>
慢慢欣赏linux exec加载执行程序
查看>>
慢慢欣赏linux 页框lru的作用
查看>>
慢慢欣赏linux glibc相关
查看>>
慢慢欣赏linux PCI-PCIE初始化总结
查看>>
慢慢欣赏linux PCI-PCIE定制化
查看>>
慢慢欣赏git
查看>>
慢慢欣赏linux 网络协议栈一 全景图
查看>>