github.com/choria-io/go-choria@v0.28.1-0.20240416190746-b3bf9c7d5a45/broker/network/stats.go (about)

     1  // Copyright (c) 2017-2021, R.I. Pienaar and the Choria Project contributors
     2  //
     3  // SPDX-License-Identifier: Apache-2.0
     4  
     5  package network
     6  
     7  import (
     8  	"context"
     9  	"strconv"
    10  	"strings"
    11  	"time"
    12  
    13  	gnatsd "github.com/nats-io/nats-server/v2/server"
    14  	"github.com/prometheus/client_golang/prometheus"
    15  	log "github.com/sirupsen/logrus"
    16  )
    17  
    18  var (
    19  	connectionsGauge = prometheus.NewGaugeVec(prometheus.GaugeOpts{
    20  		Name: "choria_network_connections",
    21  		Help: "Current connections on the network broker",
    22  	}, []string{"identity"})
    23  
    24  	totalConnectionsGauge = prometheus.NewGaugeVec(prometheus.GaugeOpts{
    25  		Name: "choria_network_total_connections",
    26  		Help: "Total connections received since start",
    27  	}, []string{"identity"})
    28  
    29  	routesGauge = prometheus.NewGaugeVec(prometheus.GaugeOpts{
    30  		Name: "choria_network_routes",
    31  		Help: "Current active routes to other brokers",
    32  	}, []string{"identity"})
    33  
    34  	remotesGauge = prometheus.NewGaugeVec(prometheus.GaugeOpts{
    35  		Name: "choria_network_remotes",
    36  		Help: "Current active connections to other brokers",
    37  	}, []string{"identity"})
    38  
    39  	leafsGauge = prometheus.NewGaugeVec(prometheus.GaugeOpts{
    40  		Name: "choria_network_leafnode_remotes",
    41  		Help: "Current active connections to other leafnodes",
    42  	}, []string{"identity"})
    43  
    44  	inMsgsGauge = prometheus.NewGaugeVec(prometheus.GaugeOpts{
    45  		Name: "choria_network_in_msgs",
    46  		Help: "Messages received by the network broker",
    47  	}, []string{"identity"})
    48  
    49  	outMsgsGauge = prometheus.NewGaugeVec(prometheus.GaugeOpts{
    50  		Name: "choria_network_out_msgs",
    51  		Help: "Messages sent by the network broker",
    52  	}, []string{"identity"})
    53  
    54  	inBytesGauge = prometheus.NewGaugeVec(prometheus.GaugeOpts{
    55  		Name: "choria_network_in_bytes",
    56  		Help: "Total size of messages received by the network broker",
    57  	}, []string{"identity"})
    58  
    59  	outBytesGauge = prometheus.NewGaugeVec(prometheus.GaugeOpts{
    60  		Name: "choria_network_out_bytes",
    61  		Help: "Total size of messages sent by the network broker",
    62  	}, []string{"identity"})
    63  
    64  	slowConsumerGauge = prometheus.NewGaugeVec(prometheus.GaugeOpts{
    65  		Name: "choria_network_slow_consumers",
    66  		Help: "Total number of clients who were considered slow consumers",
    67  	}, []string{"identity"})
    68  
    69  	subscriptionsGauge = prometheus.NewGaugeVec(prometheus.GaugeOpts{
    70  		Name: "choria_network_subscriptions",
    71  		Help: "Number of active subscriptions to subjects on this broker",
    72  	}, []string{"identity"})
    73  
    74  	leafTTGauge = prometheus.NewGaugeVec(prometheus.GaugeOpts{
    75  		Name: "choria_network_leafnode_rtt_ms",
    76  		Help: "RTT for the Leafnode connection",
    77  	}, []string{"identity", "host", "port", "account"})
    78  
    79  	leafMsgsInGauge = prometheus.NewGaugeVec(prometheus.GaugeOpts{
    80  		Name: "choria_network_leafnode_in_msgs",
    81  		Help: "Messages received over the leafnode connection",
    82  	}, []string{"identity", "host", "port", "account"})
    83  
    84  	leafMsgsOutGauge = prometheus.NewGaugeVec(prometheus.GaugeOpts{
    85  		Name: "choria_network_leafnode_out_msgs",
    86  		Help: "Messages sent over the leafnode connection",
    87  	}, []string{"identity", "host", "port", "account"})
    88  
    89  	leafBytesInGauge = prometheus.NewGaugeVec(prometheus.GaugeOpts{
    90  		Name: "choria_network_leafnode_in_bytes",
    91  		Help: "Bytes received over the leafnode connection",
    92  	}, []string{"identity", "host", "port", "account"})
    93  
    94  	leafBytesOutGauge = prometheus.NewGaugeVec(prometheus.GaugeOpts{
    95  		Name: "choria_network_leafnode_out_bytes",
    96  		Help: "Total size of messages sent over the leafnode connection",
    97  	}, []string{"identity", "host", "port", "account"})
    98  
    99  	leafSubscriptionsGauge = prometheus.NewGaugeVec(prometheus.GaugeOpts{
   100  		Name: "choria_network_leafnode_subscriptions",
   101  		Help: "Number of active subscriptions to subjects on this leafnode",
   102  	}, []string{"identity", "host", "port", "account"})
   103  
   104  	streamMemoryMaxGauge = prometheus.NewGaugeVec(prometheus.GaugeOpts{
   105  		Name: "choria_network_stream_memorystore_max",
   106  		Help: "Maximum amount of Memory Storage allocated to Choria Streams",
   107  	}, []string{"identity"})
   108  
   109  	streamFileMaxGauge = prometheus.NewGaugeVec(prometheus.GaugeOpts{
   110  		Name: "choria_network_stream_filestore_max",
   111  		Help: "Maximum amount of File Storage allocated to Choria Streams",
   112  	}, []string{"identity"})
   113  
   114  	streamMemoryUsedGauge = prometheus.NewGaugeVec(prometheus.GaugeOpts{
   115  		Name: "choria_network_stream_memorystore_used",
   116  		Help: "Memory in use by Choria Streams",
   117  	}, []string{"identity"})
   118  
   119  	streamFileUsedGauge = prometheus.NewGaugeVec(prometheus.GaugeOpts{
   120  		Name: "choria_network_stream_filestore_used",
   121  		Help: "Memory in use by Choria Streams",
   122  	}, []string{"identity"})
   123  
   124  	streamStreamsGauge = prometheus.NewGaugeVec(prometheus.GaugeOpts{
   125  		Name: "choria_network_stream_streams",
   126  		Help: "Number of active streams",
   127  	}, []string{"identity"})
   128  
   129  	streamConsumersGauge = prometheus.NewGaugeVec(prometheus.GaugeOpts{
   130  		Name: "choria_network_stream_consumers",
   131  		Help: "Number of active consumers",
   132  	}, []string{"identity"})
   133  
   134  	streamMessagesGauge = prometheus.NewGaugeVec(prometheus.GaugeOpts{
   135  		Name: "choria_network_stream_messages",
   136  		Help: "Number of messages stored",
   137  	}, []string{"identity"})
   138  
   139  	streamMessageBytesGauge = prometheus.NewGaugeVec(prometheus.GaugeOpts{
   140  		Name: "choria_network_stream_message_bytes",
   141  		Help: "Size in bytes of messages stored",
   142  	}, []string{"identity"})
   143  )
   144  
   145  func init() {
   146  	prometheus.MustRegister(connectionsGauge)
   147  	prometheus.MustRegister(totalConnectionsGauge)
   148  	prometheus.MustRegister(routesGauge)
   149  	prometheus.MustRegister(remotesGauge)
   150  	prometheus.MustRegister(leafsGauge)
   151  	prometheus.MustRegister(inMsgsGauge)
   152  	prometheus.MustRegister(outMsgsGauge)
   153  	prometheus.MustRegister(inBytesGauge)
   154  	prometheus.MustRegister(outBytesGauge)
   155  	prometheus.MustRegister(slowConsumerGauge)
   156  	prometheus.MustRegister(subscriptionsGauge)
   157  
   158  	// leafnodes
   159  	prometheus.MustRegister(leafTTGauge)
   160  	prometheus.MustRegister(leafMsgsInGauge)
   161  	prometheus.MustRegister(leafMsgsOutGauge)
   162  	prometheus.MustRegister(leafBytesInGauge)
   163  	prometheus.MustRegister(leafBytesOutGauge)
   164  	prometheus.MustRegister(leafSubscriptionsGauge)
   165  
   166  	// streams
   167  	prometheus.MustRegister(streamMemoryMaxGauge)
   168  	prometheus.MustRegister(streamFileMaxGauge)
   169  	prometheus.MustRegister(streamMemoryUsedGauge)
   170  	prometheus.MustRegister(streamFileUsedGauge)
   171  	prometheus.MustRegister(streamStreamsGauge)
   172  	prometheus.MustRegister(streamConsumersGauge)
   173  	prometheus.MustRegister(streamMessagesGauge)
   174  	prometheus.MustRegister(streamMessageBytesGauge)
   175  }
   176  
   177  func (s *Server) getVarz() (*gnatsd.Varz, error) {
   178  	return s.gnatsd.Varz(&gnatsd.VarzOptions{})
   179  }
   180  
   181  func (s *Server) getLeafz() (*gnatsd.Leafz, error) {
   182  	return s.gnatsd.Leafz(&gnatsd.LeafzOptions{Subscriptions: false})
   183  }
   184  
   185  func (s *Server) getJSZ() (*gnatsd.JSInfo, error) {
   186  	return s.gnatsd.Jsz(&gnatsd.JSzOptions{
   187  		Config: true,
   188  	})
   189  }
   190  
   191  func (s *Server) publishStats(ctx context.Context, interval time.Duration) {
   192  	if s.opts.HTTPPort == 0 {
   193  		return
   194  	}
   195  
   196  	ticker := time.NewTicker(interval)
   197  
   198  	for {
   199  		select {
   200  		case <-ticker.C:
   201  			log.Debug("Starting NATS /varz update")
   202  
   203  			s.updatePrometheus()
   204  		case <-ctx.Done():
   205  			return
   206  		}
   207  	}
   208  }
   209  
   210  func (s *Server) updatePrometheus() {
   211  	varz, err := s.getVarz()
   212  	if err != nil {
   213  		log.Errorf("Could not publish network broker stats: %s", err)
   214  		return
   215  	}
   216  
   217  	i := s.config.Identity
   218  
   219  	connectionsGauge.WithLabelValues(i).Set(float64(varz.Connections))
   220  	totalConnectionsGauge.WithLabelValues(i).Set(float64(varz.TotalConnections))
   221  	routesGauge.WithLabelValues(i).Set(float64(varz.Routes))
   222  	remotesGauge.WithLabelValues(i).Set(float64(varz.Remotes))
   223  	inMsgsGauge.WithLabelValues(i).Set(float64(varz.InMsgs))
   224  	outMsgsGauge.WithLabelValues(i).Set(float64(varz.OutMsgs))
   225  	inBytesGauge.WithLabelValues(i).Set(float64(varz.InBytes))
   226  	outBytesGauge.WithLabelValues(i).Set(float64(varz.OutBytes))
   227  	slowConsumerGauge.WithLabelValues(i).Set(float64(varz.SlowConsumers))
   228  	subscriptionsGauge.WithLabelValues(i).Set(float64(varz.Subscriptions))
   229  	leafsGauge.WithLabelValues(i).Set(float64(varz.Leafs))
   230  
   231  	leafz, err := s.getLeafz()
   232  	if err == nil {
   233  		for _, leaf := range leafz.Leafs {
   234  			leafMsgsInGauge.WithLabelValues(i, leaf.IP, strconv.Itoa(leaf.Port), leaf.Account).Set(float64(leaf.InMsgs))
   235  			leafMsgsOutGauge.WithLabelValues(i, leaf.IP, strconv.Itoa(leaf.Port), leaf.Account).Set(float64(leaf.OutMsgs))
   236  			leafBytesInGauge.WithLabelValues(i, leaf.IP, strconv.Itoa(leaf.Port), leaf.Account).Set(float64(leaf.InBytes))
   237  			leafBytesOutGauge.WithLabelValues(i, leaf.IP, strconv.Itoa(leaf.Port), leaf.Account).Set(float64(leaf.OutBytes))
   238  			leafSubscriptionsGauge.WithLabelValues(i, leaf.IP, strconv.Itoa(leaf.Port), leaf.Account).Set(float64(leaf.NumSubs))
   239  
   240  			rtt, err := strconv.Atoi(strings.TrimSuffix(leaf.RTT, "ms"))
   241  			if err == nil {
   242  				leafTTGauge.WithLabelValues(i, leaf.IP, strconv.Itoa(leaf.Port), leaf.Account).Set(float64(rtt))
   243  			}
   244  		}
   245  	}
   246  
   247  	jsz, err := s.getJSZ()
   248  	if err == nil {
   249  		streamMemoryMaxGauge.WithLabelValues(i).Set(float64(jsz.Config.MaxMemory))
   250  		streamFileMaxGauge.WithLabelValues(i).Set(float64(jsz.Config.MaxStore))
   251  		streamMemoryUsedGauge.WithLabelValues(i).Set(float64(jsz.Memory))
   252  		streamFileUsedGauge.WithLabelValues(i).Set(float64(jsz.Store))
   253  		streamStreamsGauge.WithLabelValues(i).Set(float64(jsz.Streams))
   254  		streamConsumersGauge.WithLabelValues(i).Set(float64(jsz.Consumers))
   255  		streamMessagesGauge.WithLabelValues(i).Set(float64(jsz.Messages))
   256  		streamMessageBytesGauge.WithLabelValues(i).Set(float64(jsz.Bytes))
   257  	}
   258  }