diff options
author | Paul Gier <pgier@redhat.com> | 2019-09-04 09:27:25 -0500 |
---|---|---|
committer | Ben Kochie <superq@gmail.com> | 2019-09-04 16:27:25 +0200 |
commit | 8c3de12c2213c775217290d2b97f465c23f7bff6 (patch) | |
tree | addc6999a7bb131caa59deaac6785d72fb03bd97 /collector | |
parent | d3478a207ebc665d4bd06c3dff5e9fb0a5e44eff (diff) | |
download | prometheus_node_collector-8c3de12c2213c775217290d2b97f465c23f7bff6.tar.bz2 prometheus_node_collector-8c3de12c2213c775217290d2b97f465c23f7bff6.tar.xz prometheus_node_collector-8c3de12c2213c775217290d2b97f465c23f7bff6.zip |
systemd: check version for availability of properties (#1413)
The dbus property 'SystemState' and the timer property 'LastTriggerUSec'
were added in version 212 of systemd.
Check that the version of systemd is higher than 212 before attempting
to query these properties
https://github.com/systemd/systemd/commit/f755e3b74b94296a534033dd6ae04d9506434210
https://github.com/systemd/systemd/commit/dedabea4b3d61a87cedb5c8d7ccce5b86ea84afe
Resolves issue #291
Signed-off-by: Paul Gier <pgier@redhat.com>
Diffstat (limited to 'collector')
-rw-r--r-- | collector/systemd_linux.go | 74 |
1 files changed, 62 insertions, 12 deletions
diff --git a/collector/systemd_linux.go b/collector/systemd_linux.go index 4b9db10..eb1fa78 100644 --- a/collector/systemd_linux.go +++ b/collector/systemd_linux.go | |||
@@ -19,6 +19,7 @@ import ( | |||
19 | "fmt" | 19 | "fmt" |
20 | "math" | 20 | "math" |
21 | "regexp" | 21 | "regexp" |
22 | "strconv" | ||
22 | "strings" | 23 | "strings" |
23 | "sync" | 24 | "sync" |
24 | "time" | 25 | "time" |
@@ -29,6 +30,13 @@ import ( | |||
29 | kingpin "gopkg.in/alecthomas/kingpin.v2" | 30 | kingpin "gopkg.in/alecthomas/kingpin.v2" |
30 | ) | 31 | ) |
31 | 32 | ||
33 | const ( | ||
34 | // minSystemdVersionSystemState is the minimum SystemD version for availability of | ||
35 | // the 'SystemState' manager property and the timer property 'LastTriggerUSec' | ||
36 | // https://github.com/prometheus/node_exporter/issues/291 | ||
37 | minSystemdVersionSystemState = 212 | ||
38 | ) | ||
39 | |||
32 | var ( | 40 | var ( |
33 | unitWhitelist = kingpin.Flag("collector.systemd.unit-whitelist", "Regexp of systemd units to whitelist. Units must both match whitelist and not match blacklist to be included.").Default(".+").String() | 41 | unitWhitelist = kingpin.Flag("collector.systemd.unit-whitelist", "Regexp of systemd units to whitelist. Units must both match whitelist and not match blacklist to be included.").Default(".+").String() |
34 | unitBlacklist = kingpin.Flag("collector.systemd.unit-blacklist", "Regexp of systemd units to blacklist. Units must both match whitelist and not match blacklist to be included.").Default(".+\\.(automount|device|mount|scope|slice)").String() | 42 | unitBlacklist = kingpin.Flag("collector.systemd.unit-blacklist", "Regexp of systemd units to blacklist. Units must both match whitelist and not match blacklist to be included.").Default(".+\\.(automount|device|mount|scope|slice)").String() |
@@ -50,6 +58,8 @@ type systemdCollector struct { | |||
50 | socketAcceptedConnectionsDesc *prometheus.Desc | 58 | socketAcceptedConnectionsDesc *prometheus.Desc |
51 | socketCurrentConnectionsDesc *prometheus.Desc | 59 | socketCurrentConnectionsDesc *prometheus.Desc |
52 | socketRefusedConnectionsDesc *prometheus.Desc | 60 | socketRefusedConnectionsDesc *prometheus.Desc |
61 | systemdVersionDesc *prometheus.Desc | ||
62 | systemdVersion int | ||
53 | unitWhitelistPattern *regexp.Regexp | 63 | unitWhitelistPattern *regexp.Regexp |
54 | unitBlacklistPattern *regexp.Regexp | 64 | unitBlacklistPattern *regexp.Regexp |
55 | } | 65 | } |
@@ -103,9 +113,18 @@ func NewSystemdCollector() (Collector, error) { | |||
103 | socketRefusedConnectionsDesc := prometheus.NewDesc( | 113 | socketRefusedConnectionsDesc := prometheus.NewDesc( |
104 | prometheus.BuildFQName(namespace, subsystem, "socket_refused_connections_total"), | 114 | prometheus.BuildFQName(namespace, subsystem, "socket_refused_connections_total"), |
105 | "Total number of refused socket connections", []string{"name"}, nil) | 115 | "Total number of refused socket connections", []string{"name"}, nil) |
116 | systemdVersionDesc := prometheus.NewDesc( | ||
117 | prometheus.BuildFQName(namespace, subsystem, "version"), | ||
118 | "Detected systemd version", []string{}, nil) | ||
106 | unitWhitelistPattern := regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *unitWhitelist)) | 119 | unitWhitelistPattern := regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *unitWhitelist)) |
107 | unitBlacklistPattern := regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *unitBlacklist)) | 120 | unitBlacklistPattern := regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *unitBlacklist)) |
108 | 121 | ||
122 | systemdVersion := getSystemdVersion() | ||
123 | if systemdVersion < minSystemdVersionSystemState { | ||
124 | log.Warnf("Detected systemd version %v is lower than minimum %v", systemdVersion, minSystemdVersionSystemState) | ||
125 | log.Warn("Some systemd state and timer metrics will not be available") | ||
126 | } | ||
127 | |||
109 | return &systemdCollector{ | 128 | return &systemdCollector{ |
110 | unitDesc: unitDesc, | 129 | unitDesc: unitDesc, |
111 | unitStartTimeDesc: unitStartTimeDesc, | 130 | unitStartTimeDesc: unitStartTimeDesc, |
@@ -118,6 +137,8 @@ func NewSystemdCollector() (Collector, error) { | |||
118 | socketAcceptedConnectionsDesc: socketAcceptedConnectionsDesc, | 137 | socketAcceptedConnectionsDesc: socketAcceptedConnectionsDesc, |
119 | socketCurrentConnectionsDesc: socketCurrentConnectionsDesc, | 138 | socketCurrentConnectionsDesc: socketCurrentConnectionsDesc, |
120 | socketRefusedConnectionsDesc: socketRefusedConnectionsDesc, | 139 | socketRefusedConnectionsDesc: socketRefusedConnectionsDesc, |
140 | systemdVersionDesc: systemdVersionDesc, | ||
141 | systemdVersion: systemdVersion, | ||
121 | unitWhitelistPattern: unitWhitelistPattern, | 142 | unitWhitelistPattern: unitWhitelistPattern, |
122 | unitBlacklistPattern: unitBlacklistPattern, | 143 | unitBlacklistPattern: unitBlacklistPattern, |
123 | }, nil | 144 | }, nil |
@@ -127,7 +148,7 @@ func NewSystemdCollector() (Collector, error) { | |||
127 | // to reduce wait time for responses. | 148 | // to reduce wait time for responses. |
128 | func (c *systemdCollector) Update(ch chan<- prometheus.Metric) error { | 149 | func (c *systemdCollector) Update(ch chan<- prometheus.Metric) error { |
129 | begin := time.Now() | 150 | begin := time.Now() |
130 | conn, err := c.newDbus() | 151 | conn, err := newSystemdDbusConn() |
131 | if err != nil { | 152 | if err != nil { |
132 | return fmt.Errorf("couldn't get dbus connection: %s", err) | 153 | return fmt.Errorf("couldn't get dbus connection: %s", err) |
133 | } | 154 | } |
@@ -179,13 +200,15 @@ func (c *systemdCollector) Update(ch chan<- prometheus.Metric) error { | |||
179 | }() | 200 | }() |
180 | } | 201 | } |
181 | 202 | ||
182 | wg.Add(1) | 203 | if c.systemdVersion >= minSystemdVersionSystemState { |
183 | go func() { | 204 | wg.Add(1) |
184 | defer wg.Done() | 205 | go func() { |
185 | begin = time.Now() | 206 | defer wg.Done() |
186 | c.collectTimers(conn, ch, units) | 207 | begin = time.Now() |
187 | log.Debugf("systemd collectTimers took %f", time.Since(begin).Seconds()) | 208 | c.collectTimers(conn, ch, units) |
188 | }() | 209 | log.Debugf("systemd collectTimers took %f", time.Since(begin).Seconds()) |
210 | }() | ||
211 | } | ||
189 | 212 | ||
190 | wg.Add(1) | 213 | wg.Add(1) |
191 | go func() { | 214 | go func() { |
@@ -195,9 +218,15 @@ func (c *systemdCollector) Update(ch chan<- prometheus.Metric) error { | |||
195 | log.Debugf("systemd collectSockets took %f", time.Since(begin).Seconds()) | 218 | log.Debugf("systemd collectSockets took %f", time.Since(begin).Seconds()) |
196 | }() | 219 | }() |
197 | 220 | ||
198 | begin = time.Now() | 221 | if c.systemdVersion >= minSystemdVersionSystemState { |
199 | err = c.collectSystemState(conn, ch) | 222 | begin = time.Now() |
200 | log.Debugf("systemd collectSystemState took %f", time.Since(begin).Seconds()) | 223 | err = c.collectSystemState(conn, ch) |
224 | log.Debugf("systemd collectSystemState took %f", time.Since(begin).Seconds()) | ||
225 | } | ||
226 | |||
227 | ch <- prometheus.MustNewConstMetric( | ||
228 | c.systemdVersionDesc, prometheus.GaugeValue, float64(c.systemdVersion)) | ||
229 | |||
201 | return err | 230 | return err |
202 | } | 231 | } |
203 | 232 | ||
@@ -369,7 +398,7 @@ func (c *systemdCollector) collectSystemState(conn *dbus.Conn, ch chan<- prometh | |||
369 | return nil | 398 | return nil |
370 | } | 399 | } |
371 | 400 | ||
372 | func (c *systemdCollector) newDbus() (*dbus.Conn, error) { | 401 | func newSystemdDbusConn() (*dbus.Conn, error) { |
373 | if *systemdPrivate { | 402 | if *systemdPrivate { |
374 | return dbus.NewSystemdConnection() | 403 | return dbus.NewSystemdConnection() |
375 | } | 404 | } |
@@ -424,3 +453,24 @@ func filterUnits(units []unit, whitelistPattern, blacklistPattern *regexp.Regexp | |||
424 | 453 | ||
425 | return filtered | 454 | return filtered |
426 | } | 455 | } |
456 | |||
457 | func getSystemdVersion() int { | ||
458 | conn, err := newSystemdDbusConn() | ||
459 | if err != nil { | ||
460 | log.Warnf("Unable to get systemd dbus connection, defaulting systemd version to 0: %s", err) | ||
461 | return 0 | ||
462 | } | ||
463 | defer conn.Close() | ||
464 | version, err := conn.GetManagerProperty("Version") | ||
465 | if err != nil { | ||
466 | log.Warn("Unable to get systemd version property, defaulting to 0") | ||
467 | return 0 | ||
468 | } | ||
469 | version = strings.Replace(version, "\"", "", 2) | ||
470 | v, err := strconv.Atoi(version) | ||
471 | if err != nil { | ||
472 | log.Warnf("Got invalid systemd version: %v", version) | ||
473 | return 0 | ||
474 | } | ||
475 | return v | ||
476 | } | ||