Library / SDK
czerwonk/ping_exporter avatar
czerwonk/ping_exporter

ping_exporter: Prometheus metrics for ICMP echo, including loss and RTT spread

Prometheus exporter for ICMP echo requests using https://github.com/digineo/go-ping

637 stars129 forksGoMIT

At a glance

What is it?
ping_exporter is a small Go program that runs ICMP echo requests through the go-ping library and exposes the results as Prometheus metrics, with a YAML target list, a Kubernetes resolver, a Helm chart and a container image.
Who is it for?
Adopt ping_exporter if you want round trip time distribution and packet loss as Prometheus series for a set of hosts, and you can give the process the raw socket capability it needs on Linux. Do not adopt it if you need traceroute style path diagnostics or TCP level metrics, since the exporter is built around ICMP echo only.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A thin exporter over the go-ping library

ping_exporter is described as a simple server that scrapes go-ping stats and exports them via HTTP for Prometheus consumption. That framing is accurate: the actual ICMP work is done by github.com/digineo/go-ping, which the README notes is built and maintained by Digineo GmbH, and this project is the Prometheus shaped wrapper around it. The audience is an operator or platform engineer who wants to alert on packet loss and latency to a set of hosts, networks or endpoints, and who already runs Prometheus. It is deliberately not a network monitoring suite. There is no traceroute, no TCP handshake timing, no DNS monitoring, and no topology discovery in the feature list. The module metadata shows a small dependency set, with digineo/go-ping at the centre, the Prometheus client library for the exposition format, kingpin for flag parsing, logrus for logging, fsnotify and yaml.v2 for the configuration file, and the Kubernetes client libraries for the cluster resolver. The code sits in a handful of flat files at the repository root, collector.go, custom_labels.go, resolver.go, k8sresolver.go, rttscale.go and target.go.

Targets live in a YAML file, not on the command line

The primary configuration is a YAML file with four sections. The targets section is a list that mixes plain IP addresses with objects that carry a hostname and an optional ASN, so a domain target can be recorded with extra context. The dns section sets how often names are refreshed and which nameserver to use. The ping section holds the interval, timeout, history size, payload size and an fw-mark value. The options section has a single switch, disableIPv6.

yaml
targets:
  - 8.8.8.8
  - 8.8.4.4
  - 2001:4860:4860::8888
  - 2001:4860:4860::8844
  - host: google.com
    asn: 15169

dns:
  refresh: 2m15s
  nameserver: 1.1.1.1

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

options:
  disableIPv6: false

The README flags a breaking change here: in v1.2.0 the config file format changed, so anyone with an older file containing custom labels has to rewrite it into this shape. Domains are resolved regularly to their A and AAAA records, and the system resolver does that translation by default, which you can override with the --dns.nameserver flag.

The config file is watched, but global options are not

This is a small operational detail with real consequences. The configuration file is watched via inotify, and when the file changes, ping_exporter updates its targets. But global options such as the ping interval or the history size only take effect on a restart of the exporter. So editing the file in place is a fine way to add or remove targets during an incident, and a misleading way to change timing behaviour, because the file will look applied while the running process keeps the old values. The README is explicit about the split, and it is worth remembering when a dashboard shows an interval you did not expect.

The DNS behaviour is also worth understanding precisely. Because domains are resolved to their A and AAAA records and then pinged as addresses, the metric labels reflect the address rather than the name you typed, and a domain that resolves to several addresses will be pinged on each of them.

The metric set: RTT spread, loss ratio and a liveness gauge

Five series describe the ping itself, each labelled with the target's IP address, the IP version as 4 or 6, and the target name. They are ping_rtt_best_seconds for the best round trip time, ping_rtt_worst_seconds for the worst, ping_rtt_mean_seconds for the mean, ping_rtt_std_deviation_seconds for the standard deviation, and ping_loss_ratio for packet loss as a value from 0.0 to 1.0. The split of round trip time into best, worst, mean and standard deviation is the interesting part, because a mean alone hides jitter and a single latency number hides degradation. The loss ratio as a fraction rather than a count is convenient for Prometheus queries and for recording rules. Separately, a ping_up metric reports whether the exporter is running and in which version, which is the series to alert on when the exporter itself has died rather than the network.

Running it, and the capability it needs on Linux

The exporter takes either targets on the command line or a config file path, and it serves on port 9427.

bash
$ ./ping_exporter [options] target1 target2 ...
bash
$ ./ping_exporter --config.path my-config-file [options]
bash
$ curl http://localhost:9427/metrics

The privilege question is the one that catches people. On Linux, CAP_NET_RAW is required to run the exporter as an unprivileged user, and the README gives two ways to grant it. The first is to set the file capability on the binary directly, so the kernel permits raw sockets without the process running as root.

bash
# setcap cap_net_raw+ep /path/to/ping_exporter

The second is a systemd unit fragment, adding a capability bounding set and ambient capabilities in the [Service] section.

bash
CapabilityBoundingSet=CAP_NET_RAW
AmbientCapabilities=CAP_NET_RAW

For a rootless Docker setup on Linux, the README says to add the --cap-add=CAP_NET_RAW flag to the docker run invocation.

A container image and a Helm chart for the Kubernetes path

The Docker image is published under the czerwonk/ping_exporter name, and the run command publishes the exporter port and mounts a configuration directory read only.

bash
$ docker run -p 9427:9427 -v /path/to/config/directory:/config:ro --name ping_exporter czerwonk/ping_exporter

The Dockerfile in the repository shows the shape of that image. It builds from a pinned golang alpine base, compiles a static binary with CGO disabled and the target platform passed in as build arguments, then copies the binary into a distroless static Debian base, which is about as small as a Go image gets. The Dockerfile sets the file capability on the binary inside the builder stage with setcap, and the final image sets a CONFIG_FILE environment variable pointing at /config/config.yml, exposes 9427, and runs the binary as its entrypoint.

For Kubernetes there is a supplied Helm chart, requiring Helm v3.0.0 or newer, installed from a chart repository hosted by the maintainer.

bash
$ helm repo add ping-exporter "https://czerwonk.github.io/ping_exporter"
"ping-exporter" has been added to your repositories

$ helm repo update

$ helm install ping-exporter ping-exporter/ping_exporter
NAME: ping-exporter
...

The chart values cover the usual surface, including the image repository and tag, an ingress toggle, an affinity block, an args list for extra command line flags, and a config object that holds the contents of the exporter's config file, so the target list is managed through Helm values rather than a ConfigMap you patch by hand. The module also pulls in the Kubernetes client libraries, which is what backs the cluster aware resolver.

Where ping_exporter is the wrong tool

Two limitations are structural rather than fixable. The first is that ICMP echo is the only probe. If what you care about is whether a TCP service is accepting connections, or whether a path is broken at a hop rather than at the destination, an echo based exporter gives you the wrong signal, and the loss you see will not tell you where the traffic stopped. The second is the privilege requirement. CAP_NET_RAW is a real capability grant, and in a locked down environment where security teams restrict raw sockets, or where a platform does not permit file capabilities on the binary, you will be running the exporter as root, which is a finding in most security reviews. There is also a resolution blind spot worth naming: because the exporter pings resolved addresses, a target behind a load balancer will be measured at whichever address DNS returned, not at the service as a user experiences it, and a change in DNS can change what the metrics mean. For those cases, a blackbox style probe that speaks the application protocol is the tool that answers the question.

Editorial conclusion

Adopt ping_exporter if you want round trip time distribution and packet loss as Prometheus series for a set of hosts, and you can give the process the raw socket capability it needs on Linux. Do not adopt it if you need traceroute style path diagnostics or TCP level metrics, since the exporter is built around ICMP echo only. Verify first that your targets resolve the way you expect, because domains are resolved to their A and AAAA records and the exporter then pings the addresses rather than the name, and note that the config file format changed in v1.2.0 if you are upgrading an older deployment.

Frequently asked questions

What metrics does ping_exporter export to Prometheus?

Five ping series, each labelled with ip, ip_version and target: ping_rtt_best_seconds, ping_rtt_worst_seconds, ping_rtt_mean_seconds, ping_rtt_std_deviation_seconds, and ping_loss_ratio as a value from 0.0 to 1.0. A separate ping_up metric reports whether the exporter is running and in which version.

How do I run ping_exporter without root privileges on Linux?

CAP_NET_RAW is required. The README suggests setting the file capability on the binary with setcap cap_net_raw+ep, or adding CapabilityBoundingSet=CAP_NET_RAW and AmbientCapabilities=CAP_NET_RAW to the systemd unit's [Service] section.

Does ping_exporter pick up config file changes without a restart?

Partly. The configuration file is watched via inotify and target changes are applied, but global options such as the ping interval or history size only take effect after you restart the exporter.

How do I install ping_exporter on Kubernetes?

A Helm chart is supplied and requires Helm v3.0.0 or newer. Add the chart repository with helm repo add ping-exporter, run helm repo update, then helm install ping-exporter ping-exporter/ping_exporter, with the config file contents supplied through the chart's config values.

Official sources

  1. czerwonk/ping_exporter on GitHub
  2. Issues
  3. License: MIT
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/czerwonk-ping-exporter.svg)](https://hysenlabs.com/projects/czerwonk-ping-exporter)

Was this useful?