feat(plugins/inputs/systemd_units): add pattern support (#9665)

This commit is contained in:
David B 2021-08-26 22:34:52 +02:00 committed by GitHub
parent 1a59157b91
commit 4dc2967e34
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 37 additions and 10 deletions

View File

@ -1,7 +1,7 @@
# systemd Units Input Plugin
The systemd_units plugin gathers systemd unit status on Linux. It relies on
`systemctl list-units --all --plain --type=service` to collect data on service status.
`systemctl list-units [PATTERN] --all --plain --type=service` to collect data on service status.
The results are tagged with the unit name and provide enumerated fields for
loaded, active and running fields, indicating the unit health.
@ -22,6 +22,13 @@ see `systemctl list-units --all --type help` for possible options.
## values are "socket", "target", "device", "mount", "automount", "swap",
## "timer", "path", "slice" and "scope ":
# unittype = "service"
#
## Filter for a specific pattern, default is "" (i.e. all), other possible
## values are valid pattern for systemctl, e.g. "a*" for all units with
## names starting with "a"
# pattern = ""
## pattern = "telegraf* influxdb*"
## pattern = "a*"
```
### Metrics

View File

@ -18,10 +18,11 @@ import (
type SystemdUnits struct {
Timeout config.Duration
UnitType string `toml:"unittype"`
Pattern string `toml:"pattern"`
systemctl systemctl
}
type systemctl func(timeout config.Duration, unitType string) (*bytes.Buffer, error)
type systemctl func(timeout config.Duration, unitType string, pattern string) (*bytes.Buffer, error)
const measurement = "systemd_units"
@ -115,6 +116,7 @@ var subMap = map[string]int{
var (
defaultTimeout = config.Duration(time.Second)
defaultUnitType = "service"
defaultPattern = ""
)
// Description returns a short description of the plugin
@ -132,12 +134,19 @@ func (s *SystemdUnits) SampleConfig() string {
## values are "socket", "target", "device", "mount", "automount", "swap",
## "timer", "path", "slice" and "scope ":
# unittype = "service"
#
## Filter for a specific pattern, default is "" (i.e. all), other possible
## values are valid pattern for systemctl, e.g. "a*" for all units with
## names starting with "a"
# pattern = ""
## pattern = "telegraf* influxdb*"
## pattern = "a*"
`
}
// Gather parses systemctl outputs and adds counters to the Accumulator
func (s *SystemdUnits) Gather(acc telegraf.Accumulator) error {
out, err := s.systemctl(s.Timeout, s.UnitType)
out, err := s.systemctl(s.Timeout, s.UnitType, s.Pattern)
if err != nil {
return err
}
@ -192,22 +201,32 @@ func (s *SystemdUnits) Gather(acc telegraf.Accumulator) error {
return nil
}
func setSystemctl(timeout config.Duration, unitType string) (*bytes.Buffer, error) {
func setSystemctl(timeout config.Duration, unitType string, pattern string) (*bytes.Buffer, error) {
// is systemctl available ?
systemctlPath, err := exec.LookPath("systemctl")
if err != nil {
return nil, err
}
cmd := exec.Command(systemctlPath, "list-units", "--all", "--plain", fmt.Sprintf("--type=%s", unitType), "--no-legend")
// build parameters for systemctl call
params := []string{"list-units"}
// create patterns parameters if provided in config
if pattern != "" {
psplit := strings.SplitN(pattern, " ", -1)
for v := range psplit {
params = append(params, psplit[v])
}
}
params = append(params, "--all", "--plain")
// add type as configured in config
params = append(params, fmt.Sprintf("--type=%s", unitType))
params = append(params, "--no-legend")
cmd := exec.Command(systemctlPath, params...)
var out bytes.Buffer
cmd.Stdout = &out
err = internal.RunTimeout(cmd, time.Duration(timeout))
if err != nil {
return &out, fmt.Errorf("error running systemctl list-units --all --plain --type=%s --no-legend: %s", unitType, err)
return &out, fmt.Errorf("error running systemctl %s: %s", strings.Join(params, " "), err)
}
return &out, nil
}
@ -217,6 +236,7 @@ func init() {
systemctl: setSystemctl,
Timeout: defaultTimeout,
UnitType: defaultUnitType,
Pattern: defaultPattern,
}
})
}

View File

@ -74,7 +74,7 @@ func TestSystemdUnits(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
systemdUnits := &SystemdUnits{
systemctl: func(timeout config.Duration, unitType string) (*bytes.Buffer, error) {
systemctl: func(timeout config.Duration, unitType string, pattern string) (*bytes.Buffer, error) {
return bytes.NewBufferString(tt.line), nil
},
}