Skip to content

Commit 4e9b1c5

Browse files
authored
Merge pull request #8030 from onflow/yurii/7391-extend-collection-building-metrics
[Overload Resilience] Metrics for prioritized transactions
2 parents 1d72062 + b4ac007 commit 4e9b1c5

File tree

5 files changed

+61
-39
lines changed

5 files changed

+61
-39
lines changed

module/builder/collection/builder.go

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ func (b *Builder) BuildOn(parentID flow.Identifier, setter func(*flow.HeaderBody
191191
// STEP 2: build a payload of valid transactions, while at the same
192192
// time figuring out the correct reference block ID for the collection.
193193
span, _ = b.tracer.StartSpanFromContext(ctx, trace.COLBuildOnCreatePayload)
194-
payload, err := b.buildPayload(buildCtx)
194+
payload, priorityTransactionsCount, err := b.buildPayload(buildCtx)
195195
span.End()
196196
if err != nil {
197197
return nil, fmt.Errorf("could not build payload: %w", err)
@@ -216,6 +216,8 @@ func (b *Builder) BuildOn(parentID flow.Identifier, setter func(*flow.HeaderBody
216216
return nil, fmt.Errorf("could not build cluster block: %w", err)
217217
}
218218

219+
b.metrics.ClusterBlockCreated(block, priorityTransactionsCount)
220+
219221
blockProposal, err := cluster.NewProposal(
220222
cluster.UntrustedProposal{
221223
Block: *block,
@@ -403,8 +405,13 @@ func (b *Builder) populateFinalizedAncestryLookup(lctx lockctx.Proof, ctx *block
403405

404406
// buildPayload constructs a valid payload based on transactions available in the mempool.
405407
// If the mempool is empty, an empty payload will be returned.
408+
// Return values:
409+
// - *cluster.Payload: the payload that has been built.
410+
// - uint: number of prioritized transactions included in the payload.
411+
// - error: exception if failed to build the payload.
412+
//
406413
// No errors are expected during normal operation.
407-
func (b *Builder) buildPayload(buildCtx *blockBuildContext) (*cluster.Payload, error) {
414+
func (b *Builder) buildPayload(buildCtx *blockBuildContext) (*cluster.Payload, uint, error) {
408415
lookup := buildCtx.lookup
409416
limiter := buildCtx.limiter
410417
config := buildCtx.config
@@ -469,7 +476,7 @@ func (b *Builder) buildPayload(buildCtx *blockBuildContext) (*cluster.Payload, e
469476
continue // in case we are configured with liberal transaction ingest rules
470477
}
471478
if err != nil {
472-
return nil, fmt.Errorf("could not retrieve reference header: %w", err)
479+
return nil, 0, fmt.Errorf("could not retrieve reference header: %w", err)
473480
}
474481

475482
// disallow un-finalized reference blocks, and reference blocks beyond the cluster's operating epoch
@@ -480,7 +487,7 @@ func (b *Builder) buildPayload(buildCtx *blockBuildContext) (*cluster.Payload, e
480487
// make sure the reference block is finalized and not orphaned
481488
blockIDFinalizedAtRefHeight, err := b.mainHeaders.BlockIDByHeight(refHeader.Height)
482489
if err != nil {
483-
return nil, fmt.Errorf("could not check that reference block (id=%x) for transaction (id=%x) is finalized: %w", tx.ReferenceBlockID, txID, err)
490+
return nil, 0, fmt.Errorf("could not check that reference block (id=%x) for transaction (id=%x) is finalized: %w", tx.ReferenceBlockID, txID, err)
484491
}
485492
if blockIDFinalizedAtRefHeight != tx.ReferenceBlockID {
486493
// the transaction references an orphaned block - it will never be valid
@@ -544,7 +551,7 @@ func (b *Builder) buildPayload(buildCtx *blockBuildContext) (*cluster.Payload, e
544551
// build the payload from the transactions
545552
collection, err := flow.NewCollection(flow.UntrustedCollection{Transactions: transactions})
546553
if err != nil {
547-
return nil, fmt.Errorf("could not build the collection from the transactions: %w", err)
554+
return nil, 0, fmt.Errorf("could not build the collection from the transactions: %w", err)
548555
}
549556

550557
payload, err := cluster.NewPayload(
@@ -554,9 +561,9 @@ func (b *Builder) buildPayload(buildCtx *blockBuildContext) (*cluster.Payload, e
554561
},
555562
)
556563
if err != nil {
557-
return nil, fmt.Errorf("could not build a payload: %w", err)
564+
return nil, 0, fmt.Errorf("could not build a payload: %w", err)
558565
}
559-
return payload, nil
566+
return payload, uint(len(priorityTransactions)), nil
560567
}
561568

562569
// buildHeader constructs the header for the cluster block being built.

module/metrics.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -615,15 +615,16 @@ type CollectionMetrics interface {
615615
// a tx->col span for the transaction.
616616
TransactionIngested(txID flow.Identifier)
617617

618-
// ClusterBlockProposed is called when a new collection is proposed by us or
619-
// any other node in the cluster.
620-
ClusterBlockProposed(block *cluster.Block)
621-
622618
// ClusterBlockFinalized is called when a collection is finalized.
623619
ClusterBlockFinalized(block *cluster.Block)
624620

625621
// CollectionMaxSize measures the current maximum size of a collection.
626622
CollectionMaxSize(size uint)
623+
624+
// ClusterBlockCreated informs about cluster blocks being PROPOSED by THIS NODE.
625+
// CAUTION: These metrics will represent a partial picture of cluster block creation across the network,
626+
// as each node will only report on cluster blocks where they are the proposer.
627+
ClusterBlockCreated(block *cluster.Block, priorityTxnsCount uint)
627628
}
628629

629630
type ConsensusMetrics interface {

module/metrics/collection.go

Lines changed: 36 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@ type CollectionCollector struct {
1515
transactionsIngested prometheus.Counter // tracks the number of ingested transactions
1616
finalizedHeight *prometheus.GaugeVec // tracks the finalized height
1717
maxCollectionSize prometheus.Gauge // tracks the maximum collection size
18-
proposals *prometheus.HistogramVec // tracks the number/size of PROPOSED collections
1918
guarantees *prometheus.HistogramVec // counts the number/size of FINALIZED collections
19+
collectionSize *prometheus.HistogramVec // number of transactions included ONLY in the cluster blocks proposed by this node
20+
priorityTxns *prometheus.HistogramVec // number of priority transactions included ONLY in cluster blocks proposed by this node
2021
}
2122

2223
var _ module.CollectionMetrics = (*CollectionCollector)(nil)
@@ -46,20 +47,28 @@ func NewCollectionCollector(tracer module.Tracer) *CollectionCollector {
4647
Help: "last used max collection size",
4748
}),
4849

49-
proposals: promauto.NewHistogramVec(prometheus.HistogramOpts{
50+
guarantees: promauto.NewHistogramVec(prometheus.HistogramOpts{
5051
Namespace: namespaceCollection,
5152
Subsystem: subsystemProposal,
5253
Buckets: []float64{1, 2, 5, 10, 20},
53-
Name: "proposals_size_transactions",
54-
Help: "size/number of proposed collections",
54+
Name: "guarantees_size_transactions",
55+
Help: "size/number of guaranteed/finalized collections",
5556
}, []string{LabelChain}),
5657

57-
guarantees: promauto.NewHistogramVec(prometheus.HistogramOpts{
58+
collectionSize: promauto.NewHistogramVec(prometheus.HistogramOpts{
5859
Namespace: namespaceCollection,
5960
Subsystem: subsystemProposal,
6061
Buckets: []float64{1, 2, 5, 10, 20},
61-
Name: "guarantees_size_transactions",
62-
Help: "size/number of guaranteed/finalized collections",
62+
Name: "collection_size",
63+
Help: "number of transactions included ONLY in the cluster blocks proposed by this node",
64+
}, []string{LabelChain}),
65+
66+
priorityTxns: promauto.NewHistogramVec(prometheus.HistogramOpts{
67+
Namespace: namespaceCollection,
68+
Subsystem: subsystemProposal,
69+
Buckets: []float64{1, 2, 5, 10, 20},
70+
Name: "priority_transactions",
71+
Help: "number of priority transactions included ONLY in cluster blocks proposed by this node",
6372
}, []string{LabelChain}),
6473
}
6574

@@ -72,33 +81,38 @@ func (cc *CollectionCollector) TransactionIngested(txID flow.Identifier) {
7281
cc.transactionsIngested.Inc()
7382
}
7483

75-
// ClusterBlockProposed tracks the size and number of proposals, as well as
76-
// starting the collection->guarantee span.
77-
func (cc *CollectionCollector) ClusterBlockProposed(block *cluster.Block) {
78-
collection := block.Payload.Collection.Light()
79-
80-
cc.proposals.
81-
With(prometheus.Labels{LabelChain: block.ChainID.String()}).
82-
Observe(float64(collection.Len()))
83-
}
84-
8584
// ClusterBlockFinalized updates the guaranteed collection size gauge and
8685
// finishes the tx->collection span for each constituent transaction.
8786
func (cc *CollectionCollector) ClusterBlockFinalized(block *cluster.Block) {
88-
collection := block.Payload.Collection.Light()
89-
chainID := block.ChainID
87+
chainID := block.ChainID.String()
9088

9189
cc.finalizedHeight.
92-
With(prometheus.Labels{LabelChain: chainID.String()}).
90+
With(prometheus.Labels{LabelChain: chainID}).
9391
Set(float64(block.Height))
9492
cc.guarantees.
9593
With(prometheus.Labels{
96-
LabelChain: chainID.String(),
94+
LabelChain: chainID,
9795
}).
98-
Observe(float64(collection.Len()))
96+
Observe(float64(block.Payload.Collection.Len()))
9997
}
10098

10199
// CollectionMaxSize measures the current maximum size of a collection.
102100
func (cc *CollectionCollector) CollectionMaxSize(size uint) {
103101
cc.maxCollectionSize.Set(float64(size))
104102
}
103+
104+
// ClusterBlockCreated informs about cluster block being proposed by this node.
105+
// CAUTION: These metrics will represent a partial picture of cluster block creation across the network,
106+
// as each node will only report on cluster blocks where they are the proposer.
107+
// It reports several metrics, specifically how many transactions have been included and how many of them are priority txns.
108+
func (cc *CollectionCollector) ClusterBlockCreated(block *cluster.Block, priorityTxnsCount uint) {
109+
chainID := block.ChainID.String()
110+
111+
cc.collectionSize.
112+
With(prometheus.Labels{LabelChain: chainID}).
113+
Observe(float64(block.Payload.Collection.Len()))
114+
115+
cc.priorityTxns.
116+
With(prometheus.Labels{LabelChain: chainID}).
117+
Observe(float64(priorityTxnsCount))
118+
}

module/metrics/noop.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,9 +125,9 @@ func (nc *NoopCollector) ValidatorProcessingDuration(duration time.Duration)
125125
func (nc *NoopCollector) PayloadProductionDuration(duration time.Duration) {}
126126
func (nc *NoopCollector) TimeoutCollectorsRange(uint64, uint64, int) {}
127127
func (nc *NoopCollector) TransactionIngested(txID flow.Identifier) {}
128-
func (nc *NoopCollector) ClusterBlockProposed(*cluster.Block) {}
129128
func (nc *NoopCollector) ClusterBlockFinalized(*cluster.Block) {}
130129
func (nc *NoopCollector) CollectionMaxSize(uint) {}
130+
func (nc *NoopCollector) ClusterBlockCreated(*cluster.Block, uint) {}
131131
func (nc *NoopCollector) StartCollectionToFinalized(collectionID flow.Identifier) {}
132132
func (nc *NoopCollector) FinishCollectionToFinalized(collectionID flow.Identifier) {}
133133
func (nc *NoopCollector) StartBlockToSeal(blockID flow.Identifier) {}

module/mock/collection_metrics.go

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)