diff --git a/README.md b/README.md index 04df3a1..1276668 100644 --- a/README.md +++ b/README.md @@ -87,8 +87,9 @@ Metrics (without prefix) | Description `missed_blocks` | Number of missed blocks per validator (for a bonded validator) `tracked_blocks` | Number of blocks tracked since start `skipped_blocks` | Number of blocks skipped (ie. not tracked) since start -`validator_bonded` | Set to 1 if the validator is bonded -`validator_jail` | Set to 1 if the validator is jailed +`bonded_tokens` | Number of bonded tokens per validator +`is_bonded` | Set to 1 if the validator is bonded +`is_jail` | Set to 1 if the validator is jailed `node_block_height` | Latest fetched block height for each node `node_synced` | Set to 1 is the node is synced (ie. not catching-up) diff --git a/go.mod b/go.mod index e293eb6..419424c 100644 --- a/go.mod +++ b/go.mod @@ -10,6 +10,8 @@ require ( github.com/prometheus/client_golang v1.16.0 github.com/prometheus/client_model v0.3.0 github.com/rs/zerolog v1.30.0 + github.com/shopspring/decimal v1.3.1 + github.com/stretchr/testify v1.8.4 github.com/urfave/cli/v2 v2.25.7 golang.org/x/sync v0.3.0 gotest.tools v2.2.0+incompatible @@ -97,7 +99,6 @@ require ( github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/viper v1.14.0 // indirect - github.com/stretchr/testify v1.8.4 // indirect github.com/subosito/gotenv v1.4.1 // indirect github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c // indirect diff --git a/go.sum b/go.sum index 80dce5b..9fda80a 100644 --- a/go.sum +++ b/go.sum @@ -438,6 +438,8 @@ github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sasha-s/go-deadlock v0.3.1 h1:sqv7fDNShgjcaxkO0JNcOAlr8B9+cV5Ey/OB71efZx0= github.com/sasha-s/go-deadlock v0.3.1/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM= +github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= +github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= diff --git a/pkg/exporter/exporter.go b/pkg/exporter/exporter.go index 0d42221..68a83ae 100644 --- a/pkg/exporter/exporter.go +++ b/pkg/exporter/exporter.go @@ -13,6 +13,7 @@ import ( "github.com/fatih/color" "github.com/kilnfi/cosmos-validator-watcher/pkg/metrics" "github.com/rs/zerolog/log" + "github.com/shopspring/decimal" ) // TrackedValidator adds the ability to attach a custom name to a validator address @@ -159,8 +160,11 @@ func (e *Exporter) handleValidators(validators []stakingtypes.Validator) { address := pubkey.Address().String() if tracked.Address == address { - e.cfg.Metrics.ValidatorBonded.WithLabelValues(address, name).Set(metrics.BoolToFloat64(val.Status == stakingtypes.Bonded)) - e.cfg.Metrics.ValidatorJail.WithLabelValues(address, name).Set(metrics.BoolToFloat64(val.Jailed)) + bondedTokens, _ := decimal.NewFromBigInt(val.BondedTokens().BigInt(), -6).Float64() + + e.cfg.Metrics.BondedTokens.WithLabelValues(address, name).Set(bondedTokens) + e.cfg.Metrics.IsBonded.WithLabelValues(address, name).Set(metrics.BoolToFloat64(val.Status == stakingtypes.Bonded)) + e.cfg.Metrics.IsJailed.WithLabelValues(address, name).Set(metrics.BoolToFloat64(val.Jailed)) break } } diff --git a/pkg/exporter/exporter_test.go b/pkg/exporter/exporter_test.go index 3fa2398..d168a77 100644 --- a/pkg/exporter/exporter_test.go +++ b/pkg/exporter/exporter_test.go @@ -6,6 +6,7 @@ import ( "strings" "testing" + "cosmossdk.io/math" "github.com/cometbft/cometbft/types" codectypes "github.com/cosmos/cosmos-sdk/codec/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" @@ -149,18 +150,23 @@ func TestExporter(t *testing.T) { ConsensusPubkey: addr, Jailed: false, Status: stakingtypes.Bonded, + Tokens: math.NewInt(42000000), }, } exporter.handleValidators(validators) + assert.Equal(t, + `label: label: gauge: `, + ReadMetric(exporter.cfg.Metrics.BondedTokens.WithLabelValues(address, name)), + ) assert.Equal(t, `label: label: gauge: `, - ReadMetric(exporter.cfg.Metrics.ValidatorBonded.WithLabelValues(address, name)), + ReadMetric(exporter.cfg.Metrics.IsBonded.WithLabelValues(address, name)), ) assert.Equal(t, `label: label: gauge: `, - ReadMetric(exporter.cfg.Metrics.ValidatorJail.WithLabelValues(address, name)), + ReadMetric(exporter.cfg.Metrics.IsJailed.WithLabelValues(address, name)), ) }) } diff --git a/pkg/metrics/metrics.go b/pkg/metrics/metrics.go index ac76f02..edbf579 100644 --- a/pkg/metrics/metrics.go +++ b/pkg/metrics/metrics.go @@ -9,8 +9,9 @@ type Metrics struct { MissedBlocks *prometheus.CounterVec TrackedBlocks prometheus.Counter SkippedBlocks prometheus.Counter - ValidatorBonded *prometheus.GaugeVec - ValidatorJail *prometheus.GaugeVec + BondedTokens *prometheus.GaugeVec + IsBonded *prometheus.GaugeVec + IsJailed *prometheus.GaugeVec // Node metrics NodeBlockHeight *prometheus.GaugeVec @@ -56,18 +57,26 @@ func New(namespace string) *Metrics { Help: "Number of blocks skipped (ie. not tracked) since start", }, ), - ValidatorBonded: prometheus.NewGaugeVec( + BondedTokens: prometheus.NewGaugeVec( prometheus.GaugeOpts{ Namespace: namespace, - Name: "validator_bonded", + Name: "bonded_tokens", + Help: "Number of bonded tokens per validator", + }, + []string{"address", "name"}, + ), + IsBonded: prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Namespace: namespace, + Name: "is_bonded", Help: "Set to 1 if the validator is bonded", }, []string{"address", "name"}, ), - ValidatorJail: prometheus.NewGaugeVec( + IsJailed: prometheus.NewGaugeVec( prometheus.GaugeOpts{ Namespace: namespace, - Name: "validator_jail", + Name: "is_jailed", Help: "Set to 1 if the validator is jailed", }, []string{"address", "name"}, @@ -95,8 +104,9 @@ func New(namespace string) *Metrics { prometheus.MustRegister(metrics.MissedBlocks) prometheus.MustRegister(metrics.TrackedBlocks) prometheus.MustRegister(metrics.SkippedBlocks) - prometheus.MustRegister(metrics.ValidatorBonded) - prometheus.MustRegister(metrics.ValidatorJail) + prometheus.MustRegister(metrics.BondedTokens) + prometheus.MustRegister(metrics.IsBonded) + prometheus.MustRegister(metrics.IsJailed) prometheus.MustRegister(metrics.NodeBlockHeight) prometheus.MustRegister(metrics.NodeSynced) diff --git a/pkg/watcher/watcher.go b/pkg/watcher/watcher.go index dec9da5..0968b81 100644 --- a/pkg/watcher/watcher.go +++ b/pkg/watcher/watcher.go @@ -213,8 +213,11 @@ func (w *Watcher) getValidators(ctx context.Context) ([]*types.Validator, error) } func (w *Watcher) syncStakingValidators(ctx context.Context) error { - clientCtx := (client.Context{}).WithClient(w.rpcClient) + if !w.Ready() { + return nil + } + clientCtx := (client.Context{}).WithClient(w.rpcClient) queryClient := stakingtypes.NewQueryClient(clientCtx) validators, err := queryClient.Validators(ctx, &stakingtypes.QueryValidatorsRequest{