github.com/dim4egster/coreth@v0.10.2/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/dim4egster/coreth/metrics" 11 "github.com/dim4egster/coreth/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 switch msg.NodeType { 103 case message.StateTrieNode: 104 return c.stateTrieLeavesMetric, nil 105 case message.AtomicTrieNode: 106 return c.atomicTrieLeavesMetric, nil 107 default: 108 return nil, fmt.Errorf("invalid leafs request for node type: %T", msg.NodeType) 109 } 110 default: 111 return nil, fmt.Errorf("attempted to get metric for invalid request with type %T", msg) 112 } 113 } 114 115 // no-op implementation of ClientSyncerStats 116 type noopStats struct { 117 noop noopMsgMetric 118 } 119 120 type noopMsgMetric struct{} 121 122 func (noopMsgMetric) IncRequested() {} 123 func (noopMsgMetric) IncSucceeded() {} 124 func (noopMsgMetric) IncFailed() {} 125 func (noopMsgMetric) IncInvalidResponse() {} 126 func (noopMsgMetric) IncReceived(int64) {} 127 func (noopMsgMetric) UpdateRequestLatency(time.Duration) {} 128 129 func NewNoOpStats() ClientSyncerStats { 130 return &noopStats{} 131 } 132 133 func (n noopStats) GetMetric(_ message.Request) (MessageMetric, error) { 134 return n.noop, nil 135 } 136 137 // NewStats returns syncer stats if enabled or a no-op version if disabled. 138 func NewStats(enabled bool) ClientSyncerStats { 139 if enabled { 140 return NewClientSyncerStats() 141 } else { 142 return NewNoOpStats() 143 } 144 }