精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

通過Exporter收集一切指標(biāo)

安全 應(yīng)用安全
Exporter 是一個采集監(jiān)控數(shù)據(jù)并通過 Prometheus 監(jiān)控規(guī)范對外提供數(shù)據(jù)的組件,它負(fù)責(zé)從目標(biāo)系統(tǒng)(Your 服務(wù))搜集數(shù)據(jù),并將其轉(zhuǎn)化為 Prometheus 支持的格式。

[[420791]]

本文轉(zhuǎn)載自微信公眾號「運(yùn)維開發(fā)故事」,作者沒有文案的夏老師。轉(zhuǎn)載本文請聯(lián)系運(yùn)維開發(fā)故事公眾號。

Exporter介紹

Exporter 是一個采集監(jiān)控數(shù)據(jù)并通過 Prometheus 監(jiān)控規(guī)范對外提供數(shù)據(jù)的組件,它負(fù)責(zé)從目標(biāo)系統(tǒng)(Your 服務(wù))搜集數(shù)據(jù),并將其轉(zhuǎn)化為 Prometheus 支持的格式。Prometheus 會周期性地調(diào)用 Exporter 提供的 metrics 數(shù)據(jù)接口來獲取數(shù)據(jù)。那么使用 Exporter 的好處是什么?舉例來說,如果要監(jiān)控 Mysql/Redis 等數(shù)據(jù)庫,我們必須要調(diào)用它們的接口來獲取信息(前提要有),這樣每家都有一套接口,這樣非常不通用。所以 Prometheus 做法是每個軟件做一個 Exporter,Prometheus 的 Http 讀取 Exporter 的信息(將監(jiān)控指標(biāo)進(jìn)行統(tǒng)一的格式化并暴露出來)。簡單類比,Exporter 就是個翻譯,把各種語言翻譯成一種統(tǒng)一的語言。

對于Exporter而言,它的功能主要就是將數(shù)據(jù)周期性地從監(jiān)控對象中取出來進(jìn)行加工,然后將數(shù)據(jù)規(guī)范化后通過端點(diǎn)暴露給Prometheus,所以主要包含如下3個功能。

  • 封裝功能模塊獲取監(jiān)控系統(tǒng)內(nèi)部的統(tǒng)計信息。
  • 將返回數(shù)據(jù)進(jìn)行規(guī)范化映射,使其成為符合Prometheus要求的格式化數(shù)據(jù)。
  • Collect模塊負(fù)責(zé)存儲規(guī)范化后的數(shù)據(jù),最后當(dāng)Prometheus定時從Exporter提取數(shù)據(jù)時,Exporter就將Collector收集的數(shù)據(jù)通過HTTP的形式在/metrics端點(diǎn)進(jìn)行暴露。

介紹Primetheus client

本文將介紹Primetheus client的使用,基于golang語言,golang client 是當(dāng)pro收集所監(jiān)控的系統(tǒng)的數(shù)據(jù)時,用于響應(yīng)pro的請求,按照一定的格式給pro返回數(shù)據(jù),說白了就是一個http server, 源碼參見github,相關(guān)的文檔參見GoDoc,讀者可以直接閱讀文檔進(jìn)行開發(fā),本文只是幫助理解。以下是簡化流程圖:

四種數(shù)據(jù)類型

prometheus將所有數(shù)據(jù)保存為timeseries data,用metric name和label區(qū)分,label是在metric name上的更細(xì)維度的劃分,其中的每一個實(shí)例是由一個float64和timestamp組成,只不過timestamp是隱式加上去的,有時候不會顯示出來。如下面所示(數(shù)據(jù)來源于prometheus暴露的監(jiān)控數(shù)據(jù),訪問http://localhost:9090/metrics 可得),其中g(shù)o_gc_duration_seconds是metrics name,quantile="0.5"是key-value pair的label,而后面的值是float64 value。

  1. # HELP go_gc_duration_seconds A summary of the GC invocation durations. 
  2. # TYPE go_gc_duration_seconds summary 
  3. go_gc_duration_seconds{quantile="0.5"} 0.000107458 
  4. go_gc_duration_seconds{quantile="0.75"} 0.000200112 
  5. go_gc_duration_seconds{quantile="1"} 0.000299278 
  6. go_gc_duration_seconds_sum 0.002341738 
  7. go_gc_duration_seconds_count 18 
  8. # HELP go_goroutines Number of goroutines that currently exist. 
  9. # TYPE go_goroutines gauge 
  10. go_goroutines 107 

這些信息有一個共同點(diǎn),就是采用了不同于JSON或者Protocol Buffers的數(shù)據(jù)組織形式——文本形式。在文本形式中,每個指標(biāo)都占用一行,#HELP代表指標(biāo)的注釋信息,#TYPE用于定義樣本的類型注釋信息,緊隨其后的語句就是具體的監(jiān)控指標(biāo)(即樣本)。#HELP的內(nèi)容格式如下所示,需要填入指標(biāo)名稱及相應(yīng)的說明信息。

  1. HELP <metrics_name> <doc_string> 

#TYPE的內(nèi)容格式如下所示,需要填入指標(biāo)名稱和指標(biāo)類型(如果沒有明確的指標(biāo)類型,需要返回untyped)。

  1. TYPE <metrics_name> <metrics_type> 

監(jiān)控樣本部分需要滿足如下格式規(guī)范。

  1. metric_name [ "{" label_name "=" " label_value " { "," label_name "=" " label_value " } [ "," ] "}" ] value [ timestamp ] 

其中,metric_name和label_name必須遵循PromQL的格式規(guī)范。value是一個f loat格式的數(shù)據(jù),timestamp的類型為int64(從1970-01-01 00:00:00開始至今的總毫秒數(shù)),可設(shè)置其默認(rèn)為當(dāng)前時間。具有相同metric_name的樣本必須按照一個組的形式排列,并且每一行必須是唯一的指標(biāo)名稱和標(biāo)簽鍵值對組合。Prometheus為了方便client library的使用提供了四種數(shù)據(jù)類型:

Counter:Counter是一個累加的數(shù)據(jù)類型。一個Counter類型的指標(biāo)只會隨著時間逐漸遞增(當(dāng)系統(tǒng)重啟的時候,Counter指標(biāo)會被重置為0)。記錄系統(tǒng)完成的總?cè)蝿?wù)數(shù)量、系統(tǒng)從最近一次啟動到目前為止發(fā)生的總錯誤數(shù)等場景都適合使用Counter類型的指標(biāo)。

  • Gauge:Gauge指標(biāo)主要用于記錄一個瞬時值,這個指標(biāo)可以增加也可以減少,比如CPU的使用情況、內(nèi)存使用量以及硬盤當(dāng)前的空間容量等。
  • Histogram:Histogram表示柱狀圖,主要用于統(tǒng)計一些數(shù)據(jù)分布的情況,可以計算在一定范圍內(nèi)的數(shù)據(jù)分布情況,同時還提供了指標(biāo)值的總和。在大多數(shù)情況下,用戶會使用某些指標(biāo)的平均值作為參考,例如,使用系統(tǒng)的平均響應(yīng)時間來衡量系統(tǒng)的響應(yīng)能力。這種方式有個明顯的問題——如果大多數(shù)請求的響應(yīng)時間都維持在100ms內(nèi),而個別請求的響應(yīng)時間需要1s甚至更久,那么響應(yīng)時間的平均值體現(xiàn)不出響應(yīng)時間中的尖刺,這就是所謂的“長尾問題”。為了更加真實(shí)地反映系統(tǒng)響應(yīng)能力,常用的方式是按照請求延遲的范圍進(jìn)行分組,例如在上述示例中,可以分別統(tǒng)計響應(yīng)時間在[0,100ms]、[100,1s]和[1s,∞]這3個區(qū)間的請求數(shù),通過查看這3個分區(qū)中請求量的分布,就可以比較客觀地分析出系統(tǒng)的響應(yīng)能力。
  • Summary:Summary與Histogram類似,也會統(tǒng)計指標(biāo)的總數(shù)(以_count作為后綴)以及sum值(以_sum作為后綴)。兩者的主要區(qū)別在于,Histogram指標(biāo)直接記錄了在不同區(qū)間內(nèi)樣本的個數(shù),而Summary類型則由客戶端計算對應(yīng)的分位數(shù)。例如下面展示了一個Summary類型的指標(biāo),其中quantile=”0.5”表示中位數(shù),quantile=”0.9”表示九分位數(shù)。

廣義上講,所有可以向Prometheus提供監(jiān)控樣本數(shù)據(jù)的程序都可以被稱為一個Exporter,Exporter的一個實(shí)例被稱為target,Prometheus會通過輪詢的形式定期從這些target中獲取樣本數(shù)據(jù)。

自己動手編寫一個Exporter

一般來說,絕大多數(shù)Exporter都是基于Go語言編寫的,一小部分是基于Python語言編寫的,還有很小一部分是使用Java語言編寫的。比如官方提供的Consul Metrics自定義采集器Exporter,如果是在Go語言的運(yùn)行環(huán)境下,需要按照如下所示代碼運(yùn)行這個Exporter。

  1. package main 
  2.   
  3. import ( 
  4.     "log" 
  5.     "net/http" 
  6.   
  7.     "github.com/prometheus/client_golang/prometheus" 
  8.     "github.com/prometheus/client_golang/prometheus/promhttp" 
  9.   
  10. var ( 
  11.     cpuTemp = prometheus.NewGauge(prometheus.GaugeOpts{ 
  12.         NameSpace: "our_idc"
  13.         Subsystem: "k8s" 
  14.         Name"cpu_temperature_celsius"
  15.         Help: "Current temperature of the CPU."
  16.     }) 
  17.     hdFailures = prometheus.NewCounterVec( 
  18.         prometheus.CounterOpts{ 
  19.             NameSpace: "our_idc"
  20.             Subsystem: "k8s" 
  21.             Name"hd_errors_total"
  22.             Help: "Number of hard-disk errors."
  23.         }, 
  24.         []string{"device"}, 
  25.     ) 
  26.   
  27. func init() { 
  28.     // Metrics have to be registered to be exposed: 
  29.     prometheus.MustRegister(cpuTemp) 
  30.     prometheus.MustRegister(hdFailures) 
  31.   
  32. func main() { 
  33.     cpuTemp.Set(65.3) 
  34.     hdFailures.With(prometheus.Labels{"device":"/dev/sda"}).Inc() 
  35.   
  36.     // The Handler function provides a default handler to expose metrics 
  37.     // via an HTTP server. "/metrics" is the usual endpoint for that. 
  38.     http.Handle("/metrics", promhttp.Handler()) 
  39.     log.Fatal(http.ListenAndServe(":8888", nil)) 

其中創(chuàng)建了一個gauge和CounterVec對象,并分別指定了metric name和help信息,其中CounterVec是用來管理相同metric下不同label的一組Counter,同理存在GaugeVec,可以看到上面代碼中聲明了一個lable的key為“device”,使用的時候也需要指定一個lable: hdFailures.With(prometheus.Labels{"device":"/dev/sda"}).Inc()。變量定義后進(jìn)行注冊,最后再開啟一個http服務(wù)的8888端口就完成了整個程序,Prometheus采集數(shù)據(jù)是通過定期請求該服務(wù)http端口來實(shí)現(xiàn)的。啟動程序之后可以在web瀏覽器里輸入http://localhost:8888/metrics 就可以得到client暴露的數(shù)據(jù),其中有片段顯示為:

  1. # HELP our_idc_k8s_cpu_temperature_celsius Current temperature of the CPU. 
  2. # TYPE our_idc_k8s_cpu_temperature_celsius gauge 
  3. our_idc_k8s_cpu_temperature_celsius 65.3 
  4. # HELP our_idc_k8s_hd_errors_total Number of hard-disk errors. 
  5. # TYPE our_idc_k8s_hd_errors_total counter 
  6. our_idc_k8s_hd_errors_total{device="/dev/sda"} 1 

上圖就是示例程序所暴露出來的數(shù)據(jù),并且可以看到counterVec是有l(wèi)abel的,而單純的gauage對象卻不用lable標(biāo)識,這就是基本數(shù)據(jù)類型和對應(yīng)Vec版本的差別。此時再查看http://localhost:9090/graph 就會發(fā)現(xiàn)服務(wù)狀態(tài)已經(jīng)變?yōu)閁P了。上面的例子只是一個簡單的demo,因?yàn)樵趐rometheus.yml配置文件中我們指定采集服務(wù)器信息的時間間隔為60s,每隔60s Prometheus會通過http請求一次自己暴露的數(shù)據(jù),而在代碼中我們只設(shè)置了一次gauge變量cupTemp的值,如果在60s的采樣間隔里將該值設(shè)置多次,前面的值就會被覆蓋,只有Prometheus采集數(shù)據(jù)那一刻的值能被看到,并且如果不再改變這個值,Prometheus就始終能看到這個恒定的變量,除非用戶顯式通過Delete函數(shù)刪除這個變量。使用Counter,Gauage等這些結(jié)構(gòu)比較簡單,但是如果不再使用這些變量需要我們手動刪,我們可以調(diào)用resetfunction來清除之前的metrics。

自定義Collector

直接使用Collector,go client Colletor只會在每次響應(yīng)Prometheus請求的時候才收集數(shù)據(jù)。需要每次顯式傳遞變量的值,否則就不會再維持該變量,在Prometheus也將看不到這個變量。Collector是一個接口,所有收集metrics數(shù)據(jù)的對象都需要實(shí)現(xiàn)這個接口,Counter和Gauage等不例外。它內(nèi)部提供了兩個函數(shù),Collector用于收集用戶數(shù)據(jù),將收集好的數(shù)據(jù)傳遞給傳入?yún)?shù)Channel就可;Descirbe函數(shù)用于描述這個Collector。

當(dāng)收集系統(tǒng)收集的數(shù)據(jù)太多時時,就可以自定義Collector收集的方式,優(yōu)化流程,并且在某些情況下如果已經(jīng)有了一個成熟的metrics,就不需要使用Counter,Gauage等這些數(shù)據(jù)結(jié)構(gòu),直接在Collector內(nèi)部實(shí)現(xiàn)一個代理的功能即可。

基本上所有的export都是通過自定義Collector實(shí)現(xiàn)。一個簡單的Collector的實(shí)現(xiàn)export的代碼如下:

  1. package main 
  2.  
  3. import ( 
  4.  "github.com/prometheus/client_golang/prometheus" 
  5.  "github.com/prometheus/client_golang/prometheus/promhttp" 
  6.  "net/http" 
  7.  "sync" 
  8.  
  9. type ClusterManager struct { 
  10.  sync.Mutex 
  11.  Zone              string 
  12.  metricMapCounters map[string]string 
  13.  metricMapGauges   map[string]string 
  14.  
  15. //Simulate prepare the data 
  16. func (c *ClusterManager) ReallyExpensiveAssessmentOfTheSystemState() ( 
  17.  metrics map[string]float64, 
  18. ) { 
  19.  metrics = map[string]float64{ 
  20.   "oom_crashes_total": 42.00, 
  21.   "ram_usage":         6.023e23, 
  22.  } 
  23.  return 
  24. //通過NewClusterManager方法創(chuàng)建結(jié)構(gòu)體及對應(yīng)的指標(biāo)信息,代碼如下所示。 
  25. // NewClusterManager creates the two Descs OOMCountDesc and RAMUsageDesc. Note 
  26. // that the zone is set as a ConstLabel. (It's different in each instance of the 
  27. // ClusterManager, but constant over the lifetime of an instance.) Then there is 
  28. // a variable label "host", since we want to partition the collected metrics by 
  29. // host. Since all Descs created in this way are consistent across instances, 
  30. // with a guaranteed distinction by the "zone" label, we can register different 
  31. // ClusterManager instances with the same registry. 
  32. func NewClusterManager(zone string) *ClusterManager { 
  33.  return &ClusterManager{ 
  34.   Zone: zone, 
  35.   metricMapGauges: map[string]string{ 
  36.    "ram_usage""ram_usage_bytes"
  37.   }, 
  38.   metricMapCounters: map[string]string{ 
  39.    "oom_crashes""oom_crashes_total"
  40.   }, 
  41.  } 
  42. //首先,采集器必須實(shí)現(xiàn)prometheus.Collector接口,也必須實(shí)現(xiàn)Describe和Collect方法。實(shí)現(xiàn)接口的代碼如下所示。 
  43. // Describe simply sends the two Descs in the struct to the channel. 
  44. // Prometheus的注冊器調(diào)用Collect來抓取參數(shù)  
  45. // 將收集的數(shù)據(jù)傳遞到Channel中并返回  
  46. // 收集的指標(biāo)信息來自Describe,可以并發(fā)地執(zhí)行抓取工作,但是必須要保證線程的安全  
  47.  
  48. func (c *ClusterManager) Describe(ch chan<- *prometheus.Desc) { 
  49.  // prometheus.NewDesc(prometheus.BuildFQName(namespace, "", metricName), docString, labels, nil) 
  50.  for _, v := range c.metricMapGauges { 
  51.   ch <- prometheus.NewDesc(prometheus.BuildFQName(c.Zone, "", v), v, nil, nil) 
  52.  } 
  53.  
  54.  for _, v := range c.metricMapCounters { 
  55.   ch <- prometheus.NewDesc(prometheus.BuildFQName(c.Zone, "", v), v, nil, nil) 
  56.  } 
  57.  
  58. //Collect方法是核心,它會抓取你需要的所有數(shù)據(jù),根據(jù)需求對其進(jìn)行分析,然后將指標(biāo)發(fā)送回客戶端庫。 
  59. // 用于傳遞所有可能指標(biāo)的定義描述符  
  60. // 可以在程序運(yùn)行期間添加新的描述,收集新的指標(biāo)信息  
  61. // 重復(fù)的描述符將被忽略。兩個不同的Collector不要設(shè)置相同的描述符  
  62. func (c *ClusterManager) Collect(ch chan<- prometheus.Metric) { 
  63.  c.Lock() 
  64.  defer c.Unlock() 
  65.  m := c.ReallyExpensiveAssessmentOfTheSystemState() 
  66.  for k, v := range m { 
  67.   t := prometheus.GaugeValue 
  68.   if c.metricMapCounters[k] != "" { 
  69.    t = prometheus.CounterValue 
  70.   } 
  71.   c.registerConstMetric(ch, k, v, t) 
  72.  } 
  73. // 用于傳遞所有可能指標(biāo)的定義描述符給指標(biāo) 
  74. func (c *ClusterManager) registerConstMetric(ch chan<- prometheus.Metric, metric string, val float64, valType prometheus.ValueType, labelValues ...string) { 
  75.  descr := prometheus.NewDesc(prometheus.BuildFQName(c.Zone, "", metric), metric, nil, nil) 
  76.  if m, err := prometheus.NewConstMetric(descr, valType, val, labelValues...); err == nil { 
  77.   ch <- m 
  78.  } 
  79.  
  80. func main() { 
  81.  workerCA := NewClusterManager("xiaodian"
  82.  reg := prometheus.NewPedanticRegistry() 
  83.  reg.MustRegister(workerCA) 
  84.     //當(dāng)promhttp.Handler()被執(zhí)行時,所有metric被序列化輸出。題外話,其實(shí)輸出的格式既可以是plain text,也可以是protocol Buffers。 
  85.  http.Handle("/metrics", promhttp.HandlerFor(reg, promhttp.HandlerOpts{})) 
  86.  http.ListenAndServe(":8888", nil) 

此時就可以去http://localhost:8888/metrics 看到傳遞過去的數(shù)據(jù)了。

高質(zhì)量Exporter的編寫原則與方法

主要方法

參考鏈接:https://prometheus.io/docs/instrumenting/writing_exporters/。1.在訪問Exporter的主頁(即http://yourExporter/這樣的根路徑)時,它會返回一個簡單的頁面,這就是Exporter的落地頁(Landing Page)。落地頁中可以放文檔和幫助信息,包括監(jiān)控指標(biāo)項(xiàng)的說明。落地頁上還包括最近執(zhí)行的檢查列表、列表的狀態(tài)以及調(diào)試信息,這對故障排查非常有幫助。

2.一臺服務(wù)器或者容器上可能會有許多Exporter和Prometheus組件,它們都有自己的端口號。因此,在寫Exporter和發(fā)布Exporter之前,需要檢查新添加的端口是否已經(jīng)被使用[1],建議使用默認(rèn)端口分配范圍之外的端口。

3.我們應(yīng)該根據(jù)業(yè)務(wù)類型設(shè)計好指標(biāo)的#HELP#TYPE的格式。這些指標(biāo)往往是可配置的,包括默認(rèn)開啟的指標(biāo)和默認(rèn)關(guān)閉的指標(biāo)。這是因?yàn)榇蟛糠种笜?biāo)并不會真正被用到,設(shè)計過多的指標(biāo)不僅會消耗不必要的資源,還會影響整體的性能。

其他方法

對于如何寫高質(zhì)量Exporter,除了合理分配端口號、設(shè)計落地頁、梳理指標(biāo)這3個方面外,還有一些其他的原則。

  • 記錄Exporter本身的運(yùn)行狀態(tài)指標(biāo)。
  • 可配置化進(jìn)行功能的啟用和關(guān)閉。
  • 推薦使用YAML作為配置格式。
  • 遵循度量標(biāo)準(zhǔn)命名的最佳實(shí)踐[2],特別是_count、_sum、_total、_bucket和info等問題。
  • 為度量提供正確的單位。
  • 標(biāo)簽的唯一性、可讀性及必要的冗余信息設(shè)計。
  • 通過Docker等方式一鍵配置Exporter。
  • 盡量使用Collectors方式收集指標(biāo),如Go語言中的MustNewConstMetric。
  • 提供scrapes刮擦失敗的錯誤設(shè)計,這有助于性能調(diào)試。
  • 盡量不要重復(fù)提供已有的指標(biāo),如Node Exporter已經(jīng)提供的CPU、磁盤等信息。
  • 向Prometheus公開原始的度量數(shù)據(jù),不建議自行計算,Exporter的核心是采集原始指標(biāo)。

Redis Exporter源碼解析

在本章中,讀者可以發(fā)現(xiàn)開源領(lǐng)域有著不計其數(shù)的Exporter,阿里巴巴開源的Exporter就有RocketMQ Exporter、Sentinel Exporter、Sentry Exporter、Alibaba Cloud Exporter等多種。編寫Exporter和編寫Spring Boot Starter一樣,可以多參考其他優(yōu)秀的開源軟件的代碼。本節(jié)就來簡單分析一下運(yùn)維工作中用到的Redis Exporter源碼。在使用Redis Exporter時,可以通過redis_exporter--help命令查看完整的參數(shù)列表。默認(rèn)情況下,它在端口9192上運(yùn)行,并在路徑/metrics上暴露指標(biāo)??梢酝ㄟ^--web.listen-addres和--web.telemetry-path命令來設(shè)置端口和路徑,代碼如下所示。

  1. redis_exporter -web.listen-address=":8888" -web.telemetry-path="/node_metrics" 

上述代碼將修改redis Exporter綁定到端口8888并在路徑/node_metrics上暴露指標(biāo)。這個邏輯是在源碼redis_exporter.go中實(shí)現(xiàn)的.Redis Exporter[3]主要通過Redis原生的命令獲取Redis所有的信息,它支持2.x、3.x、4.x、5.x和6.x版本。在源碼中,可以看到多處使用了doRedisCmd方法發(fā)送命令以獲取性能指標(biāo),代碼如下所示。主要是通過原生的INFO命令獲取所有性能信息。該命令的返回結(jié)果詳情參考[4]。

  1. infoAll, err := redis.String(doRedisCmd(c, "INFO""ALL")) 

生成的infoAll信息通過func (e *Exporter) extractInfoMetrics(ch chan<- prometheus.Metric, info string, dbCount int)繼續(xù)處理。它的主要目的是遍歷查詢到的結(jié)果,根據(jù)指標(biāo)生成一個hash值。源代碼如下所示:

  1. func (e *Exporter) extractInfoMetrics(ch chan<- prometheus.Metric, info string, dbCount int) { 
  2.  keyValues := map[string]string{} 
  3.  handledDBs := map[string]bool{} 
  4.  
  5.  fieldClass := "" 
  6.     //以換行符進(jìn)行分割 
  7.  lines := strings.Split(info, "\n"
  8.  masterHost := "" 
  9.  masterPort := "" 
  10.     //遍歷查詢到的結(jié)果,根據(jù)指標(biāo)生成一個hash值 
  11.  for _, line := range lines { 
  12.   line = strings.TrimSpace(line) 
  13.   log.Debugf("info: %s", line) 
  14.         //去除帶#的注釋文件 
  15.   if len(line) > 0 && strings.HasPrefix(line, "# ") { 
  16.    fieldClass = line[2:] 
  17.    log.Debugf("set fieldClass: %s", fieldClass) 
  18.    continue 
  19.   } 
  20.         //去除不帶:的或者字符小于2的 
  21.   if (len(line) < 2) || (!strings.Contains(line, ":")) { 
  22.    continue 
  23.   } 
  24.         //以冒號進(jìn)行分割 
  25.   split := strings.SplitN(line, ":", 2) 
  26.   fieldKey := split[0] 
  27.   fieldValue := split[1] 
  28.         //將指標(biāo)名稱與值存到hash中 
  29.   keyValues[fieldKey] = fieldValue 
  30.  
  31.   if fieldKey == "master_host" { 
  32.    masterHost = fieldValue 
  33.   } 
  34.  
  35.   if fieldKey == "master_port" { 
  36.    masterPort = fieldValue 
  37.   } 
  38.         //按照集群和副本和哨兵模式進(jìn)行處理 
  39.   switch fieldClass { 
  40.  
  41.   case "Replication"
  42.    if ok := e.handleMetricsReplication(ch, masterHost, masterPort, fieldKey, fieldValue); ok { 
  43.     continue 
  44.    } 
  45.  
  46.   case "Server"
  47.    e.handleMetricsServer(ch, fieldKey, fieldValue) 
  48.  
  49.   case "Commandstats"
  50.    e.handleMetricsCommandStats(ch, fieldKey, fieldValue) 
  51.    continue 
  52.  
  53.   case "Keyspace"
  54.    if keysTotal, keysEx, avgTTL, ok := parseDBKeyspaceString(fieldKey, fieldValue); ok { 
  55.     dbName := fieldKey 
  56.  
  57.     e.registerConstMetricGauge(ch, "db_keys", keysTotal, dbName) 
  58.     e.registerConstMetricGauge(ch, "db_keys_expiring", keysEx, dbName) 
  59.  
  60.     if avgTTL > -1 { 
  61.      e.registerConstMetricGauge(ch, "db_avg_ttl_seconds", avgTTL, dbName) 
  62.     } 
  63.     handledDBs[dbName] = true 
  64.     continue 
  65.    } 
  66.  
  67.   case "Sentinel"
  68.    e.handleMetricsSentinel(ch, fieldKey, fieldValue) 
  69.   } 
  70.  
  71.   if !e.includeMetric(fieldKey) { 
  72.    continue 
  73.   } 
  74.         //將收集到信息進(jìn)行按照一定規(guī)則進(jìn)行處理 
  75.   e.parseAndRegisterConstMetric(ch, fieldKey, fieldValue) 
  76.  } 
  77.  
  78.  for dbIndex := 0; dbIndex < dbCount; dbIndex++ { 
  79.   dbName := "db" + strconv.Itoa(dbIndex) 
  80.   if _, exists := handledDBs[dbName]; !exists { 
  81.    e.registerConstMetricGauge(ch, "db_keys", 0, dbName) 
  82.    e.registerConstMetricGauge(ch, "db_keys_expiring", 0, dbName) 
  83.   } 
  84.  } 
  85.        
  86.  e.registerConstMetricGauge(ch, "instance_info", 1, 
  87.   keyValues["role"], 
  88.   keyValues["redis_version"], 
  89.   keyValues["redis_build_id"], 
  90.   keyValues["redis_mode"], 
  91.   keyValues["os"], 
  92.   keyValues["maxmemory_policy"], 
  93.   keyValues["tcp_port"], keyValues["run_id"], keyValues["process_id"], 
  94.  ) 
  95.  
  96.  if keyValues["role"] == "slave" { 
  97.   e.registerConstMetricGauge(ch, "slave_info", 1, 
  98.    keyValues["master_host"], 
  99.    keyValues["master_port"], 
  100.    keyValues["slave_read_only"]) 
  101.  } 

然后通過e.parseAndRegisterConstMetric(ch, fieldKey, fieldValue)方法,將收集到hash中的信息,按照一定的規(guī)則生成prometheus.Metric。核心代碼如下:

  1. func (e *Exporter) registerConstMetric(ch chan<- prometheus.Metric, metric string, val float64, valType prometheus.ValueType, labelValues ...string) { 
  2.  descr := e.metricDescriptions[metric] 
  3.  if descr == nil { 
  4.   descr = newMetricDescr(e.options.Namespace, metric, metric+" metric", labelValues) 
  5.  } 
  6.  
  7.  if m, err := prometheus.NewConstMetric(descr, valType, val, labelValues...); err == nil { 
  8.   ch <- m 
  9.  } 

最后*Exporter.Collect的方法調(diào)用registerConstMetric方法,就完成了redis的info指標(biāo)的收集。其他指標(biāo)的收集原來也是相同的,有興趣的讀者可以自行閱讀。

總結(jié)

本文介紹了Exporter的概念。Exporter的來源主要有兩個:一個是社區(qū)提供的,一個是用戶自定義的。在實(shí)際生產(chǎn)中,官方提供的Exporter主要涵蓋數(shù)據(jù)庫、硬件、問題跟蹤及持續(xù)集成、消息系統(tǒng)、存儲、HTTP、API、日志、其他監(jiān)控系統(tǒng)等,這些已有的Exporter可以滿足絕大多數(shù)開發(fā)人員及運(yùn)維人員的需求。對于系統(tǒng)、軟件沒有Exporter的情況,本章也從數(shù)據(jù)規(guī)范、數(shù)據(jù)采集方式、代碼案例撰寫等方面帶領(lǐng)讀者體驗(yàn)了Exporter的設(shè)計與實(shí)踐,一步步指導(dǎo)讀者打造定制化Exporter。為了幫助讀者形成良好的代碼風(fēng)格并能夠真正編寫高質(zhì)量Exporter,本章還給出了編寫高質(zhì)量Exporter的建議,并結(jié)合 Redis Exporter的原理進(jìn)行了實(shí)戰(zhàn)解析。通過對本章的學(xué)習(xí),讀者可以掌握使用和定制Exporter的能力。

[1] Exporter端口列表:https://github.com/prometheus/prometheus/wiki/Default-port-allocations。

[2] 標(biāo)準(zhǔn)命名最佳實(shí)踐:https://prometheus.io/docs/practices/naming。

[3] Redis Exporter地址:https://github.com/oliver006/redis_Exporter。

 

[4] Redis INFO命令地址:https://redis.io/commands/info。

 

責(zé)任編輯:武曉燕 來源: 運(yùn)維開發(fā)故事
相關(guān)推薦

2011-11-30 09:28:37

iCloud信息圖云計算

2014-11-20 17:46:08

2020-09-11 10:55:10

useState組件前端

2016-08-31 17:24:05

大數(shù)據(jù)分析

2012-12-31 11:22:58

開源開放

2021-02-19 23:08:27

軟件測試軟件開發(fā)

2018-11-23 11:17:24

負(fù)載均衡分布式系統(tǒng)架構(gòu)

2021-02-28 09:47:54

軟件架構(gòu)軟件開發(fā)軟件設(shè)計

2012-11-05 15:22:59

康普光纜DCD

2025-03-10 13:11:00

2015-07-17 09:59:18

2025-11-20 10:25:07

2020-10-14 08:04:28

JavaScrip

2020-09-16 11:46:05

AI

2021-05-28 07:12:59

Python閉包函數(shù)

2018-02-25 05:45:35

2023-04-27 09:27:44

視頻AI

2015-09-22 09:55:27

TalkingData大數(shù)據(jù)移動

2022-04-27 09:28:11

HTTPExpires

2013-11-04 14:02:24

AMD
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

久久久精品高清| 亚洲狠狠婷婷综合久久久| 精品无码av在线| 欧美日韩一区二区三区在线电影| 欧美日韩在线观看视频| 日本一区二区精品| 国产裸体永久免费无遮挡| 欧美日韩少妇| 亚洲欧美在线一区二区| 91视频这里只有精品| 日本aa在线| 久久久久久久国产精品影院| 国产日本欧美一区| 国产精品视频一区二区三| 清纯唯美亚洲经典中文字幕| 欧美日韩另类一区| 久久精品国产sm调教网站演员| 国产黄色在线| 成人午夜在线播放| 国产精品盗摄久久久| 免费一级片在线观看| 免费一区二区三区视频导航| 欧美一区二区三区婷婷月色| 99爱视频在线| 亚洲小说区图片| 国产网红主播福利一区二区| 97av影视网在线观看| 亚洲大尺度在线观看| 在线高清一区| xxxxx91麻豆| 人妻精品久久久久中文字幕| 精品一区二区三区在线观看视频| 91久久精品网| av7777777| 先锋影音在线资源站91| 中文字幕乱码亚洲精品一区| 久久久7777| 黄色一级大片在线免费看国产一| 极品销魂美女一区二区三区| 国产成人精品一区| 亚洲免费在线观看av| 欧美日本一区二区视频在线观看 | 99在线观看免费| 玖玖玖国产精品| 777精品视频| 国产亚洲欧美精品久久久www| 91精品国产自产拍在线观看蜜| 亚洲人精品午夜在线观看| 一本加勒比波多野结衣| 中文字幕一区二区三区中文字幕| 欧美乱妇一区二区三区不卡视频| 亚欧在线免费观看| 欧美极度另类| 一本色道久久加勒比精品 | 欧美亚洲三区| 午夜精品一区二区三区在线视 | 国外av在线| 97精品国产露脸对白| www.久久久| 亚洲一区二区人妻| 久久成人免费电影| 国产精品第3页| 欧美日韩乱国产| 亚洲国产美女| 国产最新精品视频| 久久久久久久久久久久久久久久久 | 久久av电影| 日韩国产一区三区| 亚洲激情 欧美| 欧美变态网站| 亚洲成人久久一区| 17c国产在线| 欧美在线va视频| 色哟哟亚洲精品| 欧美日韩第二页| 中文在线аv在线| 欧美性猛交丰臀xxxxx网站| 国产精品裸体瑜伽视频| 色综合999| 亚洲成人综合视频| 国产原创中文在线观看 | 欧美激情在线播放| 久久精品免费在线| 国产在线欧美| 高清一区二区三区四区五区| 日韩精品在线免费看| 一区二区三区精品视频在线观看| 羞羞色国产精品| 国产精品人人人人| 久久成人18免费观看| 国产区精品在线观看| 国产人妖在线播放| 国产成人免费xxxxxxxx| 国产亚洲欧美一区二区| 色窝窝无码一区二区三区成人网站| 成人毛片在线观看| 欧美一级视频在线播放| 奇米影视首页 狠狠色丁香婷婷久久综合 | 国产福利电影在线播放| 亚洲成人黄色影院| 俄罗斯av网站| 久久久久久一区二区三区四区别墅 | 日本道在线视频| √天堂8资源中文在线| 色婷婷亚洲综合| 性猛交ⅹ×××乱大交| 国产精久久久| 亚洲国产成人久久| av小说在线观看| 午夜精品av| 欧美主播福利视频| 国产精品久久久久久无人区| 成人成人成人在线视频| 日本一区二区三区精品视频| 欧美性猛交xxx乱大交3蜜桃| 一区二区三区欧美| 尤物av无码色av无码| 成人黄色免费观看| 欧美变态凌虐bdsm| 手机看片福利视频| 88国产精品视频一区二区三区| 久久全国免费视频| 国产偷人爽久久久久久老妇app| 国产精品中文字幕日韩精品| 久久久久无码国产精品一区| 九义人在线观看完整免费版电视剧| 亚洲电影在线免费观看| 国产又黄又猛又粗又爽的视频| 日韩黄色av| 亚洲人在线观看| 欧美成人精品欧美一级| 日韩成人一区二区三区在线观看| 波多野结衣久草一区| 成人影视在线播放| 亚洲一区二区三区小说| 欧美男女交配视频| 偷拍视屏一区| 九九热精品视频| 中文字幕日本人妻久久久免费 | 潘金莲一级淫片aaaaaaa| 嫩草影视亚洲| 久久久欧美一区二区| 亚洲网站在线免费观看| 99精品欧美一区二区三区综合在线| 伊人久久大香线蕉av一区| 日韩脚交footjobhd| 日韩亚洲欧美一区| 林心如三级全黄裸体| 国产精品亚洲欧美| 国产精品麻豆免费版| 污污的视频在线观看| 欧美午夜精品久久久久久孕妇| 免费成人蒂法网站| 欧美日韩亚洲一区在线观看| 成人久久久久久| shkd中文字幕久久在线观看| 精品免费在线视频| 久久久久国产精品无码免费看| 亚洲精品888| 国产主播精品在线| 欧美三级电影一区二区三区| 色婷婷国产精品久久包臀| 欧美无人区码suv| 极品中文字幕一区| 粉嫩av四季av绯色av第一区| 中文字幕免费高清电视剧网站在线观看 | 狠狠88综合久久久久综合网| 国产精品一区二区电影| 久久av少妇| 日本韩国欧美一区二区三区| 亚洲欧美视频在线播放| 日韩视频在线一区二区三区 | 中文字幕人成一区| 视频91a欧美| 日韩日本欧美亚洲| 国产乱淫av免费| 亚洲女子a中天字幕| 在线免费看v片| 欧美久久九九| 国产精品久久久一区二区三区 | 隔壁老王国产在线精品| 国产成人无码www免费视频播放| 亚洲国产综合91精品麻豆| 91精品人妻一区二区三区四区| 欧美午夜国产| 好吊色欧美一区二区三区视频| 蜜桃视频m3u8在线观看| 亚洲精品视频中文字幕| 日本中文字幕久久| 欧美国产成人精品| 亚洲va综合va国产va中文| 欧美+亚洲+精品+三区| 国产精品乱子乱xxxx| 超碰在线99| 夜夜嗨av色一区二区不卡| 亚洲在线精品视频| 亚洲精品日韩专区silk| 精品久久久久一区二区| 久久久国产亚洲精品| 水蜜桃一区二区| 日日夜夜亚洲| 久久久之久亚州精品露出| 神马电影在线观看| 欧美三区免费完整视频在线观看| 久久99久久99精品免费看小说| 国产成人av影院| 妞干网在线视频观看| 欧美女王vk| 国产精品高潮在线| 日韩激情av| 国产亚洲精品美女久久久| 国产绳艺sm调教室论坛| 欧美日韩在线视频观看| 天天操天天摸天天舔| 成人自拍视频在线观看| 亚洲色精品三区二区一区| 永久91嫩草亚洲精品人人| 精品久久久久久一区二区里番| 日本在线影院| 欧美精品中文字幕一区| 久久视频www| 日韩一级免费观看| 在线观看日韩中文字幕| 亚洲精品午夜久久久| 午夜理伦三级做爰电影| 国产精品77777竹菊影视小说| 99精品视频在线看| 日韩久久精品| 欧美久久久久久| 99久久人爽人人添人人澡| 国产精品久久久av久久久| 欧美理论片在线播放| 中文字幕日韩综合av| 丰满人妻一区二区| 欧美精品tushy高清| 日本高清不卡码| 亚洲在线观看免费视频| 又色又爽的视频| 久久久久久久久久久久久女国产乱| 在线看黄色的网站| 精品亚洲porn| 狠狠热免费视频| 中文国产一区| 亚洲中文字幕无码一区二区三区 | www.99re6| 久久亚洲欧美国产精品乐播| 精品久久久久久无码人妻| 久久国产精品72免费观看| 国产成人无码av在线播放dvd| 亚洲国产激情| 又大又硬又爽免费视频| 欧美国产三区| 99re99热| 999国产精品999久久久久久| 欧美日韩一区二区视频在线| 欧美深夜视频| 国产精品果冻传媒潘| 国产91精品入| 96pao国产成视频永久免费| 成人a在线观看高清电影| 国产精品aaaa| 欧美第一视频| 日韩美女在线播放| 亚洲人成在线网站| 91精品国产色综合久久不卡98| 性xxxfreexxxx性欧美| 久久久女人电视剧免费播放下载| 天堂成人av| 欧美精品性视频| 女子免费在线观看视频www| 九九久久综合网站| 影音先锋在线视频| 欧美激情精品久久久久久黑人| 影音先锋男人资源在线| 欧美大秀在线观看| 黄色的视频在线观看| 欧美激情视频在线免费观看 欧美视频免费一 | 欧美精品久久久久久久久老牛影院| 无码视频在线观看| 欧美伊人久久久久久久久影院| 麻豆成人免费视频| 欧美视频中文字幕| 91精品视频免费在线观看| 5858s免费视频成人| 国产熟女一区二区三区五月婷| 91精品国模一区二区三区| 国产浮力第一页| 亚洲第一网中文字幕| 高清乱码毛片入口| 亚洲伦理中文字幕| 成人免费高清在线播放| 日韩网站在线观看| 操你啦视频在线| 国内精品中文字幕| 欧美精品高清| 91美女片黄在线观看游戏| 国产欧美视频在线| 美日韩免费视频| 天天天综合网| 91九色丨porny丨国产jk| 久久精品30| 国产欧美精品一二三| 高清成人免费视频| www.狠狠爱| 国产精品免费aⅴ片在线观看| 久久精品免费av| 在线一区二区三区| 99精品在线视频观看| 亚洲黄色在线看| 日韩在线免费电影| 性欧美暴力猛交69hd| 69堂免费精品视频在线播放| 亚洲va久久久噜噜噜久久天堂| 国产成人一二片| 亚洲国产精品久久久久久女王| 亚洲色图88| www.日日操| 成人午夜又粗又硬又大| 人妻熟人中文字幕一区二区| 亚洲一级二级三级在线免费观看| 波多野结衣小视频| 在线成人免费视频| 狠狠狠综合7777久夜色撩人| 精品中文字幕在线观看| 9i看片成人免费高清| 91中文在线视频| 亚洲另类春色校园小说| 欧美日韩一区二区三区电影| 久久中文精品| 中文字幕影片免费在线观看| 亚洲欧美aⅴ...| 乱子伦一区二区三区| 精品福利在线导航| 激情成人四房播| 国产精品爱久久久久久久| 99久久婷婷国产综合精品青牛牛| 久久久婷婷一区二区三区不卡| 欧美午夜一区二区福利视频| 天天操天天摸天天爽| 91丨九色丨蝌蚪富婆spa| 91porn在线视频| 欧美午夜精品久久久久久超碰| 天堂av中文字幕| 久久97精品久久久久久久不卡| 福利精品一区| 亚洲欧洲日韩综合二区| 亚洲在线视频| 国模无码视频一区| 一区二区高清视频在线观看| 日韩国产亚洲欧美| 日韩精品一区二区三区在线播放 | av在线不卡电影| 丝袜 亚洲 另类 欧美 重口| 欧美视频在线一区| 国产三级在线免费观看| 青青草成人在线| 亚洲第一论坛sis| 成品人视频ww入口| 高清在线不卡av| 久久黄色免费网站| 日韩欧美成人午夜| 99自拍视频在线观看| 亚洲一区二区免费| 成人久久一区| 五月天婷婷影视| 亚洲欧美一区二区三区极速播放 | 在线电影一区二区三区| 最近高清中文在线字幕在线观看| 日韩av免费看网站| 国产影视一区| 国产小视频精品| 成人免费小视频| 国产高潮流白浆喷水视频| 欧美xxxx18国产| 99久久婷婷国产综合精品青牛牛 | 精品福利视频导航大全| 97视频网站入口| jlzzjlzz亚洲女人| 91丨九色丨蝌蚪| 亚洲激情自拍偷拍| 亚洲精品一区二区三区不卡| 久久久亚洲天堂| 窝窝社区一区二区| 国产男女在线观看| 国产精品久久久久久久久免费樱桃 | 久久久精品免费网站| 怡春院在线视频| 久久久av免费| 91综合久久爱com| 日韩精品视频久久| 欧美激情一区二区三区在线| 中文字幕无码乱码人妻日韩精品| 麻豆一区二区在线观看| 99久久免费精品国产72精品九九| 国产成人a亚洲精v品无码| 国产日产欧美一区| 国产裸体无遮挡| 欧美激情伊人电影| 精品无人区麻豆乱码久久久| 免费网站在线观看黄|