编程开源技术交流,分享技术与知识

网站首页 > 开源技术 正文

MiniProfiler,一个.NET简单但有效的微型分析器

wxchong 2024-06-28 10:29:30 开源技术 12 ℃ 0 评论

背景

MVC MiniProfiler是Stack Overflow团队设计的一款对ASP.NET MVC的性能分析的小程序。可以对一个页面本身,及该页面通过直接引用、Ajax、Iframe形式访问的其它页面进行监控,监控内容包括数据库内容,并可以显示数据库访问的SQL(支持EF、EF CodeFirst等 )。并且以很友好的方式展现在页面上。

该Profiler的一个特别有用的功能是它与数据库框架的集成。除了.NET原生的 DbConnection类,profiler还内置了对实体框架(Entity Framework)以及LINQ to SQL的支持。任何执行的Step都会包括当时查询的次数和所花费的时间。为了检测常见的错误,如N+1反模式,profiler将检测仅有参数值存在差 异的多个查询。

MiniProfiler是以Apache License V2.0协议发布的,你可以在NuGet找到。配置及使用可以看这里:http://code.google.com/p/mvc-mini-profiler

概述

在WebApi中,对其性能进行分析监测是很有必要的。而悲剧的是,MVC项目中可以使用的MiniProfiler或Glimpse等,这些都不支持WebApi项目,而且WebApi项目通常也没有界面,不能进行性能分析的交互。在这篇文章中,我们就来一步步实现为WebApi项目集成Miniprofiler。集成后,我们可以监控EF执行效率,执行语句,页面执行时间等,这些结果将以很友好的方式显示在界面上。

问题

本质上,集成Miniprofiler可以分解为三个问题:

  1. 怎样监测一个WebApi项目的性能。

  2. 将性能分析监测信息从后端发送到UI。

  3. 在UI显示分析监测结果。

实现方式

首先安装Miniprofiler,MiniProfiler.EF6

在Global.asax 加入

using BQoolCommon.Helpers.Model;using Elmah;using ResearchManager.Web.App_Start;using System;using System.Configuration;using System.Web;using System.Web.Mvc;using System.Web.Routing;using StackExchange.Profiling;using StackExchange.Profiling.Mvc;using StackExchange.Profiling.EntityFramework6;using System.Web.Optimization;using NLog;using ResearchManager.Models.ValidateAttribute;
namespace ResearchManager.Web{ public class MvcApplication : HttpApplication { protected void Application_Start() { AreaRegistration.RegisterAllAreas(); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); //Remove Header X-AspNetMvc-Version MvcHandler.DisableMvcResponseHeader = true; AutofacConfig.Bootstrapper(); //在 Controller 之前對 Model 做處理(字串 Trim) ModelBinders.Binders.DefaultBinder = new BQoolModelBinder(); //註冊自訂的 Validation (複寫預設的錯誤訊息) CustomerValidation.RegisterCustomerValidation();
DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(CustomizedRequired), typeof(RequiredAttributeAdapter));
DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(CustomizedStringLength), typeof(StringLengthAttributeAdapter));
#region 测试
//////if (bool.Parse(ConfigurationManager.AppSettings["MiniProfiler"] ?? "false")) //////{ ////MiniProfiler.Configure(new MiniProfilerOptions ////{ //// RouteBasePath = "~/profiler", //// PopupRenderPosition = RenderPosition.Right, // defaults to left //// PopupMaxTracesToShow = 10, // defaults to 15 //// ResultsAuthorize = request => request.IsLocal, //// ResultsListAuthorize = request => //// { //// return true; // all requests are legit in this example //// }, //// // Stack trace settings //// StackMaxLength = 256, // default is 120 characters //// TrackConnectionOpenClose = true ////} //// .ExcludeType("SessionFactory") // Ignore any class with the name of SessionFactory) //// .ExcludeAssembly("NHibernate") // Ignore any assembly named NHibernate //// .ExcludeMethod("Flush") // Ignore any method with the name of Flush //// .AddViewProfiling() // Add MVC view profiling (you want this) //// ); ////MiniProfilerEF6.Initialize(); //////}
#endregion 测试 }
protected void Application_BeginRequest(Object source, EventArgs e) { BundleTable.EnableOptimizations = false;
#region 测试
////MiniProfiler.StartNew();
#endregion 测试 }
protected void Application_EndRequest() { #region 测试
//////MiniProfiler.Current?.Stop(); // Be sure to stop the profiler!
#endregion 测试 }
#region Elmah
private static readonly string _exceptionMsg = "A potentially dangerous Request.Path value was detected from the client";
protected void Application_Error(object sender, EventArgs e) { Exception ex = Server.GetLastError(); Logger nlogger = LogManager.GetCurrentClassLogger(); nlogger.Error(ex);
if (BQoolCommon.Helpers.Setting.CommonSetting.IsProd()) { if (e is ExceptionFilterEventArgs exceptionFilter) { if (exceptionFilter.Exception is HttpException httpException && httpException.Message.StartsWith(_exceptionMsg)) { Response.Redirect("/"); } } Response.Clear(); Server.ClearError(); Response.StatusCode = 404; } }
/// <summary> /// 排除 Elmah 404 寄信通知 /// </summary> public void ErrorMail_Filtering(object sender, ExceptionFilterEventArgs e) { if (e.Exception is HttpException httpException && (httpException.GetHttpCode() == 404 || httpException.Message.StartsWith(_exceptionMsg))) { e.Dismiss(); } }
/// <summary> /// 自定 Elmah 發信主旨 /// </summary> private void ErrorMail_Mailing(object sender, Elmah.ErrorMailEventArgs e) { string machineName = "none server"; try { if (Request != ) { machineName = Request.ServerVariables["HTTP_HOST"]; } } catch { }
// 取得 Elamh ErrorMail 的主旨 // "$MachineName$ at $ErrorTime$ : {0}" string elmahSubject = e.Mail.Subject; //替換 ErrorMail 的主旨內容 string emailSubject = string.Format("ResearchManager.Web Error => {0}", elmahSubject .Replace("$MachineName$", machineName) );
e.Mail.Subject = emailSubject; }
#endregion Elmah }}

运行效果

运行项目,http://localhost//profiler/results-index 即可看到监测结果

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表