Skip to content
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

Merged
merged 5 commits into from
Jan 15, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions config.example.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@ targets:
simple-probe:
- namespace: monitoring
rps: 1.0


icmp:
- name: 'google'
host: 'www.google.com'
rps: 0.5 # 2 RPS
timeout: '1s'
ttl: 100
- name: 'digikala'
host: 'www.digikala.com'
rps: 0.5 # 2 RPS
timeout: '1s'

8 changes: 8 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ type Target struct {
HTTP []HTTP `mapstructure:"http"`
DNS []DNS `mapstructure:"dns"`
K8S K8S `mapstructure:"k8s"`
ICMP []ICMP `mapstructure:"icmp"`
}

type HTTP struct {
Expand Down Expand Up @@ -72,3 +73,10 @@ type K8S_SimpleProbe struct {
NameSpace string `mapstructure:"namespace"`
RPS float64 `mapstructure:"rps"`
}
type ICMP struct {
Name string `mapstructure:"name"`
Host string `mapstructure:"host"`
TTL int `mapstructure:"ttl"`
RPS float64 `mapstructure:"rps"`
Timeout time.Duration `mapstructure:"timeout"`
}
8 changes: 8 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ require (
k8s.io/klog/v2 v2.40.1
)

require (
github.com/go-ping/ping v0.0.0-20211130115550-779d1e919534
github.com/kr/pretty v0.2.0
)

require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.1.1 // indirect
Expand All @@ -23,9 +28,11 @@ require (
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/go-cmp v0.5.6 // indirect
github.com/google/gofuzz v1.1.0 // indirect
github.com/google/uuid v1.2.0 // indirect
github.com/googleapis/gnostic v0.5.5 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/magiconair/properties v1.8.5 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
github.com/mitchellh/mapstructure v1.4.2 // indirect
Expand All @@ -41,6 +48,7 @@ require (
github.com/spf13/pflag v1.0.5 // indirect
github.com/subosito/gotenv v1.2.0 // indirect
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f // indirect
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
Expand Down
5 changes: 5 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,8 @@ github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-ping/ping v0.0.0-20211130115550-779d1e919534 h1:dhy9OQKGBh4zVXbjwbxxHjRxMJtLXj3zfgpBYQaR4Q4=
github.com/go-ping/ping v0.0.0-20211130115550-779d1e919534/go.mod h1:xIFjORFzTxqIV/tDVGO4eDy/bLuSyawEeojSm3GfRGk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
Expand Down Expand Up @@ -209,6 +211,8 @@ github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLe
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs=
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0=
Expand Down Expand Up @@ -262,6 +266,7 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxv
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs=
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
Expand Down
8 changes: 8 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,14 @@ func main() {
} else {
klog.Infof("K8S Prober is Disabled")
}
for _, i := range config.Get().Targets.ICMP {

icmpProber := prober.NewICMP(i.Name, i.Host, i.RPS, i.TTL, i.Timeout)
klog.Infof("Probing ICMP target '%s' with host '%s', RPS: %.2f, timeout: %s, ttl: %v\n",
i.Name, i.Host, i.RPS, i.Timeout, i.TTL)
go icmpProber.Start(ctx)

}

mux := http.NewServeMux()
mux.Handle("/metrics", promhttp.Handler())
Expand Down
141 changes: 141 additions & 0 deletions prober/icmp.go
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 {
Copy link
Member

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.

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",
Copy link
Member

Choose a reason for hiding this comment

The 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{
Copy link
Member

Choose a reason for hiding this comment

The 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))
})()

}
}
}