- package consensus
-
- import (
- "strings"
- "time"
-
- "github.com/go-kit/kit/metrics"
- "github.com/go-kit/kit/metrics/discard"
-
- cstypes "github.com/tendermint/tendermint/internal/consensus/types"
- "github.com/tendermint/tendermint/types"
-
- prometheus "github.com/go-kit/kit/metrics/prometheus"
- stdprometheus "github.com/prometheus/client_golang/prometheus"
- )
-
- const (
- // MetricsSubsystem is a subsystem shared by all metrics exposed by this
- // package.
- MetricsSubsystem = "consensus"
- )
-
- // Metrics contains metrics exposed by this package.
- type Metrics struct {
- // Height of the chain.
- Height metrics.Gauge
-
- // ValidatorLastSignedHeight of a validator.
- ValidatorLastSignedHeight metrics.Gauge
-
- // Number of rounds.
- Rounds metrics.Gauge
-
- // Histogram of round duration.
- RoundDuration metrics.Histogram
-
- // Number of validators.
- Validators metrics.Gauge
- // Total power of all validators.
- ValidatorsPower metrics.Gauge
- // Power of a validator.
- ValidatorPower metrics.Gauge
- // Amount of blocks missed by a validator.
- ValidatorMissedBlocks metrics.Gauge
- // Number of validators who did not sign.
- MissingValidators metrics.Gauge
- // Total power of the missing validators.
- MissingValidatorsPower metrics.Gauge
- // Number of validators who tried to double sign.
- ByzantineValidators metrics.Gauge
- // Total power of the byzantine validators.
- ByzantineValidatorsPower metrics.Gauge
-
- // Time between this and the last block.
- BlockIntervalSeconds metrics.Histogram
-
- // Number of transactions.
- NumTxs metrics.Gauge
- // Size of the block.
- BlockSizeBytes metrics.Histogram
- // Total number of transactions.
- TotalTxs metrics.Gauge
- // The latest block height.
- CommittedHeight metrics.Gauge
- // Whether or not a node is block syncing. 1 if yes, 0 if no.
- BlockSyncing metrics.Gauge
- // Whether or not a node is state syncing. 1 if yes, 0 if no.
- StateSyncing metrics.Gauge
-
- // Number of blockparts transmitted by peer.
- BlockParts metrics.Counter
-
- // Histogram of step duration.
- StepDuration metrics.Histogram
- stepStart time.Time
-
- // Histogram of time taken to receive a block in seconds, measured between when a new block is first
- // discovered to when the block is completed.
- BlockGossipReceiveLatency metrics.Histogram
- blockGossipStart time.Time
-
- // Number of block parts received by the node, separated 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.
- //
- // To compute it, sum the voting power over each prevote received, in increasing
- // order of timestamp. The timestamp of the first prevote to increase the sum to
- // be above 2/3 of the total voting power of the network defines the endpoint
- // the endpoint of the interval. Subtract the proposal timestamp from this endpoint
- // to obtain the quorum delay.
- QuorumPrevoteMessageDelay metrics.Gauge
-
- // FullPrevoteMessageDelay is the interval in seconds between the proposal
- // timestamp and the timestamp of the latest prevote in a round where 100%
- // of the voting power on the network issued prevotes.
- FullPrevoteMessageDelay metrics.Gauge
-
- // ProposalTimestampDifference is the difference between the timestamp in
- // the proposal message and the local time of the validator at the time
- // that the validator received the message.
- ProposalTimestampDifference metrics.Histogram
- }
-
- // PrometheusMetrics returns Metrics build using Prometheus client library.
- // Optionally, labels can be provided along with their values ("foo",
- // "fooValue").
- func PrometheusMetrics(namespace string, labelsAndValues ...string) *Metrics {
- labels := []string{}
- for i := 0; i < len(labelsAndValues); i += 2 {
- labels = append(labels, labelsAndValues[i])
- }
- return &Metrics{
- Height: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
- Namespace: namespace,
- Subsystem: MetricsSubsystem,
- Name: "height",
- Help: "Height of the chain.",
- }, labels).With(labelsAndValues...),
- Rounds: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
- Namespace: namespace,
- Subsystem: MetricsSubsystem,
- Name: "rounds",
- Help: "Number of rounds.",
- }, labels).With(labelsAndValues...),
- RoundDuration: prometheus.NewHistogramFrom(stdprometheus.HistogramOpts{
- Namespace: namespace,
- Subsystem: MetricsSubsystem,
- Name: "round_duration",
- Help: "Time spent in a round.",
- Buckets: stdprometheus.ExponentialBucketsRange(0.1, 100, 8),
- }, labels).With(labelsAndValues...),
- Validators: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
- Namespace: namespace,
- Subsystem: MetricsSubsystem,
- Name: "validators",
- Help: "Number of validators.",
- }, labels).With(labelsAndValues...),
- ValidatorLastSignedHeight: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
- Namespace: namespace,
- Subsystem: MetricsSubsystem,
- Name: "validator_last_signed_height",
- Help: "Last signed height for a validator",
- }, append(labels, "validator_address")).With(labelsAndValues...),
- ValidatorMissedBlocks: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
- Namespace: namespace,
- Subsystem: MetricsSubsystem,
- Name: "validator_missed_blocks",
- Help: "Total missed blocks for a validator",
- }, append(labels, "validator_address")).With(labelsAndValues...),
- ValidatorsPower: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
- Namespace: namespace,
- Subsystem: MetricsSubsystem,
- Name: "validators_power",
- Help: "Total power of all validators.",
- }, labels).With(labelsAndValues...),
- ValidatorPower: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
- Namespace: namespace,
- Subsystem: MetricsSubsystem,
- Name: "validator_power",
- Help: "Power of a validator",
- }, append(labels, "validator_address")).With(labelsAndValues...),
- MissingValidators: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
- Namespace: namespace,
- Subsystem: MetricsSubsystem,
- Name: "missing_validators",
- Help: "Number of validators who did not sign.",
- }, labels).With(labelsAndValues...),
- MissingValidatorsPower: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
- Namespace: namespace,
- Subsystem: MetricsSubsystem,
- Name: "missing_validators_power",
- Help: "Total power of the missing validators.",
- }, labels).With(labelsAndValues...),
- ByzantineValidators: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
- Namespace: namespace,
- Subsystem: MetricsSubsystem,
- Name: "byzantine_validators",
- Help: "Number of validators who tried to double sign.",
- }, labels).With(labelsAndValues...),
- ByzantineValidatorsPower: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
- Namespace: namespace,
- Subsystem: MetricsSubsystem,
- Name: "byzantine_validators_power",
- Help: "Total power of the byzantine validators.",
- }, labels).With(labelsAndValues...),
- BlockIntervalSeconds: prometheus.NewHistogramFrom(stdprometheus.HistogramOpts{
- Namespace: namespace,
- Subsystem: MetricsSubsystem,
- Name: "block_interval_seconds",
- Help: "Time between this and the last block.",
- }, labels).With(labelsAndValues...),
- NumTxs: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
- Namespace: namespace,
- Subsystem: MetricsSubsystem,
- Name: "num_txs",
- Help: "Number of transactions.",
- }, labels).With(labelsAndValues...),
- BlockSizeBytes: prometheus.NewHistogramFrom(stdprometheus.HistogramOpts{
- Namespace: namespace,
- Subsystem: MetricsSubsystem,
- Name: "block_size_bytes",
- Help: "Size of the block.",
- }, labels).With(labelsAndValues...),
- TotalTxs: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
- Namespace: namespace,
- Subsystem: MetricsSubsystem,
- Name: "total_txs",
- Help: "Total number of transactions.",
- }, labels).With(labelsAndValues...),
- CommittedHeight: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
- Namespace: namespace,
- Subsystem: MetricsSubsystem,
- Name: "latest_block_height",
- Help: "The latest block height.",
- }, labels).With(labelsAndValues...),
- BlockSyncing: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
- Namespace: namespace,
- Subsystem: MetricsSubsystem,
- Name: "block_syncing",
- Help: "Whether or not a node is block syncing. 1 if yes, 0 if no.",
- }, labels).With(labelsAndValues...),
- StateSyncing: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
- Namespace: namespace,
- Subsystem: MetricsSubsystem,
- Name: "state_syncing",
- Help: "Whether or not a node is state syncing. 1 if yes, 0 if no.",
- }, labels).With(labelsAndValues...),
- BlockParts: prometheus.NewCounterFrom(stdprometheus.CounterOpts{
- Namespace: namespace,
- Subsystem: MetricsSubsystem,
- Name: "block_parts",
- Help: "Number of blockparts transmitted by peer.",
- }, append(labels, "peer_id")).With(labelsAndValues...),
- BlockGossipReceiveLatency: prometheus.NewHistogramFrom(stdprometheus.HistogramOpts{
- Namespace: namespace,
- Subsystem: MetricsSubsystem,
- Name: "block_gossip_receive_latency",
- Help: "Difference in seconds between when the validator learns of a new block" +
- "and when the validator receives the last piece of the block.",
- Buckets: stdprometheus.ExponentialBucketsRange(0.1, 100, 8),
- }, 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...),
- StepDuration: prometheus.NewHistogramFrom(stdprometheus.HistogramOpts{
- Namespace: namespace,
- Subsystem: MetricsSubsystem,
- Name: "step_duration",
- Help: "Time spent per step.",
- Buckets: stdprometheus.ExponentialBucketsRange(0.1, 100, 8),
- }, append(labels, "step")).With(labelsAndValues...),
- QuorumPrevoteMessageDelay: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
- Namespace: namespace,
- Subsystem: MetricsSubsystem,
- Name: "quorum_prevote_message_delay",
- Help: "Difference in seconds between the proposal timestamp and the timestamp " +
- "of the latest prevote that achieved a quorum in the prevote step.",
- }, append(labels, "proposer_address")).With(labelsAndValues...),
- FullPrevoteMessageDelay: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
- Namespace: namespace,
- Subsystem: MetricsSubsystem,
- Name: "full_prevote_message_delay",
- Help: "Difference in seconds between the proposal timestamp and the timestamp " +
- "of the latest prevote that achieved 100% of the voting power in the prevote step.",
- }, append(labels, "proposer_address")).With(labelsAndValues...),
- ProposalTimestampDifference: prometheus.NewHistogramFrom(stdprometheus.HistogramOpts{
- Namespace: namespace,
- Subsystem: MetricsSubsystem,
- Name: "proposal_timestamp_difference",
- Help: "Difference in seconds between the timestamp in the proposal " +
- "message and the local time when the message was received. " +
- "Only calculated when a new block is proposed.",
- Buckets: []float64{-10, -.5, -.025, 0, .1, .5, 1, 1.5, 2, 10},
- }, append(labels, "is_timely")).With(labelsAndValues...),
- }
- }
-
- // NopMetrics returns no-op Metrics.
- func NopMetrics() *Metrics {
- return &Metrics{
- Height: discard.NewGauge(),
-
- ValidatorLastSignedHeight: discard.NewGauge(),
-
- Rounds: discard.NewGauge(),
- RoundDuration: discard.NewHistogram(),
- StepDuration: discard.NewHistogram(),
-
- Validators: discard.NewGauge(),
- ValidatorsPower: discard.NewGauge(),
- ValidatorPower: discard.NewGauge(),
- ValidatorMissedBlocks: discard.NewGauge(),
- MissingValidators: discard.NewGauge(),
- MissingValidatorsPower: discard.NewGauge(),
- ByzantineValidators: discard.NewGauge(),
- ByzantineValidatorsPower: discard.NewGauge(),
-
- BlockIntervalSeconds: discard.NewHistogram(),
-
- NumTxs: discard.NewGauge(),
- BlockSizeBytes: discard.NewHistogram(),
- TotalTxs: discard.NewGauge(),
- CommittedHeight: discard.NewGauge(),
- BlockSyncing: discard.NewGauge(),
- StateSyncing: discard.NewGauge(),
- BlockParts: discard.NewCounter(),
- BlockGossipReceiveLatency: discard.NewHistogram(),
- BlockGossipPartsReceived: discard.NewCounter(),
- QuorumPrevoteMessageDelay: discard.NewGauge(),
- FullPrevoteMessageDelay: discard.NewGauge(),
- ProposalTimestampDifference: discard.NewHistogram(),
- }
- }
-
- // RecordConsMetrics uses for recording the block related metrics during fast-sync.
- func (m *Metrics) RecordConsMetrics(block *types.Block) {
- m.NumTxs.Set(float64(len(block.Data.Txs)))
- m.TotalTxs.Add(float64(len(block.Data.Txs)))
- m.BlockSizeBytes.Observe(float64(block.Size()))
- m.CommittedHeight.Set(float64(block.Height))
- }
-
- func (m *Metrics) MarkBlockGossipStarted() {
- m.blockGossipStart = time.Now()
- }
-
- func (m *Metrics) MarkBlockGossipComplete() {
- m.BlockGossipReceiveLatency.Observe(time.Since(m.blockGossipStart).Seconds())
- }
-
- func (m *Metrics) MarkRound(r int32, st time.Time) {
- m.Rounds.Set(float64(r))
- roundTime := time.Since(st).Seconds()
- m.RoundDuration.Observe(roundTime)
- }
-
- func (m *Metrics) MarkStep(s cstypes.RoundStepType) {
- if !m.stepStart.IsZero() {
- stepTime := time.Since(m.stepStart).Seconds()
- stepName := strings.TrimPrefix(s.String(), "RoundStep")
- m.StepDuration.With("step", stepName).Observe(stepTime)
- }
- m.stepStart = time.Now()
- }
|