github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/module/state_synchronization/indexer/collection_executed_metric.go (about)

     1  package indexer
     2  
     3  import (
     4  	"errors"
     5  	"time"
     6  
     7  	"github.com/rs/zerolog"
     8  
     9  	"github.com/onflow/flow-go/model/flow"
    10  	"github.com/onflow/flow-go/module"
    11  	"github.com/onflow/flow-go/module/mempool/stdmap"
    12  	"github.com/onflow/flow-go/storage"
    13  )
    14  
    15  var _ module.CollectionExecutedMetric = (*CollectionExecutedMetricImpl)(nil)
    16  
    17  // CollectionExecutedMetricImpl tracks metrics to measure how long it takes for tx to reach each step in their lifecycle
    18  type CollectionExecutedMetricImpl struct {
    19  	log zerolog.Logger // used to log relevant actions with context
    20  
    21  	accessMetrics              module.AccessMetrics
    22  	collectionsToMarkFinalized *stdmap.Times
    23  	collectionsToMarkExecuted  *stdmap.Times
    24  	blocksToMarkExecuted       *stdmap.Times
    25  
    26  	collections storage.Collections
    27  	blocks      storage.Blocks
    28  }
    29  
    30  func NewCollectionExecutedMetricImpl(
    31  	log zerolog.Logger,
    32  	accessMetrics module.AccessMetrics,
    33  	collectionsToMarkFinalized *stdmap.Times,
    34  	collectionsToMarkExecuted *stdmap.Times,
    35  	blocksToMarkExecuted *stdmap.Times,
    36  	collections storage.Collections,
    37  	blocks storage.Blocks,
    38  ) (*CollectionExecutedMetricImpl, error) {
    39  	return &CollectionExecutedMetricImpl{
    40  		log:                        log,
    41  		accessMetrics:              accessMetrics,
    42  		collectionsToMarkFinalized: collectionsToMarkFinalized,
    43  		collectionsToMarkExecuted:  collectionsToMarkExecuted,
    44  		blocksToMarkExecuted:       blocksToMarkExecuted,
    45  		collections:                collections,
    46  		blocks:                     blocks,
    47  	}, nil
    48  }
    49  
    50  // CollectionFinalized tracks collections to mark finalized
    51  func (c *CollectionExecutedMetricImpl) CollectionFinalized(light flow.LightCollection) {
    52  	if ti, found := c.collectionsToMarkFinalized.ByID(light.ID()); found {
    53  		for _, t := range light.Transactions {
    54  			c.accessMetrics.TransactionFinalized(t, ti)
    55  		}
    56  		c.collectionsToMarkFinalized.Remove(light.ID())
    57  	}
    58  }
    59  
    60  // CollectionExecuted tracks collections to mark executed
    61  func (c *CollectionExecutedMetricImpl) CollectionExecuted(light flow.LightCollection) {
    62  	if ti, found := c.collectionsToMarkExecuted.ByID(light.ID()); found {
    63  		for _, t := range light.Transactions {
    64  			c.accessMetrics.TransactionExecuted(t, ti)
    65  		}
    66  		c.collectionsToMarkExecuted.Remove(light.ID())
    67  	}
    68  }
    69  
    70  // BlockFinalized tracks finalized metric for block
    71  func (c *CollectionExecutedMetricImpl) BlockFinalized(block *flow.Block) {
    72  	// TODO: lookup actual finalization time by looking at the block finalizing `b`
    73  	now := time.Now().UTC()
    74  	blockID := block.ID()
    75  
    76  	// mark all transactions as finalized
    77  	// TODO: sample to reduce performance overhead
    78  	for _, g := range block.Payload.Guarantees {
    79  		l, err := c.collections.LightByID(g.CollectionID)
    80  		if errors.Is(err, storage.ErrNotFound) {
    81  			c.collectionsToMarkFinalized.Add(g.CollectionID, now)
    82  			continue
    83  		} else if err != nil {
    84  			c.log.Warn().Err(err).Str("collection_id", g.CollectionID.String()).
    85  				Msg("could not track tx finalized metric: finalized collection not found locally")
    86  			continue
    87  		}
    88  
    89  		for _, t := range l.Transactions {
    90  			c.accessMetrics.TransactionFinalized(t, now)
    91  		}
    92  	}
    93  
    94  	if ti, found := c.blocksToMarkExecuted.ByID(blockID); found {
    95  		c.blockExecuted(block, ti)
    96  		c.accessMetrics.UpdateExecutionReceiptMaxHeight(block.Header.Height)
    97  		c.blocksToMarkExecuted.Remove(blockID)
    98  	}
    99  }
   100  
   101  // ExecutionReceiptReceived tracks execution receipt metrics
   102  func (c *CollectionExecutedMetricImpl) ExecutionReceiptReceived(r *flow.ExecutionReceipt) {
   103  	// TODO add actual execution time to execution receipt?
   104  	now := time.Now().UTC()
   105  
   106  	// retrieve the block
   107  	// TODO: consider using storage.Index.ByBlockID, the index contains collection id and seals ID
   108  	b, err := c.blocks.ByID(r.ExecutionResult.BlockID)
   109  
   110  	if errors.Is(err, storage.ErrNotFound) {
   111  		c.blocksToMarkExecuted.Add(r.ExecutionResult.BlockID, now)
   112  		return
   113  	}
   114  
   115  	if err != nil {
   116  		c.log.Warn().Err(err).Msg("could not track tx executed metric: executed block not found locally")
   117  		return
   118  	}
   119  
   120  	c.accessMetrics.UpdateExecutionReceiptMaxHeight(b.Header.Height)
   121  
   122  	c.blockExecuted(b, now)
   123  }
   124  
   125  func (c *CollectionExecutedMetricImpl) UpdateLastFullBlockHeight(height uint64) {
   126  	c.accessMetrics.UpdateLastFullBlockHeight(height)
   127  }
   128  
   129  // blockExecuted tracks executed metric for block
   130  func (c *CollectionExecutedMetricImpl) blockExecuted(block *flow.Block, ti time.Time) {
   131  	// mark all transactions as executed
   132  	// TODO: sample to reduce performance overhead
   133  	for _, g := range block.Payload.Guarantees {
   134  		l, err := c.collections.LightByID(g.CollectionID)
   135  		if errors.Is(err, storage.ErrNotFound) {
   136  			c.collectionsToMarkExecuted.Add(g.CollectionID, ti)
   137  			continue
   138  		} else if err != nil {
   139  			c.log.Warn().Err(err).Str("collection_id", g.CollectionID.String()).
   140  				Msg("could not track tx executed metric: executed collection not found locally")
   141  			continue
   142  		}
   143  
   144  		for _, t := range l.Transactions {
   145  			c.accessMetrics.TransactionExecuted(t, ti)
   146  		}
   147  	}
   148  }