mirror of
https://github.com/gogrlx/nats-server.git
synced 2026-04-02 03:38:42 -07:00
Fix to allow sorting by rtt for connz.
Signed-off-by: Derek Collison <derek@nats.io>
This commit is contained in:
@@ -137,6 +137,9 @@ type ConnInfo struct {
|
||||
NameTag string `json:"name_tag,omitempty"`
|
||||
Tags jwt.TagList `json:"tags,omitempty"`
|
||||
MQTTClient string `json:"mqtt_client,omitempty"` // This is the MQTT client id
|
||||
|
||||
// Internal
|
||||
rtt int64 // For fast sorting
|
||||
}
|
||||
|
||||
// TLSPeerCert contains basic information about a TLS peer certificate
|
||||
@@ -190,9 +193,7 @@ func (s *Server) Connz(opts *ConnzOptions) (*Connz, error) {
|
||||
|
||||
if opts != nil {
|
||||
// If no sort option given or sort is by uptime, then sort by cid
|
||||
if opts.Sort == _EMPTY_ {
|
||||
sortOpt = ByCid
|
||||
} else {
|
||||
if opts.Sort != _EMPTY_ {
|
||||
sortOpt = opts.Sort
|
||||
if !sortOpt.IsValid() {
|
||||
return nil, fmt.Errorf("invalid sorting option: %s", sortOpt)
|
||||
@@ -498,6 +499,8 @@ func (s *Server) Connz(opts *ConnzOptions) (*Connz, error) {
|
||||
sort.Sort(sort.Reverse(byStop{pconns}))
|
||||
case ByReason:
|
||||
sort.Sort(byReason{pconns})
|
||||
case ByRTT:
|
||||
sort.Sort(sort.Reverse(byRTT{pconns}))
|
||||
}
|
||||
|
||||
minoff := c.Offset
|
||||
@@ -527,6 +530,10 @@ func (s *Server) Connz(opts *ConnzOptions) (*Connz, error) {
|
||||
// Fills in the ConnInfo from the client.
|
||||
// client should be locked.
|
||||
func (ci *ConnInfo) fill(client *client, nc net.Conn, now time.Time, auth bool) {
|
||||
// For fast sort if required.
|
||||
rtt := client.getRTT()
|
||||
ci.rtt = int64(rtt)
|
||||
|
||||
ci.Cid = client.cid
|
||||
ci.MQTTClient = client.getMQTTClientID()
|
||||
ci.Kind = client.kindString()
|
||||
@@ -535,7 +542,7 @@ func (ci *ConnInfo) fill(client *client, nc net.Conn, now time.Time, auth bool)
|
||||
ci.LastActivity = client.last
|
||||
ci.Uptime = myUptime(now.Sub(client.start))
|
||||
ci.Idle = myUptime(now.Sub(client.last))
|
||||
ci.RTT = client.getRTT().String()
|
||||
ci.RTT = rtt.String()
|
||||
ci.OutMsgs = client.outMsgs
|
||||
ci.OutBytes = client.outBytes
|
||||
ci.NumSubs = uint32(len(client.subs))
|
||||
@@ -584,7 +591,7 @@ func (c *client) getRTT() time.Duration {
|
||||
if c.rtt == 0 {
|
||||
// If a real client, go ahead and send ping now to get a value
|
||||
// for RTT. For tests and telnet, or if client is closing, etc skip.
|
||||
if c.opts.Lang != "" {
|
||||
if c.opts.Lang != _EMPTY_ {
|
||||
c.sendRTTPingLocked()
|
||||
}
|
||||
return 0
|
||||
|
||||
@@ -45,7 +45,7 @@ const (
|
||||
ByUptime SortOpt = "uptime" // By the amount of time connections exist
|
||||
ByStop SortOpt = "stop" // By the stop time for a closed connection
|
||||
ByReason SortOpt = "reason" // By the reason for a closed connection
|
||||
|
||||
ByRTT SortOpt = "rtt" // By the round trip time
|
||||
)
|
||||
|
||||
// Individual sort options provide the Less for sort.Interface. Len and Swap are on cList.
|
||||
@@ -139,10 +139,15 @@ func (l byReason) Less(i, j int) bool {
|
||||
return l.ConnInfos[i].Reason < l.ConnInfos[j].Reason
|
||||
}
|
||||
|
||||
// RTT - Default is descending
|
||||
type byRTT struct{ ConnInfos }
|
||||
|
||||
func (l byRTT) Less(i, j int) bool { return l.ConnInfos[i].rtt < l.ConnInfos[j].rtt }
|
||||
|
||||
// IsValid determines if a sort option is valid
|
||||
func (s SortOpt) IsValid() bool {
|
||||
switch s {
|
||||
case "", ByCid, ByStart, BySubs, ByPending, ByOutMsgs, ByInMsgs, ByOutBytes, ByInBytes, ByLast, ByIdle, ByUptime, ByStop, ByReason:
|
||||
case _EMPTY_, ByCid, ByStart, BySubs, ByPending, ByOutMsgs, ByInMsgs, ByOutBytes, ByInBytes, ByLast, ByIdle, ByUptime, ByStop, ByReason, ByRTT:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2013-2022 The NATS Authors
|
||||
// Copyright 2013-2023 The NATS Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
@@ -4686,3 +4686,51 @@ func TestMonitorConnzOperatorModeFilterByUser(t *testing.T) {
|
||||
require_True(t, ci.AuthorizedUser == aUser)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMonitorConnzSortByRTT(t *testing.T) {
|
||||
s := runMonitorServer()
|
||||
defer s.Shutdown()
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
nc, err := nats.Connect(s.ClientURL())
|
||||
require_NoError(t, err)
|
||||
defer nc.Close()
|
||||
}
|
||||
|
||||
connz := pollConz(t, s, 1, _EMPTY_, &ConnzOptions{Sort: ByRTT})
|
||||
require_True(t, connz.NumConns == 10)
|
||||
|
||||
var rtt int64
|
||||
for _, ci := range connz.Conns {
|
||||
if rtt == 0 {
|
||||
rtt = ci.rtt
|
||||
} else {
|
||||
if ci.rtt > rtt {
|
||||
t.Fatalf("RTT not in descending order: %v vs %v",
|
||||
time.Duration(rtt), time.Duration(ci.rtt))
|
||||
}
|
||||
rtt = ci.rtt
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure url works as well.
|
||||
url := fmt.Sprintf("http://127.0.0.1:%d/connz?sort=rtt", s.MonitorAddr().Port)
|
||||
connz = pollConz(t, s, 0, url, nil)
|
||||
require_True(t, connz.NumConns == 10)
|
||||
|
||||
rtt = 0
|
||||
for _, ci := range connz.Conns {
|
||||
crttd, err := time.ParseDuration(ci.RTT)
|
||||
require_NoError(t, err)
|
||||
crtt := int64(crttd)
|
||||
if rtt == 0 {
|
||||
rtt = crtt
|
||||
} else {
|
||||
if crtt > rtt {
|
||||
t.Fatalf("RTT not in descending order: %v vs %v",
|
||||
time.Duration(rtt), time.Duration(crtt))
|
||||
}
|
||||
rtt = ci.rtt
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user