Skip to content

Commit d2cb972

Browse files
committed
Initial commit
0 parents  commit d2cb972

14 files changed

+971
-0
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
*_exporter
2+
scripts/github_api_token
3+
tmp/

CONTRIBUTING.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Hello there - glad to see you're interested in contributing!
2+
3+
This is a personal project and I bet that it'll be used by other hobbyists, so I am more than happy to support adding your pull request that...
4+
- Explains what you're adding/removing/changing
5+
- Passes test cases
6+
- Doesn't expand the project beyond its intended scope

LICENSE

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
Copyright 2020 Daniel Ruggeri
2+
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
7+
http://www.apache.org/licenses/LICENSE-2.0
8+
9+
Unless required by applicable law or agreed to in writing, software
10+
distributed under the License is distributed on an "AS IS" BASIS,
11+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
See the License for the specific language governing permissions and
13+
limitations under the License.

README.md

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# ISC dhcpd Leases Prometheus Exporter
2+
3+
A [Prometheus](https://prometheus.io) exporter for the ISC dhcpd server. This exporter consumes the `dhcpd.leases` file which is periodically written by the dameon. It is based on the [node_exporter](https://github.com/prometheus/node_exporter) and [cf_exporter](https://github.com/bosh-prometheus/cf_exporter) projects.
4+
5+
## Installation
6+
7+
### Binaries
8+
9+
Download the already existing [binaries](https://github.com/DRuggeri/dhcpd_leases_exporter/releases) for your platform:
10+
11+
```bash
12+
$ ./dhcpd_leases_exporter <flags>
13+
```
14+
15+
### From source
16+
17+
Using the standard `go install` (you must have [Go](https://golang.org/) already installed in your local machine):
18+
19+
```bash
20+
$ go install github.com/DRuggeri/dhcpd_leases_exporter
21+
$ dhcpd_leases_exporter <flags>
22+
```
23+
24+
## Usage
25+
26+
### Flags
27+
28+
```
29+
usage: dhcpd_leases_exporter [<flags>]
30+
31+
Flags:
32+
-h, --help Show context-sensitive help (also try --help-long and --help-man).
33+
--dhcpd.leases="/var/lib/dhcp/dhcpd.leases"
34+
Path of the dhcpd.leases file. Defaults to '/var/lib/dhcp/dhcpd.leases' ($DHCPD_LEASES_EXPORTER_LEASES_FILE)
35+
--filter.collectors="Stats"
36+
Comma separated collectors to enable (Stats) ($DHCPD_LEASES_EXPORTER_FILTER_COLLECTORS)
37+
--metrics.namespace="dhcpd_leases"
38+
Metrics Namespace ($DHCPD_LEASES_EXPORTER_METRICS_NAMESPACE)
39+
--web.listen-address=":9198"
40+
Address to listen on for web interface and telemetry ($DHCPD_LEASES_EXPORTER_WEB_LISTEN_ADDRESS)
41+
--web.telemetry-path="/metrics"
42+
Path under which to expose Prometheus metrics ($DHCPD_LEASES_EXPORTER_WEB_TELEMETRY_PATH)
43+
--web.auth.username=WEB.AUTH.USERNAME
44+
Username for web interface basic auth ($DHCPD_LEASES_EXPORTER_WEB_AUTH_USERNAME)
45+
--web.auth.password=WEB.AUTH.PASSWORD
46+
Password for web interface basic auth ($DHCPD_LEASES_EXPORTER_WEB_AUTH_PASSWORD)
47+
--web.tls.cert_file=WEB.TLS.CERT_FILE
48+
Path to a file that contains the TLS certificate (PEM format). If the certificate is signed by a certificate authority, the file should be the concatenation of the server's certificate, any intermediates, and the CA's certificate
49+
($DHCPD_LEASES_EXPORTER_WEB_TLS_CERTFILE)
50+
--web.tls.key_file=WEB.TLS.KEY_FILE
51+
Path to a file that contains the TLS private key (PEM format) ($DHCPD_LEASES_EXPORTER_WEB_TLS_KEYFILE)
52+
--printMetrics Print the metrics this exporter exposes and exits. Default: false ($DHCPD_LEASES_EXPORTER_PRINT_METRICS)
53+
--log.level="info" Only log messages with the given severity or above. Valid levels: [debug, info, warn, error, fatal]
54+
--log.format="logger:stderr"
55+
Set the log target and format. Example: "logger:syslog?appname=bob&local=7" or "logger:stdout?json=true"
56+
--version Show application version.
57+
```
58+
59+
## Metrics
60+
61+
### Stats
62+
This collector counts the number of leases PER UNIQUE IP found in dhcpd.leases. This means that if an IP was leased to `client X`, but is now leased to `client Y`, there will be only one entry counted (the most recent one). This is in line with how dhcpd reads the file.
63+
64+
```
65+
dhcpd_leases_stats_valid_leases - The number of leases in dhcpd.leases that have not yet expired.
66+
dhcpd_leases_stats_expired_leases - The number of leases in dhcpd.leases that have expired.
67+
dhcpd_leases_stats_count - The number of leases in dhcpd.leases
68+
dhcpd_leases_stats_scrapes_total - Total number of scrapes for stats.
69+
dhcpd_leases_stats_scrape_errors_total - Total number of scrapes errors for stats.
70+
dhcpd_leases_stats_last_scrape_error - Whether the last scrape of stats resulted in an error (1 for error, 0 for success).
71+
dhcpd_leases_stats_last_scrape_timestamp - Number of seconds since 1970 since last scrape of stat metrics.
72+
```
73+
74+
## Contributing
75+
76+
Refer to the [contributing guidelines](https://github.com/DRuggeri/dhcpd_leases_exporter/blob/master/CONTRIBUTING.md).
77+
78+
## License
79+
80+
Apache License 2.0, see [LICENSE](https://github.com/DRuggeri/dhcpd_leases_exporter/blob/master/LICENSE).

collectors/stats_collector.go

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
package collectors
2+
3+
import (
4+
"github.com/prometheus/client_golang/prometheus"
5+
"time"
6+
"github.com/DRuggeri/dhcpdleasesreader"
7+
)
8+
9+
type StatCollector struct {
10+
namespace string
11+
validMetric prometheus.Gauge
12+
expiredMetric prometheus.Gauge
13+
countMetric prometheus.Gauge
14+
modTimeMetric prometheus.Gauge
15+
info *dhcpdleasesreader.DhcpdInfo
16+
17+
scrapesTotalMetric prometheus.Counter
18+
scrapeErrorsTotalMetric prometheus.Counter
19+
lastScrapeErrorMetric prometheus.Gauge
20+
lastScrapeTimestampMetric prometheus.Gauge
21+
lastScrapeDurationSecondsMetric prometheus.Gauge
22+
}
23+
24+
func NewStatsCollector(namespace string, info *dhcpdleasesreader.DhcpdInfo) *StatCollector {
25+
validMetric := prometheus.NewGauge(
26+
prometheus.GaugeOpts{
27+
Namespace: namespace,
28+
Subsystem: "stats",
29+
Name: "valid_leases",
30+
Help: "The number of leases in dhcpd.leases that have not yet expired.",
31+
},
32+
)
33+
34+
expiredMetric := prometheus.NewGauge(
35+
prometheus.GaugeOpts{
36+
Namespace: namespace,
37+
Subsystem: "stats",
38+
Name: "expired_leases",
39+
Help: "The number of leases in dhcpd.leases that have expired.",
40+
},
41+
)
42+
43+
countMetric := prometheus.NewGauge(
44+
prometheus.GaugeOpts{
45+
Namespace: namespace,
46+
Subsystem: "stats",
47+
Name: "count",
48+
Help: "The number of leases in dhcpd.leases",
49+
},
50+
)
51+
52+
modTimeMetric := prometheus.NewGauge(
53+
prometheus.GaugeOpts{
54+
Namespace: namespace,
55+
Subsystem: "stats",
56+
Name: "filetime",
57+
Help: "The file timestamp in seconds since epoch of the dhcpd.leases file",
58+
},
59+
)
60+
61+
62+
scrapesTotalMetric := prometheus.NewCounter(
63+
prometheus.CounterOpts{
64+
Namespace: namespace,
65+
Subsystem: "stats",
66+
Name: "scrapes_total",
67+
Help: "Total number of scrapes for stats.",
68+
},
69+
)
70+
71+
scrapeErrorsTotalMetric := prometheus.NewCounter(
72+
prometheus.CounterOpts{
73+
Namespace: namespace,
74+
Subsystem: "stats",
75+
Name: "scrape_errors_total",
76+
Help: "Total number of scrapes errors for stats.",
77+
},
78+
)
79+
80+
lastScrapeErrorMetric := prometheus.NewGauge(
81+
prometheus.GaugeOpts{
82+
Namespace: namespace,
83+
Subsystem: "stats",
84+
Name: "last_scrape_error",
85+
Help: "Whether the last scrape of stats resulted in an error (1 for error, 0 for success).",
86+
},
87+
)
88+
89+
lastScrapeTimestampMetric := prometheus.NewGauge(
90+
prometheus.GaugeOpts{
91+
Namespace: namespace,
92+
Subsystem: "stats",
93+
Name: "last_scrape_timestamp",
94+
Help: "Number of seconds since 1970 since last scrape of stat metrics.",
95+
},
96+
)
97+
98+
lastScrapeDurationSecondsMetric := prometheus.NewGauge(
99+
prometheus.GaugeOpts{
100+
Namespace: namespace,
101+
Subsystem: "stats",
102+
Name: "last_scrape_duration_seconds",
103+
Help: "Duration of the last scrape of stats.",
104+
},
105+
)
106+
107+
return &StatCollector{
108+
validMetric: validMetric,
109+
expiredMetric: expiredMetric,
110+
countMetric: countMetric,
111+
modTimeMetric: modTimeMetric,
112+
info: info,
113+
114+
namespace: namespace,
115+
scrapesTotalMetric: scrapesTotalMetric,
116+
scrapeErrorsTotalMetric: scrapeErrorsTotalMetric,
117+
lastScrapeErrorMetric: lastScrapeErrorMetric,
118+
lastScrapeTimestampMetric: lastScrapeTimestampMetric,
119+
lastScrapeDurationSecondsMetric: lastScrapeDurationSecondsMetric,
120+
}
121+
}
122+
123+
func (c *StatCollector) Collect(ch chan<- prometheus.Metric) {
124+
var begun = time.Now()
125+
126+
c.validMetric.Set(float64(c.info.Valid))
127+
c.validMetric.Collect(ch)
128+
129+
c.expiredMetric.Set(float64(c.info.Expired))
130+
c.expiredMetric.Collect(ch)
131+
132+
c.countMetric.Set(float64(len(c.info.Leases)))
133+
c.countMetric.Collect(ch)
134+
135+
c.modTimeMetric.Set(float64(c.info.ModTime.Unix()))
136+
c.modTimeMetric.Collect(ch)
137+
138+
c.scrapeErrorsTotalMetric.Collect(ch)
139+
140+
c.scrapesTotalMetric.Inc()
141+
c.scrapesTotalMetric.Collect(ch)
142+
143+
c.lastScrapeErrorMetric.Set(0)
144+
c.lastScrapeErrorMetric.Collect(ch)
145+
146+
c.lastScrapeTimestampMetric.Set(float64(time.Now().Unix()))
147+
c.lastScrapeTimestampMetric.Collect(ch)
148+
149+
c.lastScrapeDurationSecondsMetric.Set(time.Since(begun).Seconds())
150+
c.lastScrapeDurationSecondsMetric.Collect(ch)
151+
}
152+
153+
func (c *StatCollector) Describe(ch chan<- *prometheus.Desc) {
154+
c.validMetric.Describe(ch)
155+
c.expiredMetric.Describe(ch)
156+
c.countMetric.Describe(ch)
157+
c.scrapesTotalMetric.Describe(ch)
158+
c.scrapeErrorsTotalMetric.Describe(ch)
159+
c.lastScrapeErrorMetric.Describe(ch)
160+
c.lastScrapeTimestampMetric.Describe(ch)
161+
c.lastScrapeDurationSecondsMetric.Describe(ch)
162+
}

0 commit comments

Comments
 (0)