API接口利用ActionFilterAttribute实现接口耗时检测
1.主要代码
using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; using System.Web; using System.Web.Http.Controllers; using System.Web.Http.Filters; namespace ZMAPI.Controllers { /// <summary> /// 监控接口执行时间 /// </summary> public class TimingActionFilter : ActionFilterAttribute { //private static readonly Logger logger = LogManager.GetCurrentClassLogger(); private const string Key = "__action_duration__"; /// <summary> /// 启用计时器 /// </summary> /// <param name="actionContext"></param> /// <param name="cancellationToken"></param> /// <returns></returns> public override Task OnActionExecutingAsync(HttpActionContext actionContext, CancellationToken cancellationToken) { /* await Trace.WriteAsync("Executing action named {0} for request {1}.", actionContext.ActionDescriptor.ActionName,actionContext.Request.GetCorrelationId()); */ if (SkipLogging(actionContext)) { return base.OnActionExecutingAsync(actionContext, cancellationToken); } var stopWatch = new Stopwatch(); actionContext.Request.Properties[Key] = stopWatch; stopWatch.Start(); return base.OnActionExecutingAsync(actionContext, cancellationToken); } /// <summary> /// 记录监控接口执行日志 /// </summary> /// <param name="actionExecutedContext"></param> /// <param name="cancellationToken"></param> /// <returns></returns> public override Task OnActionExecutedAsync(HttpActionExecutedContext actionExecutedContext, CancellationToken cancellationToken) { if (!actionExecutedContext.Request.Properties.ContainsKey(Key)) { return base.OnActionExecutedAsync(actionExecutedContext, cancellationToken); } var stopWatch = actionExecutedContext.Request.Properties[Key] as Stopwatch; if (stopWatch != null) { stopWatch.Stop(); var actionName = actionExecutedContext.ActionContext.ActionDescriptor.ActionName; var controllerName = actionExecutedContext.ActionContext.ActionDescriptor.ControllerDescriptor.ControllerName; string log = string.Format("方法名:【{0}】 - 请求类型:【{1}】 消耗时间(毫秒):【{2}】", controllerName, actionName, stopWatch.ElapsedMilliseconds); #if DEBUG Debug.Print(log); #endif //logger.Info(log); Log(stopWatch.ElapsedMilliseconds.ToZMInt32(),log); } return base.OnActionExecutedAsync(actionExecutedContext, cancellationToken); } private static bool SkipLogging(HttpActionContext actionContext) { return actionContext.ActionDescriptor.GetCustomAttributes<NoLogAttribute>().Any() || actionContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes<NoLogAttribute>().Any(); } public void Log(int stopWatch, string log) { if (stopWatch >= 3000) { Serious_log(log); } else if (stopWatch >= 1000) { Ordinary_log(log); } } /// <summary> /// 严重日志 /// </summary> public void Serious_log(string log) { Tools.PublicConfig.log_Append("接口调用时间监控: " + log, "ApiLog/API_Warning", DateTime.Now.ToString("yyyyMMdd") + "_API_Warning.log"); } /// <summary> /// 普通日志 /// </summary> public void Ordinary_log(string log) { Tools.PublicConfig.log_Append("接口调用时间监控: " + log, "ApiLog/API_Time", DateTime.Now.ToString("yyyyMMdd") + "_API.log"); } } /// <summary> /// 不记录监控接口执行日志 /// </summary> [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true)] public class NoLogAttribute : Attribute { } }
2.WebApiConfig中启用
public static void Register(HttpConfiguration config) { //启用监控接口执行时间 config.Filters.Add(new TimingActionFilter()); //默认路由 config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); }