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 }