實現起來很簡單,一個Filter就可以搞定!!!
/// <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("[execution controller:{0} - action:{1} take {2} time.]", controllerName, actionName, stopWatch.Elapsed); #if DEBUG Debug.Print(log); #endif logger.Info(log); } return base.OnActionExecutedAsync(actionExecutedContext, cancellationToken); } private static bool SkipLogging(HttpActionContext actionContext) { return actionContext.ActionDescriptor.GetCustomAttributes<NoLogAttribute>().Any() || actionContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes<NoLogAttribute>().Any(); } } /// <summary> /// 不記錄監控接口執行日志 /// </summary> [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true)] public class NoLogAttribute : Attribute { }
WebApiConfig中啟用
public static void Register(HttpConfiguration config) { //啟用監控接口執行時間 //config.Filters.Add(new TimingActionFilter()); //啟用全局驗證 config.Filters.Add(new ModelValidFilter()); //啟用特性路由 config.MapHttpAttributeRoutes(); //默認路由 config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); }
配置NLog記錄響應時間超過1秒的接口服務
<target name="database" xsi:type="Database" connectionString="Data Source=xxx;Initial Catalog=WebAPI_Log;Persist Security Info=True;User ID=xxx;Password=xxx" commandText="insert into [WebAPI_Log]([CreateOn],[Origin],[LogLevel], [Message], [Exception],[StackTrace]) values (getdate(), @origin, @logLevel, @message,@exception, @stackTrace);"> <!--日志來源--> <parameter name="@origin" layout="${callsite}"/> <!--日志等級--> <parameter name="@logLevel" layout="${level}"/> <!--日志消息--> <parameter name="@message" layout="${message}"/> <!--異常信息--> <parameter name="@exception" layout="${exception}" /> <!--堆棧信息--> <parameter name="@stackTrace" layout="${stacktrace}"/> </target>
Refer:
http://www.cnblogs.com/shanyou/p/3308058.html
http://stackoverflow.com/questions/14062028/how-to-intercept-all-the-asp-net-webapi-controller-action-methods-calls-with-nin
