本文介绍一个开源的Go语言监控项目。go-monitor基于golang开发,是一款轻量级的服务质量监控和告警分析工具。go-monitor目前不是一个独立的服务,而是希望像引入日志组件一样被大部分基于golang的项目使用。go-monitor可以做什么通过报告接口、函数或任意调用服务的耗时和成功状态,go-monitor会按照设定的周期自动进行服务质量分析、统计,并输出详细的报表数据。当服务质量达不到理想状态时,go-monitor会触发告警,当服务质量改善时,会触发恢复通知。go-monitor提供了很多灵活的配置,使得它可以在大多数场景下通过参数调整来完成服务监控的职责。go-monitor使用无锁队列来避免并发锁带来的性能问题。MBP2012版本实测500万上报数据(gotestbench)仅用1.6s完成所有分析统计(之前的并发锁方案为1.9s)。强大的性能让你可以像日志一样使用,无需担心IO压力(日志组件大多采用缓存写入磁盘来提升性能,大并发下IO压力明显)。什么场景推荐使用go-monitor?比如我们开发一个web应用对外提供服务,我们可以嵌入go-monitor来报告每次访问的耗时和状态,从而监控我们整个web应用的服务质量。当服务质量下降甚至不可用时,及时发出告警。更具体地说,我们可以报告任何调用服务的状态,比如我们访问的数据库,我们所依赖的外部接口等。除了监控服务质量,其实我们还可以使用go-提供的统计数据monitor了解任何服务的平均延迟,从一个完整的接口到一个小的数据库查询语句。使用go-monitor的成本很小,只是在golang项目中引入go-monitor,和使用日志组件一样,没有负担。使用方法安装gogetgithub.com/blurooo/go-monitor导入并使用go-monitor使用起来非常简单,只需要调用它提供的Register函数注册并获取一个reportingclient,reportingclient暴露出Report上报服务耗时指标方法:import("github.com/blurooo/go-monitor""time")//注册获取http服务质量监控的上报客户端varhttpReportClient=monitor.Register(monitor.ReportClientConfig{Name:"httpservicemonitoring",StatisticalCycle:100,//每100ms统计一次服务质量})funcmain(){t:=time.NewTicker(10*time.Millisecond)forcurTime:=ranget.C{//每10ms向http监控客户端上报一条http服务数据,耗时0-100ms,状态为200httpReportClient.Report("GET-/app/api/users",uint32(curTime.Nanosecond()%100),200)}}go-monitor会在每个统计周期(100ms,默认1min)输出一个服务质量分析报告,例如:{"timestamp":"2018-01-24T09:10:55.190503145Z","clientName":"http服务监控","interfaceName":"GET-/app/api/users","count":10,"successCount":10,“successRate”:1,“successMsAver”:48,“maxMs”:98,“minMs”:9,“fastCount”:10,“fastRate”:1,“failCount”:0,“failDistribution”:{},"timeConsumingDistribution":{"100~150":0,"150~200":0,"200~250":0,"250~300":0,"300~350":0,"350~400":0,"400~450":0,"450~500":0,"<100":10,">500":0}}默认的报表数据会在控制台输出,但是我们可以自定义,比如打印到日志文件或者写入数据库等,只需要传入我们自己的OutputCaller:import("github.com/Blurooo/go-monitor""time")//注册获取http服务质量监控的报表客户端varhttpReportClient=monitor.Register(monitor.ReportClientConfig{Name:"http服务监控",StatisticalCycle:100,//统计每100ms一次性服务质量OutputCaller:func(o*monitor.OutPutData){//写数据库等逻辑...},})funcmain(){t:=time.NewTicker(10*time.Millisecond)forcurTime:=ranget.C{//每10ms向http监控客户端上报一条http服务数据,耗时0-100ms,状态为200httpReportClient.Report("GET-/app/api/users",uint32(curTime.Nanosecond()%100),200)}}go-monitor支持多个实例并鼓励t他使用多个实例实例之间互不影响。比如在同一个应用中,我们不仅可以注册一个http服务监控,还可以注册一个函数耗时监控:ReportClientConfig{Name:"http服务监控",})//注册获取函数耗时监控的上报客户端varfuncReportClient=monitor.Register(monitor.ReportClientConfig{Name:"函数耗时监控",})中go-monitor除了分析统计数据,还有助于实现告警策略,告警策略依赖于服务异常的判断规则。默认情况下,当reportedcode为200时,认为成功。当然,在大多数应用中,这样简单的决策规则通常并不适用于各种复杂的场景。所以go-monitor允许我们使用白名单来自定义我们自己的一套规则://注册获取一个用于http服务质量监控的报告客户端varhttpReportClient=monitor.Register(monitor.ReportClientConfig{Name:"httpservicemonitoring",CodeFeatureMap:map[int]monitor.CodeFeature{0:{Success:true,Name:"Success",},10000:{Success:false,Name:"Serviceunavailable",},}})在CodeFeatureMap中是否允许声明状态码是否成功,并指定其名称(在统计报告中使用),其他代码将被视为失败。go-monitor除了使用白名单机制来判断代码外,还提供了一种更加适应性的判断方式(优先考虑CodeFeatureMap):ReportClientConfig{Name:"http服务监控",GetCodeFeature:func(codeint)(successbool,namestring){ifcode==0{returntrue,"success"}else{returnfalse,"failure"}},})在每个统计周期内,当成功率未达到预期值时,将标记该条目。连续标记几个统计周期后,go-monitor会触发成功率不达标的告警。告警数据明确表示具体的监控服务和告警入口,并附有连续数次标记为成功率不达标的统计数据。它默认打印到控制台,但也允许我们自定义它,我们可以根据自己的意愿进行处理,例如发送邮件通知相关人员://RegistertogetareportingclientforhttpservicequalitymonitoringvarhttpReportClient=monitor.Register(monitor.ReportClientConfig{Name:"http服务监控",AlertCaller:func(clientNamestring,interfaceNamestring,alertTypemonitor.AlertType,recentOutputData[]monitor.OutPutData){//处理相关告警}})除了成功率失败的告警,go-monitor还提供了耗时告警,足够准确,可以自定义每个监控项的达标时间参数。//一个全局的上报客户端耗时标准值varhttpReportClient=monitor.Register(monitor.ReportClientConfig{Name:"http服务监控",DefaultFastTime:1000,//设置http上报客户端的默认耗时标准为以内1000ms})//一个入口的耗时标准httpReportClient.AddEntryConfig("GET-/app/api/users",monitor.EntryConfig{FastLessThan:100,//设置接口"GET-/app/api/users"耗时标准值在100ms以内})go-monitor也支持服务质量恢复通知,类似告警策略。当出现告警状态时,后续连续统计数据标记为服务标准将触发恢复通知。我们就自定义RecoverCaller:varhttpReportClient=monitor.Register(monitor.ReportClientConfig{Name:"http服务监控",RecoverCaller:func(clientNamestring,interfaceNamestring,alertTypemonitor.AlertType,recentOutputData[]monitor.OutPutData){//句柄recoverynotification},})go-monitor中支持更多灵活的配置,欢迎大家在使用中发现,也欢迎有兴趣的开发者参与这项工作。在愿景中,希望go-monitor能够重生为一个完整的独立服务,支??持任何系统接入(包括前端和后端上报),并尽可能提供现成的解决方案,比如统计数据输出到数据库,邮箱告警,接口通知等。这里是一个好的开始:https://github.com/blurooo/go-monitor
