[.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对象关 ...
随机推荐
- Joseph Problem With Passwords In Java
问题描述: 编号为1,2,......,n的n个人(每个人的信息有编号.姓名和密码三项)按照顺时针方向围坐一圈, 每个人有且只有一个密码(正整数,密码用随机方式赋值,范围1-15).一开始任选一个正整 ...
- SpringBoot多数据源详细配置与使用(包含数据源和事务配置)
SpringBoot项目数据库配置文件中配置多个数据源: #********* primary jdbc ************************** spring.datasource.dr ...
- 查看Linux操作系统版本命令
(一)查看操作系统版本的方法 1.uname -a 可以查看内核版本等信息 Linux test 3.10.0-957.1.3.el7.x86_64 #1 SMP Thu Nov 29 14:49:4 ...
- (Jmeter笔记)设置全局变量,跨线程调用变量,函数助手使用方法__setProperty和__p
需求: 线程2获取线程1的Token成功,并可用 1.使用方法__setProperty定义一个内置函数 2.添加BeanShell后置处理程序 String Token=bsh.args[0]; / ...
- OWASP ZAP基本使用教程(Kali版)
简介OWASP ZAP是一款非常好用的测试工具,也是Kali里自带的工具,一键就可以扫描多种不同类型的漏洞,最好用的一点就是他可以自动爬取子域名.非常的快捷方便下面我就给大家带来OWASP ZAP的基 ...
- [2013年NOIP提高组] 积木大赛
春春幼儿园举办了一年一度的"积木大赛".今年比赛的内容是搭建一座宽度为n的大厦,大厦可以看成由n块宽度为1的积木组成,第i块积木的最终高度需要是hi. 在搭建开始之前,没有任何积木 ...
- 「SOL」E-Lite (Ural Championship 2013)
为什么这数据能水到可以枚举角度 ac 啊 # 题面 给你 \(n\) 个平面向量 \((x_i,y_i)\),对于每个 \(k=1\sim n\),求「从给出的 \(n\) 个向量中不重复地选择 \( ...
- python机器学习——随机森林算法
背景与原理: 首先我们需要知道集成学习的概念,所谓集成学习,就是使用一系列学习器进行学习,并且通过某种规则把这些学习器的学习结果整合起来从而获得比单个学习器学习效果更好的机器学习方法.这样的方法可以用 ...
- Linux ~ jenkins 直接安装
前置条件: 1. Jenkins是由java编写的,所以最好安装java8以上的环境 开始安装: 1. 配置yum源,将jenkins导入yum源 sudo wget -O /etc/yum.repo ...
- sqlsever中使用的 select top n在mysql 语句中如何更改
string sqlSelect = "select top(3) ROW_NUMBER() over(order by UserTime) as Num,* from " + & ...