巧用ActionFilterAttribute实现API日志的记录

背景

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

使用Func<T, TResult> 委托实现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; }/// <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 = "在返回结果前发生了异常";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。

/// <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);// 后续添加了获取请求的请求体,如果在实际项目中不需要删除即可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();}/// <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 = "在返回结果前发生了异常";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://www.mzph.cn/news/304831.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

activity 防止多次打开_Android开发Activity任务和返回栈

任务是用户在执行某项工作时与之互动的一系列 Activity 的集合。这些 Activity 按照每个 Activity 打开的顺序排列在一个返回堆栈中。例如&#xff0c;电子邮件应用可能有一个 Activity 来显示新邮件列表。当用户选择一封邮件时&#xff0c;系统会打开一个新的 Activity 来显示…

全程图解:Centos 5.2 下 ORACLE10G 安装配置

1、检查并安装ORACLE必须的软件包在CENTOS上安装Oracle&#xff0c;需要将ORACLE所必须的软件包逐一安装, 参考Oracle安装文档关于Red Hat Enterprise Linux 4.0部分&#xff0c;所需的软件包如下:binutils-2.17.50.0.6-6.el5compat-db-4.2.52-5.1compat-libstdc-33-3.2.3-61co…

css原生样式支持,原生JS读写CSS样式的方法

通过Element对象的getAttribute()、setAttribute()、removeAttribute()直接读写style属性如&#xff1a;elm.setAttribute(style,color:red;line-height:30px);利用document.styleSheets属性&#xff0c;返回当前页面的所有StyleSheet对象(即所有样式表)&#xff0c;它是一个只…

提升代码可读性的 10 个技巧

具有较强可读性的代码&#xff0c;能帮助你调试程序&#xff0c;不让自己活得太累。 代码可读性是计算机编程领域中普遍存在的问题。这也是我们成为开发者首先要学习的事情之一。本文会详细介绍在编写强可读性代码时最佳实践中最重要的一部分内容。 1 - 注释和文档 IDE&#xf…

phpsotrm怎么 搜索功能_Windows 10 网络搜索设计太反人类?教你如何彻底关闭它

来源&#xff1a;太平洋电脑网我们知道微软在Windows 10中&#xff0c;特别加强了系统的搜索功能&#xff0c;但Windows 10的搜索的确很难称得上好用。抛开效率低下、呈现结果少、造成系统卡顿等老生常谈的问题不论&#xff0c;在功能设计方面&#xff0c;Windows 10搜索也有硬…

支撑性服务 自动化能力

连载传送门&#xff1a;什么是云原生&#xff1f;云原生设计理念.NET 微服务谈到云原生&#xff0c;绕不开“容器化”Backing services云原生系统依赖于许多不同的辅助资源&#xff0c;例如数据存储、消息队列、监视和身份服务&#xff0c;这些服务统称为支撑性服务。下图显示了…

网站logo放在服务器,自己建网站如何设计网站LOGO

LOGO是一个网站的形象代表或者说是品牌的象征&#xff0c;用户记住了网站LOGO&#xff0c;就相当于记住了网站&#xff0c;因此&#xff0c;自己建网站时要融入网站LOGO的设计&#xff0c;潜移默化地把LOGO形象植入用户脑海中&#xff0c;把网站与LOGO紧密连接在一起&#xff0…

python http协议获取对方的ip地址_http协议(一)基础知识

参考&#xff1a;老张http://link.zhihu.com/?targethttps%3A//www.cnblogs.com/imyalost/p/5627816.html参考书籍——《图解http》当我们在浏览器的地址栏中输入网址&#xff0c;然后点击回车&#xff0c;接着&#xff0c;浏览器就会呈现出我们需要的web界面&#xff0c;那么…

好久没到这个地方来.

懒了,好久没写随笔了,学的东西不少,学过就忘记.没有整理,不成系统.最近也没什么好说的,瞎掰一通吧.--有时候觉得,我就是个愤青. 总感觉自己的思维很混乱,很没有头绪,东边拉袋水泥,西边拼块砖头的,没有结构,也不成体系,就是很多很原始的东西的简单堆积.得改...... 发现博客园是最…

TIOBE编程语言排行榜,Python遥遥领先

在这个快节奏的时代&#xff0c;要想走在潮流前端&#xff0c;你需要用最有效的方式&#xff0c;最有效率的工具&#xff0c;学习最有用的知识。而如今人工智能和数据分析爆发&#xff0c;python就是一颗冉冉升起的新星&#xff0c;因为简单易用和广阔的可能性&#xff0c;不仅…

mongodb默认的用户名密码_设置mongodb的用户名密码 | Think in Drupal

作者&#xff1a;亚艾元技术部我们在一个Nodejs项目中,使用了mongodb数据库&#xff0c;使用习惯和mysql很不一样&#xff0c;在摸索中前进&#xff0c;其中一个问题&#xff0c;mongodb安装完了以后&#xff0c;不用设置用户名密码&#xff0c;就可以登录使用。开始的时候&…

Dapr是如何简化微服务的开发和部署

基于微服务设计模式的现代应用程序面临着一系列挑战。微服务需要有一个强大的服务发现机制来实现动态连接。它们需要松散耦合&#xff0c;实现自主性和独立缩放。微服务需要支持多种语言&#xff0c;其中每个服务都是以最合适的语言、框架和运行时实现的。尽管采用容器和编排引…

table 内 下拉列表 被遮挡_一个简洁、有趣的无限下拉方案

本文主旨长列表渲染、无限下拉也算是前端开发老生常谈的问题之一了&#xff0c;本文将介绍一种简洁、巧妙、高效的方式来实现。话不多说&#xff0c;看下图&#xff0c;也许你可以发现什么&#xff1f;无限下拉示意图不知你是否从上面这张图中注意到了什么&#xff0c;比如只是…

天龙八部服务器维护后提BB,天龙八部:宠物比号值钱?玩家哭诉附体BB半年也卖不出去...

说到天龙八部的附体宝宝&#xff0c;相信许多爱美的玩家基本上都人手一只。附体后的增益多不多无所谓&#xff0c;首先附体后身上有龙、凤凰、蝴蝶等之类的特效&#xff0c;让许多玩家觉得游戏中角色颜值增添不少&#xff0c;当然一只属性不错的附体珍兽&#xff0c;也能够给游…

asp.net 动态添加JavaScript方法

//在页面顶部添加脚本 if (!Page.ClientScript.IsClientScriptBlockRegistered("myscriptKey"))//判断是否已经存在相同//键值的ScriptBlock { string myScript "function AlertHello(){alert(hello xuanhun!!);}";//脚本内容 …

写了 15 年代码,总结出提升 10 倍效率的三件事

译者&#xff1a;roy 【译者注】本文作者 Matt Watson 已经写了超过 15 年的代码&#xff0c;也由此总结出了提升 10 倍效率的三件事。Matt 表示&#xff0c;一个 10 倍效率的开发人员很快就知道了他们需要做什么&#xff0c;要问什么问题&#xff0c;什么时候不问问题&#xf…

python怎么样另存为_python要怎么保存python生成式

本篇将介绍Python的列表生成式&#xff0c;更多内容请参考:Python列表生成式列表生成式即List Comprehensions,是Python内置的非常简单却强大的可以用来创建list的生成式。举个例子&#xff0c;要生成list[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]可以用list(range(1, 11))>>>…

反锐化掩膜_光电图像处理 | 空域锐化滤波

锐化滤波Sharpen filterclc;close all;I imread(图片11.jpg);set(figure(1), name,不同梯度合成效果, numbertitle, off);subplot(221),imshow(I);title(原图);I rgb2gray(I);%% Roberts operatorH1x [0 0 0;0 -1 0;0 0 1]; H1y [0 0 0;0 0 -1;0 1 0];J1x imfilter(I,H1x)…

服务器不知道怎么回事安卓系统很卡,为什么安卓系统很容易变卡?该怎么解决?看完长知识了...

手机是我们现代生活的必备之物&#xff0c;什么都可以没有到就是不能没有手机&#xff0c;如今市面上的手机的手机不是安卓系统就是ios系统&#xff0c;安卓系统的手机虽然便宜但是有一个诟病&#xff0c;那就是安卓的手机会越用越卡&#xff0c;不管你手机配置是多么的高&…

EntityFramework Core自动返回SQL语句

【导读】给各位拜年了&#xff0c;开年第一篇&#xff0c;后续我们介绍EF Core 5.0相关新特性自动返回SQL语句当执行LINQ查询时&#xff0c;EF Core 5.0提供了ToQueryString扩展方法返回生成的SQL语句比如&#xff0c;执行如下LINQ查询var name "jeffcky"; var user…