心安
代码的世界,简单而又直接

思路:

通过重写 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     }

 

posted on 2022-07-04 14:20  逐梦の心安  阅读(212)  评论(0编辑  收藏  举报