Hangfire使用ApplicationInsigts监控
起因
我司目前使用清真的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监控的更多相关文章
- 关于hangfire的使用
hangfire 是一个分布式后台执行服务.用它可以代替ThreadPool.QueunItemWork等原生方法.当然4.5后的 task也是相当好用且功能强大.不过如果想分布式处理并且可监控的话, ...
- ABP Framework 5.0 RC.1 新特性和变更说明
.Net 6.0 发布之后,ABP Framework 也在第一时间进行了升级,并在一个多星期后(2021-11-16)发布了 5.0 RC.1 ,新功能和重要变更基本已经确定. 5.0版本新特性 新 ...
- Hangfire项目实践分享
Hangfire项目实践分享 目录 Hangfire项目实践分享 目录 什么是Hangfire Hangfire基础 基于队列的任务处理(Fire-and-forget jobs) 延迟任务执行(De ...
- Hangfire项目实践
Hangfire项目实践分享 Hangfire项目实践分享 目录 Hangfire项目实践分享 目录 什么是Hangfire Hangfire基础 基于队列的任务处理(Fire-and-forget ...
- 关于 hangfire 的权限问题
hangfire 是一个分布式后台执行服务. 官网:http://hangfire.io/ 我看中hangfire的地方是 1:使用简单 2:多种持久化保存方案.支持sqlserver ,msmq等 ...
- [开源] 基于ABP,Hangfire的开源Sharepoint文件同步程序----SuperRocket.SPSync
(一)项目背景 Sharepoint是微软的一个产品,很多公司都在使用它,也有很多公司以前使用它,现在可能需要移植到别的平台,也可能只是移植其中的文件存储,比如说移植到微软云,或者亚马逊云存储.Sup ...
- 【框架学习与探究之定时器--Hangfire】
声明 本文欢迎转载,请注明文章原始出处:http://www.cnblogs.com/DjlNet/p/7603632.html 前言 在上篇文章当中我们知道关于Quartz.NET的一些情况,其实博 ...
- 后台工作者HangFire与ABP框架Abp.Hangfire及扩展
HangFire与Quartz.NET相比主要是HangFire的内置提供集成化的控制台,方便后台查看及监控,对于大家来说,比较方便. HangFire是什么 Hangfire是一个开源框架(.NET ...
- .Net 5分钟搞定网页实时监控
一.为什么会用到网页实时监控 LZ最近在无锡买房了,虽然在上海工作,但是上海房价实在太高无法承受,所以选择还可以接受的无锡作为安身之地.买过房的小伙伴可能知道买房的流程,买房中间有一步很重要的就是需要 ...
随机推荐
- C# 程序之间传参数,Args 接收参数的处理
备忘,或者留给暂未接触但需要了解的人. C#在一个进程内传参数方法那是相当多,但是涉及到程序之间传参数就不是那么方便了(当然socket,内存共享等方式属于另一类,此处不讨论),我们的C或者C#,亦或 ...
- Python爬虫获取异步加载站点pexels并下载图片(Python爬虫实战3)
1. 异步加载爬虫 对于静态页面爬虫很容易获取到站点的数据内容,然而静态页面需要全量加载站点的所有数据,对于网站的访问和带宽是巨大的挑战,对于高并发和大访问访问量的站点来说,需要使用AJAX相关的技术 ...
- k60引脚图
/*! 枚举管脚编号 */ typedef enum { /* PTA端口 */ //0~31 PTA0, PTA1, PTA2, PTA3, PTA4, PTA5, PTA6, PTA7, PTA8 ...
- redis学习系列——redis持久化
1.写操作的流程 2.RDB快照-redis的第一个持久化策略 第一种是以快照的形式持久化到本地磁盘(RDB文件). 持久化策略是: 1.配置(save N M)在N秒内,redis至少发生M次修改, ...
- 前端div层级控制
z-index:20000;使用此属性可以控制div的层级即哪个在上哪个在下
- 利用CVE-2017-11882拿到持久性shell
利用CVE-2017-11882拿到持久性shell 近日微软又爆出一个严重漏洞,利用该漏洞可以直接拿到目标机shell.这么好玩的东西怎么能错过了,于是搭建环境复现了一把. 首先去GitHub上下载 ...
- 理解 dispatch_get_specific
这篇文章原来在用 Github Pages 搭建的博客上,现在决定重新用回博客园,所以把文章搬回来. dispatch_queue_set_specific用于给一个队列设置相关的上下文数据,disp ...
- js工具函数《转载收藏》
1.等待所有图片加载 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 var imgObjs = [], count = 0; rotate.prize ...
- [模拟赛] T3 Exploit
Description 4X概念体系,是指在PC战略游戏中一种相当普及和成熟的系统概念,得名自4个同样以"EX"为开头的英语单词. eXplore(探索) eXpand(拓张与发展 ...
- oracle相同SID对外提供多个service_names
为数据库设置多个服务名(通过SCOPE=both设置,同时修改参数文件) SQL> show parameter service_names; NAME TYPE VALUE --------- ...