diff --git a/server/monitor.go b/server/monitor.go index ec82d0bb..238f787d 100644 --- a/server/monitor.go +++ b/server/monitor.go @@ -67,8 +67,8 @@ const defaultStackBufSize = 10000 func (s *Server) HandleConnz(w http.ResponseWriter, r *http.Request) { sortOpt := SortOpt(r.URL.Query().Get("sort")) - // If no sort option given, sort by cid - if sortOpt == "" { + // If no sort option given or sort is by uptime, then sort by cid + if sortOpt == "" || sortOpt == byUptime { sortOpt = byCid } else if !sortOpt.IsValid() { w.WriteHeader(http.StatusBadRequest) diff --git a/server/monitor_sort_opts.go b/server/monitor_sort_opts.go index 91bce567..00a23d8c 100644 --- a/server/monitor_sort_opts.go +++ b/server/monitor_sort_opts.go @@ -15,12 +15,13 @@ const ( byInBytes = "bytes_from" byLast = "last" byIdle = "idle" + byUptime = "uptime" ) // IsValid determines if a sort option is valid func (s SortOpt) IsValid() bool { switch s { - case "", byCid, bySubs, byPending, byOutMsgs, byInMsgs, byOutBytes, byInBytes, byLast, byIdle: + case "", byCid, bySubs, byPending, byOutMsgs, byInMsgs, byOutBytes, byInBytes, byLast, byIdle, byUptime: return true default: return false diff --git a/server/monitor_test.go b/server/monitor_test.go index 27a6fed9..93239f34 100644 --- a/server/monitor_test.go +++ b/server/monitor_test.go @@ -877,6 +877,45 @@ func TestConnzSortedByLast(t *testing.T) { } } +func TestConnzSortedByUptime(t *testing.T) { + s := runMonitorServer() + defer s.Shutdown() + + clients := make([]*nats.Conn, 5) + for i := range clients { + clients[i] = createClientConnSubscribeAndPublish(t) + defer clients[i].Close() + time.Sleep(250 * time.Millisecond) + } + + url := fmt.Sprintf("http://localhost:%d/", MONITOR_PORT) + resp, err := http.Get(url + "connz?sort=uptime") + if err != nil { + t.Fatalf("Expected no error: Got %v\n", err) + } + if resp.StatusCode != 200 { + t.Fatalf("Expected a 200 response, got %d\n", resp.StatusCode) + } + defer resp.Body.Close() + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + t.Fatalf("Got an error reading the body: %v\n", err) + } + + c := Connz{} + if err := json.Unmarshal(body, &c); err != nil { + t.Fatalf("Got an error unmarshalling the body: %v\n", err) + } + + // uptime is generated by Conn.Start + if c.Conns[0].Start.UnixNano() > c.Conns[1].Start.UnixNano() || + c.Conns[1].Start.UnixNano() > c.Conns[2].Start.UnixNano() || + c.Conns[2].Start.UnixNano() > c.Conns[3].Start.UnixNano() { + t.Fatalf("Expected conns sorted in ascending order by start time, got %v > one of [%v, %v, %v]\n", + c.Conns[0].Start, c.Conns[1].Start, c.Conns[2].Start, c.Conns[3].Start) + } +} + func TestConnzSortedByIdle(t *testing.T) { s := runMonitorServer() defer s.Shutdown()