github.com/SmartMeshFoundation/Spectrum@v0.0.0-20220621030607-452a266fee1e/eth/metrics.go (about)

     1  // Copyright 2015 The Spectrum Authors
     2  // This file is part of the Spectrum library.
     3  //
     4  // The Spectrum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The Spectrum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the Spectrum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package eth
    18  
    19  import (
    20  	"github.com/SmartMeshFoundation/Spectrum/metrics"
    21  	"github.com/SmartMeshFoundation/Spectrum/p2p"
    22  )
    23  
    24  var (
    25  	propTxnInPacketsMeter     = metrics.NewMeter("eth/prop/txns/in/packets")
    26  	propTxnInTrafficMeter     = metrics.NewMeter("eth/prop/txns/in/traffic")
    27  	propTxnOutPacketsMeter    = metrics.NewMeter("eth/prop/txns/out/packets")
    28  	propTxnOutTrafficMeter    = metrics.NewMeter("eth/prop/txns/out/traffic")
    29  	propHashInPacketsMeter    = metrics.NewMeter("eth/prop/hashes/in/packets")
    30  	propHashInTrafficMeter    = metrics.NewMeter("eth/prop/hashes/in/traffic")
    31  	propHashOutPacketsMeter   = metrics.NewMeter("eth/prop/hashes/out/packets")
    32  	propHashOutTrafficMeter   = metrics.NewMeter("eth/prop/hashes/out/traffic")
    33  	propBlockInPacketsMeter   = metrics.NewMeter("eth/prop/blocks/in/packets")
    34  	propBlockInTrafficMeter   = metrics.NewMeter("eth/prop/blocks/in/traffic")
    35  	propBlockOutPacketsMeter  = metrics.NewMeter("eth/prop/blocks/out/packets")
    36  	propBlockOutTrafficMeter  = metrics.NewMeter("eth/prop/blocks/out/traffic")
    37  	reqHeaderInPacketsMeter   = metrics.NewMeter("eth/req/headers/in/packets")
    38  	reqHeaderInTrafficMeter   = metrics.NewMeter("eth/req/headers/in/traffic")
    39  	reqHeaderOutPacketsMeter  = metrics.NewMeter("eth/req/headers/out/packets")
    40  	reqHeaderOutTrafficMeter  = metrics.NewMeter("eth/req/headers/out/traffic")
    41  	reqBodyInPacketsMeter     = metrics.NewMeter("eth/req/bodies/in/packets")
    42  	reqBodyInTrafficMeter     = metrics.NewMeter("eth/req/bodies/in/traffic")
    43  	reqBodyOutPacketsMeter    = metrics.NewMeter("eth/req/bodies/out/packets")
    44  	reqBodyOutTrafficMeter    = metrics.NewMeter("eth/req/bodies/out/traffic")
    45  	reqStateInPacketsMeter    = metrics.NewMeter("eth/req/states/in/packets")
    46  	reqStateInTrafficMeter    = metrics.NewMeter("eth/req/states/in/traffic")
    47  	reqStateOutPacketsMeter   = metrics.NewMeter("eth/req/states/out/packets")
    48  	reqStateOutTrafficMeter   = metrics.NewMeter("eth/req/states/out/traffic")
    49  	reqReceiptInPacketsMeter  = metrics.NewMeter("eth/req/receipts/in/packets")
    50  	reqReceiptInTrafficMeter  = metrics.NewMeter("eth/req/receipts/in/traffic")
    51  	reqReceiptOutPacketsMeter = metrics.NewMeter("eth/req/receipts/out/packets")
    52  	reqReceiptOutTrafficMeter = metrics.NewMeter("eth/req/receipts/out/traffic")
    53  	miscInPacketsMeter        = metrics.NewMeter("eth/misc/in/packets")
    54  	miscInTrafficMeter        = metrics.NewMeter("eth/misc/in/traffic")
    55  	miscOutPacketsMeter       = metrics.NewMeter("eth/misc/out/packets")
    56  	miscOutTrafficMeter       = metrics.NewMeter("eth/misc/out/traffic")
    57  )
    58  
    59  // meteredMsgReadWriter is a wrapper around a p2p.MsgReadWriter, capable of
    60  // accumulating the above defined metrics based on the data stream contents.
    61  type meteredMsgReadWriter struct {
    62  	p2p.MsgReadWriter     // Wrapped message stream to meter
    63  	version           int // Protocol version to select correct meters
    64  }
    65  
    66  // newMeteredMsgWriter wraps a p2p MsgReadWriter with metering support. If the
    67  // metrics system is disabled, this function returns the original object.
    68  func newMeteredMsgWriter(rw p2p.MsgReadWriter) p2p.MsgReadWriter {
    69  	if !metrics.Enabled {
    70  		return rw
    71  	}
    72  	return &meteredMsgReadWriter{MsgReadWriter: rw}
    73  }
    74  
    75  // Init sets the protocol version used by the stream to know which meters to
    76  // increment in case of overlapping message ids between protocol versions.
    77  func (rw *meteredMsgReadWriter) Init(version int) {
    78  	rw.version = version
    79  }
    80  
    81  func (rw *meteredMsgReadWriter) ReadMsg() (p2p.Msg, error) {
    82  	// Read the message and short circuit in case of an error
    83  	msg, err := rw.MsgReadWriter.ReadMsg()
    84  	if err != nil {
    85  		return msg, err
    86  	}
    87  	// Account for the data traffic
    88  	packets, traffic := miscInPacketsMeter, miscInTrafficMeter
    89  	switch {
    90  	case msg.Code == BlockHeadersMsg:
    91  		packets, traffic = reqHeaderInPacketsMeter, reqHeaderInTrafficMeter
    92  	case msg.Code == BlockBodiesMsg:
    93  		packets, traffic = reqBodyInPacketsMeter, reqBodyInTrafficMeter
    94  
    95  	case rw.version >= eth63 && msg.Code == NodeDataMsg:
    96  		packets, traffic = reqStateInPacketsMeter, reqStateInTrafficMeter
    97  	case rw.version >= eth63 && msg.Code == ReceiptsMsg:
    98  		packets, traffic = reqReceiptInPacketsMeter, reqReceiptInTrafficMeter
    99  
   100  	case msg.Code == NewBlockHashesMsg:
   101  		packets, traffic = propHashInPacketsMeter, propHashInTrafficMeter
   102  	case msg.Code == NewBlockMsg:
   103  		packets, traffic = propBlockInPacketsMeter, propBlockInTrafficMeter
   104  	case msg.Code == TxMsg:
   105  		packets, traffic = propTxnInPacketsMeter, propTxnInTrafficMeter
   106  	}
   107  	packets.Mark(1)
   108  	traffic.Mark(int64(msg.Size))
   109  
   110  	return msg, err
   111  }
   112  
   113  func (rw *meteredMsgReadWriter) WriteMsg(msg p2p.Msg) error {
   114  	// Account for the data traffic
   115  	packets, traffic := miscOutPacketsMeter, miscOutTrafficMeter
   116  	switch {
   117  	case msg.Code == BlockHeadersMsg:
   118  		packets, traffic = reqHeaderOutPacketsMeter, reqHeaderOutTrafficMeter
   119  	case msg.Code == BlockBodiesMsg:
   120  		packets, traffic = reqBodyOutPacketsMeter, reqBodyOutTrafficMeter
   121  
   122  	case rw.version >= eth63 && msg.Code == NodeDataMsg:
   123  		packets, traffic = reqStateOutPacketsMeter, reqStateOutTrafficMeter
   124  	case rw.version >= eth63 && msg.Code == ReceiptsMsg:
   125  		packets, traffic = reqReceiptOutPacketsMeter, reqReceiptOutTrafficMeter
   126  
   127  	case msg.Code == NewBlockHashesMsg:
   128  		packets, traffic = propHashOutPacketsMeter, propHashOutTrafficMeter
   129  	case msg.Code == NewBlockMsg:
   130  		packets, traffic = propBlockOutPacketsMeter, propBlockOutTrafficMeter
   131  	case msg.Code == TxMsg:
   132  		packets, traffic = propTxnOutPacketsMeter, propTxnOutTrafficMeter
   133  	}
   134  	packets.Mark(1)
   135  	traffic.Mark(int64(msg.Size))
   136  
   137  	// Send the packet to the p2p layer
   138  	return rw.MsgReadWriter.WriteMsg(msg)
   139  }