prometheus的网络ping监控exporter
Posted 姚__
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了prometheus的网络ping监控exporter相关的知识,希望对你有一定的参考价值。
轻量级的对网站和服务的ping监控插件,使用go语言实现
核心代码比较简单
github地址
已经有编译好的可执行文件。windows执行bat,linux执行sh
直接执行main -h 可以查看帮助
启动方法
./main -port 8889 -pingaddr www.baidu.com -count 4
启动后访问 127.0.0.1:8889/metrics
可以查看到输出指标,有无法访问次数和平均延迟统计信息
下面是代码,参考网上大佬的,我改造加了我的需求
package main
import (
"bytes"
"encoding/binary"
"flag"
"fmt"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"log"
"net"
"net/http"
"strconv"
"time"
)
var (
opsQueued = prometheus.NewGaugeVec(
prometheus.GaugeOpts
Name: "run_times",
Help: "Number of run times.",
,
[]string
// Which user has requested the operation?
"addr",
// Of what type is the operation?
"type",
,
)
pingResult = prometheus.NewGauge(
prometheus.GaugeOpts
Name: "ping_avg_time",
Help: "Time of the ping avg.",
)
pingLost = prometheus.NewGauge(
prometheus.GaugeOpts
Name: "ping_lost",
Help: "lost of the ping.",
)
)
func init()
// Metrics have to be registered to be exposed:
prometheus.MustRegister(opsQueued)
prometheus.MustRegister(pingResult)
prometheus.MustRegister(pingLost)
const (
MAX_PG = 2000
)
// 封装 icmp 报头
type ICMP struct
Type uint8
Code uint8
Checksum uint16
Identifier uint16
SequenceNum uint16
var (
originBytes []byte
githubPath string = "https://github.com"
version string = "v1.0"
listenAddress string
help bool
pingAddress string
pingTimes int64
)
func init()
originBytes = make([]byte, MAX_PG)
flag.StringVar(&listenAddress,"port","8888","this exporter listened port")
flag.BoolVar(&help,"h",false,"help")
flag.Int64Var(&pingTimes,"count",4,"ping count")
flag.StringVar(&pingAddress,"pingaddr","www.baidu.com","pingaddr")
func CheckSum(data []byte) (rt uint16)
var (
sum uint32
length int = len(data)
index int
)
for length > 1
sum += uint32(data[index])<<8 + uint32(data[index+1])
index += 2
length -= 2
if length > 0
sum += uint32(data[index]) << 8
rt = uint16(sum) + uint16(sum>>16)
return ^rt
func Ping(domain string, PS, Count int)
var (
icmp ICMP
laddr = net.IPAddrIP: net.ParseIP("0.0.0.0") // 得到本机的IP地址结构
raddr, _ = net.ResolveIPAddr("ip", domain) // 解析域名得到 IP 地址结构
max_lan, min_lan, avg_lan float64
)
// 返回一个 ip socket
conn, err := net.DialIP("ip4:icmp", &laddr, raddr)
if err != nil
fmt.Println(`socket Error:`+err.Error())
pingResult.Set(3000)
pingLost.Set(100)
return
defer conn.Close()
// 初始化 icmp 报文
icmp = ICMP8, 0, 0, 0, 0
var buffer bytes.Buffer
binary.Write(&buffer, binary.BigEndian, icmp)
//fmt.Println(buffer.Bytes())
binary.Write(&buffer, binary.BigEndian, originBytes[0:PS])
b := buffer.Bytes()
binary.BigEndian.PutUint16(b[2:], CheckSum(b))
//fmt.Println(b)
fmt.Printf("\\n正在 Ping %s 具有 %d(%d) 字节的数据:\\n", raddr.String(), PS, PS+28)
recv := make([]byte, 1024)
ret_list := []float64
dropPack := 0.0 /*统计丢包的次数,用于计算丢包率*/
max_lan = 3000.0
min_lan = 0.0
avg_lan = 0.0
for i := Count; i > 0; i--
/*
向目标地址发送二进制报文包
如果发送失败就丢包 ++
*/
if _, err := conn.Write(buffer.Bytes()); err != nil
dropPack++
time.Sleep(time.Second)
continue
// 否则记录当前得时间
t_start := time.Now()
conn.SetReadDeadline((time.Now().Add(time.Second * 3)))
len, err := conn.Read(recv)
/*
查目标地址是否返回失败
如果返回失败则丢包 ++
*/
if err != nil
dropPack++
time.Sleep(time.Second)
continue
t_end := time.Now()
dur := float64(t_end.Sub(t_start).Nanoseconds()) / 1e6
ret_list = append(ret_list, dur)
if dur < max_lan
max_lan = dur
if dur > min_lan
min_lan = dur
fmt.Printf("来自 %s 的回复: 大小 = %d byte 时间 = %.3fms\\n", raddr.String(), len ,dur)
time.Sleep(time.Second)
fmt.Printf("丢包率: %.2f%%\\n", dropPack/float64(Count)*100)
if len(ret_list) == 0
avg_lan = 3000.0
else
sum := 0.0
for _, n := range ret_list
sum += n
avg_lan = sum / float64(len(ret_list))
fmt.Printf("rtt 最短 = %.3fms 平均 = %.3fms 最长 = %.3fms\\n", min_lan, avg_lan, max_lan)
pingResult.Set(Decimal(avg_lan))
pingLost.Set(Decimal(dropPack/float64(Count)*100))
func Decimal(value float64) float64
value, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", value), 64)
return value
func main()
flag.Parse()
if help
flag.Usage()
return
if(pingTimes>100)
fmt.Printf("最大次数不能超过100")
return
go func()
for
fmt.Printf("开始执行ping \\n")
Ping(pingAddress, 32, int(pingTimes))
opsQueued.WithLabelValues(pingAddress, "ping").Inc()
time.Sleep(10 * time.Second)
()
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request)
w.Write([]byte(`<html>
<head><title>Ping_exporter</title></head>
<body>
<h1><a style="text-decoration:none" href='` + githubPath + `'>Ping_exporter</a></h1>
<p><a href='\\metrics'>Metrics</a></p>
<h2>Build</h2>
<pre>` + version + `</pre>
</body>
</html>`))
)
// The Handler function provides a default handler to expose metrics
// via an HTTP server. "/metrics" is the usual endpoint for that.
http.Handle("/metrics", promhttp.Handler())
log.Fatal(http.ListenAndServe(`:`+listenAddress, nil))
以上是关于prometheus的网络ping监控exporter的主要内容,如果未能解决你的问题,请参考以下文章
Prometheus blackbox-exporter ICMP ping 监控配置所有目标都显示出来
使用prometheus+blackbox_exporter监控httpicmp网络性能
性能监控之 Blackbox_exporter+Prometheus+Grafana 实现网络探测