mirror of
https://github.com/trezor/blockbook.git
synced 2026-02-19 16:31:19 +01:00
455 lines
16 KiB
Go
455 lines
16 KiB
Go
package common
|
|
|
|
import (
|
|
"reflect"
|
|
|
|
"github.com/prometheus/client_golang/prometheus"
|
|
)
|
|
|
|
// Metrics holds prometheus collectors for various metrics collected by Blockbook
|
|
type Metrics struct {
|
|
SocketIORequests *prometheus.CounterVec
|
|
SocketIOSubscribes *prometheus.CounterVec
|
|
SocketIOClients prometheus.Gauge
|
|
SocketIOReqDuration *prometheus.HistogramVec
|
|
WebsocketRequests *prometheus.CounterVec
|
|
WebsocketSubscribes *prometheus.GaugeVec
|
|
WebsocketClients prometheus.Gauge
|
|
WebsocketReqDuration *prometheus.HistogramVec
|
|
WebsocketChannelCloses *prometheus.CounterVec
|
|
WebsocketUnknownMethods *prometheus.CounterVec
|
|
WebsocketAddrNotifications *prometheus.CounterVec
|
|
WebsocketNewBlockTxs *prometheus.CounterVec
|
|
WebsocketNewBlockTxsDuration *prometheus.HistogramVec
|
|
WebsocketEthReceipt *prometheus.CounterVec
|
|
WebsocketNewBlockTxsSubscriptions prometheus.Gauge
|
|
IndexResyncDuration prometheus.Histogram
|
|
MempoolResyncDuration prometheus.Histogram
|
|
TxCacheEfficiency *prometheus.CounterVec
|
|
RPCLatency *prometheus.HistogramVec
|
|
EthCallRequests *prometheus.CounterVec
|
|
EthCallErrors *prometheus.CounterVec
|
|
EthCallBatchSize prometheus.Histogram
|
|
EthCallContractInfo *prometheus.CounterVec
|
|
EthCallTokenURI *prometheus.CounterVec
|
|
EthCallStakingPool *prometheus.CounterVec
|
|
IndexResyncErrors *prometheus.CounterVec
|
|
IndexDBSize prometheus.Gauge
|
|
ExplorerViews *prometheus.CounterVec
|
|
MempoolSize prometheus.Gauge
|
|
EstimatedFee *prometheus.GaugeVec
|
|
AvgBlockPeriod prometheus.Gauge
|
|
SyncBlockStats *prometheus.GaugeVec
|
|
SyncHotnessStats *prometheus.GaugeVec
|
|
AddrContractsCacheEntries prometheus.Gauge
|
|
AddrContractsCacheBytes prometheus.Gauge
|
|
AddrContractsCacheHits prometheus.Counter
|
|
AddrContractsCacheMisses prometheus.Counter
|
|
AddrContractsCacheFlushes *prometheus.CounterVec
|
|
DbColumnRows *prometheus.GaugeVec
|
|
DbColumnSize *prometheus.GaugeVec
|
|
BlockbookAppInfo *prometheus.GaugeVec
|
|
BackendBestHeight prometheus.Gauge
|
|
BlockbookBestHeight prometheus.Gauge
|
|
ExplorerPendingRequests *prometheus.GaugeVec
|
|
WebsocketPendingRequests *prometheus.GaugeVec
|
|
SocketIOPendingRequests *prometheus.GaugeVec
|
|
XPubCacheSize prometheus.Gauge
|
|
CoingeckoRequests *prometheus.CounterVec
|
|
}
|
|
|
|
// Labels represents a collection of label name -> value mappings.
|
|
type Labels = prometheus.Labels
|
|
|
|
// GetMetrics returns struct holding prometheus collectors for various metrics collected by Blockbook
|
|
func GetMetrics(coin string) (*Metrics, error) {
|
|
metrics := Metrics{}
|
|
|
|
metrics.SocketIORequests = prometheus.NewCounterVec(
|
|
prometheus.CounterOpts{
|
|
Name: "blockbook_socketio_requests",
|
|
Help: "Total number of socketio requests by method and status",
|
|
ConstLabels: Labels{"coin": coin},
|
|
},
|
|
[]string{"method", "status"},
|
|
)
|
|
metrics.SocketIOSubscribes = prometheus.NewCounterVec(
|
|
prometheus.CounterOpts{
|
|
Name: "blockbook_socketio_subscribes",
|
|
Help: "Total number of socketio subscribes by channel and status",
|
|
ConstLabels: Labels{"coin": coin},
|
|
},
|
|
[]string{"channel", "status"},
|
|
)
|
|
metrics.SocketIOClients = prometheus.NewGauge(
|
|
prometheus.GaugeOpts{
|
|
Name: "blockbook_socketio_clients",
|
|
Help: "Number of currently connected socketio clients",
|
|
ConstLabels: Labels{"coin": coin},
|
|
},
|
|
)
|
|
metrics.SocketIOReqDuration = prometheus.NewHistogramVec(
|
|
prometheus.HistogramOpts{
|
|
Name: "blockbook_socketio_req_duration",
|
|
Help: "Socketio request duration by method (in microseconds)",
|
|
Buckets: []float64{10, 100, 1_000, 10_000, 100_000, 1_000_000, 10_0000_000},
|
|
ConstLabels: Labels{"coin": coin},
|
|
},
|
|
[]string{"method"},
|
|
)
|
|
metrics.WebsocketRequests = prometheus.NewCounterVec(
|
|
prometheus.CounterOpts{
|
|
Name: "blockbook_websocket_requests",
|
|
Help: "Total number of websocket requests by method and status",
|
|
ConstLabels: Labels{"coin": coin},
|
|
},
|
|
[]string{"method", "status"},
|
|
)
|
|
metrics.WebsocketSubscribes = prometheus.NewGaugeVec(
|
|
prometheus.GaugeOpts{
|
|
Name: "blockbook_websocket_subscribes",
|
|
Help: "Number of websocket subscriptions by method",
|
|
ConstLabels: Labels{"coin": coin},
|
|
},
|
|
[]string{"method"},
|
|
)
|
|
metrics.WebsocketClients = prometheus.NewGauge(
|
|
prometheus.GaugeOpts{
|
|
Name: "blockbook_websocket_clients",
|
|
Help: "Number of currently connected websocket clients",
|
|
ConstLabels: Labels{"coin": coin},
|
|
},
|
|
)
|
|
metrics.WebsocketReqDuration = prometheus.NewHistogramVec(
|
|
prometheus.HistogramOpts{
|
|
Name: "blockbook_websocket_req_duration",
|
|
Help: "Websocket request duration by method (in microseconds)",
|
|
Buckets: []float64{10, 100, 1_000, 10_000, 100_000, 1_000_000, 10_0000_000},
|
|
ConstLabels: Labels{"coin": coin},
|
|
},
|
|
[]string{"method"},
|
|
)
|
|
metrics.WebsocketChannelCloses = prometheus.NewCounterVec(
|
|
prometheus.CounterOpts{
|
|
Name: "blockbook_websocket_channel_closes",
|
|
Help: "Total number of websocket channel closes by reason",
|
|
ConstLabels: Labels{"coin": coin},
|
|
},
|
|
[]string{"reason"},
|
|
)
|
|
metrics.WebsocketUnknownMethods = prometheus.NewCounterVec(
|
|
prometheus.CounterOpts{
|
|
Name: "blockbook_websocket_unknown_methods",
|
|
Help: "Total number of websocket requests with unknown method",
|
|
ConstLabels: Labels{"coin": coin},
|
|
},
|
|
[]string{"method"},
|
|
)
|
|
metrics.WebsocketAddrNotifications = prometheus.NewCounterVec(
|
|
prometheus.CounterOpts{
|
|
Name: "blockbook_websocket_addr_notifications",
|
|
Help: "Total number of per-address websocket tx notifications by source",
|
|
ConstLabels: Labels{"coin": coin},
|
|
},
|
|
[]string{"source"},
|
|
)
|
|
metrics.WebsocketNewBlockTxs = prometheus.NewCounterVec(
|
|
prometheus.CounterOpts{
|
|
Name: "blockbook_websocket_new_block_txs",
|
|
Help: "Total number of websocket newBlockTxs events by stage and status",
|
|
ConstLabels: Labels{"coin": coin},
|
|
},
|
|
[]string{"stage", "status"},
|
|
)
|
|
metrics.WebsocketNewBlockTxsDuration = prometheus.NewHistogramVec(
|
|
prometheus.HistogramOpts{
|
|
Name: "blockbook_websocket_new_block_txs_duration_seconds",
|
|
Help: "Duration of websocket newBlockTxs processing stages in seconds",
|
|
Buckets: []float64{0.0005, 0.001, 0.005, 0.01, 0.05, 0.1, 0.25, 0.5, 1, 2, 5, 10},
|
|
ConstLabels: Labels{"coin": coin},
|
|
},
|
|
[]string{"stage"},
|
|
)
|
|
metrics.WebsocketEthReceipt = prometheus.NewCounterVec(
|
|
prometheus.CounterOpts{
|
|
Name: "blockbook_websocket_eth_receipt",
|
|
Help: "Total number of websocket Ethereum receipt enrichment outcomes",
|
|
ConstLabels: Labels{"coin": coin},
|
|
},
|
|
[]string{"status"},
|
|
)
|
|
metrics.WebsocketNewBlockTxsSubscriptions = prometheus.NewGauge(
|
|
prometheus.GaugeOpts{
|
|
Name: "blockbook_websocket_new_block_txs_subscriptions",
|
|
Help: "Number of websocket address subscriptions with newBlockTxs enabled",
|
|
ConstLabels: Labels{"coin": coin},
|
|
},
|
|
)
|
|
metrics.IndexResyncDuration = prometheus.NewHistogram(
|
|
prometheus.HistogramOpts{
|
|
Name: "blockbook_index_resync_duration",
|
|
Help: "Duration of index resync operation (in milliseconds)",
|
|
Buckets: []float64{10, 100, 500, 1000, 2000, 5000, 10000},
|
|
ConstLabels: Labels{"coin": coin},
|
|
},
|
|
)
|
|
metrics.MempoolResyncDuration = prometheus.NewHistogram(
|
|
prometheus.HistogramOpts{
|
|
Name: "blockbook_mempool_resync_duration",
|
|
Help: "Duration of mempool resync operation (in milliseconds)",
|
|
Buckets: []float64{10, 100, 500, 1000, 2000, 5000, 10000},
|
|
ConstLabels: Labels{"coin": coin},
|
|
},
|
|
)
|
|
metrics.TxCacheEfficiency = prometheus.NewCounterVec(
|
|
prometheus.CounterOpts{
|
|
Name: "blockbook_txcache_efficiency",
|
|
Help: "Efficiency of txCache",
|
|
ConstLabels: Labels{"coin": coin},
|
|
},
|
|
[]string{"status"},
|
|
)
|
|
metrics.RPCLatency = prometheus.NewHistogramVec(
|
|
prometheus.HistogramOpts{
|
|
Name: "blockbook_rpc_latency",
|
|
Help: "Latency of blockchain RPC by method (in milliseconds)",
|
|
Buckets: []float64{0.1, 0.5, 1, 5, 10, 25, 50, 75, 100, 250},
|
|
ConstLabels: Labels{"coin": coin},
|
|
},
|
|
[]string{"method", "error"},
|
|
)
|
|
metrics.EthCallRequests = prometheus.NewCounterVec(
|
|
prometheus.CounterOpts{
|
|
Name: "blockbook_eth_call_requests",
|
|
Help: "Total number of eth_call requests by mode",
|
|
ConstLabels: Labels{"coin": coin},
|
|
},
|
|
[]string{"mode"},
|
|
)
|
|
metrics.EthCallErrors = prometheus.NewCounterVec(
|
|
prometheus.CounterOpts{
|
|
Name: "blockbook_eth_call_errors",
|
|
Help: "Total number of eth_call errors by mode and type",
|
|
ConstLabels: Labels{"coin": coin},
|
|
},
|
|
[]string{"mode", "type"},
|
|
)
|
|
metrics.EthCallBatchSize = prometheus.NewHistogram(
|
|
prometheus.HistogramOpts{
|
|
Name: "blockbook_eth_call_batch_size",
|
|
Help: "Number of eth_call items per batch request",
|
|
Buckets: []float64{1, 2, 5, 10, 20, 50, 100, 200},
|
|
ConstLabels: Labels{"coin": coin},
|
|
},
|
|
)
|
|
metrics.EthCallContractInfo = prometheus.NewCounterVec(
|
|
prometheus.CounterOpts{
|
|
Name: "blockbook_eth_call_contract_info_requests",
|
|
Help: "Total number of eth_call requests for contract info fields",
|
|
ConstLabels: Labels{"coin": coin},
|
|
},
|
|
[]string{"field"},
|
|
)
|
|
metrics.EthCallTokenURI = prometheus.NewCounterVec(
|
|
prometheus.CounterOpts{
|
|
Name: "blockbook_eth_call_token_uri_requests",
|
|
Help: "Total number of eth_call requests for token URI lookups",
|
|
ConstLabels: Labels{"coin": coin},
|
|
},
|
|
[]string{"method"},
|
|
)
|
|
metrics.EthCallStakingPool = prometheus.NewCounterVec(
|
|
prometheus.CounterOpts{
|
|
Name: "blockbook_eth_call_staking_pool_requests",
|
|
Help: "Total number of eth_call requests for staking pool lookups",
|
|
ConstLabels: Labels{"coin": coin},
|
|
},
|
|
[]string{"field"},
|
|
)
|
|
metrics.IndexResyncErrors = prometheus.NewCounterVec(
|
|
prometheus.CounterOpts{
|
|
Name: "blockbook_index_resync_errors",
|
|
Help: "Number of errors of index resync operation",
|
|
ConstLabels: Labels{"coin": coin},
|
|
},
|
|
[]string{"error"},
|
|
)
|
|
metrics.IndexDBSize = prometheus.NewGauge(
|
|
prometheus.GaugeOpts{
|
|
Name: "blockbook_index_db_size",
|
|
Help: "Size of index database (in bytes)",
|
|
ConstLabels: Labels{"coin": coin},
|
|
},
|
|
)
|
|
metrics.ExplorerViews = prometheus.NewCounterVec(
|
|
prometheus.CounterOpts{
|
|
Name: "blockbook_explorer_views",
|
|
Help: "Number of explorer views",
|
|
ConstLabels: Labels{"coin": coin},
|
|
},
|
|
[]string{"action"},
|
|
)
|
|
metrics.MempoolSize = prometheus.NewGauge(
|
|
prometheus.GaugeOpts{
|
|
Name: "blockbook_mempool_size",
|
|
Help: "Mempool size (number of transactions)",
|
|
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.SyncBlockStats = prometheus.NewGaugeVec(
|
|
prometheus.GaugeOpts{
|
|
Name: "blockbook_sync_block_stats",
|
|
Help: "Per-interval block stats for bulk sync and per-block stats at chain tip",
|
|
ConstLabels: Labels{"coin": coin},
|
|
},
|
|
[]string{"scope", "kind"},
|
|
)
|
|
metrics.SyncHotnessStats = prometheus.NewGaugeVec(
|
|
prometheus.GaugeOpts{
|
|
Name: "blockbook_sync_hotness_stats",
|
|
Help: "Hot address stats for bulk sync intervals and per-block chain tip processing (Ethereum-type only)",
|
|
ConstLabels: Labels{"coin": coin},
|
|
},
|
|
[]string{"scope", "kind"},
|
|
)
|
|
metrics.AddrContractsCacheEntries = prometheus.NewGauge(
|
|
prometheus.GaugeOpts{
|
|
Name: "blockbook_addr_contracts_cache_entries",
|
|
Help: "Number of cached addressContracts entries",
|
|
ConstLabels: Labels{"coin": coin},
|
|
},
|
|
)
|
|
metrics.AddrContractsCacheBytes = prometheus.NewGauge(
|
|
prometheus.GaugeOpts{
|
|
Name: "blockbook_addr_contracts_cache_bytes",
|
|
Help: "Estimated bytes in the addressContracts cache",
|
|
ConstLabels: Labels{"coin": coin},
|
|
},
|
|
)
|
|
metrics.AddrContractsCacheHits = prometheus.NewCounter(
|
|
prometheus.CounterOpts{
|
|
Name: "blockbook_addr_contracts_cache_hits_total",
|
|
Help: "Total number of addressContracts cache hits",
|
|
ConstLabels: Labels{"coin": coin},
|
|
},
|
|
)
|
|
metrics.AddrContractsCacheMisses = prometheus.NewCounter(
|
|
prometheus.CounterOpts{
|
|
Name: "blockbook_addr_contracts_cache_misses_total",
|
|
Help: "Total number of addressContracts cache misses",
|
|
ConstLabels: Labels{"coin": coin},
|
|
},
|
|
)
|
|
metrics.AddrContractsCacheFlushes = prometheus.NewCounterVec(
|
|
prometheus.CounterOpts{
|
|
Name: "blockbook_addr_contracts_cache_flush_total",
|
|
Help: "Total number of addressContracts cache flushes by reason",
|
|
ConstLabels: Labels{"coin": coin},
|
|
},
|
|
[]string{"reason"},
|
|
)
|
|
metrics.DbColumnRows = prometheus.NewGaugeVec(
|
|
prometheus.GaugeOpts{
|
|
Name: "blockbook_dbcolumn_rows",
|
|
Help: "Number of rows in db column",
|
|
ConstLabels: Labels{"coin": coin},
|
|
},
|
|
[]string{"column"},
|
|
)
|
|
metrics.DbColumnSize = prometheus.NewGaugeVec(
|
|
prometheus.GaugeOpts{
|
|
Name: "blockbook_dbcolumn_size",
|
|
Help: "Size of db column (in bytes)",
|
|
ConstLabels: Labels{"coin": coin},
|
|
},
|
|
[]string{"column"},
|
|
)
|
|
metrics.BlockbookAppInfo = prometheus.NewGaugeVec(
|
|
prometheus.GaugeOpts{
|
|
Name: "blockbook_app_info",
|
|
Help: "Information about blockbook and backend application versions",
|
|
ConstLabels: Labels{"coin": coin},
|
|
},
|
|
[]string{"blockbook_version", "blockbook_commit", "blockbook_buildtime", "backend_version", "backend_subversion", "backend_protocol_version"},
|
|
)
|
|
metrics.BlockbookBestHeight = prometheus.NewGauge(
|
|
prometheus.GaugeOpts{
|
|
Name: "blockbook_best_height",
|
|
Help: "Block height in Blockbook",
|
|
ConstLabels: Labels{"coin": coin},
|
|
},
|
|
)
|
|
metrics.BackendBestHeight = prometheus.NewGauge(
|
|
prometheus.GaugeOpts{
|
|
Name: "blockbook_backend_best_height",
|
|
Help: "Block height in backend",
|
|
ConstLabels: Labels{"coin": coin},
|
|
},
|
|
)
|
|
metrics.ExplorerPendingRequests = prometheus.NewGaugeVec(
|
|
prometheus.GaugeOpts{
|
|
Name: "blockbook_explorer_pending_requests",
|
|
Help: "Number of unfinished requests in explorer interface",
|
|
ConstLabels: Labels{"coin": coin},
|
|
},
|
|
[]string{"method"},
|
|
)
|
|
metrics.WebsocketPendingRequests = prometheus.NewGaugeVec(
|
|
prometheus.GaugeOpts{
|
|
Name: "blockbook_websocket_pending_requests",
|
|
Help: "Number of unfinished requests in websocket interface",
|
|
ConstLabels: Labels{"coin": coin},
|
|
},
|
|
[]string{"method"},
|
|
)
|
|
metrics.SocketIOPendingRequests = prometheus.NewGaugeVec(
|
|
prometheus.GaugeOpts{
|
|
Name: "blockbook_socketio_pending_requests",
|
|
Help: "Number of unfinished requests in socketio interface",
|
|
ConstLabels: Labels{"coin": coin},
|
|
},
|
|
[]string{"method"},
|
|
)
|
|
metrics.XPubCacheSize = prometheus.NewGauge(
|
|
prometheus.GaugeOpts{
|
|
Name: "blockbook_xpub_cache_size",
|
|
Help: "Number of cached xpubs",
|
|
ConstLabels: Labels{"coin": coin},
|
|
},
|
|
)
|
|
metrics.CoingeckoRequests = prometheus.NewCounterVec(
|
|
prometheus.CounterOpts{
|
|
Name: "blockbook_coingecko_requests",
|
|
Help: "Total number of requests to coingecko",
|
|
ConstLabels: Labels{"coin": coin},
|
|
},
|
|
[]string{"endpoint", "status"},
|
|
)
|
|
|
|
v := reflect.ValueOf(metrics)
|
|
for i := 0; i < v.NumField(); i++ {
|
|
c := v.Field(i).Interface().(prometheus.Collector)
|
|
err := prometheus.Register(c)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
return &metrics, nil
|
|
}
|