在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. HttpPost方式调用接口的3种方式

    第一种:需要httpclient的依赖包 <dependency> <groupId>org.apache.httpcomponents</groupId> < ...

  2. [模板] dfs序, 树链剖分, 换根

    树链剖分 树链剖分是一种对树的分治, 可以把树上的任意一条链分解为 \(O(\log n)\) 条在dfs序上相邻的子链, 便于数据结构(如线段树)来维护. 另外, 子树在dfs序上也是一个连续的区间 ...

  3. SSL 证书生成与转化

    1.windows 的keytool工具 2.如何将jks文件转换为pfx格式并导入客户端 https://jingyan.baidu.com/article/a65957f4c69dfc24e67f ...

  4. Elasticsearch6.x和Kibana6.x的安装

    Elasticsearch6.x的安装(centos6.x下) Elasticsearch6.x目前需要至少jdk8的支持,关于如何安装jdk不在讲述.Oracle的推荐安装文档可以在Oracle的网 ...

  5. centos7下使用LVM给系统硬盘扩容超详细

    简单介绍: LVM是逻辑盘卷管理(Logical Volume Manager)的简称,它是Linux环境下对磁盘分区进行管理的一种机制,LVM是建立在硬盘和分区之上的一个逻辑层,来提高磁盘分区管理的 ...

  6. JSTL和EL的使用

    JSTL和EL的使用 使用JSTL前的准备 想要使用JSTL,首先需要给工程导入JSTL的包(JSTL.jar和standard.jar). JSTL标签库 在JSTL中分为以下五个标签 核心标签 格 ...

  7. C++回顾day03---<输入输出流>

    一:C++输入输出包含下面3个方面 (一)标准I/O 对系统指定的标准设备的输入和输出.即从键盘输入数据,输出到显示器屏幕.这种输入输出称为标准的输入输出. (二)文件I/O 以外存磁盘文件为对象进行 ...

  8. docker 安装入门

    install docker 命令 docker version // docker 版本 docker pull nginx // 拉取nginx docker images // 查看本机dock ...

  9. Typora使用说明(记录总结)

    目录 区域元素 YAML FONT Matters 菜单 段落 标题 引注 序列 可选序列 代码块 数学块 表格 脚注 水平线 特征元素 链接 超链接 内链接 相关链 URLs 图片 斜体 加粗 删除 ...

  10. [再寄小读者之数学篇](2014-04-18 from 352558840@qq.com [南开大学 2014 年高等代数考研试题]反对称矩阵的组合)

    (2014-04-18 from 352558840@qq.com [南开大学 2014 年高等代数考研试题]反对称矩阵的组合) 设 ${\bf A},{\bf B}$ 都是反对称矩阵, 且 ${\b ...