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
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=
"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"
)
}
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"),
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())