github.com/koko1123/flow-go-1@v0.29.6/module/metrics/example/verification/main.go (about)

     1  package main
     2  
     3  import (
     4  	"flag"
     5  	"math/rand"
     6  	"testing"
     7  	"time"
     8  
     9  	"github.com/prometheus/client_golang/prometheus"
    10  	"github.com/rs/zerolog"
    11  
    12  	vertestutils "github.com/koko1123/flow-go-1/engine/verification/utils/unittest"
    13  	"github.com/koko1123/flow-go-1/module/buffer"
    14  	"github.com/koko1123/flow-go-1/module/mempool/stdmap"
    15  	"github.com/koko1123/flow-go-1/module/metrics"
    16  	"github.com/koko1123/flow-go-1/module/metrics/example"
    17  	"github.com/koko1123/flow-go-1/module/trace"
    18  	"github.com/koko1123/flow-go-1/utils/unittest"
    19  )
    20  
    21  // main runs a local tracer server on the machine and starts monitoring some metrics for sake of verification, which
    22  // increases result approvals counter and checked chunks counter 100 times each
    23  func main() {
    24  	hp := flag.Bool("happypath", false, "run happy path")
    25  	flag.Parse()
    26  
    27  	if *hp {
    28  		happyPathExample()
    29  	} else {
    30  		demo()
    31  	}
    32  }
    33  
    34  // happyPathExample captures the metrics on running VerificationHappyPath with 10 blocks, each with 10 execution receipts of 10 chunks.
    35  func happyPathExample() {
    36  	example.WithMetricsServer(func(logger zerolog.Logger) {
    37  		tracer, err := trace.NewTracer(logger, "verification", "test", trace.SensitivityCaptureAll)
    38  		if err != nil {
    39  			panic(err)
    40  		}
    41  
    42  		// initiates and starts mempool collector
    43  		// since happy path goes very fast leap timer on collector set to 1 nanosecond.
    44  		mempoolCollector := metrics.NewMempoolCollector(1 * time.Nanosecond)
    45  		<-mempoolCollector.Ready()
    46  
    47  		// starts happy path
    48  		t := &testing.T{}
    49  		verificationCollector := metrics.NewVerificationCollector(tracer, prometheus.DefaultRegisterer)
    50  
    51  		ops := []vertestutils.CompleteExecutionReceiptBuilderOpt{
    52  			vertestutils.WithResults(10),
    53  			vertestutils.WithChunksCount(10),
    54  			vertestutils.WithCopies(1),
    55  		}
    56  		blockCount := 10
    57  		eventRepetition := 1
    58  		trials := 1
    59  		vertestutils.NewVerificationHappyPathTest(t,
    60  			true,
    61  			blockCount,
    62  			eventRepetition,
    63  			verificationCollector,
    64  			mempoolCollector,
    65  			trials,
    66  			ops...)
    67  		<-mempoolCollector.Done()
    68  	})
    69  }
    70  
    71  // demo runs a local tracer server on the machine and starts monitoring some metrics for sake of verification, which
    72  // increases result approvals counter and checked chunks counter 100 times each
    73  func demo() {
    74  	example.WithMetricsServer(func(logger zerolog.Logger) {
    75  		tracer, err := trace.NewTracer(logger, "verification", "test", trace.SensitivityCaptureAll)
    76  		if err != nil {
    77  			panic(err)
    78  		}
    79  
    80  		vc := metrics.NewVerificationCollector(tracer, prometheus.DefaultRegisterer)
    81  		mc := metrics.NewMempoolCollector(5 * time.Second)
    82  
    83  		// starts periodic launch of mempoolCollector
    84  		<-mc.Ready()
    85  
    86  		// creates a receipt mempool and registers a metric on its size
    87  		receipts, err := stdmap.NewReceipts(100)
    88  		if err != nil {
    89  			panic(err)
    90  		}
    91  		err = mc.Register(metrics.ResourceReceipt, receipts.Size)
    92  		if err != nil {
    93  			panic(err)
    94  		}
    95  
    96  		// creates pending receipt ids by block mempool, and registers size method of backend for metrics
    97  		receiptIDsByBlock, err := stdmap.NewIdentifierMap(100)
    98  		if err != nil {
    99  			panic(err)
   100  		}
   101  		err = mc.Register(metrics.ResourcePendingReceiptIDsByBlock, receiptIDsByBlock.Size)
   102  		if err != nil {
   103  			panic(err)
   104  		}
   105  
   106  		// creates pending receipt ids by result mempool, and registers size method of backend for metrics
   107  		receiptIDsByResult, err := stdmap.NewIdentifierMap(100)
   108  		if err != nil {
   109  			panic(err)
   110  		}
   111  		err = mc.Register(metrics.ResourceReceiptIDsByResult, receiptIDsByResult.Size)
   112  		if err != nil {
   113  			panic(err)
   114  		}
   115  
   116  		// creates processed results ids mempool, and registers size method of backend for metrics
   117  		processedResultsIDs, err := stdmap.NewIdentifiers(100)
   118  		if err != nil {
   119  			panic(err)
   120  		}
   121  		err = mc.Register(metrics.ResourceProcessedResultID, processedResultsIDs.Size)
   122  		if err != nil {
   123  			panic(err)
   124  		}
   125  
   126  		// creates consensus cache for follower engine, and registers size method of backend for metrics
   127  		pendingBlocks := buffer.NewPendingBlocks()
   128  		err = mc.Register(metrics.ResourcePendingBlock, pendingBlocks.Size)
   129  		if err != nil {
   130  			panic(err)
   131  		}
   132  
   133  		// Over iterations each metric is gone through
   134  		// a probabilistic experiment with probability 0.5
   135  		// to collect or not.
   136  		// This is done to stretch metrics and scatter their pattern
   137  		// for a clear visualization.
   138  		for i := 0; i < 100; i++ {
   139  			// consumer
   140  			tryRandomCall(func() {
   141  				vc.OnBlockConsumerJobDone(rand.Uint64() % 10000)
   142  			})
   143  			tryRandomCall(func() {
   144  				vc.OnChunkConsumerJobDone(rand.Uint64() % 10000)
   145  			})
   146  
   147  			// assigner
   148  			tryRandomCall(func() {
   149  				vc.OnFinalizedBlockArrivedAtAssigner(uint64(i))
   150  			})
   151  			tryRandomCall(func() {
   152  				vc.OnChunksAssignmentDoneAtAssigner(rand.Int() % 10)
   153  			})
   154  			tryRandomCall(vc.OnAssignedChunkProcessedAtAssigner)
   155  			tryRandomCall(vc.OnExecutionResultReceivedAtAssignerEngine)
   156  
   157  			// fetcher
   158  			tryRandomCall(vc.OnAssignedChunkReceivedAtFetcher)
   159  			tryRandomCall(vc.OnVerifiableChunkSentToVerifier)
   160  			tryRandomCall(vc.OnChunkDataPackArrivedAtFetcher)
   161  			tryRandomCall(vc.OnChunkDataPackRequestSentByFetcher)
   162  
   163  			// requester
   164  			tryRandomCall(vc.OnChunkDataPackRequestReceivedByRequester)
   165  			tryRandomCall(vc.OnChunkDataPackRequestDispatchedInNetworkByRequester)
   166  			tryRandomCall(vc.OnChunkDataPackResponseReceivedFromNetworkByRequester)
   167  			tryRandomCall(vc.OnChunkDataPackSentToFetcher)
   168  			tryRandomCall(func() {
   169  				vc.SetMaxChunkDataPackAttemptsForNextUnsealedHeightAtRequester(uint64(i))
   170  			})
   171  
   172  			// verifier
   173  			tryRandomCall(vc.OnVerifiableChunkReceivedAtVerifierEngine)
   174  			tryRandomCall(vc.OnResultApprovalDispatchedInNetworkByVerifier)
   175  
   176  			// memory pools
   177  			receipt := unittest.ExecutionReceiptFixture()
   178  			tryRandomCall(func() {
   179  				receipts.Add(receipt)
   180  			})
   181  
   182  			tryRandomCall(func() {
   183  				err := receiptIDsByBlock.Append(receipt.ExecutionResult.BlockID, receipt.ID())
   184  				if err != nil {
   185  					panic(err)
   186  				}
   187  			})
   188  
   189  			tryRandomCall(func() {
   190  				err = receiptIDsByResult.Append(receipt.ExecutionResult.BlockID, receipt.ExecutionResult.ID())
   191  				if err != nil {
   192  					panic(err)
   193  				}
   194  			})
   195  
   196  			tryRandomCall(func() {
   197  				processedResultsIDs.Add(receipt.ExecutionResult.ID())
   198  			})
   199  
   200  			tryRandomCall(func() {
   201  				block := unittest.BlockFixture()
   202  				pendingBlocks.Add(unittest.IdentifierFixture(), &block)
   203  			})
   204  
   205  			// adds a synthetic 1 s delay for verification duration
   206  			time.Sleep(1 * time.Second)
   207  
   208  			tryRandomCall(vc.OnResultApprovalDispatchedInNetworkByVerifier)
   209  		}
   210  	})
   211  }
   212  
   213  // tryRandomCall executes function f with a probability of 1/2 that does not necessarily follow a uniform distribution.
   214  //
   215  // DISCLAIMER: this function should not be utilized for production code. Solely meant for testing and demo.
   216  func tryRandomCall(f func()) {
   217  	if rand.Int()%2 == 0 {
   218  		f()
   219  	}
   220  }