8000 feat(inputs.systemd_units): Support user scoped units (#12053) by pegaz · Pull Request #15458 · influxdata/telegraf · GitHub
[go: up one dir, main page]

Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(inputs.systemd_units): Support user scoped units (#12053) #15458

Merged
merged 8 commits into from
Jun 25, 2024
17 changes: 11 additions & 6 deletions plugins/inputs/systemd_units/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ See the [CONFIGURATION.md][CONFIGURATION.md] for more details.
## automount, swap, timer, path, slice and scope
# unittype = "service"

## Collect system or user scoped units
## ex: scope = "user"
# scope = "system"

## Collect also units not loaded by systemd, i.e. disabled or static units
## Enabling this feature might introduce significant load when used with
## unspecific patterns (such as '*') as systemd will need to load all
Expand Down Expand Up @@ -69,6 +73,7 @@ These metrics are available in both modes:
- load (string, load state)
- active (string, active state)
- sub (string, sub state)
- user (string, username only for user scope)
- fields:
- load_code (int, see below)
- active_code (int, see below)
Expand Down Expand Up @@ -198,15 +203,15 @@ were removed, tables are hex aligned to keep some space for future values
### Output in non-detailed mode

```text
systemd_units,host=host1.example.com,name=dbus.service,load=loaded,active=active,sub=running load_code=0i,active_code=0i,sub_code=0i 1533730725000000000
systemd_units,host=host1.example.com,name=networking.service,load=loaded,active=failed,sub=failed load_code=0i,active_code=3i,sub_code=12i 1533730725000000000
systemd_units,host=host1.example.com,name=ssh.service,load=loaded,active=active,sub=running load_code=0i,active_code=0i,sub_code=0i 1533730725000000000
systemd_units,host=host1.example.com,name=dbus.service,load=loaded,active=active,sub=running,user=telegraf load_code=0i,active_code=0i,sub_code=0i 1533730725000000000
systemd_units,host=host1.example.com,name=networking.service,load=loaded,active=failed,sub=failed,user=telegraf load_code=0i,active_code=3i,sub_code=12i 1533730725000000000
systemd_units,host=host1.example.com,name=ssh.service,load=loaded,active=active,sub=running,user=telegraf load_code=0i,active_code=0i,sub_code=0i 1533730725000000000
```

### Output in detailed mode

```text
systemd_units,active=active,host=host1.example.com,load=loaded,name=dbus.service,sub=running,preset=disabled,state=static active_code=0i,load_code=0i,mem_avail=6470856704i,mem_current=2691072i,mem_peak=3895296i,pid=481i,restarts=0i,status_errno=0i,sub_code=0i,swap_current=794624i,swap_peak=884736i 1533730725000000000
systemd_units,active=inactive,host=host1.example.com,load=not-found,name=networking.service,sub=dead active_code=2i,load_code=2i,pid=0i,restarts=0i,status_errno=0i,sub_code=1i 1533730725000000000
systemd_units,active=active,host=host1.example.com,load=loaded,name=pcscd.service,sub=running,preset=disabled,state=indirect active_code=0i,load_code=0i,mem_avail=6370541568i,mem_current=512000i,mem_peak=4399104i,pid=1673i,restarts=0i,status_errno=0i,sub_code=0i,swap_current=3149824i,swap_peak=3149824i 1533730725000000000
systemd_units,active=active,host=host1.example.com,load=loaded,name=dbus.service,sub=running,preset=disabled,state=static,user=telegraf active_code=0i,load_code=0i,mem_avail=6470856704i,mem_current=2691072i,mem_peak=3895296i,pid=481i,restarts=0i,status_errno=0i,sub_code=0i,swap_current=794624i,swap_peak=884736i 1533730725000000000
systemd_units,active=inactive,host=host1.example.com,load=not-found,name=networking.service,sub=dead,user=telegraf active_code=2i,load_code=2i,pid=0i,restarts=0i,status_errno=0i,sub_code=1i 1533730725000000000
systemd_units,active=active,host=host1.example.com,load=loaded,name=pcscd.service,sub=running,preset=disabled,state=indirect,user=telegraf active_code=0i,load_code=0i,mem_avail=6370541568i,mem_current=512000i,mem_peak=4399104i,pid=1673i,restarts=0i,status_errno=0i,sub_code=0i,swap_current=3149824i,swap_peak=3149824i 1533730725000000000
```
4 changes: 4 additions & 0 deletions plugins/inputs/systemd_units/sample.conf
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
## automount, swap, timer, path, slice and scope
# unittype = "service"

## Collect system or user scoped units
## ex: scope = "user"
# scope = "system"

## Collect also units not loaded by systemd, i.e. disabled or static units
## Enabling this feature might introduce significant load when used with
## unspecific patterns (such as '*') as systemd will need to load all
Expand Down
1 change: 1 addition & 0 deletions plugins/inputs/systemd_units/systemd_units.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ var sampleConfig string
type SystemdUnits struct {
Pattern string `toml:"pattern"`
UnitType string `toml:"unittype"`
Scope string `toml:"scope"`
Details bool `toml:"details"`
CollectDisabled bool `toml:"collect_disabled_units"`
Timeout config.Duration `toml:"timeout"`
Expand Down
49 changes: 43 additions & 6 deletions plugins/inputs/systemd_units/systemd_units_linux.go
8000
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"context"
"fmt"
"math"
"os/user"
"path"
"strings"
"time"
Expand Down Expand Up @@ -131,6 +132,8 @@ type archParams struct {
pattern []string
filter filter.Filter
unitTypeDBus string
scope string
user string
}

func (s *SystemdUnits) Init() error {
Expand Down Expand Up @@ -158,15 +161,38 @@ func (s *SystemdUnits) Init() error {
}
s.filter = f
8000
switch s.Scope {
case "", "system":
s.scope = "system"
case "user":
u, err := user.Current()
if err != nil {
return fmt.Errorf("unable to determine user: %w", err)
}

s.scope = "user"
s.user = u.Username
default:
return fmt.Errorf("invalid 'scope' %q", s.Scope)
}

return nil
}

func (s *SystemdUnits) Start(telegraf.Accumulator) error {
ctx := context.Background()
client, err := dbus.NewSystemConnectionContext(ctx)

var client *dbus.Conn
var err error
if s.scope == "user" {
client, err = dbus.NewUserConnectionContext(ctx)
} else {
client, err = dbus.NewSystemConnectionContext(ctx)
}
if err != nil {
return err
}

s.client = client

return nil
Expand Down Expand Up @@ -314,12 +340,23 @@ func (s *SystemdUnits) Gather(acc telegraf.Accumulator) error {
continue
}

var tags map[string]string
// Create the metric
tags := map[string]string{
"name": state.Name,
"load": state.LoadState,
"active": state.ActiveState,
"sub": state.SubState,
if s.scope == "user" {
tags = map[string]string{
"name": state.Name,
"load": state.LoadState,
"active": state.ActiveState,
"sub": state.SubState,
"user": s.user,
}
} else {
tags = map[string]string{
"name": state.Name,
"load": state.LoadState,
"active": state.ActiveState,
"sub": state.SubState,
}
}

fields := map[string]interface{}{
Expand Down
45 changes: 45 additions & 0 deletions plugins/inputs/systemd_units/systemd_units_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"errors"
"fmt"
"math"
"os/user"
"strings"
"testing"
"time"
Expand Down Expand Up @@ -38,6 +39,50 @@ func TestDefaultPattern(t *testing.T) {
require.Equal(t, "*", plugin.Pattern)
}

func TestDefaultScope(t *testing.T) {
u, err := user.Current()
if err != nil {
return
}

tests := []struct {
name string
scope string
expectedScope string
expectedUser string
}{
{
name: "default scope",
scope: "",
expectedScope: "system",
expectedUser: "",
},
{
name: "system scope",
scope: "system",
expectedScope: "system",
expectedUser: "",
},
{
name: "user scope",
scope: "user",
expectedScope: "user",
expectedUser: u.Username,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
plugin := &SystemdUnits{
Scope: tt.scope,
}
require.NoError(t, plugin.Init())
require.Equal(t, tt.expectedScope, plugin.scope)
require.Equal(t, tt.expectedUser, plugin.user)
})
}
}

func TestListFiles(t *testing.T) {
tests := []struct {
name string
Expand Down
Loading
0