collector/systemd: add new label "type" for systemd_unit_state
Adds a new label called "type" systemd_unit_state which contains the
Type field from the unit file.  This applies only to the .service and
.mount unit types.  The other unit types do not include the optional
type field.
Fixes
@@ -17,14 +17,14 @@ package collector
import (
"fmt"
+ "math"
"regexp"
"strings"
"github.com/coreos/go-systemd/dbus"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/log"
- "gopkg.in/alecthomas/kingpin.v2"
- "math"
+ kingpin "gopkg.in/alecthomas/kingpin.v2"
)
var (
@@ -61,7 +61,7 @@ func NewSystemdCollector() (Collector, error) {
unitDesc := prometheus.NewDesc(
prometheus.BuildFQName(namespace, subsystem, "unit_state"),
- "Systemd unit", []string{"name", "state"}, nil,
+ "Systemd unit", []string{"name", "state", "type"}, nil,
)
unitStartTimeDesc := prometheus.NewDesc(
prometheus.BuildFQName(namespace, subsystem, "unit_start_time_seconds"),
@@ -153,7 +153,7 @@ func (c *systemdCollector) collectUnitStatusMetrics(ch chan<- prometheus.Metric,
}
ch <- prometheus.MustNewConstMetric(
c.unitDesc, prometheus.GaugeValue, isActive,
- unit.Name, stateName)
+ unit.Name, stateName, unit.serviceType)
}
if strings.HasSuffix(unit.Name, ".service") && unit.nRestarts != nil {
ch <- prometheus.MustNewConstMetric(
@@ -252,11 +252,22 @@ type unit struct {
tasksCurrent *uint64
tasksMax *uint64
nRestarts *uint32
+ serviceType string
acceptedConnections uint32
currentConnections uint32
refusedConnections *uint32
}
+// unitType gets the suffix after the last "." in the
+// unit name and capitalizes the first letter
+func (u *unit) unitType() string {
+ suffixIndex := strings.LastIndex(u.Name, ".") + 1
+ if suffixIndex < 1 || suffixIndex > len(u.Name) {
+ return ""
+ }
+ return strings.Title(u.Name[suffixIndex:])
+}
+
func (c *systemdCollector) getAllUnits() ([]unit, error) {
conn, err := c.newDbus()
if err != nil {
@@ -276,7 +287,15 @@ func (c *systemdCollector) getAllUnits() ([]unit, error) {
unit := unit{
UnitStatus: status,
}
-
+ unitType := unit.unitType()
+ if unitType == "Service" || unitType == "Mount" {
+ serviceType, err := conn.GetUnitTypeProperty(unit.Name, unitType, "Type")
+ if err != nil {
+ log.Debugf("couldn't get type for unit '%s': %s", unit.Name, err)
+ } else {
+ unit.serviceType = serviceType.Value.Value().(string)
+ }
+ }
if strings.HasSuffix(unit.Name, ".timer") {
lastTriggerValue, err := conn.GetUnitTypeProperty(unit.Name, "Timer", "LastTriggerUSec")
if err != nil {
