-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add/icmp prober #20
Add/icmp prober #20
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
package prober | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"net" | ||
"strconv" | ||
"time" | ||
|
||
"github.com/go-ping/ping" | ||
"github.com/prometheus/client_golang/prometheus" | ||
klog "k8s.io/klog/v2" | ||
) | ||
|
||
var ( | ||
icmpRequests = prometheus.NewCounterVec( | ||
prometheus.CounterOpts{ | ||
Name: "health_icmp_requests_total", | ||
Help: "The number of icmp requests", | ||
}, | ||
[]string{"name", "ttl", "result", "host"}, | ||
) | ||
icmpDurations = prometheus.NewHistogramVec( | ||
prometheus.HistogramOpts{ | ||
Name: "health_icmp_duration_seconds", | ||
Help: "The response time of icmp requests", | ||
Buckets: []float64{0.001, 0.005, 0.01, 0.02, 0.03, 0.05, 0.075, 0.1, 0.2, 0.5, 0.75, 1, 1.5, 2, 2.5, 3, 4, 5}, | ||
}, | ||
[]string{"name", "ttl", "result", "host"}, | ||
) | ||
) | ||
|
||
type ICMP struct { | ||
Name string | ||
Host string | ||
TTL int | ||
RPS float64 | ||
Timeout time.Duration | ||
ticker *time.Ticker | ||
} | ||
type ICMPResult struct { | ||
Size int | ||
IPAddr *net.IPAddr | ||
Seq int | ||
RTT time.Duration | ||
TTL int | ||
ErrorType string | ||
Error error | ||
} | ||
|
||
// TODO: it could be a bad practice! | ||
func init() { | ||
prometheus.MustRegister(icmpDurations) | ||
prometheus.MustRegister(icmpRequests) | ||
|
||
} | ||
func NewICMP(name string, host string, rps float64, ttl int, timeout time.Duration) ICMP { | ||
|
||
return ICMP{ | ||
Name: name, | ||
Host: host, | ||
TTL: ttl, | ||
RPS: rps, | ||
Timeout: timeout, | ||
} | ||
|
||
} | ||
func (i *ICMP) calculateInterval() time.Duration { | ||
return time.Duration(1000.0/i.RPS) * time.Millisecond | ||
} | ||
|
||
func (i *ICMP) sendRequest(ctx context.Context) ICMPResult { | ||
icmpresult := ICMPResult{} | ||
pinger, err := ping.NewPinger(i.Host) | ||
if err != nil { | ||
return ICMPResult{Error: err} | ||
} | ||
//set default | ||
pinger.Timeout = time.Second * 100000 | ||
pinger.TTL = 64 | ||
pinger.Timeout = i.Timeout | ||
if i.TTL != 0 { | ||
pinger.TTL = i.TTL | ||
} | ||
pinger.SetPrivileged(false) | ||
pinger.OnRecv = func(pkt *ping.Packet) { | ||
fmt.Printf("%d bytes from %s: icmp_seq=%d time=%v ttl=%v\n", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. please remove this |
||
pkt.Nbytes, pkt.IPAddr, pkt.Seq, pkt.Rtt, pkt.Ttl) | ||
icmpresult = ICMPResult{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do we need to save and resturn a full ICMPResult? if we are not using those results in anyway, so why should we have them in struct? (e.g. Size, Seq,,...). We can only use the values which we are using (log, metric.observe, etc). If we ever need them, we can add those later (YAGNI :D) |
||
Size: pkt.Nbytes, | ||
IPAddr: pkt.IPAddr, | ||
Seq: pkt.Seq, | ||
RTT: pkt.Rtt, | ||
TTL: pkt.Ttl, | ||
} | ||
} | ||
err = pinger.Run() | ||
if err != nil { | ||
return ICMPResult{Error: err} | ||
} | ||
return icmpresult | ||
|
||
} | ||
|
||
func (i *ICMP) Start(ctx context.Context) { | ||
|
||
i.ticker = time.NewTicker(i.calculateInterval()) | ||
defer i.ticker.Stop() | ||
|
||
for { | ||
select { | ||
case <-ctx.Done(): | ||
klog.Info("Context is done!") | ||
return | ||
case <-i.ticker.C: | ||
go (func() { | ||
stats := i.sendRequest(ctx) | ||
var result string | ||
if stats.Error == nil { | ||
result = "icmp_success" | ||
} else { | ||
result = "icmp_error" | ||
} | ||
|
||
icmpRequests.With(prometheus.Labels{ | ||
"host": i.Host, | ||
"result": result, | ||
"name": i.Name, | ||
"ttl": strconv.Itoa(stats.TTL), | ||
}).Inc() | ||
icmpDurations.With(prometheus.Labels{ | ||
"host": i.Host, | ||
"result": result, | ||
"name": i.Name, | ||
"ttl": strconv.Itoa(stats.TTL), | ||
}).Observe(float64(stats.RTT)) | ||
})() | ||
|
||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can move this to a utils.go
func calculateInterval(rps int) time.Duration {
and refactor other modules (http, dns) with this function as well. We can do this in another PR if you want to merge this before that.