<commit_before>// Copyright 2013-2015 Apcera Inc. All rights reserved.

package server

import (
	"encoding/json"
	"fmt"
	"net"
	"net/http"
	"runtime"
	"strconv"
	"time"

	"github.com/nats-io/gnatsd/sublist"
)

// Snapshot this
var numCores int

func init() {
	numCores = runtime.NumCPU()
}

// Connz represents detailed information on current client connections.
type Connz struct {
	Now      time.Time   `json:"now"`
	NumConns int         `json:"num_connections"`
	Offset   int         `json:"offset"`
	Limit    int         `json:"limit"`
	Conns    []*ConnInfo `json:"connections"`
}

// ConnInfo has detailed information on a per connection basis.
type ConnInfo struct {
	Cid      uint64   `json:"cid"`
	IP       string   `json:"ip"`
	Port     int      `json:"port"`
	Pending  int      `json:"pending_size"`
	InMsgs   int64    `json:"in_msgs"`
	OutMsgs  int64    `json:"out_msgs"`
	InBytes  int64    `json:"in_bytes"`
	OutBytes int64    `json:"out_bytes"`
	NumSubs  uint32   `json:"subscriptions"`
	Lang     string   `json:"lang,omitempty"`
	Version  string   `json:"version,omitempty"`
	Subs     []string `json:"subscriptions_list,omitempty"`
}

const DefaultConnListSize = 1024

// HandleConnz process HTTP requests for connection information.
func (s *Server) HandleConnz(w http.ResponseWriter, r *http.Request) {
	c := &Connz{Conns: []*ConnInfo{}}
	c.Now = time.Now()

	subs, _ := strconv.Atoi(r.URL.Query().Get("subs"))
	c.Offset, _ = strconv.Atoi(r.URL.Query().Get("offset"))
	c.Limit, _ = strconv.Atoi(r.URL.Query().Get("limit"))
	if c.Limit == 0 {
		c.Limit = DefaultConnListSize
	}

	// Walk the list
	s.mu.Lock()
	c.NumConns = len(s.clients)

	i := 0
	for _, client := range s.clients {<commit_msg>Add option for sorting the connz in monitor server<commit_after>// Copyright 2013-2015 Apcera Inc. All rights reserved.

package server

import (
	"encoding/json"
	"fmt"
	"net"
	"net/http"
	"runtime"
	"sort"
	"strconv"
	"time"

	"github.com/nats-io/gnatsd/sublist"
)

// Snapshot this
var numCores int

func init() {
	numCores = runtime.NumCPU()
}

// Connz represents detailed information on current client connections.
type Connz struct {
	Now      time.Time   `json:"now"`
	NumConns int         `json:"num_connections"`
	Offset   int         `json:"offset"`
	Limit    int         `json:"limit"`
	Conns    []*ConnInfo `json:"connections"`
}

// ConnInfo has detailed information on a per connection basis.
type ConnInfo struct {
	Cid      uint64   `json:"cid"`
	IP       string   `json:"ip"`
	Port     int      `json:"port"`
	Pending  int      `json:"pending_size"`
	InMsgs   int64    `json:"in_msgs"`
	OutMsgs  int64    `json:"out_msgs"`
	InBytes  int64    `json:"in_bytes"`
	OutBytes int64    `json:"out_bytes"`
	NumSubs  uint32   `json:"subscriptions"`
	Lang     string   `json:"lang,omitempty"`
	Version  string   `json:"version,omitempty"`
	Subs     []string `json:"subscriptions_list,omitempty"`
}

// Helper types to sort by ConnInfo values
type Pair struct {
	Key int
	Val int
}

type Pairs []Pair

func (d Pairs) Len() int {
	return len(d)
}
func (d Pairs) Swap(i, j int) {
	d[i], d[j] = d[j], d[i]
}
func (d Pairs) Less(i, j int) bool {
	return d[i].Val < d[j].Val
}

const DefaultConnListSize = 1024

// HandleConnz process HTTP requests for connection information.
func (s *Server) HandleConnz(w http.ResponseWriter, r *http.Request) {
	c := &Connz{Conns: []*ConnInfo{}}
	c.Now = time.Now()

	subs, _ := strconv.Atoi(r.URL.Query().Get("subs"))
	c.Offset, _ = strconv.Atoi(r.URL.Query().Get("offset"))
	c.Limit, _ = strconv.Atoi(r.URL.Query().Get("limit"))
	sortOpt := r.URL.Query().Get("sort")

	if c.Limit == 0 {
		c.Limit = DefaultConnListSize
	}

	// Walk the list
	s.mu.Lock()
	c.NumConns = len(s.clients)

	// Filter key value pairs used for sorting in another structure
	pairs := Pairs{}
	switch sortOpt {
	case "cid":
		for i, c := range s.clients {
			pairs = append(pairs, Pair{Key: int(i), Val: int(c.cid)})
		}
	case "subs":
		for i, c := range s.clients {
			pairs = append(pairs, Pair{Key: int(i), Val: int(c.subs.Count())})
		}
	case "msgs_to":
		for i, c := range s.clients {
			pairs = append(pairs, Pair{Key: int(i), Val: int(c.inMsgs)})
		}
	case "msgs_from":
		for i, c := range s.clients {
			pairs = append(pairs, Pair{Key: int(i), Val: int(c.outMsgs)})
		}
	case "bytes_to":
		for i, c := range s.clients {
			pairs = append(pairs, Pair{Key: int(i), Val: int(c.inBytes)})
		}
	case "bytes_from":
		for i, c := range s.clients {
			pairs = append(pairs, Pair{Key: int(i), Val: int(c.outBytes)})
		}
	default:
		// Just get the unsorted keys
		for i, _ := range s.clients {
			pairs = append(pairs, Pair{Key: int(i)})
		}
	}

	// Return in descending order
	if len(pairs) > 0 {
		sort.Sort(sort.Reverse(pairs))
	}

	i := 0
	for _, pair := range pairs {
		client := s.clients[uint64(pair.Key)]
{'fraction_non_alphanumeric': 0.15298738887740335, 'fraction_numerical': 0.011370684308455654, 'mean_word_length': 3.386219401631913, 'pattern_counts': {'":': 6, '<': 4, '<?xml version=': 0, '>': 4, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1410013', 'n_tokens_mistral': 1930, 'n_tokens_neox': 1821, 'n_words': 465}