Apply v2.0.0 deprecations

* Remove deprecated collectors.
* Remove deprecated flags.
* Flip rapl label feature flag to true.

Signed-off-by: Ben Kochie <superq@gmail.com>
This commit is contained in:
Ben Kochie 2024-09-11 11:52:04 +02:00
parent 090957658e
commit a678362345
No known key found for this signature in database
GPG key ID: C646B23C9E3245F1
13 changed files with 16 additions and 584 deletions

View file

@ -40,10 +40,6 @@ var (
diskstatsDeviceExcludeSet = true
return nil
}).String()
oldDiskstatsDeviceExclude = kingpin.Flag(
"collector.diskstats.ignored-devices",
"DEPRECATED: Use collector.diskstats.device-exclude",
).Hidden().String()
diskstatsDeviceInclude = kingpin.Flag("collector.diskstats.device-include", "Regexp of diskstats devices to include (mutually exclusive to device-exclude).").String()
@ -93,15 +89,6 @@ var (
)
func newDiskstatsDeviceFilter(logger *slog.Logger) (deviceFilter, error) {
if *oldDiskstatsDeviceExclude != "" {
if !diskstatsDeviceExcludeSet {
logger.Warn("--collector.diskstats.ignored-devices is DEPRECATED and will be removed in 2.0.0, use --collector.diskstats.device-exclude")
*diskstatsDeviceExclude = *oldDiskstatsDeviceExclude
} else {
return deviceFilter{}, errors.New("--collector.diskstats.ignored-devices and --collector.diskstats.device-exclude are mutually exclusive")
}
}
if *diskstatsDeviceExclude != "" && *diskstatsDeviceInclude != "" {
return deviceFilter{}, errors.New("device-exclude & device-include are mutually exclusive")
}

View file

@ -18,7 +18,6 @@
package collector
import (
"errors"
"log/slog"
"regexp"
@ -41,10 +40,6 @@ var (
mountPointsExcludeSet = true
return nil
}).String()
oldMountPointsExcluded = kingpin.Flag(
"collector.filesystem.ignored-mount-points",
"Regexp of mount points to ignore for filesystem collector.",
).Hidden().String()
fsTypesExcludeSet bool
fsTypesExclude = kingpin.Flag(
@ -54,10 +49,6 @@ var (
fsTypesExcludeSet = true
return nil
}).String()
oldFSTypesExcluded = kingpin.Flag(
"collector.filesystem.ignored-fs-types",
"Regexp of filesystem types to ignore for filesystem collector.",
).Hidden().String()
filesystemLabelNames = []string{"device", "mountpoint", "fstype", "device_error"}
)
@ -89,24 +80,6 @@ func init() {
// NewFilesystemCollector returns a new Collector exposing filesystems stats.
func NewFilesystemCollector(logger *slog.Logger) (Collector, error) {
if *oldMountPointsExcluded != "" {
if !mountPointsExcludeSet {
logger.Warn("--collector.filesystem.ignored-mount-points is DEPRECATED and will be removed in 2.0.0, use --collector.filesystem.mount-points-exclude")
*mountPointsExclude = *oldMountPointsExcluded
} else {
return nil, errors.New("--collector.filesystem.ignored-mount-points and --collector.filesystem.mount-points-exclude are mutually exclusive")
}
}
if *oldFSTypesExcluded != "" {
if !fsTypesExcludeSet {
logger.Warn("--collector.filesystem.ignored-fs-types is DEPRECATED and will be removed in 2.0.0, use --collector.filesystem.fs-types-exclude")
*fsTypesExclude = *oldFSTypesExcluded
} else {
return nil, errors.New("--collector.filesystem.ignored-fs-types and --collector.filesystem.fs-types-exclude are mutually exclusive")
}
}
subsystem := "filesystem"
logger.Info("Parsed flag --collector.filesystem.mount-points-exclude", "flag", *mountPointsExclude)
mountPointPattern := regexp.MustCompile(*mountPointsExclude)

View file

@ -2912,12 +2912,10 @@ node_qdisc_packets_total{device="wlan0",kind="fq"} 42
# TYPE node_qdisc_requeues_total counter
node_qdisc_requeues_total{device="eth0",kind="pfifo_fast"} 2
node_qdisc_requeues_total{device="wlan0",kind="fq"} 1
# HELP node_rapl_core_joules_total Current RAPL core value in joules
# TYPE node_rapl_core_joules_total counter
node_rapl_core_joules_total{index="0",path="collector/fixtures/sys/class/powercap/intel-rapl:0:0"} 118821.284256
# HELP node_rapl_package_joules_total Current RAPL package value in joules
# TYPE node_rapl_package_joules_total counter
node_rapl_package_joules_total{index="0",path="collector/fixtures/sys/class/powercap/intel-rapl:0"} 240422.366267
# HELP node_rapl_joules_total Current RAPL value in joules
# TYPE node_rapl_joules_total counter
node_rapl_joules_total{index="0",path="collector/fixtures/sys/class/powercap/intel-rapl:0",rapl_zone="package"} 240422.366267
node_rapl_joules_total{index="0",path="collector/fixtures/sys/class/powercap/intel-rapl:0:0",rapl_zone="core"} 118821.284256
# HELP node_schedstat_running_seconds_total Number of seconds CPU spent running a process.
# TYPE node_schedstat_running_seconds_total counter
node_schedstat_running_seconds_total{cpu="0"} 2.045936778163039e+06

View file

@ -2934,12 +2934,10 @@ node_qdisc_packets_total{device="wlan0",kind="fq"} 42
# TYPE node_qdisc_requeues_total counter
node_qdisc_requeues_total{device="eth0",kind="pfifo_fast"} 2
node_qdisc_requeues_total{device="wlan0",kind="fq"} 1
# HELP node_rapl_core_joules_total Current RAPL core value in joules
# TYPE node_rapl_core_joules_total counter
node_rapl_core_joules_total{index="0",path="collector/fixtures/sys/class/powercap/intel-rapl:0:0"} 118821.284256
# HELP node_rapl_package_joules_total Current RAPL package value in joules
# TYPE node_rapl_package_joules_total counter
node_rapl_package_joules_total{index="0",path="collector/fixtures/sys/class/powercap/intel-rapl:0"} 240422.366267
# HELP node_rapl_joules_total Current RAPL value in joules
# TYPE node_rapl_joules_total counter
node_rapl_joules_total{index="0",path="collector/fixtures/sys/class/powercap/intel-rapl:0",rapl_zone="package"} 240422.366267
node_rapl_joules_total{index="0",path="collector/fixtures/sys/class/powercap/intel-rapl:0:0",rapl_zone="core"} 118821.284256
# HELP node_schedstat_running_seconds_total Number of seconds CPU spent running a process.
# TYPE node_schedstat_running_seconds_total counter
node_schedstat_running_seconds_total{cpu="0"} 2.045936778163039e+06

View file

@ -30,12 +30,10 @@ import (
)
var (
netdevDeviceInclude = kingpin.Flag("collector.netdev.device-include", "Regexp of net devices to include (mutually exclusive to device-exclude).").String()
oldNetdevDeviceInclude = kingpin.Flag("collector.netdev.device-whitelist", "DEPRECATED: Use collector.netdev.device-include").Hidden().String()
netdevDeviceExclude = kingpin.Flag("collector.netdev.device-exclude", "Regexp of net devices to exclude (mutually exclusive to device-include).").String()
oldNetdevDeviceExclude = kingpin.Flag("collector.netdev.device-blacklist", "DEPRECATED: Use collector.netdev.device-exclude").Hidden().String()
netdevAddressInfo = kingpin.Flag("collector.netdev.address-info", "Collect address-info for every device").Bool()
netdevDetailedMetrics = kingpin.Flag("collector.netdev.enable-detailed-metrics", "Use (incompatible) metric names that provide more detailed stats on Linux").Bool()
netdevDeviceInclude = kingpin.Flag("collector.netdev.device-include", "Regexp of net devices to include (mutually exclusive to device-exclude).").String()
netdevDeviceExclude = kingpin.Flag("collector.netdev.device-exclude", "Regexp of net devices to exclude (mutually exclusive to device-include).").String()
netdevAddressInfo = kingpin.Flag("collector.netdev.address-info", "Collect address-info for every device").Bool()
netdevDetailedMetrics = kingpin.Flag("collector.netdev.enable-detailed-metrics", "Use (incompatible) metric names that provide more detailed stats on Linux").Bool()
)
type netDevCollector struct {
@ -54,24 +52,6 @@ func init() {
// NewNetDevCollector returns a new Collector exposing network device stats.
func NewNetDevCollector(logger *slog.Logger) (Collector, error) {
if *oldNetdevDeviceInclude != "" {
if *netdevDeviceInclude == "" {
logger.Warn("--collector.netdev.device-whitelist is DEPRECATED and will be removed in 2.0.0, use --collector.netdev.device-include")
*netdevDeviceInclude = *oldNetdevDeviceInclude
} else {
return nil, errors.New("--collector.netdev.device-whitelist and --collector.netdev.device-include are mutually exclusive")
}
}
if *oldNetdevDeviceExclude != "" {
if *netdevDeviceExclude == "" {
logger.Warn("--collector.netdev.device-blacklist is DEPRECATED and will be removed in 2.0.0, use --collector.netdev.device-exclude")
*netdevDeviceExclude = *oldNetdevDeviceExclude
} else {
return nil, errors.New("--collector.netdev.device-blacklist and --collector.netdev.device-exclude are mutually exclusive")
}
}
if *netdevDeviceExclude != "" && *netdevDeviceInclude != "" {
return nil, errors.New("device-exclude & device-include are mutually exclusive")
}

View file

@ -1,177 +0,0 @@
// Copyright 2015 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build !nontp
// +build !nontp
package collector
import (
"fmt"
"log/slog"
"net"
"sync"
"time"
"github.com/alecthomas/kingpin/v2"
"github.com/beevik/ntp"
"github.com/prometheus/client_golang/prometheus"
)
const (
hour24 = 24 * time.Hour // `time` does not export `Day` as Day != 24h because of DST
ntpSubsystem = "ntp"
)
var (
ntpServer = kingpin.Flag("collector.ntp.server", "NTP server to use for ntp collector").Default("127.0.0.1").String()
ntpServerPort = kingpin.Flag("collector.ntp.server-port", "UDP port number to connect to on NTP server").Default("123").Int()
ntpProtocolVersion = kingpin.Flag("collector.ntp.protocol-version", "NTP protocol version").Default("4").Int()
ntpServerIsLocal = kingpin.Flag("collector.ntp.server-is-local", "Certify that collector.ntp.server address is not a public ntp server").Default("false").Bool()
ntpIPTTL = kingpin.Flag("collector.ntp.ip-ttl", "IP TTL to use while sending NTP query").Default("1").Int()
// 3.46608s ~ 1.5s + PHI * (1 << maxPoll), where 1.5s is MAXDIST from ntp.org, it is 1.0 in RFC5905
// max-distance option is used as-is without phi*(1<<poll)
ntpMaxDistance = kingpin.Flag("collector.ntp.max-distance", "Max accumulated distance to the root").Default("3.46608s").Duration()
ntpOffsetTolerance = kingpin.Flag("collector.ntp.local-offset-tolerance", "Offset between local clock and local ntpd time to tolerate").Default("1ms").Duration()
leapMidnight time.Time
leapMidnightMutex = &sync.Mutex{}
)
type ntpCollector struct {
stratum, leap, rtt, offset, reftime, rootDelay, rootDispersion, sanity typedDesc
logger *slog.Logger
}
func init() {
registerCollector("ntp", defaultDisabled, NewNtpCollector)
}
// NewNtpCollector returns a new Collector exposing sanity of local NTP server.
// Default definition of "local" is:
// - collector.ntp.server address is a loopback address (or collector.ntp.server-is-mine flag is turned on)
// - the server is reachable with outgoin IP_TTL = 1
func NewNtpCollector(logger *slog.Logger) (Collector, error) {
ipaddr := net.ParseIP(*ntpServer)
if !*ntpServerIsLocal && (ipaddr == nil || !ipaddr.IsLoopback()) {
return nil, fmt.Errorf("only IP address of local NTP server is valid for --collector.ntp.server")
}
if *ntpProtocolVersion < 2 || *ntpProtocolVersion > 4 {
return nil, fmt.Errorf("invalid NTP protocol version %d; must be 2, 3, or 4", *ntpProtocolVersion)
}
if *ntpOffsetTolerance < 0 {
return nil, fmt.Errorf("offset tolerance must be non-negative")
}
if *ntpServerPort < 1 || *ntpServerPort > 65535 {
return nil, fmt.Errorf("invalid NTP port number %d; must be between 1 and 65535 inclusive", *ntpServerPort)
}
logger.Warn("This collector is deprecated and will be removed in the next major version release.")
return &ntpCollector{
stratum: typedDesc{prometheus.NewDesc(
prometheus.BuildFQName(namespace, ntpSubsystem, "stratum"),
"NTPD stratum.",
nil, nil,
), prometheus.GaugeValue},
leap: typedDesc{prometheus.NewDesc(
prometheus.BuildFQName(namespace, ntpSubsystem, "leap"),
"NTPD leap second indicator, 2 bits.",
nil, nil,
), prometheus.GaugeValue},
rtt: typedDesc{prometheus.NewDesc(
prometheus.BuildFQName(namespace, ntpSubsystem, "rtt_seconds"),
"RTT to NTPD.",
nil, nil,
), prometheus.GaugeValue},
offset: typedDesc{prometheus.NewDesc(
prometheus.BuildFQName(namespace, ntpSubsystem, "offset_seconds"),
"ClockOffset between NTP and local clock.",
nil, nil,
), prometheus.GaugeValue},
reftime: typedDesc{prometheus.NewDesc(
prometheus.BuildFQName(namespace, ntpSubsystem, "reference_timestamp_seconds"),
"NTPD ReferenceTime, UNIX timestamp.",
nil, nil,
), prometheus.GaugeValue},
rootDelay: typedDesc{prometheus.NewDesc(
prometheus.BuildFQName(namespace, ntpSubsystem, "root_delay_seconds"),
"NTPD RootDelay.",
nil, nil,
), prometheus.GaugeValue},
rootDispersion: typedDesc{prometheus.NewDesc(
prometheus.BuildFQName(namespace, ntpSubsystem, "root_dispersion_seconds"),
"NTPD RootDispersion.",
nil, nil,
), prometheus.GaugeValue},
sanity: typedDesc{prometheus.NewDesc(
prometheus.BuildFQName(namespace, ntpSubsystem, "sanity"),
"NTPD sanity according to RFC5905 heuristics and configured limits.",
nil, nil,
), prometheus.GaugeValue},
logger: logger,
}, nil
}
func (c *ntpCollector) Update(ch chan<- prometheus.Metric) error {
resp, err := ntp.QueryWithOptions(*ntpServer, ntp.QueryOptions{
Version: *ntpProtocolVersion,
TTL: *ntpIPTTL,
Timeout: time.Second, // default `ntpdate` timeout
Port: *ntpServerPort,
})
if err != nil {
return fmt.Errorf("couldn't get SNTP reply: %w", err)
}
ch <- c.stratum.mustNewConstMetric(float64(resp.Stratum))
ch <- c.leap.mustNewConstMetric(float64(resp.Leap))
ch <- c.rtt.mustNewConstMetric(resp.RTT.Seconds())
ch <- c.offset.mustNewConstMetric(resp.ClockOffset.Seconds())
if resp.ReferenceTime.Unix() > 0 {
// Go Zero is 0001-01-01 00:00:00 UTC
// NTP Zero is 1900-01-01 00:00:00 UTC
// UNIX Zero is 1970-01-01 00:00:00 UTC
// so let's keep ALL ancient `reftime` values as zero
ch <- c.reftime.mustNewConstMetric(float64(resp.ReferenceTime.UnixNano()) / 1e9)
} else {
ch <- c.reftime.mustNewConstMetric(0)
}
ch <- c.rootDelay.mustNewConstMetric(resp.RootDelay.Seconds())
ch <- c.rootDispersion.mustNewConstMetric(resp.RootDispersion.Seconds())
// Here is SNTP packet sanity check that is exposed to move burden of
// configuration from node_exporter user to the developer.
maxerr := *ntpOffsetTolerance
leapMidnightMutex.Lock()
if resp.Leap == ntp.LeapAddSecond || resp.Leap == ntp.LeapDelSecond {
// state of leapMidnight is cached as leap flag is dropped right after midnight
leapMidnight = resp.Time.Truncate(hour24).Add(hour24)
}
if leapMidnight.Add(-hour24).Before(resp.Time) && resp.Time.Before(leapMidnight.Add(hour24)) {
// tolerate leap smearing
maxerr += time.Second
}
leapMidnightMutex.Unlock()
if resp.Validate() == nil && resp.RootDistance <= *ntpMaxDistance && resp.MinError <= maxerr {
ch <- c.sanity.mustNewConstMetric(1)
} else {
ch <- c.sanity.mustNewConstMetric(0)
}
return nil
}

View file

@ -41,11 +41,9 @@ type qdiscStatCollector struct {
}
var (
collectorQdisc = kingpin.Flag("collector.qdisc.fixtures", "test fixtures to use for qdisc collector end-to-end testing").Default("").String()
collectorQdiscDeviceInclude = kingpin.Flag("collector.qdisc.device-include", "Regexp of qdisc devices to include (mutually exclusive to device-exclude).").String()
oldCollectorQdiskDeviceInclude = kingpin.Flag("collector.qdisk.device-include", "DEPRECATED: Use collector.qdisc.device-include").Hidden().String()
collectorQdiscDeviceExclude = kingpin.Flag("collector.qdisc.device-exclude", "Regexp of qdisc devices to exclude (mutually exclusive to device-include).").String()
oldCollectorQdiskDeviceExclude = kingpin.Flag("collector.qdisk.device-exclude", "DEPRECATED: Use collector.qdisc.device-exclude").Hidden().String()
collectorQdisc = kingpin.Flag("collector.qdisc.fixtures", "test fixtures to use for qdisc collector end-to-end testing").Default("").String()
collectorQdiscDeviceInclude = kingpin.Flag("collector.qdisc.device-include", "Regexp of qdisc devices to include (mutually exclusive to device-exclude).").String()
collectorQdiscDeviceExclude = kingpin.Flag("collector.qdisc.device-exclude", "Regexp of qdisc devices to exclude (mutually exclusive to device-include).").String()
)
func init() {
@ -54,24 +52,6 @@ func init() {
// NewQdiscStatCollector returns a new Collector exposing queuing discipline statistics.
func NewQdiscStatCollector(logger *slog.Logger) (Collector, error) {
if *oldCollectorQdiskDeviceInclude != "" {
if *collectorQdiscDeviceInclude == "" {
logger.Warn("--collector.qdisk.device-include is DEPRECATED and will be removed in 2.0.0, use --collector.qdisc.device-include")
*collectorQdiscDeviceInclude = *oldCollectorQdiskDeviceInclude
} else {
return nil, fmt.Errorf("--collector.qdisk.device-include and --collector.qdisc.device-include are mutually exclusive")
}
}
if *oldCollectorQdiskDeviceExclude != "" {
if *collectorQdiscDeviceExclude == "" {
logger.Warn("--collector.qdisk.device-exclude is DEPRECATED and will be removed in 2.0.0, use --collector.qdisc.device-exclude")
*collectorQdiscDeviceExclude = *oldCollectorQdiskDeviceExclude
} else {
return nil, fmt.Errorf("--collector.qdisk.device-exclude and --collector.qdisc.device-exclude are mutually exclusive")
}
}
if *collectorQdiscDeviceExclude != "" && *collectorQdiscDeviceInclude != "" {
return nil, fmt.Errorf("collector.qdisc.device-include and collector.qdisc.device-exclude are mutaly exclusive")
}

View file

@ -42,7 +42,7 @@ func init() {
}
var (
raplZoneLabel = kingpin.Flag("collector.rapl.enable-zone-label", "Enables service unit metric unit_start_time_seconds").Bool()
raplZoneLabel = kingpin.Flag("collector.rapl.enable-zone-label", "Enables service unit metric unit_start_time_seconds").Default("true").Bool()
)
// NewRaplCollector returns a new Collector exposing RAPL metrics.

View file

@ -1,99 +0,0 @@
// Copyright 2015 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build !norunit
// +build !norunit
package collector
import (
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/go-runit/runit"
"github.com/prometheus/client_golang/prometheus"
"log/slog"
)
var runitServiceDir = kingpin.Flag("collector.runit.servicedir", "Path to runit service directory.").Default("/etc/service").String()
type runitCollector struct {
state typedDesc
stateDesired typedDesc
stateNormal typedDesc
stateTimestamp typedDesc
logger *slog.Logger
}
func init() {
registerCollector("runit", defaultDisabled, NewRunitCollector)
}
// NewRunitCollector returns a new Collector exposing runit statistics.
func NewRunitCollector(logger *slog.Logger) (Collector, error) {
var (
subsystem = "service"
constLabels = prometheus.Labels{"supervisor": "runit"}
labelNames = []string{"service"}
)
logger.Warn("This collector is deprecated and will be removed in the next major version release.")
return &runitCollector{
state: typedDesc{prometheus.NewDesc(
prometheus.BuildFQName(namespace, subsystem, "state"),
"State of runit service.",
labelNames, constLabels,
), prometheus.GaugeValue},
stateDesired: typedDesc{prometheus.NewDesc(
prometheus.BuildFQName(namespace, subsystem, "desired_state"),
"Desired state of runit service.",
labelNames, constLabels,
), prometheus.GaugeValue},
stateNormal: typedDesc{prometheus.NewDesc(
prometheus.BuildFQName(namespace, subsystem, "normal_state"),
"Normal state of runit service.",
labelNames, constLabels,
), prometheus.GaugeValue},
stateTimestamp: typedDesc{prometheus.NewDesc(
prometheus.BuildFQName(namespace, subsystem, "state_last_change_timestamp_seconds"),
"Unix timestamp of the last runit service state change.",
labelNames, constLabels,
), prometheus.GaugeValue},
logger: logger,
}, nil
}
func (c *runitCollector) Update(ch chan<- prometheus.Metric) error {
services, err := runit.GetServices(*runitServiceDir)
if err != nil {
return err
}
for _, service := range services {
status, err := service.Status()
if err != nil {
c.logger.Debug("Couldn't get status", "service", service.Name, "err", err)
continue
}
c.logger.Debug("duration", "service", service.Name, "status", status.State, "pid", status.Pid, "duration_seconds", status.Duration)
ch <- c.state.mustNewConstMetric(float64(status.State), service.Name)
ch <- c.stateDesired.mustNewConstMetric(float64(status.Want), service.Name)
ch <- c.stateTimestamp.mustNewConstMetric(float64(status.Timestamp.Unix()), service.Name)
if status.NormallyUp {
ch <- c.stateNormal.mustNewConstMetric(1, service.Name)
} else {
ch <- c.stateNormal.mustNewConstMetric(0, service.Name)
}
}
return nil
}

View file

@ -1,180 +0,0 @@
// Copyright 2015 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build !nosupervisord
// +build !nosupervisord
package collector
import (
"context"
"fmt"
"log/slog"
"net"
"net/http"
"net/url"
"time"
"github.com/alecthomas/kingpin/v2"
"github.com/mattn/go-xmlrpc"
"github.com/prometheus/client_golang/prometheus"
)
var (
supervisordURL = kingpin.Flag("collector.supervisord.url", "XML RPC endpoint.").Default("http://localhost:9001/RPC2").Envar("SUPERVISORD_URL").String()
xrpc *xmlrpc.Client
)
type supervisordCollector struct {
upDesc *prometheus.Desc
stateDesc *prometheus.Desc
exitStatusDesc *prometheus.Desc
startTimeDesc *prometheus.Desc
logger *slog.Logger
}
func init() {
registerCollector("supervisord", defaultDisabled, NewSupervisordCollector)
}
// NewSupervisordCollector returns a new Collector exposing supervisord statistics.
func NewSupervisordCollector(logger *slog.Logger) (Collector, error) {
var (
subsystem = "supervisord"
labelNames = []string{"name", "group"}
)
if u, err := url.Parse(*supervisordURL); err == nil && u.Scheme == "unix" {
// Fake the URI scheme as http, since net/http.*Transport.roundTrip will complain
// about a non-http(s) transport.
xrpc = xmlrpc.NewClient("http://unix/RPC2")
xrpc.HttpClient.Transport = &http.Transport{
DialContext: func(ctx context.Context, _, _ string) (net.Conn, error) {
d := net.Dialer{Timeout: 10 * time.Second}
return d.DialContext(ctx, "unix", u.Path)
},
}
} else {
xrpc = xmlrpc.NewClient(*supervisordURL)
}
logger.Warn("This collector is deprecated and will be removed in the next major version release.")
return &supervisordCollector{
upDesc: prometheus.NewDesc(
prometheus.BuildFQName(namespace, subsystem, "up"),
"Process Up",
labelNames,
nil,
),
stateDesc: prometheus.NewDesc(
prometheus.BuildFQName(namespace, subsystem, "state"),
"Process State",
labelNames,
nil,
),
exitStatusDesc: prometheus.NewDesc(
prometheus.BuildFQName(namespace, subsystem, "exit_status"),
"Process Exit Status",
labelNames,
nil,
),
startTimeDesc: prometheus.NewDesc(
prometheus.BuildFQName(namespace, subsystem, "start_time_seconds"),
"Process start time",
labelNames,
nil,
),
logger: logger,
}, nil
}
func (c *supervisordCollector) isRunning(state int) bool {
// http://supervisord.org/subprocess.html#process-states
const (
// STOPPED = 0
STARTING = 10
RUNNING = 20
// BACKOFF = 30
STOPPING = 40
// EXITED = 100
// FATAL = 200
// UNKNOWN = 1000
)
switch state {
case STARTING, RUNNING, STOPPING:
return true
}
return false
}
func (c *supervisordCollector) Update(ch chan<- prometheus.Metric) error {
var info struct {
Name string `xmlrpc:"name"`
Group string `xmlrpc:"group"`
Start int `xmlrpc:"start"`
Stop int `xmlrpc:"stop"`
Now int `xmlrpc:"now"`
State int `xmlrpc:"state"`
StateName string `xmlrpc:"statename"`
SpawnErr string `xmlrpc:"spanerr"`
ExitStatus int `xmlrpc:"exitstatus"`
StdoutLogfile string `xmlrcp:"stdout_logfile"`
StderrLogfile string `xmlrcp:"stderr_logfile"`
PID int `xmlrpc:"pid"`
}
res, err := xrpc.Call("supervisor.getAllProcessInfo")
if err != nil {
return fmt.Errorf("unable to call supervisord: %w", err)
}
for _, p := range res.(xmlrpc.Array) {
for k, v := range p.(xmlrpc.Struct) {
switch k {
case "name":
info.Name = v.(string)
case "group":
info.Group = v.(string)
case "start":
info.Start = v.(int)
case "stop":
info.Stop = v.(int)
case "now":
info.Now = v.(int)
case "state":
info.State = v.(int)
case "statename":
info.StateName = v.(string)
case "exitstatus":
info.ExitStatus = v.(int)
case "pid":
info.PID = v.(int)
}
}
labels := []string{info.Name, info.Group}
ch <- prometheus.MustNewConstMetric(c.stateDesc, prometheus.GaugeValue, float64(info.State), labels...)
ch <- prometheus.MustNewConstMetric(c.exitStatusDesc, prometheus.GaugeValue, float64(info.ExitStatus), labels...)
if c.isRunning(info.State) {
ch <- prometheus.MustNewConstMetric(c.upDesc, prometheus.GaugeValue, 1, labels...)
ch <- prometheus.MustNewConstMetric(c.startTimeDesc, prometheus.CounterValue, float64(info.Start), labels...)
} else {
ch <- prometheus.MustNewConstMetric(c.upDesc, prometheus.GaugeValue, 0, labels...)
}
c.logger.Debug("process info", "group", info.Group, "name", info.Name, "state", info.StateName, "pid", info.PID)
}
return nil
}

View file

@ -18,7 +18,6 @@ package collector
import (
"context"
"errors"
"fmt"
"log/slog"
"math"
@ -46,13 +45,11 @@ var (
systemdUnitIncludeSet = true
return nil
}).String()
oldSystemdUnitInclude = kingpin.Flag("collector.systemd.unit-whitelist", "DEPRECATED: Use --collector.systemd.unit-include").Hidden().String()
systemdUnitExcludeSet bool
systemdUnitExclude = kingpin.Flag("collector.systemd.unit-exclude", "Regexp of systemd units to exclude. Units must both match include and not match exclude to be included.").Default(".+\\.(automount|device|mount|scope|slice)").PreAction(func(c *kingpin.ParseContext) error {
systemdUnitExcludeSet = true
return nil
}).String()
oldSystemdUnitExclude = kingpin.Flag("collector.systemd.unit-blacklist", "DEPRECATED: Use collector.systemd.unit-exclude").Hidden().String()
systemdPrivate = kingpin.Flag("collector.systemd.private", "Establish a private, direct connection to systemd without dbus (Strongly discouraged since it requires root. For testing purposes only).").Hidden().Bool()
enableTaskMetrics = kingpin.Flag("collector.systemd.enable-task-metrics", "Enables service unit tasks metrics unit_tasks_current and unit_tasks_max").Bool()
enableRestartsMetrics = kingpin.Flag("collector.systemd.enable-restarts-metrics", "Enables service unit metric service_restart_total").Bool()
@ -133,22 +130,6 @@ func NewSystemdCollector(logger *slog.Logger) (Collector, error) {
prometheus.BuildFQName(namespace, subsystem, "version"),
"Detected systemd version", []string{"version"}, nil)
if *oldSystemdUnitExclude != "" {
if !systemdUnitExcludeSet {
logger.Warn("--collector.systemd.unit-blacklist is DEPRECATED and will be removed in 2.0.0, use --collector.systemd.unit-exclude")
*systemdUnitExclude = *oldSystemdUnitExclude
} else {
return nil, errors.New("--collector.systemd.unit-blacklist and --collector.systemd.unit-exclude are mutually exclusive")
}
}
if *oldSystemdUnitInclude != "" {
if !systemdUnitIncludeSet {
logger.Warn("--collector.systemd.unit-whitelist is DEPRECATED and will be removed in 2.0.0, use --collector.systemd.unit-include")
*systemdUnitInclude = *oldSystemdUnitInclude
} else {
return nil, errors.New("--collector.systemd.unit-whitelist and --collector.systemd.unit-include are mutually exclusive")
}
}
logger.Info("Parsed flag --collector.systemd.unit-include", "flag", *systemdUnitInclude)
systemdUnitIncludePattern := regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *systemdUnitInclude))
logger.Info("Parsed flag --collector.systemd.unit-exclude", "flag", *systemdUnitExclude)

3
go.mod
View file

@ -4,7 +4,6 @@ go 1.22.0
require (
github.com/alecthomas/kingpin/v2 v2.4.0
github.com/beevik/ntp v1.4.3
github.com/coreos/go-systemd/v22 v22.5.0
github.com/dennwc/btrfs v0.0.0-20240418142341-0167142bde7a
github.com/ema/qdisc v1.0.0
@ -15,12 +14,10 @@ require (
github.com/josharian/native v1.1.0
github.com/jsimonetti/rtnetlink v1.4.2
github.com/lufia/iostat v1.2.1
github.com/mattn/go-xmlrpc v0.0.3
github.com/mdlayher/ethtool v0.2.0
github.com/mdlayher/netlink v1.7.2
github.com/mdlayher/wifi v0.2.0
github.com/opencontainers/selinux v1.11.0
github.com/prometheus-community/go-runit v0.1.0
github.com/prometheus/client_golang v1.20.3
github.com/prometheus/client_model v0.6.1
github.com/prometheus/common v0.59.1

6
go.sum
View file

@ -2,8 +2,6 @@ github.com/alecthomas/kingpin/v2 v2.4.0 h1:f48lwail6p8zpO1bC4TxtqACaGqHYA22qkHjH
github.com/alecthomas/kingpin/v2 v2.4.0/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE=
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc=
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE=
github.com/beevik/ntp v1.4.3 h1:PlbTvE5NNy4QHmA4Mg57n7mcFTmr1W1j3gcK7L1lqho=
github.com/beevik/ntp v1.4.3/go.mod h1:Unr8Zg+2dRn7d8bHFuehIMSvvUYssHMxW3Q5Nx4RW5Q=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
@ -49,8 +47,6 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/lufia/iostat v1.2.1 h1:tnCdZBIglgxD47RyD55kfWQcJMGzO+1QBziSQfesf2k=
github.com/lufia/iostat v1.2.1/go.mod h1:rEPNA0xXgjHQjuI5Cy05sLlS2oRcSlWHRLrvh/AQ+Pg=
github.com/mattn/go-xmlrpc v0.0.3 h1:Y6WEMLEsqs3RviBrAa1/7qmbGB7DVD3brZIbqMbQdGY=
github.com/mattn/go-xmlrpc v0.0.3/go.mod h1:mqc2dz7tP5x5BKlCahN/n+hs7OSZKJkS9JsHNBRlrxA=
github.com/mdlayher/ethtool v0.2.0 h1:akcA4WZVWozzirPASeMq8qgLkxpF3ykftVXwnrMKrhY=
github.com/mdlayher/ethtool v0.2.0/go.mod h1:W0pIBrNPK1TslIN4Z9wt1EVbay66Kbvek2z2f29VBfw=
github.com/mdlayher/genetlink v1.3.2 h1:KdrNKe+CTu+IbZnm/GVUMXSqBBLqcGpRDa0xkQy56gw=
@ -71,8 +67,6 @@ github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaL
github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus-community/go-runit v0.1.0 h1:uTWEj/Fn2RoLdfg/etSqwzgYNOYPrARx1BHUN052tGA=
github.com/prometheus-community/go-runit v0.1.0/go.mod h1:AvJ9Jo3gAFu2lbM4+qfjdpq30FfiLDJZKbQ015u08IQ=
github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4=
github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=