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 }