起因

我司目前使用清真的ApplicationInsights(以下简称Ai)来做程序级监控。(Ai相关文档: https://azure.microsoft.com/zh-cn/services/application-insights/

其实一切都蛮好的,但是我们基于Hangfire的Job系统却无法被Ai所监控到,因为Ai它监控的原理是基于HttpModule对请求进行监控,而Hangfire则是通过轮询Storage(如Sql或者队列)来实现对Job的处理。

也就是说Hangfire理论上是没有任何对Hangfire站点本身的请求,它类似于自己一个while(true)死循环不断地轮询Storage拿到Job任务就执行。

关于Hangfire的系列可以参考官方的说明 http://docs.hangfire.io/en/latest/

虽说Hangfire自己有个Dashboard可以对Hangfire执行的任务进行监控,如下

但是一众的其他站点我全部在Azure的Portal里一目了然,就你一个Hangfire的要我跑到你自己家的Dashboard来看终归不爽,而且也容易忘,导致Hangfire站点常年处于被遗忘的角落。

最近发生了一个Hangfire站点因为某些外部原因没起来(宕掉)的事件之后更加速了要将Hangfire的监控统一到Ai里。

搜索

首先去github上找下有没相关解决方案,老实说觉得基于ai的第三方扩展还是蛮多的,在github搜ai相关的还是能搜索出好几页(https://github.com/topics/application-insights),但并没有找到我需要的。

然后google一下找到有人在hangfire论坛里问跟我类似的问题,然而也没有解决方案(https://discuss.hangfire.io/t/integrating-application-insights-appinsights-into-hangfire/3009)。

既然找不到,那干脆自己撸起袖子干。

开干

首先我们回顾下Ai默认自己监控的原理:

前文说了它有个HttpModule会在请求进来的创建一个RequestTelemetry,

并且会在线程上下文内创建个OperationId,然后在该Request的作用于内所有其他数据(如异常/Http请求/Sql请求)都会跟这个Id关联,

这个Id甚至会在你发送Http请求的时候附加在你的Http Header里,然后接收到该Http请求的站点假如也用了Ai的话会根据这个Header里的Id再进行二次关联(调用链路关联)。

先解决AI需要的相关基础知识

我们要自己在Hangfire里弄AI监控的话,其实重点就是怎么能让Request里的Id能传递到Hangfire里,然后在Hangfire一个操作的作用域里保持该Id一致(串联所有操作)。

那问题重点就清楚了,就是如何解决这个Id的问题。

那Ai自己是如何产生或者获取这个Id的呢,在Ai的2.4版本后引入了对System.Diagnostics.DiagnosticSource这个包的依赖。

所有的Id关联它都基于由此包提供的Activity这个类来事现,详情可以参考 http://apmtips.com/blog/2018/01/23/diagnosticssource-design-principles/

如果需要在自己系统里设置一个Id关联的系统的话也强烈推荐使用Activity这个类来进行处理。

别人实现的比自己弄的科学多了,之前我也自己用AsyncLocal来做过,但是后续也都替换成了Activity,

通过Activity.Current可以获取到当前的Activity实例,通过new Activity然后调用其Start方法也能快速启动一个Activity,

到此Ai相关所需要的知识就都准备妥当了。

然后解决Hangfire需要的相关基础知识

从Hangfire的角度来说,它只要提供2个功能支持就可以了。

在任务入队的时候,在数据里面要塞入在当前Request操作的Id,因为我要将Hangfire的操作能够跟Request里相关联起来。

在任务执行的时候,拿到任务数据的时候,要能取出这个Id,然后将这个Id通过Activity进行Start,然后再任务执行完之后要Stop掉这个Activity并释放掉。

(画的图”有点”丑,但大概就这个意思)

为了解决这个问题查找了下Hangfire全局过滤器相关的资料找到它有IServerFilter和IClientFilter这2个东西:

IServerFilter:服务端处理的过滤器,就是Hangfire Server在执行一个Job的时候要进行处理的过滤器,可在此位置给Hangfire的Job设置Ai的Id到上下文。

IClientFilter:客户端处理的过滤器,就是Hangfire Client在一个Job入队的时候要进行处理的过滤器,可在此位置将Request里的Id赋值给Job Data。

那在Client的时候如何解决每次都能自动塞个Id进去呢?

我的解决思路是定义个JobDtoBase,所有Hangfire任务的数据都要继承自这个类,里面就一个Id,然后通过IClientFilter在每次入队的时候都将当前Activity.Current.Id扔进去

(需要考虑Acitivity.Current为null的情况)

然后如何在Server端自动将这个Id来启动一个Activity并完成监控呢?

我是想着通过IServerFilter里通过PerformingContext里获取Job的参数然后用is来判断如果是JobDtoBase就取它的Id出来然后启动Activity并创建RequestTelemetry。

重点是在Server这边执行结束之后需要将RequestTelemetry和Activity释放掉,所以通过ThreadStatic的静态变量来对其保持引用。

效果

效果如何这个问题暂时我只能呵呵哒,因为也是刚折腾出来还没投入线上运行。

不过从测试环境来看,确实能抓到我hangfire的请求并在Ai里作为Request进行展示:

而且还能抓到依赖项跟”Request”的关联:

所以至少测试的情况来说应该是达到目的了,等之后投入线上后在看下最终具体效果。

Hangfire使用ApplicationInsigts监控的更多相关文章

  1. 关于hangfire的使用

    hangfire 是一个分布式后台执行服务.用它可以代替ThreadPool.QueunItemWork等原生方法.当然4.5后的 task也是相当好用且功能强大.不过如果想分布式处理并且可监控的话, ...

  2. ABP Framework 5.0 RC.1 新特性和变更说明

    .Net 6.0 发布之后,ABP Framework 也在第一时间进行了升级,并在一个多星期后(2021-11-16)发布了 5.0 RC.1 ,新功能和重要变更基本已经确定. 5.0版本新特性 新 ...

  3. Hangfire项目实践分享

    Hangfire项目实践分享 目录 Hangfire项目实践分享 目录 什么是Hangfire Hangfire基础 基于队列的任务处理(Fire-and-forget jobs) 延迟任务执行(De ...

  4. Hangfire项目实践

    Hangfire项目实践分享 Hangfire项目实践分享 目录 Hangfire项目实践分享 目录 什么是Hangfire Hangfire基础 基于队列的任务处理(Fire-and-forget ...

  5. 关于 hangfire 的权限问题

    hangfire 是一个分布式后台执行服务. 官网:http://hangfire.io/ 我看中hangfire的地方是 1:使用简单 2:多种持久化保存方案.支持sqlserver ,msmq等 ...

  6. [开源] 基于ABP,Hangfire的开源Sharepoint文件同步程序----SuperRocket.SPSync

    (一)项目背景 Sharepoint是微软的一个产品,很多公司都在使用它,也有很多公司以前使用它,现在可能需要移植到别的平台,也可能只是移植其中的文件存储,比如说移植到微软云,或者亚马逊云存储.Sup ...

  7. 【框架学习与探究之定时器--Hangfire】

    声明 本文欢迎转载,请注明文章原始出处:http://www.cnblogs.com/DjlNet/p/7603632.html 前言 在上篇文章当中我们知道关于Quartz.NET的一些情况,其实博 ...

  8. 后台工作者HangFire与ABP框架Abp.Hangfire及扩展

    HangFire与Quartz.NET相比主要是HangFire的内置提供集成化的控制台,方便后台查看及监控,对于大家来说,比较方便. HangFire是什么 Hangfire是一个开源框架(.NET ...

  9. .Net 5分钟搞定网页实时监控

    一.为什么会用到网页实时监控 LZ最近在无锡买房了,虽然在上海工作,但是上海房价实在太高无法承受,所以选择还可以接受的无锡作为安身之地.买过房的小伙伴可能知道买房的流程,买房中间有一步很重要的就是需要 ...

随机推荐

  1. Java 多线程之哪个对象才是锁?

    问题背景 在感觉正常的使用ArrayList的迭代删除的操作的时候,发现了如下的崩溃日志: Caused by: java.util.ConcurrentModificationException a ...

  2. JBox使用详解

    插件说明 - jBox 是一款基于 jQuery 的多功能对话框插件,能够实现网站的整体风格效果,给用户一个新的视觉享受. 运行环境 - 兼容 IE6+.Firefox.Chrome.Safari.O ...

  3. css学习の第一弹—格式创建

    构成结构:选择符(又称为选择qi器){声明(属性:值):}*****注意:大括号,冒号,每个声明后的分号. 注释:/*注释内容写在这里*/ 一.css样式 css样式写的地方的不同分类:内联式.嵌入式 ...

  4. redis笔记总结之redis安装

    二.Redis安装 2.1 Redis下载 官网地址:http://redis.io/ 下载地址:http://download.redis.io/releases/redis-3.0.0.tar.g ...

  5. Starting a Gradle Daemon, 5 busy and 1 incompatible and 1 stopped Daemons could not be reused, use --status for details FAILURE: Build failed with an exception. * What went wrong: Could not dispatch

    执行gradle build出的问题,查看hs_err_pid11064.log日志文件发现,是电脑的RAM不足导致

  6. memcache搭建

    memcache搭建步骤: 个人原创,允许转载,请注明出处,作者,否则追究法律责任. 0.1 memcache的服务端0.2 mysql的服务端0.3 memcache 的客户端:lamp架构 1,环 ...

  7. 排序算法Java实现(归并排序)

    算法描述:对于给定的一组记录,首先将每两个相邻的长度为1的子序列进行归并,得到 n/2(向上取整)个长度为2或1的有序子序列,再将其两两归并,反复执行此过程,直到得到一个有序序列. package s ...

  8. ES6中export及export default的区别

    相信很多人都使用过export.export default.import,然而它们到底有什么区别呢? 在JavaScript ES6中,export与export default均可用于导出常量.函 ...

  9. Markdown 语法手册 (完整整理版)

    http://blog.csdn.net/witnessai1/article/details/52551362

  10. 【Ansible】 基于SSH的远程管理工具

    [Ansible] 参考文档:[http://www.ansible.com.cn/docs/intro.html] 和ansible类似的工具还有saltstack,puppet,sshpass等, ...