diff --git a/consensus/metrics.go b/consensus/metrics.go index c099eb0b5..2c74ceb7e 100644 --- a/consensus/metrics.go +++ b/consensus/metrics.go @@ -13,6 +13,8 @@ type Metrics struct { MissingValidators metrics.Gauge // number of validators who tried to double sign ByzantineValidators metrics.Gauge + // time between this and the last block + BlockIntervalSeconds metrics.Histogram // number of transactions NumTxs metrics.Gauge // total number of transactions @@ -24,12 +26,13 @@ type Metrics struct { // NopMetrics returns no-op Metrics. func NopMetrics() *Metrics { return &Metrics{ - Height: discard.NewCounter(), - Validators: discard.NewGauge(), - MissingValidators: discard.NewGauge(), - ByzantineValidators: discard.NewGauge(), - NumTxs: discard.NewGauge(), - TotalTxs: discard.NewCounter(), - BlockSizeBytes: discard.NewGauge(), + Height: discard.NewCounter(), + Validators: discard.NewGauge(), + MissingValidators: discard.NewGauge(), + ByzantineValidators: discard.NewGauge(), + BlockIntervalSeconds: discard.NewHistogram(), + NumTxs: discard.NewGauge(), + TotalTxs: discard.NewCounter(), + BlockSizeBytes: discard.NewGauge(), } } diff --git a/consensus/state.go b/consensus/state.go index 56d5a9ceb..2fb1fb694 100644 --- a/consensus/state.go +++ b/consensus/state.go @@ -1299,9 +1299,7 @@ func (cs *ConsensusState) finalizeCommit(height int64) { } func (cs *ConsensusState) recordMetrics(height int64, block *types.Block) { - heightStr := fmt.Sprintf("%d", height) - - cs.metrics.Validators.With("height", heightStr).Set(float64(cs.Validators.Size())) + cs.metrics.Validators.Set(float64(cs.Validators.Size())) missingValidators := 0 for i := range cs.Validators.Validators { var vote *types.Vote @@ -1312,13 +1310,19 @@ func (cs *ConsensusState) recordMetrics(height int64, block *types.Block) { missingValidators++ } } - cs.metrics.MissingValidators.With("height", heightStr).Set(float64(missingValidators)) - cs.metrics.ByzantineValidators.With("height", heightStr).Set(float64(len(block.Evidence.Evidence))) + cs.metrics.MissingValidators.Set(float64(missingValidators)) + cs.metrics.ByzantineValidators.Set(float64(len(block.Evidence.Evidence))) + + if height > 1 { + lastBlockMeta := cs.blockStore.LoadBlockMeta(height - 1) + cs.metrics.BlockIntervalSeconds. + Observe(block.Time.Sub(lastBlockMeta.Header.Time).Seconds()) + } - cs.metrics.NumTxs.With("height", heightStr).Set(float64(block.NumTxs)) + cs.metrics.NumTxs.Set(float64(block.NumTxs)) cs.metrics.TotalTxs.Add(float64(block.NumTxs)) - cs.metrics.BlockSizeBytes.With("height", heightStr).Set(float64(block.Size())) + cs.metrics.BlockSizeBytes.Set(float64(block.Size())) } //----------------------------------------------------------------------------- diff --git a/node/node.go b/node/node.go index 27ef74f8f..681dc04b3 100644 --- a/node/node.go +++ b/node/node.go @@ -85,10 +85,66 @@ func DefaultNewNode(config *cfg.Config, logger log.Logger) (*Node, error) { proxy.DefaultClientCreator(config.ProxyApp, config.ABCI, config.DBDir()), DefaultGenesisDocProviderFunc(config), DefaultDBProvider, + DefaultMetricsProvider, logger, ) } +// MetricsProvider returns a consensus Metrics. +type MetricsProvider func() *cs.Metrics + +// DefaultMetrics returns a consensus Metrics build using Prometheus client +// library. +func DefaultMetricsProvider() *cs.Metrics { + return &cs.Metrics{ + Height: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ + Subsystem: "consensus", + Name: "height", + Help: "Height of the chain.", + }, []string{}), + + Validators: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ + Subsystem: "consensus", + Name: "validators", + Help: "Number of validators who signed, partitioned by height.", + }, []string{}), + MissingValidators: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ + Subsystem: "consensus", + Name: "missing_validators", + Help: "Number of validators who did not sign, partitioned by height.", + }, []string{}), + ByzantineValidators: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ + Subsystem: "consensus", + Name: "byzantine_validators", + Help: "Number of validators who tried to double sign, partitioned by height.", + }, []string{}), + + BlockIntervalSeconds: prometheus.NewHistogramFrom(stdprometheus.HistogramOpts{ + Subsystem: "consensus", + Name: "block_interval_seconds", + Help: "Time between this and the last block, partitioned by height.", + Buckets: []float64{1, 2.5, 5, 10, 60}, + }, []string{}), + + NumTxs: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ + Subsystem: "consensus", + Name: "num_txs", + Help: "Number of transactions, partitioned by height.", + }, []string{}), + TotalTxs: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ + Subsystem: "consensus", + Name: "total_txs", + Help: "Total number of transactions.", + }, []string{}), + + BlockSizeBytes: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ + Subsystem: "consensus", + Name: "block_size_bytes", + Help: "Size of the block, partitioned by height.", + }, []string{}), + } +} + //------------------------------------------------------------------------------ // Node is the highest level interface to a full Tendermint node. @@ -126,6 +182,7 @@ func NewNode(config *cfg.Config, clientCreator proxy.ClientCreator, genesisDocProvider GenesisDocProvider, dbProvider DBProvider, + metricsProvider MetricsProvider, logger log.Logger) (*Node, error) { // Get BlockStore @@ -245,65 +302,9 @@ func NewNode(config *cfg.Config, bcReactor.SetLogger(logger.With("module", "blockchain")) // Make ConsensusReactor - // TODO: extract to provider - metrics := &cs.Metrics{ - Height: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ - Subsystem: "consensus", - Name: "height", - Help: "Height of the chain.", - }, []string{}), - - Validators: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Subsystem: "consensus", - Name: "validators", - Help: "Number of validators who signed, partitioned by height.", - }, []string{"height"}), - MissingValidators: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Subsystem: "consensus", - Name: "missing_validators", - Help: "Number of validators who did not sign, partitioned by height.", - }, []string{"height"}), - ByzantineValidators: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Subsystem: "consensus", - Name: "byzantine_validators", - Help: "Number of validators who tried to double sign, partitioned by height.", - }, []string{"height"}), - - // BlockInterval: prometheus.NewHistogramFrom(stdprometheus.HistogramOpts{ - // Subsystem: "consensus", - // Name: "block_interval", - // Help: "Time between this and the last block, partitioned by height.", - // }, []string{"height"}), - // BlockTime: prometheus.NewHistogramFrom(stdprometheus.HistogramOpts{ - // Subsystem: "consensus", - // Name: "time_to_create_block", - // Help: "Time to create a block (from sending a proposal to commit), partitioned by height", - // }, []string{"height"}), - // TimeBetweenBlocks: prometheus.NewHistogramFrom(stdprometheus.HistogramOpts{ - // Subsystem: "consensus", - // Name: "time_between_blocks", - // Help: "Time between committing the last block and (receiving/sending a proposal), partitioned by height", - // }, []string{"height"}), - - NumTxs: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Subsystem: "consensus", - Name: "num_txs", - Help: "Number of transactions, partitioned by height.", - }, []string{"height"}), - TotalTxs: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ - Subsystem: "consensus", - Name: "total_txs", - Help: "Total number of transactions.", - }, []string{}), - - BlockSizeBytes: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Subsystem: "consensus", - Name: "block_size_bytes", - Help: "Size of the block, partitioned by height.", - }, []string{"height"}), - } + csMetrics := metricsProvider() consensusState := cs.NewConsensusState(config.Consensus, state.Copy(), - blockExec, blockStore, mempool, evidencePool, metrics) + blockExec, blockStore, mempool, evidencePool, csMetrics) consensusState.SetLogger(consensusLogger) if privValidator != nil { consensusState.SetPrivValidator(privValidator) diff --git a/rpc/test/helpers.go b/rpc/test/helpers.go index 5d18299bc..b434c7d92 100644 --- a/rpc/test/helpers.go +++ b/rpc/test/helpers.go @@ -122,7 +122,9 @@ func NewTendermint(app abci.Application) *nm.Node { papp := proxy.NewLocalClientCreator(app) node, err := nm.NewNode(config, pv, papp, nm.DefaultGenesisDocProviderFunc(config), - nm.DefaultDBProvider, logger) + nm.DefaultDBProvider, + nm.DefaultMetricsProvider, + logger) if err != nil { panic(err) }