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

问题分解

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

  1. 怎样监测一个WebApi项目的性能。
  2. 将性能分析监测信息从后端发送到UI。
  3. 在UI显示分析监测结果。

一、分析WebApi项目性能

安装Miniprofiler

在我们准备做Miniprofiler集成前,先思考一下Miniprofiler在监测MVC项目时是怎么做的,以便借鉴一下实现思路。当一个控制器执行后,Miniprofiler通过一个guid跟踪请求执行的每一步的时间。执行活动完成后,跟踪监测结果暂存在内存中。然后Miniprofiler通知其js模块有一个新动作执行完成了。这使得其程序终端发出调用,请求获取实时的结果。现在的问题是这是一个MVC终端,幸运的是在WebApi项目中构造这样一个终端也很容易。

  1. 首先安装Miniprofiler

    • Install-Package Miniprofiler。
    • 我们只需要Miniprofiler core,不需要Miniprofiler.mvc,但是注意一定要安装V3之后的版本。
    • ABP中,安装在Web项目和WebApi中。
  2. Install-Package Microsoft.AspNet.Mvc
    • ABP中,Web项目本身就有了,WebApi项目不需要安装。
  3. 将以下代码添加到web.config中的<handlers>节下。
<add name="MiniProfiler" path="mini-profiler-resources/*" verb="*"
type="System.Web.Routing.UrlRoutingModule" resourceType="Unspecified"
preCondition="integratedMode" />
  1. 将以下代码添加到Global.asax
protected void Application_BeginRequest()
{
MiniProfiler.Start();
}
protected void Application_EndRequest()
{
MiniProfiler.Stop();
}
  1. 测试一下所做的是否正确

    • 重新编译运行程序,在swagger中执行一个动作
    • 访问http://localhost/mini-profiler-resources/results
    • 正常执行结果类似如下

二、将分析监测信息从后台发送到UI

将Miniprofiler元数据注入swashbuckle

在MVC项目中,我们通常在razor视图中添加一个辅助方法RenderInclude,从而注入一些代码执行和渲染分析监测结果盒子。然而在WebApi中是没有页面可以注入的,所以让我们来点创新吧。

我们观察下RenderInclude的输出,可以看到Miniprofiler注入了一个异步的脚本标签。这个标签从Miniprofiler终端下载了一个js脚本,然后脚本运行展示出分析监测结果。

我们知道在swagger中可以注入js脚本,例如我们上节教程中注入的汉化js文本,然后脚本会在swaggerUI上运行。这就足够我们进行上面的步骤了。

  1. 首先我们来添加一个swagger的IDocumentFilter。

    • 这个filter在每次swagger页面加载时都会执行。
public class InjectMiniProfiler : IDocumentFilter
{
public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, IApiExplorer apiExplorer)
{
swaggerDoc.info.contact = new Contact()
{
name = MiniProfiler.RenderIncludes().ToHtmlString()
};
}
}
* 我们把Miniprofiler的渲染脚本标签赋给了swaggerDoc的联系人名称,真是太有才了 ^_^
  1. 反注释swaggerconfig.cs中的documentfilter代码,并将其指向刚才创建的filter

    c.DocumentFilter<InjectMiniProfiler>();
  2. 编译运行并刷新swagger页面,可以看到创建人是 script async... _

  3. 我们已经获得了在客户端需要的脚本。现在我们只需要用js将其改进一下。

三、在UI上显示分析监测结果

在swagger页面上运行Miniprofiler Js

  1. 添加js文件SwaggerUiCustomization.js
  2. 设置js文件属性为嵌入的资源,以确保其总是被拷贝到输出目录
  3. Js代码如下,这段代码主要是获取我们之前注入的脚本文本(使用JQuery),创建新的脚本标签,并附加到DOM,脚本会随后执行。
//Create a mini profiler script tag with the right properites
var MiniProfiler = $('#api_info > div:nth-child(3)').text();
const attributes = [
'src', 'data-version', 'data-path', 'data-current-id', 'data-ids',
'data-position', 'data-trivial', 'data-children', 'data-max-traces', 'data-controls',
'data-authorized', 'data-toggle-shortcut', 'data-start-hidden', 'data-trivial-milliseconds'
];
var GetAttr = function (input, attributeName) {
const myRegexp = attributeName + '="(.*?)"';
const re = new RegExp(myRegexp, "g");
const match = re.exec(input);
return match[1];
}
var s = document.createElement("script");
s.type = "text/javascript";
s.id = "mini-profiler";
s.async = true;
for (var i = 0; i < attributes.length; i++) {
var element = attributes[i];
s.setAttribute(element, GetAttr(MiniProfiler, element));
}
document.body.appendChild(s);
// Remove injected tag from view
$('#api_info > div:nth-child(3)').text('');
  1. 修改swaggerconfig.cs的InjectJavaScript,将上面创建的js注入。
string resourceName2 = thisAssembly.FullName.Substring(0, thisAssembly.FullName.IndexOf(",")) + ".Scripts.swaggerui.SwaggerUiCustomization.js";
c.InjectJavaScript(thisAssembly, resourceName2);
  1. 重新编译运行,刷新swagger页面,可以看到注入的文本从swagger页面上消失了,而Miniprofiler弹出层出现在页面左上角。

四、实时刷新监测结果

蛋疼的是,我们还没有完全搞定。你可以执行一个Swagger接口,然后发现Miniprofiler并未跟着更新结果,那上面这一切都没有意义了。幸运的是,Miniprofiler在MVC网站中被设计为同样可以使用AJAX调用。因此,我们可以利用这一点进行改进。扫读Miniprofiler的JS代码,我们发现它可以监听angular页面应用的xhr对象。

  1. 我们往SwaggerUiCustomization.js文件中添加代码window.angular=true;,假装我们使用angular。

    • 这就是我们要使用MiniprofilerV3.2版本的原因。V3.0版本在xhr监听上有个bug,会导致stackoverflow错误。如果你的浏览器控制台抛出stackoverflow异常,那你应该再次检查是否使用了正确的Miniprofiler版本。
  2. 重新编译运行程序,刷新Swagger页面。
  3. 到此为止我们仅仅实现了可以让Miniprofiler实时监听新的请求调用。为了显示出监测信息,还需要传递所监测的活动的ID列表。这个可以用另外一个filter轻松实现。
    • ABP项目由于存在Web项目,所以可以不必再按下面步骤处理。
  4. 在WebApi中新建Filter文件夹,创建WebApiProfilingActionFilter.cs。
    public class WebApiProfilingActionFilter : ActionFilterAttribute
{
public const string MiniProfilerResultsHeaderName = "X-MiniProfiler-Ids"; public override void OnActionExecuted(HttpActionExecutedContext filterContext)
{
var MiniProfilerJson = JsonConvert.SerializeObject(new[] {MiniProfiler.Current.Id});
filterContext.Response.Content.Headers.Add(MiniProfilerResultsHeaderName, MiniProfilerJson);
}
}
  1. WebApiConfig.cs中注册这个Filterconfig.Filters.Add(new WebApiProfilingActionFilter());

    • ABP项目中应在WebApiModule中的Initialize()方法中,添加配置Configuration.Modules.AbpWebApi().HttpConfiguration.Filters.Add(new WebApiProfilingActionFilter());
  2. 重新编译运行程序,刷新Swagger页面,之后在每次执行接口后,会发现左上角的分析监测界面会实时增加一行结果。另外,在HTTP响应头中会看见一个类似的记录"x-MiniProfiler-ids": "[\"b9512f60-9e75-42f9-bdc1-597695e5b745\"]",
  3. 大功告成!再多添加几个接口,试试效果吧~

五、总结

审视一遍最终的代码,看起来很简单,但是这个过程中是作了很多的尝试和试错,来让swashbuckle和Miniprofiler集成起来,同时做了一些重构来减少代码量,但是我对最终结果还是非常满意的。如果swashbuckle能有更简便的传递元数据的方法,那就更好啦。另外,我知道它支持定制前端页面,但是在这里我们只是要显示出监测分析结果就达到目的,所以只需要做一些调整,而不是从头开始做一个页面。

这些都实现后,我们就可以进一步使用所有的Miniprofiler插件了,譬如Entity framework profiling。

下一篇教程中,我们将把Miniprofiler EF6集成到项目中,以实现EF的监测分析。

参考链接:http://www.lambdatwist.com/webapi-profiling-with-miniprofiler-swagger/

ABP给WebApi添加性能分析组件Miniprofiler的更多相关文章

  1. ASP.NET Core WebAPI中的分析工具MiniProfiler

    介绍 作为一个开发人员,你知道如何分析自己开发的Api性能么? 在Visual Studio和Azure中, 我们可以使用Application Insight来监控项目.除此之外我们还可以使用一个免 ...

  2. ABP给WebApi添加SwaggerUI,生成可交互接口文档

    在ABP模板项目中,通过SwaggerUI可以为我们的WebApi生成动态的可交互接口文档页面,从而可以很方便的测试调用我们的WebApi接口. 一.集成Swagger 右键项目YoYo.Web,打开 ...

  3. MiniProfiler性能分析工具— .Net Core中用法

    前言: 在日常开发中,应用程序的性能是我们需要关注的一个重点问题.当然我们有很多工具来分析程序性能:如:Zipkin等:但这些过于复杂,需要单独搭建. MiniProfiler就是一款简单,但功能强大 ...

  4. Centos下给PHP7添加Xhprof性能分析

    什么是 Xhprof?XHProf是facebook 开发的一个测试php性能的扩展,本文记录了在PHP应用中使用XHProf对PHP进行性能优化,查找性能瓶颈的方法. 它报告函数级别的请求次数和各种 ...

  5. 如何进行python性能分析?

    在分析python代码性能瓶颈,但又不想修改源代码的时候,ipython shell以及第三方库提供了很多扩展工具,可以不用在代码里面加上统计性能的装饰器,也能很方便直观的分析代码性能.下面以我自己实 ...

  6. MySQL性能分析(转)

    第一步:检查系统的状态 通过操作系统的一些工具检查系统的状态,比如CPU.内存.交换.磁盘的利用率.IO.网络,根据经验或与系统正常时的状态相比对,有时系统表面上看起来看空闲,这也可能不是一个正常的状 ...

  7. LoadRunner性能分析指标解释

    Transactions(用户事务分析) 用户事务分析是站在用户角度进行的基础性能分析. 1.Transation Sunmmary(事务综述) 对事务进行综合分析是性能分析的第一步,通过分析测试时间 ...

  8. 转:asp.net mvc ef 性能监控调试工具 MiniProfiler

    MiniProfiler官网:http://miniprofiler.com/ MiniProfiler的一个特别有用的功能是它与数据库框架的集成.除了.NET原生的 DbConnection类,Mi ...

  9. 【转】JVM虚拟性能分析

    JDK自带的JAVA性能分析工具.它已经在你的JDK bin目录里了,只要你使用的是JDK1.6 Update7之后的版本.点击一下jvisualvm.exe图标它就可以运行了. 这里是VisualV ...

随机推荐

  1. Azure - Create your first function using Visual Studio

    Azure Functions lets you execute your code in a serverless environment without having to first creat ...

  2. [BZOJ 4516] [SDOI 2016] 生成魔咒

    Description 魔咒串由许多魔咒字符组成,魔咒字符可以用数字表示.例如可以将魔咒字符 1.2 拼凑起来形成一个魔咒串 [1,2]. 一个魔咒串 S 的非空字串被称为魔咒串 S 的生成魔咒. 例 ...

  3. ☆ [NOI2014] 魔法森林 「LCT动态维护最小生成树」

    题目类型:\(LCT\)动态维护最小生成树 传送门:>Here< 题意:带权无向图,每条边有权值\(a[i],b[i]\).要求一条从\(1\)到\(N\)的路径,使得这条路径上的\(Ma ...

  4. C++ bitset 常用函数及运算符

    C++ bitset--高端压位卡常题必备STL 以下内容翻译自cplusplus.com,极大地锻炼了我的英语能力. bitset存储二进制数位. bitset就像一个bool类型的数组一样,但是有 ...

  5. Null component Catalina

    "严重: Null component Catalina:type=JspMonitor,name=jsp,WebModule="错误的解决办法 在MyEclipse10环境下启动 ...

  6. platform驱动分离

    目录 platform驱动分离 框架结构 与输入子系统联系 设备描述 驱动算法 注册机制 程序 测试 platform驱动分离 框架结构 与输入子系统联系 设备描述 驱动算法 注册机制 程序 测试 - ...

  7. (转)如何阅读OpenStack源码

    1 关于该项目 本项目使用在线绘图工具web sequencediagrams完成,目标是图形化OpenStack的所有操作流程,通过操作序列图能快速学习Openstack的工作原理,理清各个组件的关 ...

  8. win7 远程连接服务器出现身份验证错误,又找不到加密Oracle修正

    今天想用远程桌面连接登录服务器,结果,弹出一个错误的提示框:发生身份验证错误,要求的函数不受支持. 然后在网上找了相关的教程,基本上所有的方法都是如下所示: 策略路径:"计算机配置" ...

  9. vue-resource的使用,前后端数据交互

    vue-resource的使用,前后端数据交互 1:导入vue与vue-resource的js js下载:   https://pan.baidu.com/s/1fs5QaNwcl2AMEyp_kUg ...

  10. JAVA第一周学习

    新学期伊始,六门专业课,课课重要,无法抉择重心,但日子还是要过的,而且要精细的过,不能得过且过 JAVA第一周任务 一:学习第一章视频 二:使用JDB调试JAVA 三:输入调试教材上代码,并把代码上传 ...