Add estimate fee and average block period prometheus metrics
This commit is contained in:
parent
aebc1c3495
commit
76a19b7f10
@ -2244,10 +2244,10 @@ type bitcoinTypeEstimatedFee struct {
|
||||
lock sync.Mutex
|
||||
}
|
||||
|
||||
const bitcoinTypeEstimatedFeeCacheSize = 300
|
||||
const estimatedFeeCacheSize = 300
|
||||
|
||||
var bitcoinTypeEstimatedFeeCache [bitcoinTypeEstimatedFeeCacheSize]bitcoinTypeEstimatedFee
|
||||
var bitcoinTypeEstimatedFeeConservativeCache [bitcoinTypeEstimatedFeeCacheSize]bitcoinTypeEstimatedFee
|
||||
var estimatedFeeCache [estimatedFeeCacheSize]bitcoinTypeEstimatedFee
|
||||
var estimatedFeeConservativeCache [estimatedFeeCacheSize]bitcoinTypeEstimatedFee
|
||||
|
||||
func (w *Worker) cachedBitcoinTypeEstimateFee(blocks int, conservative bool, s *bitcoinTypeEstimatedFee) (big.Int, error) {
|
||||
s.lock.Lock()
|
||||
@ -2261,18 +2261,22 @@ func (w *Worker) cachedBitcoinTypeEstimateFee(blocks int, conservative bool, s *
|
||||
if err == nil {
|
||||
s.timestamp = time.Now().Unix()
|
||||
s.fee = fee
|
||||
w.metrics.EstimatedFee.With(common.Labels{
|
||||
"blocks": strconv.Itoa(blocks),
|
||||
"conservative": strconv.FormatBool(conservative),
|
||||
}).Set(float64(fee.Int64()))
|
||||
}
|
||||
return fee, err
|
||||
}
|
||||
|
||||
// BitcoinTypeEstimateFee returns a fee estimation for given number of blocks
|
||||
// EstimateFee returns a fee estimation for given number of blocks
|
||||
// it uses 10 second cache to reduce calls to the backend
|
||||
func (w *Worker) BitcoinTypeEstimateFee(blocks int, conservative bool) (big.Int, error) {
|
||||
if blocks >= bitcoinTypeEstimatedFeeCacheSize {
|
||||
func (w *Worker) EstimateFee(blocks int, conservative bool) (big.Int, error) {
|
||||
if blocks >= estimatedFeeCacheSize {
|
||||
return w.chain.EstimateSmartFee(blocks, conservative)
|
||||
}
|
||||
if conservative {
|
||||
return w.cachedBitcoinTypeEstimateFee(blocks, conservative, &bitcoinTypeEstimatedFeeConservativeCache[blocks])
|
||||
return w.cachedBitcoinTypeEstimateFee(blocks, conservative, &estimatedFeeConservativeCache[blocks])
|
||||
}
|
||||
return w.cachedBitcoinTypeEstimateFee(blocks, conservative, &bitcoinTypeEstimatedFeeCache[blocks])
|
||||
return w.cachedBitcoinTypeEstimateFee(blocks, conservative, &estimatedFeeCache[blocks])
|
||||
}
|
||||
|
||||
@ -6,6 +6,8 @@ import (
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -68,6 +70,7 @@ type InternalState struct {
|
||||
BestHeight uint32 `json:"bestHeight"`
|
||||
LastSync time.Time `json:"lastSync"`
|
||||
BlockTimes []uint32 `json:"-"`
|
||||
AvgBlockPeriod uint32 `json:"-"`
|
||||
|
||||
IsMempoolSynchronized bool `json:"isMempoolSynchronized"`
|
||||
MempoolSize int `json:"mempoolSize"`
|
||||
@ -77,7 +80,6 @@ type InternalState struct {
|
||||
|
||||
UtxoChecked bool `json:"utxoChecked"`
|
||||
|
||||
// store only the historical state, not the current state of the fiat rates in DB
|
||||
HasFiatRates bool `json:"-"`
|
||||
HasTokenFiatRates bool `json:"-"`
|
||||
HistoricalFiatRatesTime time.Time `json:"historicalFiatRatesTime"`
|
||||
@ -208,11 +210,23 @@ func (is *InternalState) GetBlockTime(height uint32) uint32 {
|
||||
return 0
|
||||
}
|
||||
|
||||
// AppendBlockTime appends block time to BlockTimes
|
||||
func (is *InternalState) AppendBlockTime(time uint32) {
|
||||
// SetBlockTimes initializes BlockTimes array, returns AvgBlockPeriod
|
||||
func (is *InternalState) SetBlockTimes(blockTimes []uint32) uint32 {
|
||||
is.mux.Lock()
|
||||
defer is.mux.Unlock()
|
||||
is.BlockTimes = blockTimes
|
||||
is.computeAvgBlockPeriod()
|
||||
glog.Info("set ", len(is.BlockTimes), " block times, average block period ", is.AvgBlockPeriod, "s")
|
||||
return is.AvgBlockPeriod
|
||||
}
|
||||
|
||||
// AppendBlockTime appends block time to BlockTimes, returns AvgBlockPeriod
|
||||
func (is *InternalState) AppendBlockTime(time uint32) uint32 {
|
||||
is.mux.Lock()
|
||||
defer is.mux.Unlock()
|
||||
is.BlockTimes = append(is.BlockTimes, time)
|
||||
is.computeAvgBlockPeriod()
|
||||
return is.AvgBlockPeriod
|
||||
}
|
||||
|
||||
// RemoveLastBlockTimes removes last times from BlockTimes
|
||||
@ -223,6 +237,7 @@ func (is *InternalState) RemoveLastBlockTimes(count int) {
|
||||
count = len(is.BlockTimes)
|
||||
}
|
||||
is.BlockTimes = is.BlockTimes[:len(is.BlockTimes)-count]
|
||||
is.computeAvgBlockPeriod()
|
||||
}
|
||||
|
||||
// GetBlockHeightOfTime returns block height of the first block with time greater or equal to the given time or MaxUint32 if no such block
|
||||
@ -246,6 +261,25 @@ func (is *InternalState) GetBlockHeightOfTime(time uint32) uint32 {
|
||||
return uint32(height)
|
||||
}
|
||||
|
||||
const avgBlockPeriodSample = 100
|
||||
|
||||
// Avg100BlocksPeriod returns average period of the last 100 blocks in seconds
|
||||
func (is *InternalState) GetAvgBlockPeriod() uint32 {
|
||||
is.mux.Lock()
|
||||
defer is.mux.Unlock()
|
||||
return is.AvgBlockPeriod
|
||||
}
|
||||
|
||||
// computeAvgBlockPeriod returns computes average of the last 100 blocks in seconds
|
||||
func (is *InternalState) computeAvgBlockPeriod() {
|
||||
last := len(is.BlockTimes) - 1
|
||||
first := last - avgBlockPeriodSample - 1
|
||||
if first < 0 {
|
||||
return
|
||||
}
|
||||
is.AvgBlockPeriod = (is.BlockTimes[last] - is.BlockTimes[first]) / avgBlockPeriodSample
|
||||
}
|
||||
|
||||
// SetBackendInfo sets new BackendInfo
|
||||
func (is *InternalState) SetBackendInfo(bi *BackendInfo) {
|
||||
is.mux.Lock()
|
||||
|
||||
@ -24,6 +24,8 @@ type Metrics struct {
|
||||
IndexDBSize prometheus.Gauge
|
||||
ExplorerViews *prometheus.CounterVec
|
||||
MempoolSize prometheus.Gauge
|
||||
EstimatedFee *prometheus.GaugeVec
|
||||
AvgBlockPeriod prometheus.Gauge
|
||||
DbColumnRows *prometheus.GaugeVec
|
||||
DbColumnSize *prometheus.GaugeVec
|
||||
BlockbookAppInfo *prometheus.GaugeVec
|
||||
@ -169,6 +171,21 @@ func GetMetrics(coin string) (*Metrics, error) {
|
||||
ConstLabels: Labels{"coin": coin},
|
||||
},
|
||||
)
|
||||
metrics.EstimatedFee = prometheus.NewGaugeVec(
|
||||
prometheus.GaugeOpts{
|
||||
Name: "blockbook_estimated_fee",
|
||||
Help: "Estimated fee per byte (gas) for number of blocks",
|
||||
ConstLabels: Labels{"coin": coin},
|
||||
},
|
||||
[]string{"blocks", "conservative"},
|
||||
)
|
||||
metrics.AvgBlockPeriod = prometheus.NewGauge(
|
||||
prometheus.GaugeOpts{
|
||||
Name: "blockbook_avg_block_period",
|
||||
Help: "Average period of mining of last 100 blocks in seconds",
|
||||
ConstLabels: Labels{"coin": coin},
|
||||
},
|
||||
)
|
||||
metrics.DbColumnRows = prometheus.NewGaugeVec(
|
||||
prometheus.GaugeOpts{
|
||||
Name: "blockbook_dbcolumn_rows",
|
||||
@ -209,7 +226,7 @@ func GetMetrics(coin string) (*Metrics, error) {
|
||||
)
|
||||
metrics.ExplorerPendingRequests = prometheus.NewGaugeVec(
|
||||
prometheus.GaugeOpts{
|
||||
Name: "blockbook_explorer_pending_reqests",
|
||||
Name: "blockbook_explorer_pending_requests",
|
||||
Help: "Number of unfinished requests in explorer interface",
|
||||
ConstLabels: Labels{"coin": coin},
|
||||
},
|
||||
@ -217,7 +234,7 @@ func GetMetrics(coin string) (*Metrics, error) {
|
||||
)
|
||||
metrics.WebsocketPendingRequests = prometheus.NewGaugeVec(
|
||||
prometheus.GaugeOpts{
|
||||
Name: "blockbook_websocket_pending_reqests",
|
||||
Name: "blockbook_websocket_pending_requests",
|
||||
Help: "Number of unfinished requests in websocket interface",
|
||||
ConstLabels: Labels{"coin": coin},
|
||||
},
|
||||
@ -225,7 +242,7 @@ func GetMetrics(coin string) (*Metrics, error) {
|
||||
)
|
||||
metrics.SocketIOPendingRequests = prometheus.NewGaugeVec(
|
||||
prometheus.GaugeOpts{
|
||||
Name: "blockbook_socketio_pending_reqests",
|
||||
Name: "blockbook_socketio_pending_requests",
|
||||
Help: "Number of unfinished requests in socketio interface",
|
||||
ConstLabels: Labels{"coin": coin},
|
||||
},
|
||||
|
||||
@ -403,11 +403,14 @@ func (b *BulkConnect) Close() error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
var err error
|
||||
b.d.is.BlockTimes, err = b.d.loadBlockTimes()
|
||||
bt, err := b.d.loadBlockTimes()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
avg := b.d.is.SetBlockTimes(bt)
|
||||
if b.d.metrics != nil {
|
||||
b.d.metrics.AvgBlockPeriod.Set(float64(avg))
|
||||
}
|
||||
|
||||
if err := b.d.SetInconsistentState(false); err != nil {
|
||||
return err
|
||||
|
||||
@ -380,7 +380,10 @@ func (d *RocksDB) ConnectBlock(block *bchain.Block) error {
|
||||
if err := d.WriteBatch(wb); err != nil {
|
||||
return err
|
||||
}
|
||||
d.is.AppendBlockTime(uint32(block.Time))
|
||||
avg := d.is.AppendBlockTime(uint32(block.Time))
|
||||
if d.metrics != nil {
|
||||
d.metrics.AvgBlockPeriod.Set(float64(avg))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -1631,7 +1634,6 @@ func (d *RocksDB) loadBlockTimes() ([]uint32, error) {
|
||||
}
|
||||
times = append(times, time)
|
||||
}
|
||||
glog.Info("loaded ", len(times), " block times")
|
||||
return times, nil
|
||||
}
|
||||
|
||||
@ -1699,10 +1701,15 @@ func (d *RocksDB) LoadInternalState(rpcCoin string) (*common.InternalState, erro
|
||||
return nil, err
|
||||
}
|
||||
is.DbColumns = nc
|
||||
is.BlockTimes, err = d.loadBlockTimes()
|
||||
bt, err := d.loadBlockTimes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
avg := is.SetBlockTimes(bt)
|
||||
if d.metrics != nil {
|
||||
d.metrics.AvgBlockPeriod.Set(float64(avg))
|
||||
}
|
||||
|
||||
// after load, reset the synchronization data
|
||||
is.IsSynchronized = false
|
||||
is.IsMempoolSynchronized = false
|
||||
|
||||
@ -638,11 +638,15 @@ func (s *WebsocketServer) estimateFee(c *websocketChannel, params []byte) (inter
|
||||
return nil, err
|
||||
}
|
||||
sg := strconv.FormatUint(gas, 10)
|
||||
for i, b := range r.Blocks {
|
||||
fee, err := s.chain.EstimateSmartFee(b, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b := 1
|
||||
if len(r.Blocks) > 0 {
|
||||
b = r.Blocks[0]
|
||||
}
|
||||
fee, err := s.api.EstimateFee(b, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := range r.Blocks {
|
||||
res[i].FeePerUnit = fee.String()
|
||||
res[i].FeeLimit = sg
|
||||
fee.Mul(&fee, new(big.Int).SetUint64(gas))
|
||||
@ -666,7 +670,7 @@ func (s *WebsocketServer) estimateFee(c *websocketChannel, params []byte) (inter
|
||||
}
|
||||
}
|
||||
for i, b := range r.Blocks {
|
||||
fee, err := s.api.BitcoinTypeEstimateFee(b, conservative)
|
||||
fee, err := s.api.EstimateFee(b, conservative)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user