Skip to content

Commit

Permalink
ping plugin add exec method (#811)
Browse files Browse the repository at this point in the history
* ping plugin add exec method

* update ping plugin

* update ping plugin

---------

Co-authored-by: peter <>
  • Loading branch information
c88888 authored Feb 27, 2024
1 parent 6ab3751 commit afe93ed
Show file tree
Hide file tree
Showing 5 changed files with 564 additions and 3 deletions.
12 changes: 12 additions & 0 deletions conf/input.ping/ping.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,18 @@ targets = [
# "10.4.5.7"
]

## Method used for sending pings, can be either "exec" or "native". When set
## to "exec" the systems ping command will be executed. When set to "native"
## the plugin will send pings directly.
##
## While the default is "native" for backwards compatibility, new deployments
## are encouraged to use the "native" method for improved compatibility and
## performance.
# method = "exec"

## Specify the ping executable binary.
# binary = "ping"

# # append some labels for series
# labels = { region="cloud", product="n9e" }

Expand Down
25 changes: 25 additions & 0 deletions inputs/ping/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
ping 监控插件,探测远端目标地址能否 ping 通,如果机器没有禁 ping,这就是一个很好用的探测机器存活的手段

## Configuration
这个插件有两种主要的操作方法:`exec``native`.推荐使用 `native` 方法,因为它具有更好的系统兼容性和性能.
为了向后兼容和更精准的response_ms,`native` 方法是默认的.
使用 `method = "exec"`,将会调用系统ping程序来发送ping packets.

要探测的机器配置到 targets 中,targets 是个数组,可以配置多个,当然也可以拆成多个 `[[instances]]` 配置段,比如:

Expand Down Expand Up @@ -82,3 +85,25 @@ When using `method = "native"`, you will need permissions similar to the executa

大盘地址 [dashboard-2.0.json](https://github.com/flashcatcloud/categraf/tree/main/inputs/ping/dashboard-2.0.json)

## Example Output

```text
ping_maximum_response_ms agent_hostname=zy-fat product=n9e region=cloud target=10.0.24.136 0.036
ping_packets_transmitted agent_hostname=zy-fat product=n9e region=cloud target=10.0.24.136 1
ping_packets_received agent_hostname=zy-fat product=n9e region=cloud target=10.0.24.136 1
ping_average_response_ms agent_hostname=zy-fat product=n9e region=cloud target=10.0.24.136 0.036
ping_minimum_response_ms agent_hostname=zy-fat product=n9e region=cloud target=10.0.24.136 0.036
ping_standard_deviation_ms agent_hostname=zy-fat product=n9e region=cloud target=10.0.24.136 0
ping_result_code agent_hostname=zy-fat product=n9e region=cloud target=10.0.24.136 0
ping_percent_packet_loss agent_hostname=zy-fat product=n9e region=cloud target=10.0.24.136 0
ping_ttl agent_hostname=zy-fat product=n9e region=cloud target=10.0.24.136 64
ping_minimum_response_ms agent_hostname=zy-fat product=n9e region=cloud target=www.baidu.com 20.935
ping_average_response_ms agent_hostname=zy-fat product=n9e region=cloud target=www.baidu.com 20.935
ping_standard_deviation_ms agent_hostname=zy-fat product=n9e region=cloud target=www.baidu.com 0
ping_result_code agent_hostname=zy-fat product=n9e region=cloud target=www.baidu.com 0
ping_packets_transmitted agent_hostname=zy-fat product=n9e region=cloud target=www.baidu.com 1
ping_packets_received agent_hostname=zy-fat product=n9e region=cloud target=www.baidu.com 1
ping_ttl agent_hostname=zy-fat product=n9e region=cloud target=www.baidu.com 50
ping_percent_packet_loss agent_hostname=zy-fat product=n9e region=cloud target=www.baidu.com 0
ping_maximum_response_ms agent_hostname=zy-fat product=n9e region=cloud target=www.baidu.com 20.935
```
57 changes: 54 additions & 3 deletions inputs/ping/ping.go
Original file line number Diff line number Diff line change
@@ -1,25 +1,32 @@
package ping

import (
"bytes"
"errors"
"fmt"
"log"
"net"
"os/exec"
"runtime"
"strings"
"sync"
"time"

ping "github.com/prometheus-community/pro-bing"

"flashcat.cloud/categraf/config"
"flashcat.cloud/categraf/inputs"
"flashcat.cloud/categraf/pkg/cmdx"
"flashcat.cloud/categraf/types"
ping "github.com/prometheus-community/pro-bing"
)

const (
inputName = "ping"
defaultPingDataBytesSize = 56
)

type HostPinger func(binary string, timeout float64, args ...string) (string, error)

type Instance struct {
config.InstanceConfig

Expand All @@ -31,10 +38,17 @@ type Instance struct {
IPv6 bool `toml:"ipv6"` // Whether to resolve addresses using ipv6 or not.
Size *int `toml:"size"` // Packet size
Conc int `toml:"concurrency"` // max concurrency coroutine
Method string `toml:"method"` // Method defines how to ping (native or exec)
Binary string `toml:"binary"` // Ping executable binary

calcInterval time.Duration
calcTimeout time.Duration
sourceAddress string

// host ping function
pingHost HostPinger

Deadline int // Ping deadline, in seconds. 0 means no deadline. (ping -w <DEADLINE>)
}

func (ins *Instance) Init() error {
Expand Down Expand Up @@ -80,6 +94,15 @@ func (ins *Instance) Init() error {
}
}

if ins.Method == "" {
ins.Method = "native"
}

if ins.Method == "exec" && ins.Binary == "" {
ins.Binary = "ping"
}

ins.pingHost = hostPinger
return nil
}

Expand Down Expand Up @@ -115,21 +138,29 @@ func (ins *Instance) Gather(slist *types.SampleList) {
return
}

if ins.DebugMod {
log.Println("D! ping method", ins.Method)
}
wg := new(sync.WaitGroup)
ch := make(chan struct{}, ins.Conc)
for _, target := range ins.Targets {
ch <- struct{}{}
wg.Add(1)
go func(target string) {
defer wg.Done()
ins.gather(slist, target)
switch ins.Method {
case "exec":
ins.execGather(slist, target)
default:
ins.nativeGather(slist, target)
}
<-ch
}(target)
}
wg.Wait()
}

func (ins *Instance) gather(slist *types.SampleList, target string) {
func (ins *Instance) nativeGather(slist *types.SampleList, target string) {
if ins.DebugMod {
log.Println("D! ping...", target)
}
Expand Down Expand Up @@ -244,3 +275,23 @@ func (ins *Instance) ping(destination string) (*pingStats, error) {

return ps, nil
}

func hostPinger(binary string, timeout float64, args ...string) (string, error) {
bin, err := exec.LookPath(binary)
if err != nil {
return "", err
}

var stdout bytes.Buffer
var stderr bytes.Buffer
cmd := exec.Command(bin, args...)
cmd.Stdout = &stdout
cmd.Stderr = &stderr

err, to := cmdx.RunTimeout(cmd, time.Second*time.Duration(timeout+5))
if to {
log.Printf("E! run command: %s timeout", strings.Join(cmd.Args, " "))
return stderr.String(), errors.New("run command timeout")
}
return stdout.String(), err
}
Loading

0 comments on commit afe93ed

Please sign in to comment.