github.com/MetalBlockchain/subnet-evm@v0.4.9/sync/client/stats/stats.go (about) 1 // (c) 2021-2022, Ava Labs, Inc. All rights reserved. 2 // See the file LICENSE for licensing terms. 3 4 package stats 5 6 import ( 7 "fmt" 8 "time" 9 10 "github.com/MetalBlockchain/subnet-evm/metrics" 11 "github.com/MetalBlockchain/subnet-evm/plugin/evm/message" 12 ) 13 14 var ( 15 _ ClientSyncerStats = &clientSyncerStats{} 16 _ ClientSyncerStats = &noopStats{} 17 ) 18 19 type ClientSyncerStats interface { 20 GetMetric(message.Request) (MessageMetric, error) 21 } 22 23 type MessageMetric interface { 24 IncRequested() 25 IncSucceeded() 26 IncFailed() 27 IncInvalidResponse() 28 IncReceived(int64) 29 UpdateRequestLatency(time.Duration) 30 } 31 32 type messageMetric struct { 33 requested metrics.Counter // Number of times a request has been sent 34 succeeded metrics.Counter // Number of times a request has succeeded 35 failed metrics.Counter // Number of times a request failed (does not include invalid responses) 36 invalidResponse metrics.Counter // Number of times a request failed due to an invalid response 37 received metrics.Counter // Number of items that have been received 38 39 requestLatency metrics.Timer // Latency for this request 40 } 41 42 func NewMessageMetric(name string) MessageMetric { 43 return &messageMetric{ 44 requested: metrics.GetOrRegisterCounter(fmt.Sprintf("%s_requested", name), nil), 45 succeeded: metrics.GetOrRegisterCounter(fmt.Sprintf("%s_succeeded", name), nil), 46 failed: metrics.GetOrRegisterCounter(fmt.Sprintf("%s_failed", name), nil), 47 invalidResponse: metrics.GetOrRegisterCounter(fmt.Sprintf("%s_invalid_response", name), nil), 48 received: metrics.GetOrRegisterCounter(fmt.Sprintf("%s_received", name), nil), 49 requestLatency: metrics.GetOrRegisterTimer(fmt.Sprintf("%s_request_latency", name), nil), 50 } 51 } 52 53 func (m *messageMetric) IncRequested() { 54 m.requested.Inc(1) 55 } 56 57 func (m *messageMetric) IncSucceeded() { 58 m.succeeded.Inc(1) 59 } 60 61 func (m *messageMetric) IncFailed() { 62 m.failed.Inc(1) 63 } 64 65 func (m *messageMetric) IncInvalidResponse() { 66 m.invalidResponse.Inc(1) 67 } 68 69 func (m *messageMetric) IncReceived(size int64) { 70 m.received.Inc(size) 71 } 72 73 func (m *messageMetric) UpdateRequestLatency(duration time.Duration) { 74 m.requestLatency.Update(duration) 75 } 76 77 type clientSyncerStats struct { 78 atomicTrieLeavesMetric, 79 stateTrieLeavesMetric, 80 codeRequestMetric, 81 blockRequestMetric MessageMetric 82 } 83 84 // NewClientSyncerStats returns stats for the client syncer 85 func NewClientSyncerStats() ClientSyncerStats { 86 return &clientSyncerStats{ 87 atomicTrieLeavesMetric: NewMessageMetric("sync_atomic_trie_leaves"), 88 stateTrieLeavesMetric: NewMessageMetric("sync_state_trie_leaves"), 89 codeRequestMetric: NewMessageMetric("sync_code"), 90 blockRequestMetric: NewMessageMetric("sync_blocks"), 91 } 92 } 93 94 // GetMetric returns the appropriate messaage metric for the given request 95 func (c *clientSyncerStats) GetMetric(msgIntf message.Request) (MessageMetric, error) { 96 switch msg := msgIntf.(type) { 97 case message.BlockRequest: 98 return c.blockRequestMetric, nil 99 case message.CodeRequest: 100 return c.codeRequestMetric, nil 101 case message.LeafsRequest: 102 return c.stateTrieLeavesMetric, nil 103 default: 104 return nil, fmt.Errorf("attempted to get metric for invalid request with type %T", msg) 105 } 106 } 107 108 // no-op implementation of ClientSyncerStats 109 type noopStats struct { 110 noop noopMsgMetric 111 } 112 113 type noopMsgMetric struct{} 114 115 func (noopMsgMetric) IncRequested() {} 116 func (noopMsgMetric) IncSucceeded() {} 117 func (noopMsgMetric) IncFailed() {} 118 func (noopMsgMetric) IncInvalidResponse() {} 119 func (noopMsgMetric) IncReceived(int64) {} 120 func (noopMsgMetric) UpdateRequestLatency(time.Duration) {} 121 122 func NewNoOpStats() ClientSyncerStats { 123 return &noopStats{} 124 } 125 126 func (n noopStats) GetMetric(_ message.Request) (MessageMetric, error) { 127 return n.noop, nil 128 } 129 130 // NewStats returns syncer stats if enabled or a no-op version if disabled. 131 func NewStats(enabled bool) ClientSyncerStats { 132 if enabled { 133 return NewClientSyncerStats() 134 } else { 135 return NewNoOpStats() 136 } 137 }