【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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章