【无标题】

思路:

通过重写 ActionFilterAttribute 拦截Action的请求及返回信息,实现对接口请求的监听。

最终效果如下:

全局启用需配置如下:

 局部启用需配置如下:

 

    [TimingFilter("相关接口")]
    [RoutePrefix("PassPort")]
    public class PassPortController : ApiController
    {
}

源码如下:

 /// <summary>
    /// 统一的接口访问监控日志,
    /// 全局启用-请添加 GlobalConfiguration.Configuration.Filters.Add(new TimingFilterAttribute());
    /// 局部启用(目前模式)-在Controller或者Action上添加Attribute注入即可
    /// </summary>
    public class TimingFilterAttribute : ActionFilterAttribute
    {
        private const string Key = "__action_recordtime__";
        private const string TimeKey = "__action_receivetime__";
        /// <summary>
        /// 自定义参数
        /// </summary>
        public static string msg { get; set; }
        public static string ReqParms { get; set; }
        public TimingFilterAttribute()
        {
            msg = string.Empty;
        } 

        /// <summary>
        /// 初始化时填入类的说明
        /// </summary>
        /// <param name="message"></param>
        public TimingFilterAttribute(string message)
        {
            msg = message;
        }
        public override void OnActionExecuting(HttpActionContext actionContext)
        {
            if (IsRecordTime(actionContext))
            {
                return;
            }
           // ReqParms= GetRequestValues(actionContext);
            var stopWatch = new Stopwatch();
            actionContext.Request.Properties[Key] = stopWatch;
            actionContext.Request.Properties[TimeKey] = DateTime.Now.ToBinary();
            stopWatch.Start();
        }

        public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
        {
            if (!actionExecutedContext.Request.Properties.ContainsKey(Key) || !actionExecutedContext.Request.Properties.ContainsKey(TimeKey))
            {
                return;
            }
            object beginTime = null;
            if (!actionExecutedContext.Request.Properties.TryGetValue(TimeKey, out beginTime))
            {
                return;
            } 
            var stopWatch = actionExecutedContext.Request.Properties[Key] as Stopwatch;
            if (stopWatch == null)
            {
                return;
            }
            stopWatch.Stop();

            DateTime starttime = DateTime.FromBinary(Convert.ToInt64(beginTime));
            HttpRequest request = HttpContext.Current.Request;
            string token = string.Empty;
            var appkey = string.Empty;
            if (request.Headers.AllKeys.Contains("Token")) { token = request.Headers["Token"]; }

            if (request.Headers.AllKeys.Contains("AppKey")) { appkey = request.Headers["AppKey"]; }

            var actionName = actionExecutedContext.ActionContext.ActionDescriptor.ActionName;
            var controllerName = actionExecutedContext.ActionContext.ActionDescriptor.ControllerDescriptor.ControllerName;
              
            var ip = request.UserHostAddress;
            var UserHostName = request.UserHostName;
             var paramaters = GetRequestValues(actionExecutedContext);
            // var paramaters = ReqParms;//获取入参
            var executeResult = GetResponseValues(actionExecutedContext);//获取response响应的结果
            var  comments = msg;
            var RequestUri = request.Url.AbsoluteUri;
            var MethodType= request.HttpMethod.ToString();
            Bondex.Core.BizTool.LogPlat.LogHelper.Info($"{controllerName}/{actionName}", "E帐通接口监控服务", "TimingFilterAttribute", $"",
                $"当前接口路径:{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},备注:{comments}");
              
        }
        /// <summary>
        /// 读取request 的提交内容
        /// </summary>
        /// <param name="actionExecutedContext"></param>
        /// <returns></returns>
        public string GetRequestValues(HttpActionExecutedContext actionExecutedContext)
        {
            string result = String.Empty;
            using (var stream = actionExecutedContext.Request.Content.ReadAsStreamAsync().Result)
            {
                if (stream.CanSeek)
                {
                    stream.Position = 0;
                }
                result = actionExecutedContext.Request.Content.ReadAsStringAsync().Result;
            }
        
            return result;
        }

        /// <summary>
        /// 读取action返回的result
        /// </summary>
        /// <param name="actionExecutedContext"></param>
        /// <returns></returns>
        public string GetResponseValues(HttpActionExecutedContext actionExecutedContext)
        {
            Stream stream = actionExecutedContext.Response.Content.ReadAsStreamAsync().Result;
            Encoding encoding = Encoding.UTF8;
            /*
            这个StreamReader不能关闭,也不能dispose, 关了就傻逼了
            因为你关掉后,后面的管道  或拦截器就没办法读取了
            */
            var reader = new StreamReader(stream, encoding);
            string result = reader.ReadToEnd();
            /*
            这里也要注意:   stream.Position = 0; 
            当你读取完之后必须把stream的位置设为开始
            因为request和response读取完以后Position到最后一个位置,交给下一个方法处理的时候就会读不到内容了。
            */
            stream.Position = 0;
            return result;
        }
        /// <summary>
        /// 判断是否拦截请求,记录接口信息
        /// </summary>
        /// <param name="actionContext"></param>
        /// <returns></returns>
        private static bool IsRecordTime(HttpActionContext actionContext)
        {
            return actionContext.ActionDescriptor.GetCustomAttributes<NoRecordTimeAttribute>().Any() ||
                   actionContext.ControllerContext.ControllerDescriptor.GetCustomAttributes<NoRecordTimeAttribute>().Any();
        }
    }

    [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true)]
    public class NoRecordTimeAttribute : Attribute
    {

    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值