]> go.fuhry.dev Git - runtime.git/commitdiff
apcups_exporter: handle apcupsd restarts/downtime; add systemd unit
authorDan Fuhry <dan@fuhry.com>
Wed, 17 Jan 2024 04:21:55 +0000 (23:21 -0500)
committerDan Fuhry <dan@fuhry.com>
Wed, 17 Jan 2024 04:24:04 +0000 (23:24 -0500)
go.mod
go.sum
metrics/apcups_exporter/main.go
metrics/apcups_exporter/systemd/apcupsd-exporter.service [new file with mode: 0644]

diff --git a/go.mod b/go.mod
index ad4233c939df8b7017da00d2cfb110bb9dcda156..13a3f504e12619e4e684f529f180f86f03174ee6 100644 (file)
--- a/go.mod
+++ b/go.mod
@@ -43,6 +43,7 @@ require (
        github.com/BurntSushi/toml v1.2.1 // indirect
        github.com/beorn7/perks v1.0.1 // indirect
        github.com/cespare/xxhash/v2 v2.2.0 // indirect
+       github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf // indirect
        github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
        github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba // indirect
        github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect
diff --git a/go.sum b/go.sum
index c156bf5ca6feec88b019cfdca3c5261880610726..434c6da77eaedd8218bc6bb61b05046dea48971e 100644 (file)
--- a/go.sum
+++ b/go.sum
@@ -98,6 +98,8 @@ github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee
 github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
 github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
 github.com/coreos/go-systemd v0.0.0-20190620071333-e64a0ec8b42a/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
+github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf h1:iW4rZ826su+pqaw19uhpSCzhj44qo35pNgKFGqzDKkU=
+github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
 github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
 github.com/coreos/go-systemd/v22 v22.4.0 h1:y9YHcjnjynCd/DVbg5j9L/33jQM3MxJlbj/zWskzfGU=
 github.com/coreos/go-systemd/v22 v22.4.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
index 0fa6b6e9d8c1925f964f28c1f63db7de0a2b8532..d4ccbd9ff84b27bdbec5dc9343ad5a17c57ca2f8 100644 (file)
@@ -4,10 +4,13 @@ import (
        "context"
        "flag"
        "os/signal"
+       "sync"
        "syscall"
        "time"
 
+       "github.com/coreos/go-systemd/daemon"
        "github.com/mdlayher/apcupsd"
+
        "go.fuhry.dev/runtime/metrics/metricbus/mbclient"
        "go.fuhry.dev/runtime/utils/log"
 )
@@ -19,16 +22,20 @@ type apcMetrics struct {
 }
 
 func main() {
+       var apcConn *apcupsd.Client
+       var err error
+       var sdNotifyOnce sync.Once
+
        ctx, _ := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
        flag.Parse()
 
        svc := mbclient.NewService(ctx)
 
-       apcupsd, err := apcupsd.Dial("tcp", "127.0.0.1:3551")
-       if err != nil {
-               log.Panic(err)
-       }
-       defer apcupsd.Close()
+       defer (func() {
+               if apcConn != nil {
+                       apcConn.Close()
+               }
+       })()
 
        metrics := apcMetrics{
                lineVoltage:      svc.DefineGauge("apcups_line_voltage", "AC mains line voltage"),
@@ -48,13 +55,30 @@ func main() {
        for {
                select {
                case <-ticker.C:
-                       status, err := apcupsd.Status()
+                       if apcConn == nil {
+                               apcConn, err = apcupsd.Dial("tcp", "127.0.0.1:3551")
+                               if err != nil {
+                                       log.Default().Errorf("error getting status from apcupsd: %v", err)
+                                       continue
+                               }
+                       }
+                       status, err := apcConn.Status()
                        if err != nil {
                                log.Default().Errorf("error getting status from apcupsd: %v", err)
+                               apcConn.Close()
+
+                               apcConn = nil
                                continue
                        }
                        log.Default().V(1).Infof("UPS status: state=%s, line voltage: %.1f, load %% %.1f, seconds left %.0f, charge pct %.1f",
                                status.Status, status.LineVoltage, status.LoadPercent, status.TimeLeft.Seconds(), status.BatteryChargePercent)
+                       if status.LoadPercent == 0.0 && status.BatteryChargePercent == 0.0 {
+                               log.Default().V(1).Error("refusing to log impossible apcups state")
+                               continue
+                       }
+                       sdNotifyOnce.Do(func() {
+                               daemon.SdNotify(false, daemon.SdNotifyReady)
+                       })
                        metrics.lineVoltage.Set(status.LineVoltage)
                        metrics.loadPercentage.Set(status.LoadPercent)
                        metrics.secondsLeft.Set(status.TimeLeft.Seconds())
diff --git a/metrics/apcups_exporter/systemd/apcupsd-exporter.service b/metrics/apcups_exporter/systemd/apcupsd-exporter.service
new file mode 100644 (file)
index 0000000..b815ead
--- /dev/null
@@ -0,0 +1,11 @@
+[Unit]
+Description=Export stats from apcupsd via metric-collector
+Requires=apcupsd.service
+
+[Service]
+Type=notify
+User=daemon
+ExecStart=/usr/bin/apcupsd-exporter
+
+[Install]
+WantedBy=default.target