ping plugin done
This commit is contained in:
parent
48803f41a9
commit
e79e5e4e27
|
@ -70,6 +70,10 @@ func (r *Reader) gatherOnce() {
|
|||
|
||||
now := time.Now()
|
||||
for i := 0; i < len(samples); i++ {
|
||||
if samples[i] == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if samples[i].Timestamp.IsZero() {
|
||||
samples[i].Timestamp = now
|
||||
}
|
||||
|
|
|
@ -3,7 +3,15 @@
|
|||
|
||||
[[instances]]
|
||||
# send ping packets to
|
||||
targets = ["example.org"]
|
||||
targets = [
|
||||
"www.baidu.com",
|
||||
"127.0.0.1",
|
||||
"10.4.5.6",
|
||||
"10.4.5.7"
|
||||
]
|
||||
|
||||
# # append some labels for series
|
||||
# labels = { region="cloud", product="n9e" }
|
||||
|
||||
# # interval = global.interval * interval_times
|
||||
# interval_times = 1
|
||||
|
@ -34,10 +42,3 @@ targets = ["example.org"]
|
|||
## Number of data bytes to be sent. Corresponds to the "-s"
|
||||
## option of the ping command.
|
||||
# size = 56
|
||||
|
||||
[[instances]]
|
||||
# send ping packets to
|
||||
targets = [
|
||||
"127.0.0.1",
|
||||
"192.168.8.12"
|
||||
]
|
||||
|
|
3
go.mod
3
go.mod
|
@ -3,6 +3,7 @@ module flashcat.cloud/categraf
|
|||
go 1.17
|
||||
|
||||
require (
|
||||
github.com/go-ping/ping v0.0.0-20211130115550-779d1e919534
|
||||
github.com/gobwas/glob v0.2.3
|
||||
github.com/godror/godror v0.33.0
|
||||
github.com/golang/protobuf v1.5.2
|
||||
|
@ -27,6 +28,7 @@ require (
|
|||
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||
github.com/godror/knownpb v0.1.0 // indirect
|
||||
github.com/gogo/protobuf v1.1.1 // indirect
|
||||
github.com/google/uuid v1.2.0 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
|
||||
|
@ -35,6 +37,7 @@ require (
|
|||
github.com/yusufpapurcu/wmi v1.2.2 // indirect
|
||||
go.uber.org/automaxprocs v1.4.0 // indirect
|
||||
golang.org/x/net v0.0.0-20210525063256-abc453219eb5 // indirect
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
|
||||
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27 // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987 // indirect
|
||||
|
|
9
go.sum
9
go.sum
|
@ -87,6 +87,8 @@ github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
|
|||
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
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-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
|
||||
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
|
||||
|
@ -159,6 +161,8 @@ github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hf
|
|||
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
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/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
|
||||
|
@ -350,6 +354,7 @@ golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/
|
|||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
|
||||
golang.org/x/net v0.0.0-20210525063256-abc453219eb5 h1:wjuX4b5yYQnEQHzd+CBcrcC6OVR2J1CN6mUy0oSxIPo=
|
||||
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
|
@ -366,8 +371,9 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
|
|||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a h1:DcqTD9SDLc+1P/r1EmRBwnVsrOwW+kk2vWf9n+1sGhs=
|
||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
|
@ -404,6 +410,7 @@ golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
|
|
|
@ -22,10 +22,15 @@ func Add(name string, creator Creator) {
|
|||
InputCreators[name] = creator
|
||||
}
|
||||
|
||||
func NewSample(metric string, value float64, labels ...map[string]string) *types.Sample {
|
||||
func NewSample(metric string, value interface{}, labels ...map[string]string) *types.Sample {
|
||||
floatValue, err := conv.ToFloat64(value)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
s := &types.Sample{
|
||||
Metric: metric,
|
||||
Value: value,
|
||||
Value: floatValue,
|
||||
Labels: make(map[string]string),
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,10 @@ package ping
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
@ -10,21 +13,26 @@ import (
|
|||
"flashcat.cloud/categraf/config"
|
||||
"flashcat.cloud/categraf/inputs"
|
||||
"flashcat.cloud/categraf/types"
|
||||
"github.com/go-ping/ping"
|
||||
"github.com/toolkits/pkg/container/list"
|
||||
)
|
||||
|
||||
const inputName = "ping"
|
||||
const (
|
||||
inputName = "ping"
|
||||
defaultPingDataBytesSize = 56
|
||||
)
|
||||
|
||||
type PingInstance struct {
|
||||
Targets []string `toml:"targets"`
|
||||
IntervalTimes int64 `toml:"interval_times"`
|
||||
Count int `toml:"count"` // ping -c <COUNT>
|
||||
PingInterval float64 `toml:"ping_interval"` // ping -i <INTERVAL>
|
||||
Timeout float64 `toml:"timeout"` // ping -W <TIMEOUT>
|
||||
Deadline int `toml:"deadline"` // ping -w <DEADLINE>
|
||||
Interface string `toml:"interface"` // ping -I/-S <INTERFACE/SRC_ADDR>
|
||||
IPv6 bool `toml:"ipv6"` // Whether to resolve addresses using ipv6 or not.
|
||||
Size int `toml:"size"` // Packet size
|
||||
Targets []string `toml:"targets"`
|
||||
Labels map[string]string `toml:"labels"`
|
||||
IntervalTimes int64 `toml:"interval_times"`
|
||||
Count int `toml:"count"` // ping -c <COUNT>
|
||||
PingInterval float64 `toml:"ping_interval"` // ping -i <INTERVAL>
|
||||
Timeout float64 `toml:"timeout"` // ping -W <TIMEOUT>
|
||||
Deadline int `toml:"deadline"` // ping -w <DEADLINE>
|
||||
Interface string `toml:"interface"` // ping -I/-S <INTERFACE/SRC_ADDR>
|
||||
IPv6 bool `toml:"ipv6"` // Whether to resolve addresses using ipv6 or not.
|
||||
Size *int `toml:"size"` // Packet size
|
||||
|
||||
calcInterval time.Duration
|
||||
calcTimeout time.Duration
|
||||
|
@ -133,5 +141,124 @@ func (p *Ping) Gather() (samples []*types.Sample) {
|
|||
func (p *Ping) gatherOnce(slist *list.SafeList, ins *PingInstance) {
|
||||
defer p.wg.Done()
|
||||
|
||||
fmt.Println("ping.....", ins.Targets)
|
||||
if ins.IntervalTimes > 0 {
|
||||
counter := atomic.LoadUint64(&p.Counter)
|
||||
if counter%uint64(ins.IntervalTimes) != 0 {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
wg := new(sync.WaitGroup)
|
||||
for _, target := range ins.Targets {
|
||||
wg.Add(1)
|
||||
go func(target string) {
|
||||
defer wg.Done()
|
||||
ins.gather(slist, target)
|
||||
}(target)
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
func (ins *PingInstance) gather(slist *list.SafeList, target string) {
|
||||
labels := map[string]string{"target": target}
|
||||
for k, v := range ins.Labels {
|
||||
labels[k] = v
|
||||
}
|
||||
|
||||
fields := map[string]interface{}{}
|
||||
|
||||
defer func() {
|
||||
for field, value := range fields {
|
||||
slist.PushFront(inputs.NewSample(field, value, labels))
|
||||
}
|
||||
}()
|
||||
|
||||
stats, err := ins.ping(target)
|
||||
if err != nil {
|
||||
log.Println("E! failed to ping:", target, "error:", err)
|
||||
if strings.Contains(err.Error(), "unknown") {
|
||||
fields["result_code"] = 1
|
||||
} else {
|
||||
fields["result_code"] = 2
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
fields["result_code"] = 0
|
||||
|
||||
if stats.PacketsSent == 0 {
|
||||
if config.Config.DebugMode {
|
||||
log.Println("D! no packets sent, target:", target)
|
||||
}
|
||||
fields["result_code"] = 2
|
||||
return
|
||||
}
|
||||
|
||||
if stats.PacketsRecv == 0 {
|
||||
if config.Config.DebugMode {
|
||||
log.Println("D! no packets received, target:", target)
|
||||
}
|
||||
fields["result_code"] = 1
|
||||
fields["percent_packet_loss"] = float64(100)
|
||||
return
|
||||
}
|
||||
|
||||
fields["percent_packet_loss"] = float64(stats.PacketLoss)
|
||||
}
|
||||
|
||||
type pingStats struct {
|
||||
ping.Statistics
|
||||
ttl int
|
||||
}
|
||||
|
||||
func (ins *PingInstance) ping(destination string) (*pingStats, error) {
|
||||
ps := &pingStats{}
|
||||
|
||||
pinger, err := ping.NewPinger(destination)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create new pinger: %w", err)
|
||||
}
|
||||
|
||||
pinger.SetPrivileged(true)
|
||||
|
||||
if ins.IPv6 {
|
||||
pinger.SetNetwork("ip6")
|
||||
}
|
||||
|
||||
pinger.Size = defaultPingDataBytesSize
|
||||
if ins.Size != nil {
|
||||
pinger.Size = *ins.Size
|
||||
}
|
||||
|
||||
pinger.Source = ins.sourceAddress
|
||||
pinger.Interval = ins.calcInterval
|
||||
|
||||
if ins.Deadline > 0 {
|
||||
pinger.Timeout = time.Duration(ins.Deadline) * time.Second
|
||||
}
|
||||
|
||||
// Get Time to live (TTL) of first response, matching original implementation
|
||||
once := &sync.Once{}
|
||||
pinger.OnRecv = func(pkt *ping.Packet) {
|
||||
once.Do(func() {
|
||||
ps.ttl = pkt.Ttl
|
||||
})
|
||||
}
|
||||
|
||||
pinger.Count = ins.Count
|
||||
err = pinger.Run()
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "operation not permitted") {
|
||||
if runtime.GOOS == "linux" {
|
||||
return nil, fmt.Errorf("permission changes required, enable CAP_NET_RAW capabilities (refer to the ping plugin's README.md for more info)")
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("permission changes required, refer to the ping plugin's README.md for more info")
|
||||
}
|
||||
return nil, fmt.Errorf("%w", err)
|
||||
}
|
||||
|
||||
ps.Statistics = *pinger.Statistics()
|
||||
|
||||
return ps, nil
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue