feat(inputs.systemd_units): Add active_enter_timestamp_us field (#16287)
This commit is contained in:
parent
2ccc79ce27
commit
e3ce01abf0
2
go.mod
2
go.mod
|
|
@ -89,7 +89,6 @@ require (
|
|||
github.com/go-sql-driver/mysql v1.8.1
|
||||
github.com/go-stomp/stomp v2.1.4+incompatible
|
||||
github.com/gobwas/glob v0.2.3
|
||||
github.com/godbus/dbus/v5 v5.1.0
|
||||
github.com/gofrs/uuid/v5 v5.3.0
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1
|
||||
github.com/golang/geo v0.0.0-20190916061304-5b978397cfec
|
||||
|
|
@ -348,6 +347,7 @@ require (
|
|||
github.com/goburrow/serial v0.1.1-0.20211022031912-bfb69110f8dd // indirect
|
||||
github.com/goccy/go-json v0.10.3 // indirect
|
||||
github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect
|
||||
github.com/godbus/dbus/v5 v5.1.0 // indirect
|
||||
github.com/gofrs/uuid v4.4.0+incompatible // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.5.1 // indirect
|
||||
|
|
|
|||
|
|
@ -94,6 +94,7 @@ The following *additional* metrics are available with `details = true`:
|
|||
- swap_current (uint, current swap usage)
|
||||
- swap_peak (uint, peak swap usage)
|
||||
- mem_avail (uint, available memory for this unit)
|
||||
- active_enter_timestamp_us (uint, timestamp in us when entered the state)
|
||||
|
||||
### Load
|
||||
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ type client interface {
|
|||
ListUnitFilesByPatternsContext(ctx context.Context, states, pattern []string) ([]dbus.UnitFile, error)
|
||||
ListUnitsByNamesContext(ctx context.Context, units []string) ([]dbus.UnitStatus, error)
|
||||
GetUnitTypePropertiesContext(ctx context.Context, unit, unitType string) (map[string]interface{}, error)
|
||||
GetUnitPropertyContext(ctx context.Context, unit, propertyName string) (*dbus.Property, error)
|
||||
GetUnitPropertiesContext(ctx context.Context, unit string) (map[string]interface{}, error)
|
||||
ListUnitsContext(ctx context.Context) ([]dbus.UnitStatus, error)
|
||||
}
|
||||
|
||||
|
|
@ -134,6 +134,7 @@ type archParams struct {
|
|||
unitTypeDBus string
|
||||
scope string
|
||||
user string
|
||||
warnUnitProps map[string]bool
|
||||
}
|
||||
|
||||
func (s *SystemdUnits) Init() error {
|
||||
|
|
@ -176,6 +177,8 @@ func (s *SystemdUnits) Init() error {
|
|||
return fmt.Errorf("invalid 'scope' %q", s.Scope)
|
||||
}
|
||||
|
||||
s.warnUnitProps = make(map[string]bool)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -374,26 +377,35 @@ func (s *SystemdUnits) Gather(acc telegraf.Accumulator) error {
|
|||
}
|
||||
|
||||
// Get required unit file properties
|
||||
var unitFileState string
|
||||
if v, err := s.client.GetUnitPropertyContext(ctx, state.Name, "UnitFileState"); err == nil {
|
||||
unitFileState = strings.Trim(v.Value.String(), `'"`)
|
||||
}
|
||||
var unitFilePreset string
|
||||
if v, err := s.client.GetUnitPropertyContext(ctx, state.Name, "UnitFilePreset"); err == nil {
|
||||
unitFilePreset = strings.Trim(v.Value.String(), `'"`)
|
||||
unitProperties, err := s.client.GetUnitPropertiesContext(ctx, state.Name)
|
||||
if err != nil && !s.warnUnitProps[state.Name] {
|
||||
s.Log.Warnf("Cannot read unit properties for %q: %v", state.Name, err)
|
||||
s.warnUnitProps[state.Name] = true
|
||||
}
|
||||
|
||||
tags["state"] = unitFileState
|
||||
tags["preset"] = unitFilePreset
|
||||
// Set tags
|
||||
if v, found := unitProperties["UnitFileState"]; found {
|
||||
tags["state"] = v.(string)
|
||||
}
|
||||
if v, found := unitProperties["UnitFilePreset"]; found {
|
||||
tags["preset"] = v.(string)
|
||||
}
|
||||
|
||||
// Set fields
|
||||
if v, found := unitProperties["ActiveEnterTimestamp"]; found {
|
||||
fields["active_enter_timestamp_us"] = v
|
||||
}
|
||||
|
||||
fields["status_errno"] = properties["StatusErrno"]
|
||||
fields["restarts"] = properties["NRestarts"]
|
||||
fields["pid"] = properties["MainPID"]
|
||||
|
||||
fields["mem_current"] = properties["MemoryCurrent"]
|
||||
fields["mem_peak"] = properties["MemoryPeak"]
|
||||
fields["mem_avail"] = properties["MemoryAvailable"]
|
||||
|
||||
fields["swap_current"] = properties["MemorySwapCurrent"]
|
||||
fields["swap_peak"] = properties["MemorySwapPeak"]
|
||||
fields["mem_avail"] = properties["MemoryAvailable"]
|
||||
|
||||
// Sanitize unset memory fields
|
||||
for k, value := range fields {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ package systemd_units
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"os/user"
|
||||
|
|
@ -13,7 +12,6 @@ import (
|
|||
"time"
|
||||
|
||||
sdbus "github.com/coreos/go-systemd/v22/dbus"
|
||||
"github.com/godbus/dbus/v5"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
|
|
@ -30,6 +28,7 @@ type properties struct {
|
|||
state *sdbus.UnitStatus
|
||||
ufPreset string
|
||||
ufState string
|
||||
ufActiveEnter uint64
|
||||
properties map[string]interface{}
|
||||
}
|
||||
|
||||
|
|
@ -284,6 +283,7 @@ func TestListFiles(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestShow(t *testing.T) {
|
||||
enter := time.Now().UnixMicro()
|
||||
tests := []struct {
|
||||
name string
|
||||
properties map[string]properties
|
||||
|
|
@ -303,6 +303,7 @@ func TestShow(t *testing.T) {
|
|||
},
|
||||
ufPreset: "disabled",
|
||||
ufState: "enabled",
|
||||
ufActiveEnter: uint64(enter),
|
||||
properties: map[string]interface{}{
|
||||
"Id": "example.service",
|
||||
"StatusErrno": 0,
|
||||
|
|
@ -339,6 +340,7 @@ func TestShow(t *testing.T) {
|
|||
"swap_peak": uint64(4000),
|
||||
"mem_avail": uint64(5000),
|
||||
"pid": 9999,
|
||||
"active_enter_timestamp_us": uint64(enter),
|
||||
},
|
||||
time.Unix(0, 0),
|
||||
),
|
||||
|
|
@ -357,6 +359,7 @@ func TestShow(t *testing.T) {
|
|||
},
|
||||
ufPreset: "disabled",
|
||||
ufState: "enabled",
|
||||
ufActiveEnter: 0,
|
||||
properties: map[string]interface{}{
|
||||
"Id": "example.service",
|
||||
"StatusErrno": 0,
|
||||
|
|
@ -386,6 +389,7 @@ func TestShow(t *testing.T) {
|
|||
"swap_current": uint64(0),
|
||||
"swap_peak": uint64(0),
|
||||
"mem_avail": uint64(0),
|
||||
"active_enter_timestamp_us": uint64(0),
|
||||
},
|
||||
time.Unix(0, 0),
|
||||
),
|
||||
|
|
@ -404,6 +408,7 @@ func TestShow(t *testing.T) {
|
|||
},
|
||||
ufPreset: "disabled",
|
||||
ufState: "enabled",
|
||||
ufActiveEnter: uint64(enter),
|
||||
properties: map[string]interface{}{
|
||||
"Id": "example.service",
|
||||
"StatusErrno": 10,
|
||||
|
|
@ -438,6 +443,7 @@ func TestShow(t *testing.T) {
|
|||
"swap_current": uint64(3000),
|
||||
"swap_peak": uint64(4000),
|
||||
"mem_avail": uint64(5000),
|
||||
"active_enter_timestamp_us": uint64(enter),
|
||||
},
|
||||
time.Unix(0, 0),
|
||||
),
|
||||
|
|
@ -456,6 +462,7 @@ func TestShow(t *testing.T) {
|
|||
},
|
||||
ufPreset: "disabled",
|
||||
ufState: "enabled",
|
||||
ufActiveEnter: uint64(0),
|
||||
properties: map[string]interface{}{
|
||||
"Id": "example.service",
|
||||
},
|
||||
|
|
@ -481,6 +488,7 @@ func TestShow(t *testing.T) {
|
|||
"swap_current": uint64(0),
|
||||
"swap_peak": uint64(0),
|
||||
"mem_avail": uint64(0),
|
||||
"active_enter_timestamp_us": uint64(0),
|
||||
},
|
||||
time.Unix(0, 0),
|
||||
),
|
||||
|
|
@ -519,6 +527,7 @@ func TestShow(t *testing.T) {
|
|||
},
|
||||
ufPreset: "disabled",
|
||||
ufState: "disabled",
|
||||
ufActiveEnter: uint64(0),
|
||||
properties: map[string]interface{}{
|
||||
"Id": "example.service",
|
||||
"StatusErrno": 0,
|
||||
|
|
@ -553,6 +562,7 @@ func TestShow(t *testing.T) {
|
|||
"swap_current": uint64(0),
|
||||
"swap_peak": uint64(0),
|
||||
"mem_avail": uint64(0),
|
||||
"active_enter_timestamp_us": uint64(0),
|
||||
},
|
||||
time.Unix(0, 0),
|
||||
),
|
||||
|
|
@ -974,19 +984,17 @@ func (c *fakeClient) GetUnitTypePropertiesContext(_ context.Context, unit, unitT
|
|||
return u.properties, nil
|
||||
}
|
||||
|
||||
func (c *fakeClient) GetUnitPropertyContext(_ context.Context, unit, propertyName string) (*sdbus.Property, error) {
|
||||
func (c *fakeClient) GetUnitPropertiesContext(_ context.Context, unit string) (map[string]interface{}, error) {
|
||||
u, found := c.units[unit]
|
||||
if !found {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
switch propertyName {
|
||||
case "UnitFileState":
|
||||
return &sdbus.Property{Name: propertyName, Value: dbus.MakeVariant(u.ufState)}, nil
|
||||
case "UnitFilePreset":
|
||||
return &sdbus.Property{Name: propertyName, Value: dbus.MakeVariant(u.ufPreset)}, nil
|
||||
}
|
||||
return nil, errors.New("unknown property")
|
||||
return map[string]interface{}{
|
||||
"UnitFileState": u.ufState,
|
||||
"UnitFilePreset": u.ufPreset,
|
||||
"ActiveEnterTimestamp": u.ufActiveEnter,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *fakeClient) ListUnitsContext(_ context.Context) ([]sdbus.UnitStatus, error) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue