Skip to content

Commit

Permalink
Merge pull request #83 from Chia-Network/fee-estimates
Browse files Browse the repository at this point in the history
  • Loading branch information
cmmarslender authored Apr 11, 2023
2 parents 1940e03 + dc01eb3 commit 24067ad
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 5 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module github.com/chia-network/chia-exporter
go 1.18

require (
github.com/chia-network/go-chia-libs v0.3.0
github.com/chia-network/go-chia-libs v0.3.1
github.com/chia-network/go-modules v0.0.3
github.com/oschwald/maxminddb-golang v1.10.0
github.com/prometheus/client_golang v1.14.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chia-network/go-chia-libs v0.3.0 h1:/1q2MUxfMnzyLXZbIY1HhFtUiOvXnYbEoqORfcKnYRE=
github.com/chia-network/go-chia-libs v0.3.0/go.mod h1:yn3u6UDp5zdWvGY37PbPMK4HRW/GU8lw0psMx6J8sb0=
github.com/chia-network/go-chia-libs v0.3.1 h1:aDXj/aT1XUif3mjNYK4ufghNhE1fe4IfWh9nmas2sb0=
github.com/chia-network/go-chia-libs v0.3.1/go.mod h1:yn3u6UDp5zdWvGY37PbPMK4HRW/GU8lw0psMx6J8sb0=
github.com/chia-network/go-modules v0.0.3 h1:hLYUW8Uqzt7fjTKIrIdqIfbui2Yw3NA+2El1sU4rT78=
github.com/chia-network/go-modules v0.0.3/go.mod h1:9SHIGLdyHjZqbBxn87SUaBuHdaIolZPp68IJR8UujHE=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
Expand Down
58 changes: 56 additions & 2 deletions internal/metrics/fullnode.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,10 @@ import (
"time"

"github.com/chia-network/go-chia-libs/pkg/config"
log "github.com/sirupsen/logrus"

"github.com/chia-network/go-chia-libs/pkg/rpc"
"github.com/chia-network/go-chia-libs/pkg/types"
"github.com/prometheus/client_golang/prometheus"
log "github.com/sirupsen/logrus"

wrappedPrometheus "github.com/chia-network/go-modules/pkg/prometheus"

Expand All @@ -21,6 +20,14 @@ import (

// Metrics that are based on Full Node RPC calls are in this file

// Fee data is based on the estimates here https://github.com/Chia-Network/chia-blockchain/blob/37fcafa0d31358f6ff7276a78764a0cc7ffeb030/chia/rpc/full_node_rpc_api.py#L754
const (
CostSendXch = 9401710
CostSendCat = 36382111
CostTransferNFT = 74385541
CostTakeOffer = 721393265
)

// FullNodeServiceMetrics contains all metrics related to the full node
type FullNodeServiceMetrics struct {
// Holds a reference to the main metrics container this is a part of
Expand All @@ -37,6 +44,9 @@ type FullNodeServiceMetrics struct {
nodeHeightSynced *wrappedPrometheus.LazyGauge
nodeSynced *wrappedPrometheus.LazyGauge

// Fee Metrics
feeEstimates *prometheus.GaugeVec

// BlockCount Metrics
compactBlocks *wrappedPrometheus.LazyGauge
uncompactBlocks *wrappedPrometheus.LazyGauge
Expand Down Expand Up @@ -80,6 +90,8 @@ func (s *FullNodeServiceMetrics) InitMetrics() {
s.nodeHeightSynced = s.metrics.newGauge(chiaServiceFullNode, "node_height_synced", "Current height of the node, when synced. This will register/unregister automatically depending on sync state, and should help make rate() more sane, when you don't want rate of syncing, only rate of the chain.")
s.nodeSynced = s.metrics.newGauge(chiaServiceFullNode, "node_synced", "Indicates whether this node is currently synced")

s.feeEstimates = s.metrics.newGaugeVec(chiaServiceFullNode, "fee_estimate", "Estimate of fee required to get a particular transaction cost in a block within a specified timeframe", []string{"type", "cost", "time"})

// BlockCount Metrics
s.compactBlocks = s.metrics.newGauge(chiaServiceFullNode, "compact_blocks", "Number of fully compact blocks in this node's database")
s.uncompactBlocks = s.metrics.newGauge(chiaServiceFullNode, "uncompact_blocks", "Number of uncompact blocks in this node's database")
Expand Down Expand Up @@ -116,6 +128,7 @@ func (s *FullNodeServiceMetrics) InitialData() {
// Ask for some initial data so we dont have to wait as long
utils.LogErr(s.metrics.client.FullNodeService.GetBlockchainState()) // Also calls get_connections once we get the response
utils.LogErr(s.metrics.client.FullNodeService.GetBlockCountMetrics())
s.GetFeeEstimates()

// Things that update in the background
go func() {
Expand All @@ -141,6 +154,8 @@ func (s *FullNodeServiceMetrics) Disconnected() {
s.nodeHeightSynced.Unregister()
s.nodeSynced.Unregister()

s.feeEstimates.Reset()

s.compactBlocks.Unregister()
s.uncompactBlocks.Unregister()
s.hintCount.Unregister()
Expand Down Expand Up @@ -173,6 +188,7 @@ func (s *FullNodeServiceMetrics) ReceiveResponse(resp *types.WebsocketResponse)
s.Block(resp)
// Ask for block count metrics when we get a new block
utils.LogErr(s.metrics.client.FullNodeService.GetBlockCountMetrics())
go s.GetFeeEstimates()
case "get_connections":
s.GetConnections(resp)
case "get_block_count_metrics":
Expand Down Expand Up @@ -219,6 +235,44 @@ func (s *FullNodeServiceMetrics) GetBlockchainState(resp *types.WebsocketRespons
s.maxBlockCost.Set(float64(state.BlockchainState.BlockMaxCost))
}

// GetFeeEstimates gets fee estimates for the main costs we're estimating, for 1, 5, 15 minute windows
// We do this via http requests via async on the websocket since the fee estimate response doesn't
// indicate which cost the estimate is for
func (s *FullNodeServiceMetrics) GetFeeEstimates() {
toCheck := map[string]uint64{
"send-xch": CostSendXch,
"send-cat": CostSendCat,
"tx-nft": CostTransferNFT,
"take-offer": CostTakeOffer,
}

for label, cost := range toCheck {
// Get some fee data
txEstimate, _, err := s.metrics.httpClient.FullNodeService.GetFeeEstimate(&rpc.GetFeeEstimateOptions{
Cost: cost,
TargetTimes: []uint64{60, 300, 900},
})
if err != nil {
log.Debugf("Error getting tx estimate: %s\n", err.Error())
continue
}
estimates := txEstimate.Estimates.OrEmpty()
times := txEstimate.TargetTimes.OrEmpty()
if len(estimates) == 0 || len(times) == 0 || len(estimates) != len(times) {
log.Debugln("Unexpected TX estimate response (empty or mis-matched estimates/times)")
continue
}

for idx, estimate := range estimates {
targetTime := times[idx]
s.feeEstimates.WithLabelValues(
label,
fmt.Sprintf("%d", cost),
fmt.Sprintf("%d", targetTime)).Set(estimate)
}
}
}

// GetConnections handler for get_connections events
func (s *FullNodeServiceMetrics) GetConnections(resp *types.WebsocketResponse) {
connectionCountHelper(resp, s.connectionCount)
Expand Down

0 comments on commit 24067ad

Please sign in to comment.