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  }