diff --git a/bchain/coins/blockchain.go b/bchain/coins/blockchain.go index d17f26ef..3c3e24c9 100644 --- a/bchain/coins/blockchain.go +++ b/bchain/coins/blockchain.go @@ -9,6 +9,7 @@ import ( "fmt" "io/ioutil" "reflect" + "time" "github.com/juju/errors" ) @@ -38,5 +39,98 @@ func NewBlockChain(coin string, configfile string, pushHandler func(*bchain.MQMe if err != nil { return nil, errors.Annotatef(err, "Error parsing file %v", configfile) } - return bcf(config, pushHandler, metrics) + bc, err := bcf(config, pushHandler, metrics) + if err != nil { + return nil, err + } + return &blockChainWithMetrics{b: bc, m: metrics}, nil +} + +type blockChainWithMetrics struct { + b bchain.BlockChain + m *common.Metrics +} + +func (c *blockChainWithMetrics) observeRPCLatency(method string, start time.Time, err error) { + c.m.RPCLatency.With(common.Labels{"method": method, "error": err.Error()}).Observe(float64(time.Since(start)) / 1e6) // in milliseconds +} + +func (c *blockChainWithMetrics) Shutdown() error { + return c.b.Shutdown() +} + +func (c *blockChainWithMetrics) IsTestnet() bool { + return c.b.IsTestnet() +} + +func (c *blockChainWithMetrics) GetNetworkName() string { + return c.b.GetNetworkName() +} + +func (c *blockChainWithMetrics) GetBestBlockHash() (v string, err error) { + defer func(s time.Time) { c.observeRPCLatency("GetBestBlockHash", s, err) }(time.Now()) + return c.b.GetBestBlockHash() +} + +func (c *blockChainWithMetrics) GetBestBlockHeight() (v uint32, err error) { + defer func(s time.Time) { c.observeRPCLatency("GetBestBlockHeight", s, err) }(time.Now()) + return c.b.GetBestBlockHeight() +} + +func (c *blockChainWithMetrics) GetBlockHash(height uint32) (v string, err error) { + defer func(s time.Time) { c.observeRPCLatency("GetBlockHash", s, err) }(time.Now()) + return c.b.GetBlockHash(height) +} + +func (c *blockChainWithMetrics) GetBlockHeader(hash string) (v *bchain.BlockHeader, err error) { + defer func(s time.Time) { c.observeRPCLatency("GetBlockHeader", s, err) }(time.Now()) + return c.b.GetBlockHeader(hash) +} + +func (c *blockChainWithMetrics) GetBlock(hash string, height uint32) (v *bchain.Block, err error) { + defer func(s time.Time) { c.observeRPCLatency("GetBlock", s, err) }(time.Now()) + return c.b.GetBlock(hash, height) +} + +func (c *blockChainWithMetrics) GetMempool() (v []string, err error) { + defer func(s time.Time) { c.observeRPCLatency("GetMempool", s, err) }(time.Now()) + return c.b.GetMempool() +} + +func (c *blockChainWithMetrics) GetTransaction(txid string) (v *bchain.Tx, err error) { + defer func(s time.Time) { c.observeRPCLatency("GetTransaction", s, err) }(time.Now()) + return c.b.GetTransaction(txid) +} + +func (c *blockChainWithMetrics) EstimateSmartFee(blocks int, conservative bool) (v float64, err error) { + defer func(s time.Time) { c.observeRPCLatency("EstimateSmartFee", s, err) }(time.Now()) + return c.b.EstimateSmartFee(blocks, conservative) +} + +func (c *blockChainWithMetrics) SendRawTransaction(tx string) (v string, err error) { + defer func(s time.Time) { c.observeRPCLatency("SendRawTransaction", s, err) }(time.Now()) + return c.b.SendRawTransaction(tx) +} + +func (c *blockChainWithMetrics) ResyncMempool(onNewTxAddr func(txid string, addr string)) (err error) { + defer func(s time.Time) { c.observeRPCLatency("ResyncMempool", s, err) }(time.Now()) + return c.b.ResyncMempool(onNewTxAddr) +} + +func (c *blockChainWithMetrics) GetMempoolTransactions(address string) (v []string, err error) { + defer func(s time.Time) { c.observeRPCLatency("GetMempoolTransactions", s, err) }(time.Now()) + return c.b.GetMempoolTransactions(address) +} + +func (c *blockChainWithMetrics) GetMempoolSpentOutput(outputTxid string, vout uint32) (v string) { + return c.b.GetMempoolSpentOutput(outputTxid, vout) +} + +func (c *blockChainWithMetrics) GetMempoolEntry(txid string) (v *bchain.MempoolEntry, err error) { + defer func(s time.Time) { c.observeRPCLatency("GetMempoolEntry", s, err) }(time.Now()) + return c.b.GetMempoolEntry(txid) +} + +func (c *blockChainWithMetrics) GetChainParser() bchain.BlockChainParser { + return c.b.GetChainParser() } diff --git a/common/metrics.go b/common/metrics.go index 03ce0aff..2cc8d25c 100644 --- a/common/metrics.go +++ b/common/metrics.go @@ -88,7 +88,7 @@ func GetMetrics(coin string) (*Metrics, error) { Buckets: []float64{1, 5, 10, 25, 50, 75, 100, 250}, ConstLabels: Labels{"coin": coin}, }, - []string{"method"}, + []string{"method", "error"}, ) metrics.IndexResyncErrors = prometheus.NewCounterVec( prometheus.CounterOpts{