diff --git a/internal/consensus/metrics.go b/internal/consensus/metrics.go index 4bcf252db..2de3a44ad 100644 --- a/internal/consensus/metrics.go +++ b/internal/consensus/metrics.go @@ -73,6 +73,10 @@ type Metrics struct { BlockGossipReceiveTime metrics.Gauge blockGossipStart time.Time + // Number of block parts received by the node, seperated by whether the part + // was relevant to the block the node is trying to gather or not. + BlockGossipPartsReceived metrics.Counter + // QuroumPrevoteMessageDelay is the interval in seconds between the proposal // timestamp and the timestamp of the earliest prevote that achieved a quorum // during the prevote step. @@ -226,6 +230,13 @@ func PrometheusMetrics(namespace string, labelsAndValues ...string) *Metrics { Help: "Difference in seconds between when the validator learns of a new block" + "and when the validator receives the last piece of the block.", }, labels).With(labelsAndValues...), + BlockGossipPartsReceived: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "block_gossip_parts_received", + Help: "Number of block parts received by the node, labeled by whether the" + + "part was relevant to the block the node was currently gathering or not", + }, append(labels, "matches_current")).With(labelsAndValues...), StepTime: prometheus.NewHistogramFrom(stdprometheus.HistogramOpts{ Namespace: namespace, Subsystem: MetricsSubsystem, @@ -286,6 +297,7 @@ func NopMetrics() *Metrics { StateSyncing: discard.NewGauge(), BlockParts: discard.NewCounter(), BlockGossipReceiveTime: discard.NewGauge(), + BlockGossipPartsReceived: discard.NewCounter(), QuorumPrevoteMessageDelay: discard.NewGauge(), FullPrevoteMessageDelay: discard.NewGauge(), ProposalTimestampDifference: discard.NewHistogram(), diff --git a/internal/consensus/state.go b/internal/consensus/state.go index 5fca68a5a..7f0fa1fc3 100644 --- a/internal/consensus/state.go +++ b/internal/consensus/state.go @@ -2057,11 +2057,13 @@ func (cs *State) addProposalBlockPart( // Blocks might be reused, so round mismatch is OK if cs.Height != height { cs.logger.Debug("received block part from wrong height", "height", height, "round", round) + cs.metrics.BlockGossipPartsReceived.With("matches_current", "false").Add(1) return false, nil } // We're not expecting a block part. if cs.ProposalBlockParts == nil { + cs.metrics.BlockGossipPartsReceived.With("matches_current", "false").Add(1) // NOTE: this can happen when we've gone to a higher round and // then receive parts from the previous round - not necessarily a bad peer. cs.logger.Debug( @@ -2076,8 +2078,14 @@ func (cs *State) addProposalBlockPart( added, err = cs.ProposalBlockParts.AddPart(part) if err != nil { + if errors.Is(err, types.ErrPartSetInvalidProof) || errors.Is(err, types.ErrPartSetUnexpectedIndex) { + cs.metrics.BlockGossipPartsReceived.With("matches_current", "false").Add(1) + } return added, err } + + cs.metrics.BlockGossipPartsReceived.With("matches_current", "true").Add(1) + if cs.ProposalBlockParts.ByteSize() > cs.state.ConsensusParams.Block.MaxBytes { return added, fmt.Errorf("total size of proposal block parts exceeds maximum block bytes (%d > %d)", cs.ProposalBlockParts.ByteSize(), cs.state.ConsensusParams.Block.MaxBytes,