【go-monitor】基于golang的服务质量统计分析告警工具

简介

go-monitor基于golang开发,是一个轻量的,用于服务质量监控并实现分析告警的工具。go-monitor目前并不是一个独立的服务,而是希望被大多数基于golang开发的项目如同引入一个日志组件一样使用。

go-monitor能做什么

通过上报接口、函数、或者是任意调用服务的耗时以及其成功状态,go-monitor将按照设定的周期自动进行服务质量分析,统计,并输出详细的报告数据。

在服务质量达不到理想状态时,go-monitor将触发告警,并在服务质量回升时,触发恢复通知。

go-monitor提供非常多灵活的配置,以使其在大多数场景下都可以通过参数调整来胜任服务监控的职责。

go-monitor采用无锁队列的方式避免并发锁带来的性能问题,MBP2012版本实测500万次上报数据(go test bench)仅花费1.6s即完成所有分析统计(此前并发锁方案为1.9s),强大的性能允许你像记录日志一样来使用它,并且不需要担心IO压力(大部分日志组件使用缓存写盘的方式提升性能,大并发下IO压力明显)。

什么场景建议使用go-monitor

例如我们开发了一个web应用以对外提供服务,我们可以嵌入go-monitor,上报每一个访问的耗时、状态,以达到对我们整个web应用服务质量的监控,也可以在服务质量下滑甚至不可用时及时作出告警,更详尽的,我们可以上报任何一个调用服务的状态,例如我们所访问的数据库,所依赖的外部接口等,除了监控服务质量,事实上也可以通过go-monitor提供的统计数据了解任何一个服务的平均时延,大到一个完整的接口,小到一个数据库查询语句。而使用go-monitor的成本非常小,仅仅是在golang项目中引入go-monitor,像使用日志组件一样,毫无负担。

使用方法

安装

go get github.com/blurooo/go-monitor

引入使用

go-monitor的使用非常简单,只需调用其提供的Register函数即可注册得到一个上报客户端,上报客户端暴露了Report方法用于上报服务的耗时指标:

import (
    "github.com/blurooo/go-monitor"
    "time"
)

// 注册得到一个上报客户端用于http服务质量监控
var httpReportClient = monitor.Register(monitor.ReportClientConfig {
    Name: "http服务监控",
    StatisticalCycle: 100,  // 每100ms统计一次服务质量
})

func main() {
    t := time.NewTicker(10 * time.Millisecond)
    for curTime := range t.C {
        // 每10ms向http监控客户端上报一条http服务数据,耗时0-100ms,状态为200
        httpReportClient.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服务质量监控
var httpReportClient = monitor.Register(monitor.ReportClientConfig {
    Name: "http服务监控",
    StatisticalCycle: 100,  // 每100ms统计一次服务质量
    OutputCaller: func(o *monitor.OutPutData) {
        // 写入数据库等逻辑
        ...
    },
})

func main() {
    t := time.NewTicker(10 * time.Millisecond)
    for curTime := range t.C {
        // 每10ms向http监控客户端上报一条http服务数据,耗时0-100ms,状态为200
        httpReportClient.Report("GET - /app/api/users", uint32(curTime.Nanosecond() % 100), 200)
    }
}

go-monitor支持多实例,并鼓励使用多实例。实例之间互不影响,例如在同个应用下,我们除了可以注册一个http服务监控之外,还可以注册一个函数耗时监控:

// 注册得到一个上报客户端用于http服务质量监控
var httpReportClient = monitor.Register(monitor.ReportClientConfig {
    Name: "http服务监控",
})

// 注册得到一个上报客户端用于函数耗时监控
var funcReportClient = monitor.Register(monitor.ReportClientConfig {
    Name: "函数耗时监控",
})

go-monitor除了分析统计之外,还帮助实现告警策略,这依赖于服务异常的判定规则。默认当上报code为200时,认为成功。当然,在大多数应用中,如此简单的判定规则通常难以胜任各类复杂的场景。所以go-monitor允许我们使用白名单的方式定制自己的一套规则:

// 注册得到一个上报客户端用于http服务质量监控
var httpReportClient = monitor.Register(monitor.ReportClientConfig {
    Name: "http服务监控",
    CodeFeatureMap: map[int]monitor.CodeFeature {
        0: {
            Success: true,
            Name: "成功",
        },
        10000: {
            Success: false,
            Name: "服务不可用",
        },
    }
})

CodeFeatureMap中允许声明该状态码是否成功,并指定其名称(使用在统计报告中),除此之外的code都将认为失败。

除了使用白名单机制来决断code之外,go-monitor也提供了一个适应性更强的方式去判定(优先于CodeFeatureMap):

// 注册得到一个上报客户端用于http服务质量监控
var httpReportClient = monitor.Register(monitor.ReportClientConfig {
    Name: "http服务监控",
    GetCodeFeature: func(code int) (success bool, name string) {
        if code == 0 {
            return true, "成功"
        } else {
            return false, "失败"
        }
    },
})

在每个统计周期内,成功率达不到期望的值时,该条目将被标记,在连续标记若干个统计周期之后,go-monitor便会触发成功率不达标告警,告警数据明确指明了具体的监控服务和告警条目,并附带连续被标记为成功率不达标的几次统计数据,默认打印到控制台,但同样允许我们定制,我们可以按照自己的意愿处理,例如发送邮件通知相关人等:

// 注册得到一个上报客户端用于http服务质量监控
var httpReportClient = monitor.Register(monitor.ReportClientConfig {
    Name: "http服务监控",
    AlertCaller: func(clientName string, interfaceName string, alertType monitor.AlertType, recentOutputData []monitor.OutPutData) {
        // 处理相关告警
    }
})

除了成功率不达标告警,go-monitor也提供了耗时不达标告警,精确到每个监控条目都允许定制耗时达标参数。

// 一个上报客户端全局的耗时达标值
var httpReportClient = 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即可:

var httpReportClient = monitor.Register(monitor.ReportClientConfig {
    Name: "http服务监控",
    RecoverCaller: func(clientName string, interfaceName string, alertType monitor.AlertType, recentOutputData []monitor.OutPutData) {
        // 处理恢复通知
    },
})

还有更多灵活的配置在go-monitor中得到支持,欢迎大家在使用中发现它们,更欢迎有意向的开发人参与到这份工作来,在设想中,希望go-monitor可以脱胎为一个完善的独立服务,以支持任何系统接入(包括前后端上报),并提供尽可能多的现成方案,例如统计数据输出到数据库,邮箱告警,接口通知等。在此抛砖引玉了:github

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容