[.Net]Framwork WebAPI添加接口请求监控
思路:
通过重写 ActionFilterAttribute 拦截Action的请求及返回信息,实现对接口请求的监听。
最终效果如下:

全局启用需配置如下:

局部启用需配置如下:

源码如下:
1 /// <summary>
2 /// 统一的接口访问监控日志,
3 /// 全局启用-请添加 GlobalConfiguration.Configuration.Filters.Add(new TimingFilterAttribute());
4 /// 局部启用(目前模式)-在Controller或者Action上添加Attribute注入即可
5 /// </summary>
6 public class TimingFilterAttribute : ActionFilterAttribute
7 {
8 private const string Key = "__action_recordtime__";
9 private const string TimeKey = "__action_receivetime__";
10 /// <summary>
11 /// 自定义参数
12 /// </summary>
13 public string Message { get; set; }
14
15 public override Task OnActionExecutingAsync(HttpActionContext actionContext, CancellationToken cancellationToken)
16 {
17 if (IsRecordTime(actionContext))
18 {
19 return base.OnActionExecutingAsync(actionContext, cancellationToken);
20 }
21 // ReqParms= GetRequestValues(actionContext);
22 var stopWatch = new Stopwatch();
23 actionContext.Request.Properties[Key] = stopWatch;
24 actionContext.Request.Properties[TimeKey] = DateTime.Now.ToBinary();
25 stopWatch.Start();
26 return base.OnActionExecutingAsync(actionContext, cancellationToken);
27 }
28
29 public override Task OnActionExecutedAsync(HttpActionExecutedContext actionExecutedContext, CancellationToken cancellationToken)
30 {
31 if (!actionExecutedContext.Request.Properties.ContainsKey(Key) || !actionExecutedContext.Request.Properties.ContainsKey(TimeKey))
32 {
33 return base.OnActionExecutedAsync(actionExecutedContext, cancellationToken);
34 }
35 object beginTime = null;
36 if (!actionExecutedContext.Request.Properties.TryGetValue(TimeKey, out beginTime))
37 {
38 return base.OnActionExecutedAsync(actionExecutedContext, cancellationToken);
39 }
40 var stopWatch = actionExecutedContext.Request.Properties[Key] as Stopwatch;
41 if (stopWatch == null)
42 {
43 return base.OnActionExecutedAsync(actionExecutedContext, cancellationToken);
44 }
45 stopWatch.Stop();
46
47 DateTime starttime = DateTime.FromBinary(Convert.ToInt64(beginTime));
48 HttpRequest request = HttpContext.Current.Request;
49 string token = string.Empty;
50 var appkey = string.Empty;
51 if (request.Headers.AllKeys.Contains("Token")) { token = request.Headers["Token"]; }
52
53 if (request.Headers.AllKeys.Contains("AppKey")) { appkey = request.Headers["AppKey"]; }
54
55 var actionName = actionExecutedContext.ActionContext.ActionDescriptor.ActionName;
56 var controllerName = actionExecutedContext.ActionContext.ActionDescriptor.ControllerDescriptor.ControllerName;
57
58 var ip = request.UserHostAddress;
59 var UserHostName = request.UserHostName;
60 var paramaters = GetRequestValues(actionExecutedContext);
61 // var paramaters = ReqParms;//获取入参
62 var executeResult = GetResponseValues(actionExecutedContext);//获取response响应的结果
63
64 var RequestUri = request.Url.AbsoluteUri;
65 var MethodType= request.HttpMethod.ToString();
66 Bondex.Core.BizTool.LogPlat.LogHelper.Info($"{controllerName}/{actionName}", "E帐通接口监控服务", "TimingFilterAttribute", $"",
67 $"当前接口路径:{RequestUri},请求方式:{MethodType},请求时间:{starttime.ToString("yyyy-MM-dd HH:mm:ss:fff")},返回时间{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff")},接口执行时间:{stopWatch.Elapsed};请求IP:{ip},请求DNS:{UserHostName},请求入参:{paramaters},返回值:{executeResult},备注:{Message}");
68 return base.OnActionExecutedAsync(actionExecutedContext, cancellationToken);
69
70 }
71 /// <summary>
72 /// 读取request 的提交内容
73 /// </summary>
74 /// <param name="actionExecutedContext"></param>
75 /// <returns></returns>
76 public string GetRequestValues(HttpActionExecutedContext actionExecutedContext)
77 {
78 string result = String.Empty;
79 using (var stream = actionExecutedContext.Request.Content.ReadAsStreamAsync().Result)
80 {
81 if (stream.CanSeek)
82 {
83 stream.Position = 0;
84 }
85 result = actionExecutedContext.Request.Content.ReadAsStringAsync().Result;
86 }
87
88 return result;
89 }
90
91 /// <summary>
92 /// 读取action返回的result
93 /// </summary>
94 /// <param name="actionExecutedContext"></param>
95 /// <returns></returns>
96 public string GetResponseValues(HttpActionExecutedContext actionExecutedContext)
97 {
98 Stream stream = actionExecutedContext.Response.Content.ReadAsStreamAsync().Result;
99 Encoding encoding = Encoding.UTF8;
100 /*
101 这个StreamReader不能关闭,也不能dispose, 关了就傻逼了
102 因为你关掉后,后面的管道 或拦截器就没办法读取了
103 */
104 var reader = new StreamReader(stream, encoding);
105 string result = reader.ReadToEnd();
106 /*
107 这里也要注意: stream.Position = 0;
108 当你读取完之后必须把stream的位置设为开始
109 因为request和response读取完以后Position到最后一个位置,交给下一个方法处理的时候就会读不到内容了。
110 */
111 stream.Position = 0;
112 return result;
113 }
114 /// <summary>
115 /// 判断是否拦截请求,记录接口信息
116 /// </summary>
117 /// <param name="actionContext"></param>
118 /// <returns></returns>
119 private static bool IsRecordTime(HttpActionContext actionContext)
120 {
121 return actionContext.ActionDescriptor.GetCustomAttributes<NoRecordTimeAttribute>().Any() ||
122 actionContext.ControllerContext.ControllerDescriptor.GetCustomAttributes<NoRecordTimeAttribute>().Any();
123 }
124 }
125
126 [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true)]
127 public class NoRecordTimeAttribute : Attribute
128 {
129
130 }
[.Net]Framwork WebAPI添加接口请求监控的更多相关文章
- SpringBoot整合knife4j框架(可生成离线接口文档),并设置接口请求头token默认值
功能和swagger类似 官网地址:https://doc.xiaominfo.com/knife4j/ 这个框架可以设置返回字段的描述 引入依赖 <dependency> <gro ...
- SpringBoot整合Swagger框架 ,并设置接口请求头token默认值
引入maven依赖 <!-- swagger2--> <dependency> <groupId>io.springfox</groupId> &l ...
- WebApi接口请求失败,找不到资源。
WebApi开发接口,实现同步数据库的数据给安卓. public class UserInfoController : ApiControllerBase { private UserBLL user ...
- ASP.NET WebApi服务接口如何防止重复请求实现HTTP幂等性
一.背景描述与课程介绍 明人不说暗话,跟着阿笨一起玩WebApi.在我们平时开发项目中可能会出现下面这些情况; 1).由于用户误操作,多次点击网页表单提交按钮.由于网速等原因造成页面卡顿,用户重复刷新 ...
- restful接口就是url嘛,通过http请求发起访问。那接口进行监控,就可以监控这个restful url嘛
EasyAPI接口管理系统 专注API接口监控,让您的API接口更稳定,与APP更紧密 + 购买监控服务 接口性能分析 分析App对应的API接口请求性能,包含HTTP响应时间.吞吐率.HTTP错误率 ...
- ASP.NET Core 入门(2)(WebApi接口请求日志 Request和Response)
以前 .NET Framework WebApi 记录接口访问日志,一般是通过Filter的方式进行拦截,通过重写ActionFilterAttribute的OnActionExecuting实现拦截 ...
- ASP.NET Web API 接口执行时间监控
软件产品常常会出现这样的情况:产品性能因某些无法预料的瓶颈而受到干扰,导致程序的处理效率降低,性能得不到充分的发挥.如何快速有效地找到软件产品的性能瓶颈,则是我们感兴趣的内容之一. 在本文中,我将解释 ...
- 使用 NLog 给 Asp.Net Core 做请求监控
为了减少由于单个请求挂掉而拖垮整站的情况发生,给所有请求做统计是一个不错的解决方法,通过观察哪些请求的耗时比较长,我们就可以找到对应的接口.代码.数据表,做有针对性的优化可以提高效率.在 asp.ne ...
- Asp.Net WebAPI配置接口返回数据类型为Json格式
Asp.Net WebAPI配置接口返回数据类型为Json格式 一.默认情况下WebApi 对于没有指定请求数据类型类型的请求,返回数据类型为Xml格式 例如:从浏览器直接输入地址,或者默认的XM ...
- C# 动态创建SQL数据库(二) 在.net core web项目中生成二维码 后台Post/Get 请求接口 方式 WebForm 页面ajax 请求后台页面 方法 实现输入框小数多 自动进位展示,编辑时实际值不变 快速掌握Gif动态图实现代码 C#处理和对接HTTP接口请求
C# 动态创建SQL数据库(二) 使用Entity Framework 创建数据库与表 前面文章有说到使用SQL语句动态创建数据库与数据表,这次直接使用Entriy Framwork 的ORM对象关 ...
随机推荐
- 在vite中怎么批量注册组件
1. 在webpack中使用require来获取组件 / 参数:1. 目录 2. 是否加载子目录 3. 加载的正则匹配 //匹配当前文件夹下的所有.vue文件 注册全局组件 const importF ...
- ComPiler200003:Story-Oriented Programming
Story-Oriented Programming MAY 25TH, 2018 http://www.brandonkeown.com/2018/05/story-oriented-program ...
- 常见的SPA首屏优化方式
核心是加载和解析的性能优化 加载优化的核心是资源体积和首屏资源数量. 解析优化的核心是资源体积和代码的执行性能. 加载优化 通过webpack 的code splitting合理分包: Code ...
- Linux服务器时间校准
当发现系统时间不正确时可以通过 date 命令查看Linux系统的当前时间 最简便的修改方法,我们可以通过 date -s "20190917 22:04:00" 来直接修改Lin ...
- 实验:利用mqtt-spring-boot-starter实现后台云服务数据采集和远程控制
1.资源地址及使用说明 https://search.maven.org/artifact/com.github.tocrhz/mqtt-spring-boot-starter/1.2.7/jar 2 ...
- Get Keys In Binary Tree Layer By Layer
Get the list of list of keys in a given binary tree layer by layer. Each layer is represented by a l ...
- 【LeetCode - 1055】形成字符串的最短路径
1.题目描述 代码: #include <iostream> #include <string> using namespace std; const int MAX_LETT ...
- 兼容url传参
//兼容url传参 if(java.nio.charset.Charset.forName("ISO-8859-1").newEncoder().canEnc ...
- chap3第三小组总结
本周我们第三小组在张庆老师的带领下,走向编程的新一扇大门--分支结构. 我们第三小组是线下聚在一起学习,这样可以使我们的学习效率大大提高,我们在线下学习可以让我们的小组长更方便的指导我们的学习 ...
- MyBatis Generator使用方法
第一步:在resources文件夹下创建一个目录mybatis-generator,在目录mybatis-generator下创建文件generatorConfig.xml(此处的目录名可任意取) 第 ...