Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
58 changes: 58 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,64 @@ $ # use Cloudflare's public DNS server
$ ./ping_exporter --dns.nameserver=1.1.1.1:53 [other options]
```

### Using different settings for different targets

You can create multiple independent ping monitors, each of which can have their own target list and different parameters. To do this, instead of specifying `targets` at the top-level, instead create a `monitors` section, which contains a list of settings for each monitor. Each monitor must have at least `targets` defined, and may also override other parameters as well, for example:

```console
dns:
refresh: 2m15s
nameserver: 1.1.1.1

ping:
interval: 2s
timeout: 3s
history-size: 42
payload-size: 120

monitors:
- targets:
- 8.8.8.8
- 8.8.4.4
- targets:
- 2001:4860:4860::8888
- 2001:4860:4860::8844
ping:
interval: 5s
- targets:
- google.com
dns:
refresh: 10m

```

Any parameters which are not specified for a given monitor will default to using the global values.

### ICMP Echo ID field

By default, all ping packets for all the targets in the list will be sent with the `identifier` field set to the same value (so they will all generally be seen as part of the same "ping session"). This is usually fine, but in some circumstances such as when using NAT gateways with multiple exit routes, can sometimes cause incorrect routing of some packets.

If you want some targets to have a different identifier than others (so they will be considered a separate "session" by NAT gateways, etc), simply put them in different monitors (each monitor uses a different identifier by default).

However, it may also be desirable to change the identifier periodically (for example, to detect changes in routing due to failover, etc). This can be done using additional `id-change` parameters (under `ping`) as follows:

```console
- targets:
- 8.8.8.8
- 8.8.4.4
ping:
interval: 5s
history-size: 20
id-change:
interval: 20s
loss-threshold: 0.8
time-threshold: 15m
```

`interval` is how frequently it will check to see if it needs to change. It will change the ID if either the total packet loss is over the specified `loss-threshold` or if it has been longer than `time-threshold` since the last change. (Note: `loss-threshold` defaults to 0, so if it is not specified, the ID will always be changed every `interval` regardless)

Note: The packet loss is calculated over *all targets* in a given monitor, so if only one target is experiencing loss but others are fine, it may not be enough to go over the threshold. If you want to check each target's loss independently, you will need to put each one in its own monitor group.

### Exported metrics

- `ping_rtt_best_ms`: Best round trip time in millis
Expand Down
13 changes: 9 additions & 4 deletions collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ var (
)

type pingCollector struct {
monitor *mon.Monitor
metrics map[string]*mon.Metrics
monitors []*mon.Monitor
metrics map[string]*mon.Metrics
}

func (p *pingCollector) Describe(ch chan<- *prometheus.Desc) {
Expand All @@ -45,8 +45,13 @@ func (p *pingCollector) Collect(ch chan<- prometheus.Metric) {
mutex.Lock()
defer mutex.Unlock()

if m := p.monitor.Export(); len(m) > 0 {
p.metrics = m
if p.metrics == nil {
p.metrics = make(map[string]*mon.Metrics)
}
for _, mon := range p.monitors {
for target, metrics := range mon.Export() {
p.metrics[target] = metrics
}
}

ch <- prometheus.MustNewConstMetric(progDesc, prometheus.GaugeValue, 1)
Expand Down
30 changes: 30 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,42 @@ type Config struct {
Timeout duration `yaml:"timeout"`
History int `yaml:"history-size"`
Size uint16 `yaml:"payload-size"`
IdChange struct {
Interval duration `yaml:"interval"`
LossThreshold float64 `yaml:"loss-threshold"`
TimeThreshold duration `yaml:"time-threshold"`
} `yaml:"id-change"`
} `yaml:"ping"`

DNS struct {
Refresh duration `yaml:"refresh"`
Nameserver string `yaml:"nameserver"`
} `yaml:"dns"`

Monitors []MonitorConfig `yaml:"monitors"`
}

// This is the struct for a sub-entry under the `monitors` section. We support
// all the same fields as at the top level, except for nameserver, and
// (obviously) not the `monitors` field within sub-entries.
type MonitorConfig struct {
Targets []string `yaml:"targets"`

Ping struct {
Interval duration `yaml:"interval"`
Timeout duration `yaml:"timeout"`
History int `yaml:"history-size"`
Size uint16 `yaml:"payload-size"`
IdChange struct {
Interval duration `yaml:"interval"`
LossThreshold float64 `yaml:"loss-threshold"`
TimeThreshold duration `yaml:"time-threshold"`
} `yaml:"id-change"`
} `yaml:"ping"`

DNS struct {
Refresh duration `yaml:"refresh"`
} `yaml:"dns"`
}

type duration time.Duration
Expand Down
Loading