github.com/celestiaorg/celestia-node@v0.15.0-beta.1/share/p2p/discovery/metrics.go (about)

     1  package discovery
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  
     7  	"github.com/libp2p/go-libp2p/core/peer"
     8  	"go.opentelemetry.io/otel"
     9  	"go.opentelemetry.io/otel/attribute"
    10  	"go.opentelemetry.io/otel/metric"
    11  
    12  	"github.com/celestiaorg/celestia-node/libs/utils"
    13  )
    14  
    15  const (
    16  	discoveryEnoughPeersKey = "enough_peers"
    17  
    18  	handlePeerResultKey                    = "result"
    19  	handlePeerSkipSelf    handlePeerResult = "skip_self"
    20  	handlePeerEnoughPeers handlePeerResult = "skip_enough_peers"
    21  	handlePeerBackoff     handlePeerResult = "skip_backoff"
    22  	handlePeerConnected   handlePeerResult = "connected"
    23  	handlePeerConnErr     handlePeerResult = "conn_err"
    24  	handlePeerInSet       handlePeerResult = "in_set"
    25  
    26  	advertiseFailedKey = "failed"
    27  )
    28  
    29  var meter = otel.Meter("share_discovery")
    30  
    31  type handlePeerResult string
    32  
    33  type metrics struct {
    34  	peersAmount      metric.Int64ObservableGauge
    35  	discoveryResult  metric.Int64Counter // attributes: enough_peers[bool],is_canceled[bool]
    36  	handlePeerResult metric.Int64Counter // attributes: result[string]
    37  	advertise        metric.Int64Counter // attributes: failed[bool]
    38  	peerAdded        metric.Int64Counter
    39  	peerRemoved      metric.Int64Counter
    40  }
    41  
    42  // WithMetrics turns on metric collection in discoery.
    43  func (d *Discovery) WithMetrics() error {
    44  	metrics, err := initMetrics(d)
    45  	if err != nil {
    46  		return fmt.Errorf("discovery: init metrics: %w", err)
    47  	}
    48  	d.metrics = metrics
    49  	d.onUpdatedPeers = d.onUpdatedPeers.add(metrics.observeOnPeersUpdate)
    50  	return nil
    51  }
    52  
    53  func initMetrics(d *Discovery) (*metrics, error) {
    54  	peersAmount, err := meter.Int64ObservableGauge("discovery_amount_of_peers",
    55  		metric.WithDescription("amount of peers in discovery set"))
    56  	if err != nil {
    57  		return nil, err
    58  	}
    59  
    60  	discoveryResult, err := meter.Int64Counter("discovery_find_peers_result",
    61  		metric.WithDescription("result of find peers run"))
    62  	if err != nil {
    63  		return nil, err
    64  	}
    65  
    66  	handlePeerResultCounter, err := meter.Int64Counter("discovery_handler_peer_result",
    67  		metric.WithDescription("result handling found peer"))
    68  	if err != nil {
    69  		return nil, err
    70  	}
    71  
    72  	advertise, err := meter.Int64Counter("discovery_advertise_event",
    73  		metric.WithDescription("advertise events counter"))
    74  	if err != nil {
    75  		return nil, err
    76  	}
    77  
    78  	peerAdded, err := meter.Int64Counter("discovery_add_peer",
    79  		metric.WithDescription("add peer to discovery set counter"))
    80  	if err != nil {
    81  		return nil, err
    82  	}
    83  
    84  	peerRemoved, err := meter.Int64Counter("discovery_remove_peer",
    85  		metric.WithDescription("remove peer from discovery set counter"))
    86  	if err != nil {
    87  		return nil, err
    88  	}
    89  
    90  	backOffSize, err := meter.Int64ObservableGauge("discovery_backoff_amount",
    91  		metric.WithDescription("amount of peers in backoff"))
    92  	if err != nil {
    93  		return nil, err
    94  	}
    95  
    96  	metrics := &metrics{
    97  		peersAmount:      peersAmount,
    98  		discoveryResult:  discoveryResult,
    99  		handlePeerResult: handlePeerResultCounter,
   100  		advertise:        advertise,
   101  		peerAdded:        peerAdded,
   102  		peerRemoved:      peerRemoved,
   103  	}
   104  
   105  	callback := func(ctx context.Context, observer metric.Observer) error {
   106  		observer.ObserveInt64(peersAmount, int64(d.set.Size()))
   107  		observer.ObserveInt64(backOffSize, int64(d.connector.Size()))
   108  		return nil
   109  	}
   110  	_, err = meter.RegisterCallback(callback, peersAmount, backOffSize)
   111  	if err != nil {
   112  		return nil, fmt.Errorf("registering metrics callback: %w", err)
   113  	}
   114  	return metrics, nil
   115  }
   116  
   117  func (m *metrics) observeFindPeers(ctx context.Context, isEnoughPeers bool) {
   118  	if m == nil {
   119  		return
   120  	}
   121  	ctx = utils.ResetContextOnError(ctx)
   122  
   123  	m.discoveryResult.Add(ctx, 1,
   124  		metric.WithAttributes(
   125  			attribute.Bool(discoveryEnoughPeersKey, isEnoughPeers)))
   126  }
   127  
   128  func (m *metrics) observeHandlePeer(ctx context.Context, result handlePeerResult) {
   129  	if m == nil {
   130  		return
   131  	}
   132  	ctx = utils.ResetContextOnError(ctx)
   133  
   134  	m.handlePeerResult.Add(ctx, 1,
   135  		metric.WithAttributes(
   136  			attribute.String(handlePeerResultKey, string(result))))
   137  }
   138  
   139  func (m *metrics) observeAdvertise(ctx context.Context, err error) {
   140  	if m == nil {
   141  		return
   142  	}
   143  	ctx = utils.ResetContextOnError(ctx)
   144  
   145  	m.advertise.Add(ctx, 1,
   146  		metric.WithAttributes(
   147  			attribute.Bool(advertiseFailedKey, err != nil)))
   148  }
   149  
   150  func (m *metrics) observeOnPeersUpdate(_ peer.ID, isAdded bool) {
   151  	if m == nil {
   152  		return
   153  	}
   154  	ctx := context.Background()
   155  
   156  	if isAdded {
   157  		m.peerAdded.Add(ctx, 1)
   158  		return
   159  	}
   160  	m.peerRemoved.Add(ctx, 1)
   161  }