github.com/nsqio/nsq@v1.3.0/internal/clusterinfo/types.go (about) 1 package clusterinfo 2 3 import ( 4 "encoding/json" 5 "net" 6 "sort" 7 "strconv" 8 "time" 9 10 "github.com/blang/semver" 11 "github.com/nsqio/nsq/internal/quantile" 12 ) 13 14 type ProducerTopic struct { 15 Topic string `json:"topic"` 16 Tombstoned bool `json:"tombstoned"` 17 } 18 19 type ProducerTopics []ProducerTopic 20 21 func (pt ProducerTopics) Len() int { return len(pt) } 22 func (pt ProducerTopics) Swap(i, j int) { pt[i], pt[j] = pt[j], pt[i] } 23 func (pt ProducerTopics) Less(i, j int) bool { return pt[i].Topic < pt[j].Topic } 24 25 type Producer struct { 26 RemoteAddresses []string `json:"remote_addresses"` 27 RemoteAddress string `json:"remote_address"` 28 Hostname string `json:"hostname"` 29 BroadcastAddress string `json:"broadcast_address"` 30 TCPPort int `json:"tcp_port"` 31 HTTPPort int `json:"http_port"` 32 Version string `json:"version"` 33 VersionObj semver.Version `json:"-"` 34 Topics ProducerTopics `json:"topics"` 35 OutOfDate bool `json:"out_of_date"` 36 } 37 38 // UnmarshalJSON implements json.Unmarshaler and postprocesses of ProducerTopics and VersionObj 39 func (p *Producer) UnmarshalJSON(b []byte) error { 40 var r struct { 41 RemoteAddress string `json:"remote_address"` 42 Hostname string `json:"hostname"` 43 BroadcastAddress string `json:"broadcast_address"` 44 TCPPort int `json:"tcp_port"` 45 HTTPPort int `json:"http_port"` 46 Version string `json:"version"` 47 Topics []string `json:"topics"` 48 Tombstoned []bool `json:"tombstones"` 49 } 50 if err := json.Unmarshal(b, &r); err != nil { 51 return err 52 } 53 *p = Producer{ 54 RemoteAddress: r.RemoteAddress, 55 Hostname: r.Hostname, 56 BroadcastAddress: r.BroadcastAddress, 57 TCPPort: r.TCPPort, 58 HTTPPort: r.HTTPPort, 59 Version: r.Version, 60 } 61 for i, t := range r.Topics { 62 p.Topics = append(p.Topics, ProducerTopic{Topic: t, Tombstoned: r.Tombstoned[i]}) 63 } 64 version, err := semver.Parse(p.Version) 65 if err != nil { 66 version, _ = semver.Parse("0.0.0") 67 } 68 p.VersionObj = version 69 return nil 70 } 71 72 func (p *Producer) Address() string { 73 if p.RemoteAddress == "" { 74 return "N/A" 75 } 76 return p.RemoteAddress 77 } 78 79 func (p *Producer) HTTPAddress() string { 80 return net.JoinHostPort(p.BroadcastAddress, strconv.Itoa(p.HTTPPort)) 81 } 82 83 func (p *Producer) TCPAddress() string { 84 return net.JoinHostPort(p.BroadcastAddress, strconv.Itoa(p.TCPPort)) 85 } 86 87 // IsInconsistent checks for cases where an unexpected number of nsqd connections are 88 // reporting the same information to nsqlookupd (ie: multiple instances are using the 89 // same broadcast address), or cases where some nsqd are not reporting to all nsqlookupd. 90 func (p *Producer) IsInconsistent(numLookupd int) bool { 91 return len(p.RemoteAddresses) != numLookupd 92 } 93 94 type TopicStats struct { 95 Node string `json:"node"` 96 Hostname string `json:"hostname"` 97 TopicName string `json:"topic_name"` 98 Depth int64 `json:"depth"` 99 MemoryDepth int64 `json:"memory_depth"` 100 BackendDepth int64 `json:"backend_depth"` 101 MessageCount int64 `json:"message_count"` 102 NodeStats []*TopicStats `json:"nodes"` 103 Channels []*ChannelStats `json:"channels"` 104 Paused bool `json:"paused"` 105 106 E2eProcessingLatency *quantile.E2eProcessingLatencyAggregate `json:"e2e_processing_latency"` 107 } 108 109 func (t *TopicStats) Add(a *TopicStats) { 110 t.Node = "*" 111 t.Depth += a.Depth 112 t.MemoryDepth += a.MemoryDepth 113 t.BackendDepth += a.BackendDepth 114 t.MessageCount += a.MessageCount 115 if a.Paused { 116 t.Paused = a.Paused 117 } 118 for _, aChannelStats := range a.Channels { 119 found := false 120 for _, channelStats := range t.Channels { 121 if aChannelStats.ChannelName == channelStats.ChannelName { 122 found = true 123 channelStats.Add(aChannelStats) 124 } 125 } 126 if !found { 127 t.Channels = append(t.Channels, aChannelStats) 128 } 129 } 130 t.NodeStats = append(t.NodeStats, a) 131 sort.Sort(TopicStatsByHost{t.NodeStats}) 132 if t.E2eProcessingLatency == nil { 133 t.E2eProcessingLatency = &quantile.E2eProcessingLatencyAggregate{ 134 Addr: t.Node, 135 Topic: t.TopicName, 136 } 137 } 138 t.E2eProcessingLatency.Add(a.E2eProcessingLatency) 139 } 140 141 type ChannelStats struct { 142 Node string `json:"node"` 143 Hostname string `json:"hostname"` 144 TopicName string `json:"topic_name"` 145 ChannelName string `json:"channel_name"` 146 Depth int64 `json:"depth"` 147 MemoryDepth int64 `json:"memory_depth"` 148 BackendDepth int64 `json:"backend_depth"` 149 InFlightCount int64 `json:"in_flight_count"` 150 DeferredCount int64 `json:"deferred_count"` 151 RequeueCount int64 `json:"requeue_count"` 152 TimeoutCount int64 `json:"timeout_count"` 153 MessageCount int64 `json:"message_count"` 154 ClientCount int `json:"client_count"` 155 Selected bool `json:"-"` 156 NodeStats []*ChannelStats `json:"nodes"` 157 Clients []*ClientStats `json:"clients"` 158 Paused bool `json:"paused"` 159 160 E2eProcessingLatency *quantile.E2eProcessingLatencyAggregate `json:"e2e_processing_latency"` 161 } 162 163 func (c *ChannelStats) Add(a *ChannelStats) { 164 c.Node = "*" 165 c.Depth += a.Depth 166 c.MemoryDepth += a.MemoryDepth 167 c.BackendDepth += a.BackendDepth 168 c.InFlightCount += a.InFlightCount 169 c.DeferredCount += a.DeferredCount 170 c.RequeueCount += a.RequeueCount 171 c.TimeoutCount += a.TimeoutCount 172 c.MessageCount += a.MessageCount 173 c.ClientCount += a.ClientCount 174 if a.Paused { 175 c.Paused = a.Paused 176 } 177 c.NodeStats = append(c.NodeStats, a) 178 sort.Sort(ChannelStatsByHost{c.NodeStats}) 179 if c.E2eProcessingLatency == nil { 180 c.E2eProcessingLatency = &quantile.E2eProcessingLatencyAggregate{ 181 Addr: c.Node, 182 Topic: c.TopicName, 183 Channel: c.ChannelName, 184 } 185 } 186 c.E2eProcessingLatency.Add(a.E2eProcessingLatency) 187 c.Clients = append(c.Clients, a.Clients...) 188 sort.Sort(ClientsByHost{c.Clients}) 189 } 190 191 type ClientStats struct { 192 Node string `json:"node"` 193 RemoteAddress string `json:"remote_address"` 194 Version string `json:"version"` 195 ClientID string `json:"client_id"` 196 Hostname string `json:"hostname"` 197 UserAgent string `json:"user_agent"` 198 ConnectTs int64 `json:"connect_ts"` 199 ConnectedDuration time.Duration `json:"connected"` 200 InFlightCount int `json:"in_flight_count"` 201 ReadyCount int `json:"ready_count"` 202 FinishCount int64 `json:"finish_count"` 203 RequeueCount int64 `json:"requeue_count"` 204 MessageCount int64 `json:"message_count"` 205 SampleRate int32 `json:"sample_rate"` 206 Deflate bool `json:"deflate"` 207 Snappy bool `json:"snappy"` 208 Authed bool `json:"authed"` 209 AuthIdentity string `json:"auth_identity"` 210 AuthIdentityURL string `json:"auth_identity_url"` 211 212 TLS bool `json:"tls"` 213 CipherSuite string `json:"tls_cipher_suite"` 214 TLSVersion string `json:"tls_version"` 215 TLSNegotiatedProtocol string `json:"tls_negotiated_protocol"` 216 TLSNegotiatedProtocolIsMutual bool `json:"tls_negotiated_protocol_is_mutual"` 217 } 218 219 // UnmarshalJSON implements json.Unmarshaler and postprocesses ConnectedDuration 220 func (s *ClientStats) UnmarshalJSON(b []byte) error { 221 type locaClientStats ClientStats // re-typed to prevent recursion from json.Unmarshal 222 var ss locaClientStats 223 if err := json.Unmarshal(b, &ss); err != nil { 224 return err 225 } 226 *s = ClientStats(ss) 227 s.ConnectedDuration = time.Now().Truncate(time.Second).Sub(time.Unix(s.ConnectTs, 0)) 228 return nil 229 } 230 231 func (s *ClientStats) HasUserAgent() bool { 232 return s.UserAgent != "" 233 } 234 235 func (s *ClientStats) HasSampleRate() bool { 236 return s.SampleRate > 0 237 } 238 239 type ChannelStatsList []*ChannelStats 240 241 func (c ChannelStatsList) Len() int { return len(c) } 242 func (c ChannelStatsList) Swap(i, j int) { c[i], c[j] = c[j], c[i] } 243 244 type ChannelStatsByHost struct { 245 ChannelStatsList 246 } 247 248 func (c ChannelStatsByHost) Less(i, j int) bool { 249 return c.ChannelStatsList[i].Hostname < c.ChannelStatsList[j].Hostname 250 } 251 252 type ClientStatsList []*ClientStats 253 254 func (c ClientStatsList) Len() int { return len(c) } 255 func (c ClientStatsList) Swap(i, j int) { c[i], c[j] = c[j], c[i] } 256 257 type ClientsByHost struct { 258 ClientStatsList 259 } 260 261 func (c ClientsByHost) Less(i, j int) bool { 262 return c.ClientStatsList[i].Hostname < c.ClientStatsList[j].Hostname 263 } 264 265 type TopicStatsList []*TopicStats 266 267 func (t TopicStatsList) Len() int { return len(t) } 268 func (t TopicStatsList) Swap(i, j int) { t[i], t[j] = t[j], t[i] } 269 270 type TopicStatsByHost struct { 271 TopicStatsList 272 } 273 274 func (c TopicStatsByHost) Less(i, j int) bool { 275 return c.TopicStatsList[i].Hostname < c.TopicStatsList[j].Hostname 276 } 277 278 type Producers []*Producer 279 280 func (t Producers) Len() int { return len(t) } 281 func (t Producers) Swap(i, j int) { t[i], t[j] = t[j], t[i] } 282 283 func (t Producers) HTTPAddrs() []string { 284 var addrs []string 285 for _, p := range t { 286 addrs = append(addrs, p.HTTPAddress()) 287 } 288 return addrs 289 } 290 291 func (t Producers) Search(needle string) *Producer { 292 for _, producer := range t { 293 if needle == producer.HTTPAddress() { 294 return producer 295 } 296 } 297 return nil 298 } 299 300 type ProducersByHost struct { 301 Producers 302 } 303 304 func (c ProducersByHost) Less(i, j int) bool { 305 return c.Producers[i].Hostname < c.Producers[j].Hostname 306 }