Skip to content

Commit

Permalink
Add metrics (#33)
Browse files Browse the repository at this point in the history
* Pushing metrics to gateway
  • Loading branch information
KonradStaniec authored May 27, 2024
1 parent f5d04a9 commit a94125d
Show file tree
Hide file tree
Showing 7 changed files with 190 additions and 16 deletions.
10 changes: 9 additions & 1 deletion config/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ network = "regtest"

[remote-signer-config]
# The list of signer urls in the format http://covenant_pk@signer_host:port
urls = ["http://02f071ad9a03c3c13c0ce0107c89269edd9d3ed16c42aeaf72572e1135af34b81f@http://127.0.0.1:9791", ]
urls = ["http://03d4625ae15c25c380e131a0a95e23612805f0f314ef5a39ff6cba2a7e3c06f5d9@http://127.0.0.1:9791", ]
# The timeout of each request to the remote signing server
timeout_seconds = 2

[metrics-config]
# Enable reporting metrics
enabled = false
# IP of the Prometheus server
host = "127.0.0.1"
# Port of the Prometheus server
port = 2112
27 changes: 21 additions & 6 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,18 @@ import (
)

type Config struct {
Db DbConfig `mapstructure:"db-config"`
Btc BtcConfig `mapstructure:"btc-config"`
Signer RemoteSignerConfig `mapstructure:"remote-signer-config"`
Db DbConfig `mapstructure:"db-config"`
Btc BtcConfig `mapstructure:"btc-config"`
Signer RemoteSignerConfig `mapstructure:"remote-signer-config"`
Metrics MetricsConfig `mapstructure:"metrics-config"`
}

func DefaultConfig() *Config {
return &Config{
Db: *DefaultDBConfig(),
Btc: *DefaultBtcConfig(),
Signer: *DefaultRemoteSignerConfig(),
Db: *DefaultDBConfig(),
Btc: *DefaultBtcConfig(),
Signer: *DefaultRemoteSignerConfig(),
Metrics: *DefaultMetricsConfig(),
}
}

Expand All @@ -34,6 +36,10 @@ func (cfg *Config) Validate() error {
return fmt.Errorf("invalid remote signer config: %w", err)
}

if err := cfg.Metrics.Validate(); err != nil {
return fmt.Errorf("invalid metrics config: %w", err)
}

return nil
}

Expand Down Expand Up @@ -61,6 +67,15 @@ network = "{{ .Btc.Network }}"
urls = [{{ range .Signer.Urls }}{{ printf "%q, " . }}{{end}}]
# The timeout of each request to the remote signing server
timeout_seconds = {{ .Signer.TimeoutSeconds }}
[metrics-config]
# Enable reporting metrics
enabled = {{ .Metrics.Enabled }}
# IP of the Prometheus server
host = "{{ .Metrics.Host }}"
# Port of the Prometheus server
port = {{ .Metrics.Port }}
`

var configTemplate *template.Template
Expand Down
44 changes: 44 additions & 0 deletions internal/config/metrics.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package config

import (
"fmt"
)

const (
defaultMetricsPort = 2112
defaultMetricsHost = "127.0.0.1"
)

// MetricsConfig defines the server's basic configuration
type MetricsConfig struct {
Enabled bool `long:"enabled" description:"Enable reporting metrics"`
Host string `long:"host" description:"host of the Prometheus server"`
Port int `long:"port" description:"Port of the Prometheus server"`
}

func (cfg *MetricsConfig) Validate() error {
if cfg.Port < 0 || cfg.Port > 65535 {
return fmt.Errorf("invalid port: %d", cfg.Port)
}

if cfg.Host == "" {
return fmt.Errorf("host cannot be empty")
}

return nil
}

func (cfg *MetricsConfig) Address() (string, error) {
if err := cfg.Validate(); err != nil {
return "", err
}
return fmt.Sprintf("%s:%d", cfg.Host, cfg.Port), nil
}

func DefaultMetricsConfig() *MetricsConfig {
return &MetricsConfig{
Enabled: false,
Port: defaultMetricsPort,
Host: defaultMetricsHost,
}
}
4 changes: 2 additions & 2 deletions internal/services/persistent_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,8 @@ func (s *PersistentUnbondingStorage) AddTxWithSignature(
sigBytes := sig.Serialize()
sigHex := hex.EncodeToString(sigBytes)

stakerPkHex := pubKeyToString(info.StakerPk)
fpPkHex := pubKeyToString(info.FinalityProviderPk)
stakerPkHex := pubKeyToStringSchnorr(info.StakerPk)
fpPkHex := pubKeyToStringSchnorr(info.FinalityProviderPk)

stakingTxHex, err := serializeBTCTxToHex(stakingtTxData.StakingTransaction)
if err != nil {
Expand Down
55 changes: 50 additions & 5 deletions internal/services/unbonding_pipeline.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ import (
"github.com/babylonchain/cli-tools/internal/btcclient"
"github.com/babylonchain/cli-tools/internal/config"
"github.com/babylonchain/cli-tools/internal/db"

"github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/btcec/v2/schnorr"
"github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcd/wire"
"github.com/prometheus/client_golang/prometheus/push"
)

var (
Expand All @@ -29,10 +29,14 @@ func wrapCrititical(err error) error {
return fmt.Errorf("%s:%w", err.Error(), ErrCriticalError)
}

func pubKeyToString(pubKey *btcec.PublicKey) string {
func pubKeyToStringSchnorr(pubKey *btcec.PublicKey) string {
return hex.EncodeToString(schnorr.SerializePubKey(pubKey))
}

func pubKeyToStringCompressed(pubKey *btcec.PublicKey) string {
return hex.EncodeToString(pubKey.SerializeCompressed())
}

type SystemParamsRetriever struct {
CovenantPublicKeys []*btcec.PublicKey
CovenantQuorum uint32
Expand Down Expand Up @@ -65,6 +69,7 @@ type UnbondingPipeline struct {
signer CovenantSigner
sender BtcSender
retriever ParamsRetriever
Metrics *PipelineMetrics
btcParams *chaincfg.Params
}

Expand Down Expand Up @@ -101,12 +106,15 @@ func NewUnbondingPipelineFromConfig(
return nil, err
}

m := NewPipelineMetrics(&cfg.Metrics)

return NewUnbondingPipeline(
logger,
store,
signer,
bs,
ret,
m,
cfg.Btc.MustGetBtcNetworkParams(),
), nil
}
Expand All @@ -117,6 +125,7 @@ func NewUnbondingPipeline(
signer CovenantSigner,
sender BtcSender,
retriever ParamsRetriever,
metrics *PipelineMetrics,
btcParams *chaincfg.Params,
) *UnbondingPipeline {
return &UnbondingPipeline{
Expand All @@ -125,6 +134,7 @@ func NewUnbondingPipeline(
signer: signer,
sender: sender,
retriever: retriever,
Metrics: metrics,
btcParams: btcParams,
}
}
Expand Down Expand Up @@ -174,21 +184,21 @@ func (up *UnbondingPipeline) signUnbondingTransaction(
}

func (up *UnbondingPipeline) requestSigFromCovenant(req *SignRequest, resultChan chan *SignResult) {
pkStr := pubKeyToString(req.SignerPubKey)
pkStr := pubKeyToStringCompressed(req.SignerPubKey)
up.logger.Debug("request signatures from covenant signer",
"signer_pk", pkStr)

var res SignResult
sigPair, err := up.signer.SignUnbondingTransaction(req)
if err != nil {
// TODO record metrics
up.Metrics.RecordFailedSigningRequest(pkStr)
up.logger.Error("failed to get signatures from covenant",
"signer_pk", pkStr,
"error", err)

res.Err = err
} else {
// TODO: record metrics
up.Metrics.RecordSuccessSigningRequest(pkStr)
up.logger.Debug("got signatures from covenant signer", "signer_pk", pkStr)

res.PubKeySig = sigPair
Expand All @@ -213,6 +223,22 @@ func outputsAreEqual(a, b *wire.TxOut) bool {
return true
}

func (up *UnbondingPipeline) pushMetrics() error {
gatewayUrl, err := up.Metrics.Config.Address()
if err != nil {
return fmt.Errorf("failed to get gateway address: %w", err)
}

up.logger.Info("Pushing metrics to gateway", "gateway", gatewayUrl)

return push.New(gatewayUrl, "unbonding-pipeline").
Collector(up.Metrics.SuccessSigningReqs).
Collector(up.Metrics.FailedSigningReqs).
Collector(up.Metrics.SuccessfulSentTransactions).
Collector(up.Metrics.FailureSentTransactions).
Push()
}

func (up *UnbondingPipeline) processUnbondingTransactions(
ctx context.Context,
transactions []*UnbondingTxData,
Expand Down Expand Up @@ -317,6 +343,7 @@ func (up *UnbondingPipeline) processUnbondingTransactions(
if err := up.store.SetUnbondingTransactionProcessingFailed(ctx, utx); err != nil {
return wrapCrititical(err)
}
up.Metrics.RecordFailedUnbodingTransaction()
} else {
up.logger.Info(
"Successfully sent unbonding transaction",
Expand All @@ -325,8 +352,10 @@ func (up *UnbondingPipeline) processUnbondingTransactions(
if err := up.store.SetUnbondingTransactionProcessed(ctx, utx); err != nil {
return wrapCrititical(err)
}
up.Metrics.RecordSentUnbondingTransaction()
}
}

return nil
}

Expand All @@ -350,6 +379,14 @@ func (up *UnbondingPipeline) ProcessNewTransactions(ctx context.Context) error {
return nil
}

defer func() {
if up.Metrics.Config.Enabled {
if err := up.pushMetrics(); err != nil {
up.logger.Error("Failed to push metrics", "error", err)
}
}
}()

if err := up.processUnbondingTransactions(ctx, unbondingTransactions); err != nil {
return err
}
Expand All @@ -372,6 +409,14 @@ func (up *UnbondingPipeline) ProcessFailedTransactions(ctx context.Context) erro
return nil
}

defer func() {
if up.Metrics.Config.Enabled {
if err := up.pushMetrics(); err != nil {
up.logger.Error("Failed to push metrics", "error", err)
}
}
}()

if err := up.processUnbondingTransactions(ctx, unbondingTransactions); err != nil {
return err
}
Expand Down
62 changes: 62 additions & 0 deletions internal/services/unbonding_pipeline_metrics.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package services

import (
"github.com/babylonchain/cli-tools/internal/config"
"github.com/prometheus/client_golang/prometheus"
)

type PipelineMetrics struct {
SuccessSigningReqs *prometheus.CounterVec
FailedSigningReqs *prometheus.CounterVec
SuccessfulSentTransactions prometheus.Counter
FailureSentTransactions prometheus.Counter
Config *config.MetricsConfig
}

func NewPipelineMetrics(cfg *config.MetricsConfig) *PipelineMetrics {
return &PipelineMetrics{
SuccessSigningReqs: prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: "number_of_successful_signing_requests",
Help: "How many signing requests to given covenant were successful",
},
[]string{"covenant_pk"},
),
FailedSigningReqs: prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: "number_of_failed_signing_requests",
Help: "How many signing requests to given covenant failed",
},
[]string{"covenant_pk"},
),
SuccessfulSentTransactions: prometheus.NewCounter(
prometheus.CounterOpts{
Name: "number_of_successful_unbonding_transactions",
Help: "How many transactions were successfully sent to the network",
},
),
FailureSentTransactions: prometheus.NewCounter(
prometheus.CounterOpts{
Name: "number_of_failed_unbonding_transactions",
Help: "How many transactions failed to be sent to the network",
},
),
Config: cfg,
}
}

func (pm *PipelineMetrics) RecordSuccessSigningRequest(covenantPk string) {
pm.SuccessSigningReqs.WithLabelValues(covenantPk).Inc()
}

func (pm *PipelineMetrics) RecordFailedSigningRequest(covenantPk string) {
pm.FailedSigningReqs.WithLabelValues(covenantPk).Inc()
}

func (pm *PipelineMetrics) RecordSentUnbondingTransaction() {
pm.SuccessfulSentTransactions.Inc()
}

func (pm *PipelineMetrics) RecordFailedUnbodingTransaction() {
pm.FailureSentTransactions.Inc()
}
4 changes: 2 additions & 2 deletions internal/services/witness_gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func createWitnessSignaturesForPubKeys(
receivedSignatures := make(map[string]*schnorr.Signature)

for _, pair := range receivedSignaturePairs {
receivedSignatures[pubKeyToString(pair.PubKey)] = pair.Signature
receivedSignatures[pubKeyToStringSchnorr(pair.PubKey)] = pair.Signature
}

sortedPubKeys := sortPubKeysForWitness(covenantPubKeys)
Expand All @@ -44,7 +44,7 @@ func createWitnessSignaturesForPubKeys(

for i, key := range sortedPubKeys {
k := key
if signature, found := receivedSignatures[pubKeyToString(k)]; found {
if signature, found := receivedSignatures[pubKeyToStringSchnorr(k)]; found {
signatures[i] = signature
}
}
Expand Down

0 comments on commit a94125d

Please sign in to comment.