From 92811b9153998145efc1255e2b8d94f6dc9f8caf Mon Sep 17 00:00:00 2001 From: William Banfield <4561443+williambanfield@users.noreply.github.com> Date: Thu, 12 May 2022 14:39:12 -0400 Subject: [PATCH] metrics: transition all metrics to using metricsgen generated constructors. (#8488) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## What does this change do? This pull request completes the change to the `metricsgen` metrics. It adds `go generate` directives to all of the files containing the `Metrics` structs. Using the outputs of `metricsdiff` between these generated metrics and `master`, we can see that there is not a diff between the two sets of metrics when run locally. ``` [william@sidewinder] tendermint[wb/metrics-gen-transition]:. ◆ ./scripts/metricsgen/metricsdiff/metricsdiff metrics_master metrics_generated [william@sidewinder] tendermint[wb/metrics-gen-transition]:. ◆ ``` This change also adds parsing for a `metrics:` key in a field comment. If a comment line begins with `//metrics:` the rest of the line is interpreted to be the metric help text. Additionally, a bug where lists of labels were not properly quoted in the `metricsgen` rendered output was fixed. --- internal/consensus/metrics.gen.go | 248 ++++++++++++++ internal/consensus/metrics.go | 313 ++---------------- internal/eventlog/eventlog.go | 18 +- internal/eventlog/metrics.gen.go | 30 ++ internal/eventlog/metrics.go | 39 +-- internal/eventlog/prune.go | 4 +- internal/evidence/metrics.gen.go | 30 ++ internal/evidence/metrics.go | 33 +- internal/mempool/metrics.gen.go | 67 ++++ internal/mempool/metrics.go | 79 +---- internal/p2p/metrics.gen.go | 86 +++++ internal/p2p/metrics.go | 131 ++------ internal/p2p/metrics_test.go | 6 +- internal/p2p/pqueue.go | 5 +- internal/p2p/pqueue_test.go | 2 +- internal/p2p/router.go | 9 +- internal/proxy/metrics.gen.go | 32 ++ internal/proxy/metrics.go | 36 +- internal/state/indexer/metrics.go | 2 +- internal/state/metrics.gen.go | 46 +++ internal/state/metrics.go | 52 +-- internal/statesync/metrics.gen.go | 72 ++++ internal/statesync/metrics.go | 89 +---- scripts/metricsgen/metricsgen.go | 33 +- scripts/metricsgen/metricsgen_test.go | 4 +- .../testdata/commented/metrics.gen.go | 2 +- .../metricsgen/testdata/tags/metrics.gen.go | 3 +- 27 files changed, 760 insertions(+), 711 deletions(-) create mode 100644 internal/consensus/metrics.gen.go create mode 100644 internal/eventlog/metrics.gen.go create mode 100644 internal/evidence/metrics.gen.go create mode 100644 internal/mempool/metrics.gen.go create mode 100644 internal/p2p/metrics.gen.go create mode 100644 internal/proxy/metrics.gen.go create mode 100644 internal/state/metrics.gen.go create mode 100644 internal/statesync/metrics.gen.go diff --git a/internal/consensus/metrics.gen.go b/internal/consensus/metrics.gen.go new file mode 100644 index 000000000..55cc59f6c --- /dev/null +++ b/internal/consensus/metrics.gen.go @@ -0,0 +1,248 @@ +// Code generated by metricsgen. DO NOT EDIT. + +package consensus + +import ( + "github.com/go-kit/kit/metrics/discard" + prometheus "github.com/go-kit/kit/metrics/prometheus" + stdprometheus "github.com/prometheus/client_golang/prometheus" +) + +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...), + ValidatorLastSignedHeight: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "validator_last_signed_height", + Help: "Last height signed by this validator if the node is a validator.", + }, append(labels, "validator_address")).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: "Histogram of round duration.", + + 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...), + 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...), + ValidatorMissedBlocks: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "validator_missed_blocks", + Help: "Amount of blocks missed per 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 block parts transmitted by each peer.", + }, append(labels, "peer_id")).With(labelsAndValues...), + StepDuration: prometheus.NewHistogramFrom(stdprometheus.HistogramOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "step_duration", + Help: "Histogram of durations for each step in the consensus protocol.", + + Buckets: stdprometheus.ExponentialBucketsRange(0.1, 100, 8), + }, append(labels, "step")).With(labelsAndValues...), + BlockGossipReceiveLatency: prometheus.NewHistogramFrom(stdprometheus.HistogramOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "block_gossip_receive_latency", + Help: "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.", + + 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, separated by whether the part was relevant to the block the node is trying to gather or not.", + }, append(labels, "matches_current")).With(labelsAndValues...), + QuorumPrevoteDelay: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "quorum_prevote_delay", + Help: "Interval in seconds between the proposal timestamp and the timestamp of the earliest prevote that achieved a quorum.", + }, append(labels, "proposer_address")).With(labelsAndValues...), + FullPrevoteDelay: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "full_prevote_delay", + Help: "Interval in seconds between the proposal timestamp and the timestamp of the latest prevote in a round where all validators voted.", + }, append(labels, "proposer_address")).With(labelsAndValues...), + ProposalTimestampDifference: prometheus.NewHistogramFrom(stdprometheus.HistogramOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "proposal_timestamp_difference", + Help: "Difference between the timestamp in the proposal message and the local time of the validator at the time it received the message.", + + Buckets: []float64{-10, -.5, -.025, 0, .1, .5, 1, 1.5, 2, 10}, + }, append(labels, "is_timely")).With(labelsAndValues...), + VoteExtensionReceiveCount: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "vote_extension_receive_count", + Help: "Number of vote extensions received labeled by application response status.", + }, append(labels, "status")).With(labelsAndValues...), + ProposalReceiveCount: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "proposal_receive_count", + Help: "Total number of proposals received by the node since process start labeled by application response status.", + }, append(labels, "status")).With(labelsAndValues...), + ProposalCreateCount: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "proposal_create_count", + Help: "Total number of proposals created by the node since process start.", + }, labels).With(labelsAndValues...), + RoundVotingPowerPercent: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "round_voting_power_percent", + Help: "A value between 0 and 1.0 representing the percentage of the total voting power per vote type received within a round.", + }, append(labels, "vote_type")).With(labelsAndValues...), + LateVotes: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "late_votes", + Help: "Number of votes received by the node since process start that correspond to earlier heights and rounds than this node is currently in.", + }, append(labels, "vote_type")).With(labelsAndValues...), + } +} + +func NopMetrics() *Metrics { + return &Metrics{ + Height: discard.NewGauge(), + ValidatorLastSignedHeight: discard.NewGauge(), + Rounds: discard.NewGauge(), + RoundDuration: 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(), + StepDuration: discard.NewHistogram(), + BlockGossipReceiveLatency: discard.NewHistogram(), + BlockGossipPartsReceived: discard.NewCounter(), + QuorumPrevoteDelay: discard.NewGauge(), + FullPrevoteDelay: discard.NewGauge(), + ProposalTimestampDifference: discard.NewHistogram(), + VoteExtensionReceiveCount: discard.NewCounter(), + ProposalReceiveCount: discard.NewCounter(), + ProposalCreateCount: discard.NewCounter(), + RoundVotingPowerPercent: discard.NewGauge(), + LateVotes: discard.NewCounter(), + } +} diff --git a/internal/consensus/metrics.go b/internal/consensus/metrics.go index e5c0162f4..bdf0eb412 100644 --- a/internal/consensus/metrics.go +++ b/internal/consensus/metrics.go @@ -5,14 +5,10 @@ import ( "time" "github.com/go-kit/kit/metrics" - "github.com/go-kit/kit/metrics/discard" cstypes "github.com/tendermint/tendermint/internal/consensus/types" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" "github.com/tendermint/tendermint/types" - - prometheus "github.com/go-kit/kit/metrics/prometheus" - stdprometheus "github.com/prometheus/client_golang/prometheus" ) const ( @@ -21,28 +17,30 @@ const ( MetricsSubsystem = "consensus" ) +//go:generate go run ../../scripts/metricsgen -struct=Metrics + // Metrics contains metrics exposed by this package. type Metrics struct { // Height of the chain. Height metrics.Gauge - // ValidatorLastSignedHeight of a validator. - ValidatorLastSignedHeight metrics.Gauge + // Last height signed by this validator if the node is a validator. + ValidatorLastSignedHeight metrics.Gauge `metrics_labels:"validator_address"` // Number of rounds. Rounds metrics.Gauge // Histogram of round duration. - RoundDuration metrics.Histogram + RoundDuration metrics.Histogram `metrics_buckettype:"exprange" metrics_bucketsizes:"0.1, 100, 8"` // 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 + ValidatorPower metrics.Gauge `metrics_labels:"validator_address"` + // Amount of blocks missed per validator. + ValidatorMissedBlocks metrics.Gauge `metrics_labels:"validator_address"` // Number of validators who did not sign. MissingValidators metrics.Gauge // Total power of the missing validators. @@ -62,27 +60,27 @@ type Metrics struct { // Total number of transactions. TotalTxs metrics.Gauge // The latest block height. - CommittedHeight metrics.Gauge + CommittedHeight metrics.Gauge `metrics_name:"latest_block_height"` // 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 + // Number of block parts transmitted by each peer. + BlockParts metrics.Counter `metrics_labels:"peer_id"` - // Histogram of step duration. - StepDuration metrics.Histogram + // Histogram of durations for each step in the consensus protocol. + StepDuration metrics.Histogram `metrics_labels:"step" metrics_buckettype:"exprange" metrics_bucketsizes:"0.1, 100, 8"` 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 + BlockGossipReceiveLatency metrics.Histogram `metrics_buckettype:"exprange" metrics_bucketsizes:"0.1, 100, 8"` 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 + BlockGossipPartsReceived metrics.Counter `metrics_labels:"matches_current"` // QuroumPrevoteMessageDelay is the interval in seconds between the proposal // timestamp and the timestamp of the earliest prevote that achieved a quorum @@ -93,301 +91,50 @@ type Metrics struct { // 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. - QuorumPrevoteDelay metrics.Gauge + //metrics:Interval in seconds between the proposal timestamp and the timestamp of the earliest prevote that achieved a quorum. + QuorumPrevoteDelay metrics.Gauge `metrics_labels:"proposer_address"` // FullPrevoteDelay 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. - FullPrevoteDelay metrics.Gauge + //metrics:Interval in seconds between the proposal timestamp and the timestamp of the latest prevote in a round where all validators voted. + FullPrevoteDelay metrics.Gauge `metrics_labels:"proposer_address"` // 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 + //metrics:Difference between the timestamp in the proposal message and the local time of the validator at the time it received the message. + ProposalTimestampDifference metrics.Histogram `metrics_labels:"is_timely" metrics_bucketsizes:"-10, -.5, -.025, 0, .1, .5, 1, 1.5, 2, 10"` // VoteExtensionReceiveCount is the number of vote extensions received by this // node. The metric is annotated by the status of the vote extension from the // application, either 'accepted' or 'rejected'. - VoteExtensionReceiveCount metrics.Counter + //metrics:Number of vote extensions received labeled by application response status. + VoteExtensionReceiveCount metrics.Counter `metrics_labels:"status"` // ProposalReceiveCount is the total number of proposals received by this node // since process start. // The metric is annotated by the status of the proposal from the application, // either 'accepted' or 'rejected'. - ProposalReceiveCount metrics.Counter + //metrics:Total number of proposals received by the node since process start labeled by application response status. + ProposalReceiveCount metrics.Counter `metrics_labels:"status"` // ProposalCreationCount is the total number of proposals created by this node // since process start. - // The metric is annotated by the status of the proposal from the application, - // either 'accepted' or 'rejected'. + //metrics:Total number of proposals created by the node since process start. ProposalCreateCount metrics.Counter // RoundVotingPowerPercent is the percentage of the total voting power received // with a round. The value begins at 0 for each round and approaches 1.0 as // additional voting power is observed. The metric is labeled by vote type. - RoundVotingPowerPercent metrics.Gauge + //metrics:A value between 0 and 1.0 representing the percentage of the total voting power per vote type received within a round. + RoundVotingPowerPercent metrics.Gauge `metrics_labels:"vote_type"` // LateVotes stores the number of votes that were received by this node that // correspond to earlier heights and rounds than this node is currently // in. - LateVotes metrics.Counter -} - -// 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...), - QuorumPrevoteDelay: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: namespace, - Subsystem: MetricsSubsystem, - Name: "quorum_prevote_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...), - FullPrevoteDelay: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: namespace, - Subsystem: MetricsSubsystem, - Name: "full_prevote_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...), - VoteExtensionReceiveCount: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ - Namespace: namespace, - Subsystem: MetricsSubsystem, - Name: "vote_extension_receive_count", - Help: "Number of vote extensions received by the node since process start, labeled by " + - "the application's response to VerifyVoteExtension, either accept or reject.", - }, append(labels, "status")).With(labelsAndValues...), - - ProposalReceiveCount: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ - Namespace: namespace, - Subsystem: MetricsSubsystem, - Name: "proposal_receive_count", - Help: "Number of vote proposals received by the node since process start, labeled by " + - "the application's response to ProcessProposal, either accept or reject.", - }, append(labels, "status")).With(labelsAndValues...), - - ProposalCreateCount: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ - Namespace: namespace, - Subsystem: MetricsSubsystem, - Name: "proposal_create_count", - Help: "Number of proposals created by the node since process start.", - }, labels).With(labelsAndValues...), - - RoundVotingPowerPercent: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: namespace, - Subsystem: MetricsSubsystem, - Name: "round_voting_power_percent", - Help: "Percentage of the total voting power received with a round. " + - "The value begins at 0 for each round and approaches 1.0 as additional " + - "voting power is observed.", - }, append(labels, "vote_type")).With(labelsAndValues...), - LateVotes: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ - Namespace: namespace, - Subsystem: MetricsSubsystem, - Name: "late_votes", - Help: "Number of votes received by the node since process start that correspond to earlier heights and rounds than this node is currently in.", - }, append(labels, "vote_type")).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(), - QuorumPrevoteDelay: discard.NewGauge(), - FullPrevoteDelay: discard.NewGauge(), - ProposalTimestampDifference: discard.NewHistogram(), - VoteExtensionReceiveCount: discard.NewCounter(), - ProposalReceiveCount: discard.NewCounter(), - ProposalCreateCount: discard.NewCounter(), - RoundVotingPowerPercent: discard.NewGauge(), - LateVotes: discard.NewCounter(), - } + //metrics:Number of votes received by the node since process start that correspond to earlier heights and rounds than this node is currently in. + LateVotes metrics.Counter `metrics_labels:"vote_type"` } // RecordConsMetrics uses for recording the block related metrics during fast-sync. diff --git a/internal/eventlog/eventlog.go b/internal/eventlog/eventlog.go index b507f79bc..31c7d14fe 100644 --- a/internal/eventlog/eventlog.go +++ b/internal/eventlog/eventlog.go @@ -24,9 +24,9 @@ import ( // any number of readers. type Log struct { // These values do not change after construction. - windowSize time.Duration - maxItems int - numItemsGauge gauge + windowSize time.Duration + maxItems int + metrics *Metrics // Protects access to the fields below. Lock to modify the values of these // fields, or to read or snapshot the values. @@ -45,14 +45,14 @@ func New(opts LogSettings) (*Log, error) { return nil, errors.New("window size must be positive") } lg := &Log{ - windowSize: opts.WindowSize, - maxItems: opts.MaxItems, - numItemsGauge: discard{}, - ready: make(chan struct{}), - source: opts.Source, + windowSize: opts.WindowSize, + maxItems: opts.MaxItems, + metrics: NopMetrics(), + ready: make(chan struct{}), + source: opts.Source, } if opts.Metrics != nil { - lg.numItemsGauge = opts.Metrics.numItemsGauge + lg.metrics = opts.Metrics } return lg, nil } diff --git a/internal/eventlog/metrics.gen.go b/internal/eventlog/metrics.gen.go new file mode 100644 index 000000000..d9d86b2b9 --- /dev/null +++ b/internal/eventlog/metrics.gen.go @@ -0,0 +1,30 @@ +// Code generated by metricsgen. DO NOT EDIT. + +package eventlog + +import ( + "github.com/go-kit/kit/metrics/discard" + prometheus "github.com/go-kit/kit/metrics/prometheus" + stdprometheus "github.com/prometheus/client_golang/prometheus" +) + +func PrometheusMetrics(namespace string, labelsAndValues ...string) *Metrics { + labels := []string{} + for i := 0; i < len(labelsAndValues); i += 2 { + labels = append(labels, labelsAndValues[i]) + } + return &Metrics{ + numItems: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "num_items", + Help: "Number of items currently resident in the event log.", + }, labels).With(labelsAndValues...), + } +} + +func NopMetrics() *Metrics { + return &Metrics{ + numItems: discard.NewGauge(), + } +} diff --git a/internal/eventlog/metrics.go b/internal/eventlog/metrics.go index cc319032e..fb7ccf694 100644 --- a/internal/eventlog/metrics.go +++ b/internal/eventlog/metrics.go @@ -1,39 +1,14 @@ package eventlog -import ( - "github.com/go-kit/kit/metrics/prometheus" - stdprometheus "github.com/prometheus/client_golang/prometheus" -) +import "github.com/go-kit/kit/metrics" -// gauge is the subset of the Prometheus gauge interface used here. -type gauge interface { - Set(float64) -} +const MetricsSubsystem = "eventlog" + +//go:generate go run ../../scripts/metricsgen -struct=Metrics // Metrics define the metrics exported by the eventlog package. type Metrics struct { - numItemsGauge gauge -} - -// discard is a no-op implementation of the gauge interface. -type discard struct{} - -func (discard) Set(float64) {} - -const eventlogSubsystem = "eventlog" - -// PrometheusMetrics returns a collection of eventlog metrics for Prometheus. -func PrometheusMetrics(ns string, fields ...string) *Metrics { - var labels []string - for i := 0; i < len(fields); i += 2 { - labels = append(labels, fields[i]) - } - return &Metrics{ - numItemsGauge: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: ns, - Subsystem: eventlogSubsystem, - Name: "num_items", - Help: "Number of items currently resident in the event log.", - }, labels).With(fields...), - } + + // Number of items currently resident in the event log. + numItems metrics.Gauge } diff --git a/internal/eventlog/prune.go b/internal/eventlog/prune.go index 4c3c1f0d0..062e91bd2 100644 --- a/internal/eventlog/prune.go +++ b/internal/eventlog/prune.go @@ -12,7 +12,7 @@ func (lg *Log) checkPrune(head *logEntry, size int, age time.Duration) error { const windowSlop = 30 * time.Second if age < (lg.windowSize+windowSlop) && (lg.maxItems <= 0 || size <= lg.maxItems) { - lg.numItemsGauge.Set(float64(lg.numItems)) + lg.metrics.numItems.Set(float64(lg.numItems)) return nil // no pruning is needed } @@ -46,7 +46,7 @@ func (lg *Log) checkPrune(head *logEntry, size int, age time.Duration) error { lg.mu.Lock() defer lg.mu.Unlock() lg.numItems = newState.size - lg.numItemsGauge.Set(float64(newState.size)) + lg.metrics.numItems.Set(float64(newState.size)) lg.oldestCursor = newState.oldest lg.head = newState.head return err diff --git a/internal/evidence/metrics.gen.go b/internal/evidence/metrics.gen.go new file mode 100644 index 000000000..f2eb7dfa8 --- /dev/null +++ b/internal/evidence/metrics.gen.go @@ -0,0 +1,30 @@ +// Code generated by metricsgen. DO NOT EDIT. + +package evidence + +import ( + "github.com/go-kit/kit/metrics/discard" + prometheus "github.com/go-kit/kit/metrics/prometheus" + stdprometheus "github.com/prometheus/client_golang/prometheus" +) + +func PrometheusMetrics(namespace string, labelsAndValues ...string) *Metrics { + labels := []string{} + for i := 0; i < len(labelsAndValues); i += 2 { + labels = append(labels, labelsAndValues[i]) + } + return &Metrics{ + NumEvidence: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "num_evidence", + Help: "Number of pending evidence in the evidence pool.", + }, labels).With(labelsAndValues...), + } +} + +func NopMetrics() *Metrics { + return &Metrics{ + NumEvidence: discard.NewGauge(), + } +} diff --git a/internal/evidence/metrics.go b/internal/evidence/metrics.go index 59efc23f9..adb0260f2 100644 --- a/internal/evidence/metrics.go +++ b/internal/evidence/metrics.go @@ -2,9 +2,6 @@ package evidence import ( "github.com/go-kit/kit/metrics" - "github.com/go-kit/kit/metrics/discard" - "github.com/go-kit/kit/metrics/prometheus" - stdprometheus "github.com/prometheus/client_golang/prometheus" ) const ( @@ -13,35 +10,11 @@ const ( MetricsSubsystem = "evidence_pool" ) +//go:generate go run ../../scripts/metricsgen -struct=Metrics + // Metrics contains metrics exposed by this package. // see MetricsProvider for descriptions. type Metrics struct { - // Number of evidence in the evidence pool + // Number of pending evidence in the evidence pool. NumEvidence metrics.Gauge } - -// 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{ - - NumEvidence: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: namespace, - Subsystem: MetricsSubsystem, - Name: "num_evidence", - Help: "Number of pending evidence in evidence pool.", - }, labels).With(labelsAndValues...), - } -} - -// NopMetrics returns no-op Metrics. -func NopMetrics() *Metrics { - return &Metrics{ - NumEvidence: discard.NewGauge(), - } -} diff --git a/internal/mempool/metrics.gen.go b/internal/mempool/metrics.gen.go new file mode 100644 index 000000000..100c5e71c --- /dev/null +++ b/internal/mempool/metrics.gen.go @@ -0,0 +1,67 @@ +// Code generated by metricsgen. DO NOT EDIT. + +package mempool + +import ( + "github.com/go-kit/kit/metrics/discard" + prometheus "github.com/go-kit/kit/metrics/prometheus" + stdprometheus "github.com/prometheus/client_golang/prometheus" +) + +func PrometheusMetrics(namespace string, labelsAndValues ...string) *Metrics { + labels := []string{} + for i := 0; i < len(labelsAndValues); i += 2 { + labels = append(labels, labelsAndValues[i]) + } + return &Metrics{ + Size: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "size", + Help: "Number of uncommitted transactions in the mempool.", + }, labels).With(labelsAndValues...), + TxSizeBytes: prometheus.NewHistogramFrom(stdprometheus.HistogramOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "tx_size_bytes", + Help: "Histogram of transaction sizes in bytes.", + + Buckets: stdprometheus.ExponentialBuckets(1, 3, 7), + }, labels).With(labelsAndValues...), + FailedTxs: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "failed_txs", + Help: "Number of failed transactions.", + }, labels).With(labelsAndValues...), + RejectedTxs: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "rejected_txs", + Help: "Number of rejected transactions.", + }, labels).With(labelsAndValues...), + EvictedTxs: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "evicted_txs", + Help: "Number of evicted transactions.", + }, labels).With(labelsAndValues...), + RecheckTimes: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "recheck_times", + Help: "Number of times transactions are rechecked in the mempool.", + }, labels).With(labelsAndValues...), + } +} + +func NopMetrics() *Metrics { + return &Metrics{ + Size: discard.NewGauge(), + TxSizeBytes: discard.NewHistogram(), + FailedTxs: discard.NewCounter(), + RejectedTxs: discard.NewCounter(), + EvictedTxs: discard.NewCounter(), + RecheckTimes: discard.NewCounter(), + } +} diff --git a/internal/mempool/metrics.go b/internal/mempool/metrics.go index 5d3022e80..532307635 100644 --- a/internal/mempool/metrics.go +++ b/internal/mempool/metrics.go @@ -2,9 +2,6 @@ package mempool import ( "github.com/go-kit/kit/metrics" - "github.com/go-kit/kit/metrics/discard" - "github.com/go-kit/kit/metrics/prometheus" - stdprometheus "github.com/prometheus/client_golang/prometheus" ) const ( @@ -13,14 +10,16 @@ const ( MetricsSubsystem = "mempool" ) +//go:generate go run ../../scripts/metricsgen -struct=Metrics + // Metrics contains metrics exposed by this package. // see MetricsProvider for descriptions. type Metrics struct { - // Size of the mempool. + // Number of uncommitted transactions in the mempool. Size metrics.Gauge - // Histogram of transaction sizes, in bytes. - TxSizeBytes metrics.Histogram + // Histogram of transaction sizes in bytes. + TxSizeBytes metrics.Histogram `metrics_buckettype:"exp" metrics_bucketsizes:"1,3,7"` // Number of failed transactions. FailedTxs metrics.Counter @@ -29,80 +28,16 @@ type Metrics struct { // transactions that passed CheckTx but failed to make it into the mempool // due to resource limits, e.g. mempool is full and no lower priority // transactions exist in the mempool. + //metrics:Number of rejected transactions. RejectedTxs metrics.Counter // EvictedTxs defines the number of evicted transactions. These are valid // transactions that passed CheckTx and existed in the mempool but were later // evicted to make room for higher priority valid transactions that passed // CheckTx. + //metrics:Number of evicted transactions. EvictedTxs metrics.Counter // Number of times transactions are rechecked in the mempool. RecheckTimes metrics.Counter } - -// 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{ - Size: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: namespace, - Subsystem: MetricsSubsystem, - Name: "size", - Help: "Size of the mempool (number of uncommitted transactions).", - }, labels).With(labelsAndValues...), - - TxSizeBytes: prometheus.NewHistogramFrom(stdprometheus.HistogramOpts{ - Namespace: namespace, - Subsystem: MetricsSubsystem, - Name: "tx_size_bytes", - Help: "Transaction sizes in bytes.", - Buckets: stdprometheus.ExponentialBuckets(1, 3, 17), - }, labels).With(labelsAndValues...), - - FailedTxs: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ - Namespace: namespace, - Subsystem: MetricsSubsystem, - Name: "failed_txs", - Help: "Number of failed transactions.", - }, labels).With(labelsAndValues...), - - RejectedTxs: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ - Namespace: namespace, - Subsystem: MetricsSubsystem, - Name: "rejected_txs", - Help: "Number of rejected transactions.", - }, labels).With(labelsAndValues...), - - EvictedTxs: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ - Namespace: namespace, - Subsystem: MetricsSubsystem, - Name: "evicted_txs", - Help: "Number of evicted transactions.", - }, labels).With(labelsAndValues...), - - RecheckTimes: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ - Namespace: namespace, - Subsystem: MetricsSubsystem, - Name: "recheck_times", - Help: "Number of times transactions are rechecked in the mempool.", - }, labels).With(labelsAndValues...), - } -} - -// NopMetrics returns no-op Metrics. -func NopMetrics() *Metrics { - return &Metrics{ - Size: discard.NewGauge(), - TxSizeBytes: discard.NewHistogram(), - FailedTxs: discard.NewCounter(), - RejectedTxs: discard.NewCounter(), - EvictedTxs: discard.NewCounter(), - RecheckTimes: discard.NewCounter(), - } -} diff --git a/internal/p2p/metrics.gen.go b/internal/p2p/metrics.gen.go new file mode 100644 index 000000000..cbfba29d9 --- /dev/null +++ b/internal/p2p/metrics.gen.go @@ -0,0 +1,86 @@ +// Code generated by metricsgen. DO NOT EDIT. + +package p2p + +import ( + "github.com/go-kit/kit/metrics/discard" + prometheus "github.com/go-kit/kit/metrics/prometheus" + stdprometheus "github.com/prometheus/client_golang/prometheus" +) + +func PrometheusMetrics(namespace string, labelsAndValues ...string) *Metrics { + labels := []string{} + for i := 0; i < len(labelsAndValues); i += 2 { + labels = append(labels, labelsAndValues[i]) + } + return &Metrics{ + Peers: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "peers", + Help: "Number of peers.", + }, labels).With(labelsAndValues...), + PeerReceiveBytesTotal: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "peer_receive_bytes_total", + Help: "Number of bytes per channel received from a given peer.", + }, append(labels, "peer_id", "chID", "message_type")).With(labelsAndValues...), + PeerSendBytesTotal: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "peer_send_bytes_total", + Help: "Number of bytes per channel sent to a given peer.", + }, append(labels, "peer_id", "chID", "message_type")).With(labelsAndValues...), + PeerPendingSendBytes: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "peer_pending_send_bytes", + Help: "Number of bytes pending being sent to a given peer.", + }, append(labels, "peer_id")).With(labelsAndValues...), + RouterPeerQueueRecv: prometheus.NewHistogramFrom(stdprometheus.HistogramOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "router_peer_queue_recv", + Help: "The time taken to read off of a peer's queue before sending on the connection.", + }, labels).With(labelsAndValues...), + RouterPeerQueueSend: prometheus.NewHistogramFrom(stdprometheus.HistogramOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "router_peer_queue_send", + Help: "The time taken to send on a peer's queue which will later be read and sent on the connection.", + }, labels).With(labelsAndValues...), + RouterChannelQueueSend: prometheus.NewHistogramFrom(stdprometheus.HistogramOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "router_channel_queue_send", + Help: "The time taken to send on a p2p channel's queue which will later be consued by the corresponding reactor/service.", + }, labels).With(labelsAndValues...), + PeerQueueDroppedMsgs: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "router_channel_queue_dropped_msgs", + Help: "The number of messages dropped from a peer's queue for a specific p2p Channel.", + }, append(labels, "ch_id")).With(labelsAndValues...), + PeerQueueMsgSize: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "peer_queue_msg_size", + Help: "The size of messages sent over a peer's queue for a specific p2p Channel.", + }, append(labels, "ch_id")).With(labelsAndValues...), + } +} + +func NopMetrics() *Metrics { + return &Metrics{ + Peers: discard.NewGauge(), + PeerReceiveBytesTotal: discard.NewCounter(), + PeerSendBytesTotal: discard.NewCounter(), + PeerPendingSendBytes: discard.NewGauge(), + RouterPeerQueueRecv: discard.NewHistogram(), + RouterPeerQueueSend: discard.NewHistogram(), + RouterChannelQueueSend: discard.NewHistogram(), + PeerQueueDroppedMsgs: discard.NewCounter(), + PeerQueueMsgSize: discard.NewGauge(), + } +} diff --git a/internal/p2p/metrics.go b/internal/p2p/metrics.go index 2780d221e..b45f128e5 100644 --- a/internal/p2p/metrics.go +++ b/internal/p2p/metrics.go @@ -7,9 +7,6 @@ import ( "sync" "github.com/go-kit/kit/metrics" - "github.com/go-kit/kit/metrics/discard" - "github.com/go-kit/kit/metrics/prometheus" - stdprometheus "github.com/prometheus/client_golang/prometheus" ) const ( @@ -25,140 +22,55 @@ var ( valueToLabelRegexp = regexp.MustCompile(`\*?(\w+)\.(.*)`) ) +//go:generate go run ../../scripts/metricsgen -struct=Metrics + // Metrics contains metrics exposed by this package. type Metrics struct { // Number of peers. Peers metrics.Gauge - // Number of bytes received from a given peer. - PeerReceiveBytesTotal metrics.Counter - // Number of bytes sent to a given peer. - PeerSendBytesTotal metrics.Counter - // Pending bytes to be sent to a given peer. - PeerPendingSendBytes metrics.Gauge + // Number of bytes per channel received from a given peer. + PeerReceiveBytesTotal metrics.Counter `metrics_labels:"peer_id, chID, message_type"` + // Number of bytes per channel sent to a given peer. + PeerSendBytesTotal metrics.Counter `metrics_labels:"peer_id, chID, message_type"` + // Number of bytes pending being sent to a given peer. + PeerPendingSendBytes metrics.Gauge `metrics_labels:"peer_id"` // RouterPeerQueueRecv defines the time taken to read off of a peer's queue // before sending on the connection. + //metrics:The time taken to read off of a peer's queue before sending on the connection. RouterPeerQueueRecv metrics.Histogram // RouterPeerQueueSend defines the time taken to send on a peer's queue which // will later be read and sent on the connection (see RouterPeerQueueRecv). + //metrics:The time taken to send on a peer's queue which will later be read and sent on the connection. RouterPeerQueueSend metrics.Histogram // RouterChannelQueueSend defines the time taken to send on a p2p channel's // queue which will later be consued by the corresponding reactor/service. + //metrics:The time taken to send on a p2p channel's queue which will later be consued by the corresponding reactor/service. RouterChannelQueueSend metrics.Histogram // PeerQueueDroppedMsgs defines the number of messages dropped from a peer's // queue for a specific flow (i.e. Channel). - PeerQueueDroppedMsgs metrics.Counter + //metrics:The number of messages dropped from a peer's queue for a specific p2p Channel. + PeerQueueDroppedMsgs metrics.Counter `metrics_labels:"ch_id" metrics_name:"router_channel_queue_dropped_msgs"` // PeerQueueMsgSize defines the average size of messages sent over a peer's // queue for a specific flow (i.e. Channel). - PeerQueueMsgSize metrics.Gauge + //metrics:The size of messages sent over a peer's queue for a specific p2p Channel. + PeerQueueMsgSize metrics.Gauge `metrics_labels:"ch_id" metric_name:"router_channel_queue_msg_size"` +} +type metricsLabelCache struct { mtx *sync.RWMutex messageLabelNames map[reflect.Type]string } -// 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{ - Peers: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: namespace, - Subsystem: MetricsSubsystem, - Name: "peers", - Help: "Number of peers.", - }, labels).With(labelsAndValues...), - - PeerReceiveBytesTotal: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ - Namespace: namespace, - Subsystem: MetricsSubsystem, - Name: "peer_receive_bytes_total", - Help: "Number of bytes received from a given peer.", - }, append(labels, "peer_id", "chID", "message_type")).With(labelsAndValues...), - - PeerSendBytesTotal: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ - Namespace: namespace, - Subsystem: MetricsSubsystem, - Name: "peer_send_bytes_total", - Help: "Number of bytes sent to a given peer.", - }, append(labels, "peer_id", "chID", "message_type")).With(labelsAndValues...), - - PeerPendingSendBytes: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: namespace, - Subsystem: MetricsSubsystem, - Name: "peer_pending_send_bytes", - Help: "Number of pending bytes to be sent to a given peer.", - }, append(labels, "peer_id")).With(labelsAndValues...), - - RouterPeerQueueRecv: prometheus.NewHistogramFrom(stdprometheus.HistogramOpts{ - Namespace: namespace, - Subsystem: MetricsSubsystem, - Name: "router_peer_queue_recv", - Help: "The time taken to read off of a peer's queue before sending on the connection.", - }, labels).With(labelsAndValues...), - - RouterPeerQueueSend: prometheus.NewHistogramFrom(stdprometheus.HistogramOpts{ - Namespace: namespace, - Subsystem: MetricsSubsystem, - Name: "router_peer_queue_send", - Help: "The time taken to send on a peer's queue which will later be read and sent on the connection (see RouterPeerQueueRecv).", - }, labels).With(labelsAndValues...), - - RouterChannelQueueSend: prometheus.NewHistogramFrom(stdprometheus.HistogramOpts{ - Namespace: namespace, - Subsystem: MetricsSubsystem, - Name: "router_channel_queue_send", - Help: "The time taken to send on a p2p channel's queue which will later be consued by the corresponding reactor/service.", - }, labels).With(labelsAndValues...), - - PeerQueueDroppedMsgs: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ - Namespace: namespace, - Subsystem: MetricsSubsystem, - Name: "router_channel_queue_dropped_msgs", - Help: "The number of messages dropped from a peer's queue for a specific p2p Channel.", - }, append(labels, "ch_id")).With(labelsAndValues...), - - PeerQueueMsgSize: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: namespace, - Subsystem: MetricsSubsystem, - Name: "router_channel_queue_msg_size", - Help: "The size of messages sent over a peer's queue for a specific p2p Channel.", - }, append(labels, "ch_id")).With(labelsAndValues...), - - mtx: &sync.RWMutex{}, - messageLabelNames: map[reflect.Type]string{}, - } -} - -// NopMetrics returns no-op Metrics. -func NopMetrics() *Metrics { - return &Metrics{ - Peers: discard.NewGauge(), - PeerReceiveBytesTotal: discard.NewCounter(), - PeerSendBytesTotal: discard.NewCounter(), - PeerPendingSendBytes: discard.NewGauge(), - RouterPeerQueueRecv: discard.NewHistogram(), - RouterPeerQueueSend: discard.NewHistogram(), - RouterChannelQueueSend: discard.NewHistogram(), - PeerQueueDroppedMsgs: discard.NewCounter(), - PeerQueueMsgSize: discard.NewGauge(), - mtx: &sync.RWMutex{}, - messageLabelNames: map[reflect.Type]string{}, - } -} - // ValueToMetricLabel is a method that is used to produce a prometheus label value of the golang // type that is passed in. // This method uses a map on the Metrics struct so that each label name only needs // to be produced once to prevent expensive string operations. -func (m *Metrics) ValueToMetricLabel(i interface{}) string { +func (m *metricsLabelCache) ValueToMetricLabel(i interface{}) string { t := reflect.TypeOf(i) m.mtx.RLock() @@ -176,3 +88,10 @@ func (m *Metrics) ValueToMetricLabel(i interface{}) string { m.messageLabelNames[t] = l return l } + +func newMetricsLabelCache() *metricsLabelCache { + return &metricsLabelCache{ + mtx: &sync.RWMutex{}, + messageLabelNames: map[reflect.Type]string{}, + } +} diff --git a/internal/p2p/metrics_test.go b/internal/p2p/metrics_test.go index 839786d91..98523fe82 100644 --- a/internal/p2p/metrics_test.go +++ b/internal/p2p/metrics_test.go @@ -9,12 +9,12 @@ import ( ) func TestValueToMetricsLabel(t *testing.T) { - m := NopMetrics() + lc := newMetricsLabelCache() r := &p2p.PexResponse{} - str := m.ValueToMetricLabel(r) + str := lc.ValueToMetricLabel(r) assert.Equal(t, "p2p_PexResponse", str) // subsequent calls to the function should produce the same result - str = m.ValueToMetricLabel(r) + str = lc.ValueToMetricLabel(r) assert.Equal(t, "p2p_PexResponse", str) } diff --git a/internal/p2p/pqueue.go b/internal/p2p/pqueue.go index 21c950dfb..268daa8de 100644 --- a/internal/p2p/pqueue.go +++ b/internal/p2p/pqueue.go @@ -70,6 +70,7 @@ var _ queue = (*pqScheduler)(nil) type pqScheduler struct { logger log.Logger metrics *Metrics + lc *metricsLabelCache size uint sizes map[uint]uint // cumulative priority sizes pq *priorityQueue @@ -88,6 +89,7 @@ type pqScheduler struct { func newPQScheduler( logger log.Logger, m *Metrics, + lc *metricsLabelCache, chDescs []*ChannelDescriptor, enqueueBuf, dequeueBuf, capacity uint, ) *pqScheduler { @@ -117,6 +119,7 @@ func newPQScheduler( return &pqScheduler{ logger: logger.With("router", "scheduler"), metrics: m, + lc: lc, chDescs: chDescsCopy, capacity: capacity, chPriorities: chPriorities, @@ -251,7 +254,7 @@ func (s *pqScheduler) process(ctx context.Context) { s.metrics.PeerSendBytesTotal.With( "chID", chIDStr, "peer_id", string(pqEnv.envelope.To), - "message_type", s.metrics.ValueToMetricLabel(pqEnv.envelope.Message)).Add(float64(pqEnv.size)) + "message_type", s.lc.ValueToMetricLabel(pqEnv.envelope.Message)).Add(float64(pqEnv.size)) s.metrics.PeerPendingSendBytes.With( "peer_id", string(pqEnv.envelope.To)).Add(float64(-pqEnv.size)) select { diff --git a/internal/p2p/pqueue_test.go b/internal/p2p/pqueue_test.go index 22ecbcecb..d1057ac7e 100644 --- a/internal/p2p/pqueue_test.go +++ b/internal/p2p/pqueue_test.go @@ -17,7 +17,7 @@ func TestCloseWhileDequeueFull(t *testing.T) { chDescs := []*ChannelDescriptor{ {ID: 0x01, Priority: 1}, } - pqueue := newPQScheduler(log.NewNopLogger(), NopMetrics(), chDescs, uint(enqueueLength), 1, 120) + pqueue := newPQScheduler(log.NewNopLogger(), NopMetrics(), newMetricsLabelCache(), chDescs, uint(enqueueLength), 1, 120) for i := 0; i < enqueueLength; i++ { pqueue.enqueue() <- Envelope{ diff --git a/internal/p2p/router.go b/internal/p2p/router.go index 459be7975..a9a01f3c7 100644 --- a/internal/p2p/router.go +++ b/internal/p2p/router.go @@ -148,7 +148,9 @@ type Router struct { *service.BaseService logger log.Logger - metrics *Metrics + metrics *Metrics + lc *metricsLabelCache + options RouterOptions privKey crypto.PrivKey peerManager *PeerManager @@ -193,6 +195,7 @@ func NewRouter( router := &Router{ logger: logger, metrics: metrics, + lc: newMetricsLabelCache(), privKey: privKey, nodeInfoProducer: nodeInfoProducer, connTracker: newConnTracker( @@ -226,7 +229,7 @@ func (r *Router) createQueueFactory(ctx context.Context) (func(int) queue, error size++ } - q := newPQScheduler(r.logger, r.metrics, r.chDescs, uint(size)/2, uint(size)/2, defaultCapacity) + q := newPQScheduler(r.logger, r.metrics, r.lc, r.chDescs, uint(size)/2, uint(size)/2, defaultCapacity) q.start(ctx) return q }, nil @@ -839,7 +842,7 @@ func (r *Router) receivePeer(ctx context.Context, peerID types.NodeID, conn Conn r.metrics.PeerReceiveBytesTotal.With( "chID", fmt.Sprint(chID), "peer_id", string(peerID), - "message_type", r.metrics.ValueToMetricLabel(msg)).Add(float64(proto.Size(msg))) + "message_type", r.lc.ValueToMetricLabel(msg)).Add(float64(proto.Size(msg))) r.metrics.RouterChannelQueueSend.Observe(time.Since(start).Seconds()) r.logger.Debug("received message", "peer", peerID, "message", msg) diff --git a/internal/proxy/metrics.gen.go b/internal/proxy/metrics.gen.go new file mode 100644 index 000000000..ea483f83d --- /dev/null +++ b/internal/proxy/metrics.gen.go @@ -0,0 +1,32 @@ +// Code generated by metricsgen. DO NOT EDIT. + +package proxy + +import ( + "github.com/go-kit/kit/metrics/discard" + prometheus "github.com/go-kit/kit/metrics/prometheus" + stdprometheus "github.com/prometheus/client_golang/prometheus" +) + +func PrometheusMetrics(namespace string, labelsAndValues ...string) *Metrics { + labels := []string{} + for i := 0; i < len(labelsAndValues); i += 2 { + labels = append(labels, labelsAndValues[i]) + } + return &Metrics{ + MethodTiming: prometheus.NewHistogramFrom(stdprometheus.HistogramOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "method_timing", + Help: "Timing for each ABCI method.", + + Buckets: []float64{.0001, .0004, .002, .009, .02, .1, .65, 2, 6, 25}, + }, append(labels, "method", "type")).With(labelsAndValues...), + } +} + +func NopMetrics() *Metrics { + return &Metrics{ + MethodTiming: discard.NewHistogram(), + } +} diff --git a/internal/proxy/metrics.go b/internal/proxy/metrics.go index 99bd7d7b0..b95687a03 100644 --- a/internal/proxy/metrics.go +++ b/internal/proxy/metrics.go @@ -2,9 +2,6 @@ package proxy import ( "github.com/go-kit/kit/metrics" - "github.com/go-kit/kit/metrics/discard" - "github.com/go-kit/kit/metrics/prometheus" - stdprometheus "github.com/prometheus/client_golang/prometheus" ) const ( @@ -13,35 +10,10 @@ const ( MetricsSubsystem = "abci_connection" ) +//go:generate go run ../../scripts/metricsgen -struct=Metrics + // Metrics contains the prometheus metrics exposed by the proxy package. type Metrics struct { - MethodTiming metrics.Histogram -} - -// PrometheusMetrics constructs a Metrics instance that collects metrics samples. -// The resulting metrics will be prefixed with namespace and labeled with the -// defaultLabelsAndValues. defaultLabelsAndValues must be a list of string pairs -// where the first of each pair is the label and the second is the value. -func PrometheusMetrics(namespace string, defaultLabelsAndValues ...string) *Metrics { - defaultLabels := []string{} - for i := 0; i < len(defaultLabelsAndValues); i += 2 { - defaultLabels = append(defaultLabels, defaultLabelsAndValues[i]) - } - return &Metrics{ - MethodTiming: prometheus.NewHistogramFrom(stdprometheus.HistogramOpts{ - Namespace: namespace, - Subsystem: MetricsSubsystem, - Name: "method_timing", - Help: "ABCI Method Timing", - Buckets: []float64{.0001, .0004, .002, .009, .02, .1, .65, 2, 6, 25}, - }, append(defaultLabels, []string{"method", "type"}...)).With(defaultLabelsAndValues...), - } -} - -// NopMetrics constructs a Metrics instance that discards all samples and is suitable -// for testing. -func NopMetrics() *Metrics { - return &Metrics{ - MethodTiming: discard.NewHistogram(), - } + // Timing for each ABCI method. + MethodTiming metrics.Histogram `metrics_bucketsizes:".0001,.0004,.002,.009,.02,.1,.65,2,6,25" metrics_labels:"method, type"` } diff --git a/internal/state/indexer/metrics.go b/internal/state/indexer/metrics.go index 0b92b879e..93dd0dc9e 100644 --- a/internal/state/indexer/metrics.go +++ b/internal/state/indexer/metrics.go @@ -4,7 +4,7 @@ import ( "github.com/go-kit/kit/metrics" ) -//go:generate go run github.com/tendermint/tendermint/scripts/metricsgen -struct=Metrics +//go:generate go run ../../../scripts/metricsgen -struct=Metrics // MetricsSubsystem is a the subsystem label for the indexer package. const MetricsSubsystem = "indexer" diff --git a/internal/state/metrics.gen.go b/internal/state/metrics.gen.go new file mode 100644 index 000000000..eb8ca9f78 --- /dev/null +++ b/internal/state/metrics.gen.go @@ -0,0 +1,46 @@ +// Code generated by metricsgen. DO NOT EDIT. + +package state + +import ( + "github.com/go-kit/kit/metrics/discard" + prometheus "github.com/go-kit/kit/metrics/prometheus" + stdprometheus "github.com/prometheus/client_golang/prometheus" +) + +func PrometheusMetrics(namespace string, labelsAndValues ...string) *Metrics { + labels := []string{} + for i := 0; i < len(labelsAndValues); i += 2 { + labels = append(labels, labelsAndValues[i]) + } + return &Metrics{ + BlockProcessingTime: prometheus.NewHistogramFrom(stdprometheus.HistogramOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "block_processing_time", + Help: "Time between BeginBlock and EndBlock.", + + Buckets: stdprometheus.LinearBuckets(1, 10, 10), + }, labels).With(labelsAndValues...), + ConsensusParamUpdates: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "consensus_param_updates", + Help: "Number of consensus parameter updates returned by the application since process start.", + }, labels).With(labelsAndValues...), + ValidatorSetUpdates: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "validator_set_updates", + Help: "Number of validator set updates returned by the application since process start.", + }, labels).With(labelsAndValues...), + } +} + +func NopMetrics() *Metrics { + return &Metrics{ + BlockProcessingTime: discard.NewHistogram(), + ConsensusParamUpdates: discard.NewCounter(), + ValidatorSetUpdates: discard.NewCounter(), + } +} diff --git a/internal/state/metrics.go b/internal/state/metrics.go index 1d4a13b94..3663121a6 100644 --- a/internal/state/metrics.go +++ b/internal/state/metrics.go @@ -2,9 +2,6 @@ package state import ( "github.com/go-kit/kit/metrics" - "github.com/go-kit/kit/metrics/discard" - "github.com/go-kit/kit/metrics/prometheus" - stdprometheus "github.com/prometheus/client_golang/prometheus" ) const ( @@ -13,59 +10,20 @@ const ( MetricsSubsystem = "state" ) +//go:generate go run ../../scripts/metricsgen -struct=Metrics + // Metrics contains metrics exposed by this package. type Metrics struct { // Time between BeginBlock and EndBlock. - BlockProcessingTime metrics.Histogram + BlockProcessingTime metrics.Histogram `metrics_buckettype:"lin" metrics_bucketsizes:"1,10,10"` // ConsensusParamUpdates is the total number of times the application has // udated the consensus params since process start. + //metrics:Number of consensus parameter updates returned by the application since process start. ConsensusParamUpdates metrics.Counter // ValidatorSetUpdates is the total number of times the application has // udated the validator set since process start. + //metrics:Number of validator set updates returned by the application since process start. ValidatorSetUpdates metrics.Counter } - -// 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{ - BlockProcessingTime: prometheus.NewHistogramFrom(stdprometheus.HistogramOpts{ - Namespace: namespace, - Subsystem: MetricsSubsystem, - Name: "block_processing_time", - Help: "Time between BeginBlock and EndBlock in ms.", - Buckets: stdprometheus.LinearBuckets(1, 10, 10), - }, labels).With(labelsAndValues...), - ConsensusParamUpdates: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ - Namespace: namespace, - Subsystem: MetricsSubsystem, - Name: "consensus_param_updates", - Help: "The total number of times the application as updated the consensus " + - "parameters since process start.", - }, labels).With(labelsAndValues...), - - ValidatorSetUpdates: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ - Namespace: namespace, - Subsystem: MetricsSubsystem, - Name: "validator_set_updates", - Help: "The total number of times the application as updated the validator " + - "set since process start.", - }, labels).With(labelsAndValues...), - } -} - -// NopMetrics returns no-op Metrics. -func NopMetrics() *Metrics { - return &Metrics{ - BlockProcessingTime: discard.NewHistogram(), - ConsensusParamUpdates: discard.NewCounter(), - ValidatorSetUpdates: discard.NewCounter(), - } -} diff --git a/internal/statesync/metrics.gen.go b/internal/statesync/metrics.gen.go new file mode 100644 index 000000000..b4d5caa12 --- /dev/null +++ b/internal/statesync/metrics.gen.go @@ -0,0 +1,72 @@ +// Code generated by metricsgen. DO NOT EDIT. + +package statesync + +import ( + "github.com/go-kit/kit/metrics/discard" + prometheus "github.com/go-kit/kit/metrics/prometheus" + stdprometheus "github.com/prometheus/client_golang/prometheus" +) + +func PrometheusMetrics(namespace string, labelsAndValues ...string) *Metrics { + labels := []string{} + for i := 0; i < len(labelsAndValues); i += 2 { + labels = append(labels, labelsAndValues[i]) + } + return &Metrics{ + TotalSnapshots: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "total_snapshots", + Help: "The total number of snapshots discovered.", + }, labels).With(labelsAndValues...), + ChunkProcessAvgTime: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "chunk_process_avg_time", + Help: "The average processing time per chunk.", + }, labels).With(labelsAndValues...), + SnapshotHeight: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "snapshot_height", + Help: "The height of the current snapshot the has been processed.", + }, labels).With(labelsAndValues...), + SnapshotChunk: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "snapshot_chunk", + Help: "The current number of chunks that have been processed.", + }, labels).With(labelsAndValues...), + SnapshotChunkTotal: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "snapshot_chunk_total", + Help: "The total number of chunks in the current snapshot.", + }, labels).With(labelsAndValues...), + BackFilledBlocks: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "back_filled_blocks", + Help: "The current number of blocks that have been back-filled.", + }, labels).With(labelsAndValues...), + BackFillBlocksTotal: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "back_fill_blocks_total", + Help: "The total number of blocks that need to be back-filled.", + }, labels).With(labelsAndValues...), + } +} + +func NopMetrics() *Metrics { + return &Metrics{ + TotalSnapshots: discard.NewCounter(), + ChunkProcessAvgTime: discard.NewGauge(), + SnapshotHeight: discard.NewGauge(), + SnapshotChunk: discard.NewCounter(), + SnapshotChunkTotal: discard.NewGauge(), + BackFilledBlocks: discard.NewCounter(), + BackFillBlocksTotal: discard.NewGauge(), + } +} diff --git a/internal/statesync/metrics.go b/internal/statesync/metrics.go index fb134f580..a8a3af915 100644 --- a/internal/statesync/metrics.go +++ b/internal/statesync/metrics.go @@ -2,9 +2,6 @@ package statesync import ( "github.com/go-kit/kit/metrics" - "github.com/go-kit/kit/metrics/discard" - "github.com/go-kit/kit/metrics/prometheus" - stdprometheus "github.com/prometheus/client_golang/prometheus" ) const ( @@ -12,80 +9,22 @@ const ( MetricsSubsystem = "statesync" ) +//go:generate go run ../../scripts/metricsgen -struct=Metrics + // Metrics contains metrics exposed by this package. type Metrics struct { - TotalSnapshots metrics.Counter + // The total number of snapshots discovered. + TotalSnapshots metrics.Counter + // The average processing time per chunk. ChunkProcessAvgTime metrics.Gauge - SnapshotHeight metrics.Gauge - SnapshotChunk metrics.Counter - SnapshotChunkTotal metrics.Gauge - BackFilledBlocks metrics.Counter + // The height of the current snapshot the has been processed. + SnapshotHeight metrics.Gauge + // The current number of chunks that have been processed. + SnapshotChunk metrics.Counter + // The total number of chunks in the current snapshot. + SnapshotChunkTotal metrics.Gauge + // The current number of blocks that have been back-filled. + BackFilledBlocks metrics.Counter + // The total number of blocks that need to be back-filled. BackFillBlocksTotal metrics.Gauge } - -// 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{ - TotalSnapshots: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ - Namespace: namespace, - Subsystem: MetricsSubsystem, - Name: "total_snapshots", - Help: "The total number of snapshots discovered.", - }, labels).With(labelsAndValues...), - ChunkProcessAvgTime: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: namespace, - Subsystem: MetricsSubsystem, - Name: "chunk_process_avg_time", - Help: "The average processing time per chunk.", - }, labels).With(labelsAndValues...), - SnapshotHeight: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: namespace, - Subsystem: MetricsSubsystem, - Name: "snapshot_height", - Help: "The height of the current snapshot the has been processed.", - }, labels).With(labelsAndValues...), - SnapshotChunk: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ - Namespace: namespace, - Subsystem: MetricsSubsystem, - Name: "snapshot_chunk", - Help: "The current number of chunks that have been processed.", - }, labels).With(labelsAndValues...), - SnapshotChunkTotal: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: namespace, - Subsystem: MetricsSubsystem, - Name: "snapshot_chunks_total", - Help: "The total number of chunks in the current snapshot.", - }, labels).With(labelsAndValues...), - BackFilledBlocks: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ - Namespace: namespace, - Subsystem: MetricsSubsystem, - Name: "backfilled_blocks", - Help: "The current number of blocks that have been back-filled.", - }, labels).With(labelsAndValues...), - BackFillBlocksTotal: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ - Namespace: namespace, - Subsystem: MetricsSubsystem, - Name: "backfilled_blocks_total", - Help: "The total number of blocks that need to be back-filled.", - }, labels).With(labelsAndValues...), - } -} - -// NopMetrics returns no-op Metrics. -func NopMetrics() *Metrics { - return &Metrics{ - TotalSnapshots: discard.NewCounter(), - ChunkProcessAvgTime: discard.NewGauge(), - SnapshotHeight: discard.NewGauge(), - SnapshotChunk: discard.NewCounter(), - SnapshotChunkTotal: discard.NewGauge(), - BackFilledBlocks: discard.NewCounter(), - BackFillBlocksTotal: discard.NewGauge(), - } -} diff --git a/scripts/metricsgen/metricsgen.go b/scripts/metricsgen/metricsgen.go index 70cb36a77..0f564e66a 100644 --- a/scripts/metricsgen/metricsgen.go +++ b/scripts/metricsgen/metricsgen.go @@ -88,8 +88,8 @@ func PrometheusMetrics(namespace string, labelsAndValues...string) *Metrics { {{- if eq (len $metric.Labels) 0 }} }, labels).With(labelsAndValues...), {{ else }} - }, append(labels, {{$metric.Labels | printf "%q" }})).With(labelsAndValues...), - {{- end }} + }, append(labels, {{$metric.Labels}})).With(labelsAndValues...), + {{ end }} {{- end }} } } @@ -249,14 +249,8 @@ func findMetricsStruct(files map[string]*ast.File, structName string) (*ast.Stru } func parseMetricField(f *ast.Field) ParsedMetricField { - var comment string - if f.Doc != nil { - for _, c := range f.Doc.List { - comment += strings.TrimPrefix(c.Text, "// ") - } - } pmf := ParsedMetricField{ - Description: comment, + Description: extractHelpMessage(f.Doc), MetricName: extractFieldName(f.Names[0].String(), f.Tag), FieldName: f.Names[0].String(), TypeName: extractTypeName(f.Type), @@ -272,6 +266,21 @@ func extractTypeName(e ast.Expr) string { return strings.TrimPrefix(path.Ext(types.ExprString(e)), ".") } +func extractHelpMessage(cg *ast.CommentGroup) string { + if cg == nil { + return "" + } + var help []string //nolint: prealloc + for _, c := range cg.List { + mt := strings.TrimPrefix(c.Text, "//metrics:") + if mt != c.Text { + return strings.TrimSpace(mt) + } + help = append(help, strings.TrimSpace(strings.TrimPrefix(c.Text, "//"))) + } + return strings.Join(help, " ") +} + func isMetric(e ast.Expr, mPkgName string) bool { return strings.Contains(types.ExprString(e), fmt.Sprintf("%s.", mPkgName)) } @@ -280,7 +289,11 @@ func extractLabels(bl *ast.BasicLit) string { if bl != nil { t := reflect.StructTag(strings.Trim(bl.Value, "`")) if v := t.Get(labelsTag); v != "" { - return v + var res []string + for _, s := range strings.Split(v, ",") { + res = append(res, strconv.Quote(strings.TrimSpace(s))) + } + return strings.Join(res, ",") } } return "" diff --git a/scripts/metricsgen/metricsgen_test.go b/scripts/metricsgen/metricsgen_test.go index 83251e651..a925b591d 100644 --- a/scripts/metricsgen/metricsgen_test.go +++ b/scripts/metricsgen/metricsgen_test.go @@ -149,7 +149,7 @@ func TestParseMetricsStruct(t *testing.T) { { name: "metric labels", metricsStruct: "type Metrics struct {\n" + - "myCounter metrics.Counter `metrics_labels:\"label1, label2\"`\n" + + "myCounter metrics.Counter `metrics_labels:\"label1,label2\"`\n" + "}", expected: metricsgen.TemplateData{ Package: pkgName, @@ -158,7 +158,7 @@ func TestParseMetricsStruct(t *testing.T) { TypeName: "Counter", FieldName: "myCounter", MetricName: "my_counter", - Labels: "label1, label2", + Labels: "\"label1\",\"label2\"", }, }, }, diff --git a/scripts/metricsgen/testdata/commented/metrics.gen.go b/scripts/metricsgen/testdata/commented/metrics.gen.go index 038da3d46..c1346da38 100644 --- a/scripts/metricsgen/testdata/commented/metrics.gen.go +++ b/scripts/metricsgen/testdata/commented/metrics.gen.go @@ -18,7 +18,7 @@ func PrometheusMetrics(namespace string, labelsAndValues ...string) *Metrics { Namespace: namespace, Subsystem: MetricsSubsystem, Name: "field", - Help: "Height of the chain.We expect multi-line comments to parse correctly.", + Help: "Height of the chain. We expect multi-line comments to parse correctly.", }, labels).With(labelsAndValues...), } } diff --git a/scripts/metricsgen/testdata/tags/metrics.gen.go b/scripts/metricsgen/testdata/tags/metrics.gen.go index 7ac292d3c..43779c7a1 100644 --- a/scripts/metricsgen/testdata/tags/metrics.gen.go +++ b/scripts/metricsgen/testdata/tags/metrics.gen.go @@ -19,7 +19,8 @@ func PrometheusMetrics(namespace string, labelsAndValues ...string) *Metrics { Subsystem: MetricsSubsystem, Name: "with_labels", Help: "", - }, append(labels, "step,time")).With(labelsAndValues...), WithExpBuckets: prometheus.NewHistogramFrom(stdprometheus.HistogramOpts{ + }, append(labels, "step", "time")).With(labelsAndValues...), + WithExpBuckets: prometheus.NewHistogramFrom(stdprometheus.HistogramOpts{ Namespace: namespace, Subsystem: MetricsSubsystem, Name: "with_exp_buckets",