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: add systemd unit active state gauge #4

Merged
merged 4 commits into from
Apr 11, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ This service is responsible for providing vital network metrics for prometheus.
## Execution
The service can be executed via the following go command without having it previously built:
```
go run cmd/rddl-prometheus-exporter/main.go
go run cmd/rddl-prometheus-exporter/*.go
```

## Configuration
Expand All @@ -15,5 +15,5 @@ rpc-pass = 'password' // elementsd rpc password
rpc-user = 'user' // elementsd rpc user
service-bind = 'localhost'
service-port = 8080
wallets = 'wallet1,wallet2' // liquid wallets
service-units = '' // systemd units
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

better to give a real example here, because i can see that the string passed here "only" splits at ,. So if one puts in service-units = 'foo;bar', which looks ok, the exporter won't work correctly

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and as it seems the units need to be specified with .service extension for another string split. so a good example imho would be service-units = 'foo.service,bar.service'.

```
56 changes: 56 additions & 0 deletions cmd/rddl-prometheus-exporter/gauges.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package main

import (
"context"
"log"
"strings"

"github.com/prometheus/client_golang/prometheus"
elementsrpc "github.com/rddl-network/elements-rpc"
"github.com/rddl-network/rddl-prometheus-exporter/config"
"github.com/rddl-network/rddl-prometheus-exporter/elements"
"github.com/rddl-network/rddl-prometheus-exporter/system"
)

func setGauge(name string, help string, namespace string, subsystem string, callback func() float64) {
gaugeFunc := prometheus.NewGaugeFunc(prometheus.GaugeOpts{
Namespace: namespace,
Subsystem: subsystem,
Name: name,
Help: help,
}, callback)
prometheus.MustRegister(gaugeFunc)
}

func registerGauges(ctx context.Context, logger *log.Logger, cfg *config.Config) {
units := cfg.GetServiceUnits()
for _, unit := range units {
unit := unit
logger.Print("registering gauge for service unit: " + unit)
unitName := strings.Split(unit, ".")[0]
sanitizedUnit := strings.ReplaceAll(unitName, "-", "_")
setGauge("service_active_state_"+sanitizedUnit, "ActiveState for network relevant service: "+unitName, "systemd", "units", func() float64 {
return system.CheckUnitActiveState(ctx, unit)
})
}

wallets, err := elementsrpc.ListWallets(cfg.GetElementsURL(""), []string{})
if err != nil {
log.Fatalf("fatal error fetching wallets: %s", err.Error())
}

for _, wallet := range wallets {
wallet := strings.TrimSpace(wallet)
sanitizedWallet := strings.ReplaceAll(wallet, "-", "_")
logger.Printf("registering gauge for wallet: " + wallet)
setGauge("balance_"+sanitizedWallet, "Bitcoin balance for network relevant wallet: "+wallet, "elementsd", "wallets", func() float64 {
url := cfg.GetElementsURL(wallet)
balance, err := elements.GetWalletBalance(url, wallet)
if err != nil {
log.Print(err.Error())
return 0
}
return balance
})
}
}
35 changes: 2 additions & 33 deletions cmd/rddl-prometheus-exporter/main.go
Original file line number Diff line number Diff line change
@@ -1,27 +1,14 @@
package main

import (
"context"
"log"
"net/http"
"strings"

"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
elementsrpc "github.com/rddl-network/elements-rpc"
"github.com/rddl-network/rddl-prometheus-exporter/config"
"github.com/rddl-network/rddl-prometheus-exporter/elements"
)

func setGauge(name string, help string, namespace string, subsystem string, callback func() float64) {
gaugeFunc := prometheus.NewGaugeFunc(prometheus.GaugeOpts{
Namespace: namespace,
Subsystem: subsystem,
Name: name,
Help: help,
}, callback)
prometheus.MustRegister(gaugeFunc)
}

func main() {
cfg, err := config.LoadConfig("./")
if err != nil {
Expand All @@ -30,25 +17,7 @@ func main() {

logger := log.Default()

wallets, err := elementsrpc.ListWallets(cfg.GetElementsURL(""), []string{})
if err != nil {
log.Fatalf("fatal error fetching wallets: %s", err.Error())
}

for _, wallet := range wallets {
wallet := strings.TrimSpace(wallet)
sanitizedWallet := strings.ReplaceAll(wallet, "-", "_")
logger.Printf("registering gauge for wallet: " + wallet)
setGauge("balance_"+sanitizedWallet, "Bitcoin balance for network relevant wallet: "+wallet, "elementsd", "wallets", func() float64 {
url := cfg.GetElementsURL(wallet)
balance, err := elements.GetWalletBalance(url, wallet)
if err != nil {
log.Print(err.Error())
return 0
}
return balance
})
}
registerGauges(context.Background(), logger, cfg)

http.Handle("/metrics", promhttp.Handler())
logger.Printf("listening on port: %d", cfg.ServicePort)
Expand Down
28 changes: 18 additions & 10 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package config

import (
"fmt"
"strings"
"sync"
)

Expand All @@ -11,14 +12,16 @@ rpc-user="{{ .RPCUser }}"
rpc-pass="{{ .RPCPass }}"
service-bind="{{ .ServiceBind }}"
service-port={{ .ServicePort }}
service-units="{{ .ServiceUnits }}"
`

type Config struct {
RPCHost string `mapstructure:"rpc-host"`
RPCUser string `mapstructure:"rpc-user"`
RPCPass string `mapstructure:"rpc-pass"`
ServiceBind string `mapstructure:"service-bind"`
ServicePort int `mapstructure:"service-port"`
RPCHost string `mapstructure:"rpc-host"`
RPCUser string `mapstructure:"rpc-user"`
RPCPass string `mapstructure:"rpc-pass"`
ServiceBind string `mapstructure:"service-bind"`
ServicePort int `mapstructure:"service-port"`
ServiceUnits string `mapstructure:"service-units"`
}

var (
Expand All @@ -29,11 +32,12 @@ var (
// DefaultConfig returns distribution-service default config
func DefaultConfig() *Config {
return &Config{
RPCHost: "localhost:18884",
RPCUser: "user",
RPCPass: "password",
ServiceBind: "localhost",
ServicePort: 8080,
RPCHost: "localhost:18884",
RPCUser: "user",
RPCPass: "password",
ServiceBind: "localhost",
ServicePort: 8080,
ServiceUnits: "",
}
}

Expand All @@ -52,3 +56,7 @@ func (c *Config) GetElementsURL(wallet string) string {
url := fmt.Sprintf("http://%s:%s@%s/wallet/%s", c.RPCUser, c.RPCPass, c.RPCHost, wallet)
return url
}

func (c *Config) GetServiceUnits() []string {
return strings.Split(c.ServiceUnits, ",")
}
1 change: 1 addition & 0 deletions config/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ func LoadConfig(path string) (cfg *Config, err error) {
cfg.RPCPass = v.GetString("rpc-pass")
cfg.ServiceBind = v.GetString("service-bind")
cfg.ServicePort = v.GetInt("service-port")
cfg.ServiceUnits = v.GetString("service-units")
return
}
log.Println("no config file found.")
Expand Down
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module github.com/rddl-network/rddl-prometheus-exporter
go 1.21.5

require (
github.com/coreos/go-systemd/v22 v22.5.0
github.com/prometheus/client_golang v1.19.0
github.com/rddl-network/elements-rpc v1.1.0
github.com/spf13/viper v1.18.2
Expand All @@ -14,6 +15,7 @@ require (
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/godbus/dbus/v5 v5.0.4 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ 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.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
Expand All @@ -10,6 +12,8 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/godbus/dbus/v5 v5.0.4 h1:9349emZab16e7zQvpmsbtjc18ykshndd8y2PG3sgJbA=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
Expand Down
36 changes: 36 additions & 0 deletions system/unit.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package system

import (
"context"
"log"

"github.com/coreos/go-systemd/v22/dbus"
)

// CheckUnitActiveState takes the (unescaped) unit name and returns 1 if the unit is active or 0 if inactive
func CheckUnitActiveState(ctx context.Context, unit string) float64 {
logger := log.Default()

conn, err := dbus.NewWithContext(ctx)
if err != nil {
logger.Print(err)
return 0
}

unitProps, err := conn.GetUnitPropertiesContext(ctx, unit)
if err != nil {
logger.Print(err)
return 0
}

state, ok := unitProps["ActiveState"]
if !ok {
logger.Printf("%s properties do not contain ActiveState", unit)
}

if state != "active" {
return 0
}

return 1
}