diff --git a/consensus/metrics.go b/consensus/metrics.go index d46734b16..31e581878 100644 --- a/consensus/metrics.go +++ b/consensus/metrics.go @@ -94,7 +94,9 @@ type Metrics struct { DuplicateVoteReceive metrics.Counter - VoteSent metrics.Counter + VoteSent metrics.Counter + VoteReceived metrics.Counter + PeerVoteCount metrics.Gauge } // PrometheusMetrics returns Metrics build using Prometheus client library. @@ -265,8 +267,20 @@ func PrometheusMetrics(namespace string, labelsAndValues ...string) *Metrics { Namespace: namespace, Subsystem: MetricsSubsystem, Name: "vote_sent", - Help: "Number of votes sent by type", - }, append(labels, "type")).With(labelsAndValues...), + Help: "Number of votes of each type sent.", + }, append(labels, "vote_type")).With(labelsAndValues...), + VoteReceived: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "vote_received", + Help: "Number of votes of each type received.", + }, append(labels, "vote_type")).With(labelsAndValues...), + PeerVoteCount: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "vote_received", + Help: "Number of votes of each type received.", + }, append(labels, "peer_id", "vote_type")).With(labelsAndValues...), } } diff --git a/consensus/reactor.go b/consensus/reactor.go index bf263f65a..c42778641 100644 --- a/consensus/reactor.go +++ b/consensus/reactor.go @@ -15,6 +15,7 @@ import ( "github.com/tendermint/tendermint/libs/log" tmsync "github.com/tendermint/tendermint/libs/sync" "github.com/tendermint/tendermint/p2p" + "github.com/tendermint/tendermint/proto/tendermint/consensus" tmcons "github.com/tendermint/tendermint/proto/tendermint/consensus" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" sm "github.com/tendermint/tendermint/state" @@ -179,7 +180,7 @@ func (conR *Reactor) GetChannels() []*p2p.ChannelDescriptor { // InitPeer implements Reactor by creating a state for the peer. func (conR *Reactor) InitPeer(peer p2p.Peer) p2p.Peer { - peerState := NewPeerState(peer).SetLogger(conR.Logger) + peerState := NewPeerState(peer, conR.Metrics).SetLogger(conR.Logger) peer.Set(types.PeerStateKey, peerState) return peer } @@ -231,6 +232,10 @@ func (conR *Reactor) ReceiveEnvelope(e p2p.Envelope) { conR.Logger.Debug("Receive", "src", e.Src, "chId", e.ChannelID) return } + + if m, ok := e.Message.(*consensus.Vote); ok { + conR.Metrics.VoteReceived.With("vote_type", m.Vote.Type.String()).Add(1) + } m := e.Message if wm, ok := m.(p2p.Wrapper); ok { m = wm.Wrap() @@ -1036,8 +1041,9 @@ var ( // NOTE: THIS GETS DUMPED WITH rpc/core/consensus.go. // Be mindful of what you Expose. type PeerState struct { - peer p2p.Peer - logger log.Logger + peer p2p.Peer + logger log.Logger + conMetrics *Metrics mtx sync.Mutex // NOTE: Modify below using setters, never directly. PRS cstypes.PeerRoundState `json:"round_state"` // Exposed. @@ -1056,10 +1062,11 @@ func (pss peerStateStats) String() string { } // NewPeerState returns a new PeerState for the given Peer -func NewPeerState(peer p2p.Peer) *PeerState { +func NewPeerState(peer p2p.Peer, m *Metrics) *PeerState { return &PeerState{ - peer: peer, - logger: log.NewNopLogger(), + conMetrics: m, + peer: peer, + logger: log.NewNopLogger(), PRS: cstypes.PeerRoundState{ Round: -1, ProposalPOLRound: -1, @@ -1165,7 +1172,10 @@ func (ps *PeerState) PickSendVote(votes types.VoteSetReader) bool { Vote: vote.ToProto(), }, }, ps.logger) { + ps.conMetrics.VoteSent.With("vote_type", vote.Type.String()).Add(1) ps.SetHasVote(vote) + psVotes := ps.getVoteBitArray(votes.GetHeight(), votes.GetRound(), tmproto.SignedMsgType(votes.Type())) + ps.conMetrics.PeerVoteCount.With("peer_id", string(ps.peer.ID()), "vote_type", vote.Type.String()).Set(float64(len(psVotes.GetTrueIndices()))) return true } return false diff --git a/libs/bits/bit_array.go b/libs/bits/bit_array.go index d3aa2a444..75dc39c8b 100644 --- a/libs/bits/bit_array.go +++ b/libs/bits/bit_array.go @@ -251,7 +251,7 @@ func (bA *BitArray) PickRandom() (int, bool) { } bA.mtx.Lock() - trueIndices := bA.getTrueIndices() + trueIndices := bA.GetTrueIndices() bA.mtx.Unlock() if len(trueIndices) == 0 { // no bits set to true @@ -261,7 +261,7 @@ func (bA *BitArray) PickRandom() (int, bool) { return trueIndices[tmrand.Intn(len(trueIndices))], true } -func (bA *BitArray) getTrueIndices() []int { +func (bA *BitArray) GetTrueIndices() []int { trueIndices := make([]int, 0, bA.Bits) curBit := 0 numElems := len(bA.Elems)