Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New gateways report #1200

Merged
merged 1 commit into from
Dec 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
172 changes: 154 additions & 18 deletions cli/server_report_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"fmt"
"os"
"sort"
"time"

iu "github.com/nats-io/natscli/internal/util"

Expand Down Expand Up @@ -49,6 +50,7 @@ type SrvReportCmd struct {
stateFilter string
filterReason string
skipDiscoverClusterSize bool
gatewayName string
}

type srvReportAccountInfo struct {
Expand Down Expand Up @@ -103,10 +105,14 @@ func configureServerReportCommand(srv *fisk.CmdClause) {
jsz.Flag("sort", "Sort by a specific property (name,cluster,streams,consumers,msgs,mbytes,mem,file,api,err").Default("cluster").EnumVar(&c.sort, "name", "cluster", "streams", "consumers", "msgs", "mbytes", "bytes", "mem", "file", "store", "api", "err")
jsz.Flag("compact", "Compact server names").Default("true").BoolVar(&c.compact)

routes := report.Command("cluster", "Report on Cluster connections").Alias("route").Action(c.reportRoute)
routes := report.Command("routes", "Report on Route (cluster) connections").Alias("route").Action(c.reportRoute)
routes.Flag("cluster", "Limits the report to a specific cluster").StringVar(&c.cluster)
routes.Flag("sort", "Sort by a specific property (server,cluster,name,account,subs,in-bytes,out-bytes)").EnumVar(&c.sort, "server", "cluster", "name", "account", "subs", "in-bytes", "out-bytes")

gateways := report.Command("gateways", "Repost on Gateway (super cluster) connections").Alias("super").Alias("gateway").Action(c.reportGateway)
gateways.Flag("filter-name", "Limits responses to a certain name").StringVar(&c.gatewayName)
gateways.Flag("sort", "Sorts by a specific property (server,cluster)").EnumVar(&c.sort, "server", "cluster")

cpu := report.Command("cpu", "Reports on CPU uage").Action(c.reportCPU)
addFilterOpts(cpu)
cpu.Flag("json", "Produce JSON output").Short('j').UnNegatableBoolVar(&c.json)
Expand All @@ -116,6 +122,147 @@ func configureServerReportCommand(srv *fisk.CmdClause) {
mem.Flag("json", "Produce JSON output").Short('j').UnNegatableBoolVar(&c.json)
}

func (c *SrvReportCmd) parseRtt(rtt string, crit time.Duration) string {
d, err := time.ParseDuration(rtt)
if err != nil {
return rtt
}

if d < crit {
return f(d)
}

return color.RedString(f(d))
}

func (c *SrvReportCmd) reportGateway(_ *fisk.ParseContext) error {
nc, _, err := prepareHelper("", natsOpts()...)
if err != nil {
return err
}

req := &server.GatewayzOptions{Name: c.gatewayName, Accounts: true}
results, err := doReq(req, "$SYS.REQ.SERVER.PING.GATEWAYZ", c.waitFor, nc)
if err != nil {
return err
}

var gateways []server.ServerAPIGatewayzResponse
for _, result := range results {
g := &server.ServerAPIGatewayzResponse{}
err := json.Unmarshal(result, g)
if err != nil {
return err
}

if g.Error != nil {
return fmt.Errorf("%v", g.Error.Error())
}

gateways = append(gateways, *g)
}

// TODO: sort
sort.Slice(gateways, func(i, j int) bool {
switch c.sort {
case "server":
return c.boolReverse(gateways[i].Server.Name < gateways[j].Server.Name)
case "cluster":
return c.boolReverse(gateways[i].Server.Cluster < gateways[j].Server.Cluster)
}

return c.boolReverse(false)
})

tbl := iu.NewTableWriter(opts(), "Super Cluster Report")
tbl.AddHeaders("Server", "Name", "Port", "Kind", "Connection", "Uptime", "RTT", "Bytes", "Accounts")

var lastServer, lastName, lastDirection string
var totalBytes int64
var totalServers, totalGateways int

for _, g := range gateways {
sname := g.Server.Name
totalServers++

if sname == lastServer {
sname = ""
}
lastServer = g.Server.Name

cname := g.Server.Cluster
if cname == lastName {
cname = ""
}
lastName = g.Server.Name

tbl.AddRow(
sname,
cname,
g.Data.Port,
"",
"",
"",
"",
"",
"",
)

for gname, conns := range g.Data.InboundGateways {
for _, conn := range conns {
totalGateways++
direction := ""
if direction == lastDirection {
direction = "Inbound"
}
lastDirection = direction

uptime := conn.Connection.Uptime
if d, err := time.ParseDuration(uptime); err == nil {
uptime = f(d)
}

totalBytes += conn.Connection.InBytes
tbl.AddRow(
"", "", "",
direction,
fmt.Sprintf("%s %s:%d", gname, conn.Connection.IP, conn.Connection.Port),
uptime,
c.parseRtt(conn.Connection.RTT, 300*time.Millisecond),
fiBytes(uint64(conn.Connection.InBytes)),
f(len(conn.Accounts)),
)
}
}

for gname, conn := range g.Data.OutboundGateways {
totalGateways++
direction := ""
if direction == lastDirection {
direction = "Outbound"
}
lastDirection = direction

totalBytes += conn.Connection.OutBytes
tbl.AddRow(
"", "", "",
direction,
fmt.Sprintf("%s %s:%d", gname, conn.Connection.IP, conn.Connection.Port),
conn.Connection.Uptime,
c.parseRtt(conn.Connection.RTT, 300*time.Millisecond),
fiBytes(uint64(conn.Connection.OutBytes)),
f(len(conn.Accounts)),
)
}
}

tbl.AddFooter(f(totalServers), "", "", "", f(totalGateways), "", "", fiBytes(uint64(totalBytes)), "")

fmt.Println(tbl.Render())

return nil
}

func (c *SrvReportCmd) reportRoute(_ *fisk.ParseContext) error {
nc, _, err := prepareHelper("", natsOpts()...)
if err != nil {
Expand All @@ -128,20 +275,14 @@ func (c *SrvReportCmd) reportRoute(_ *fisk.ParseContext) error {
return err
}

type serverRoutezMsg struct {
Server server.ServerInfo `json:"server"`
Data server.Routez `json:"data"`
Error *server.ApiError `json:"error,omitempty"`
}

type routeData struct {
server server.ServerInfo
server *server.ServerInfo
routes *server.RouteInfo
}

routes := []routeData{}
for _, result := range results {
r := &serverRoutezMsg{}
r := &server.ServerAPIRoutezResponse{}
err := json.Unmarshal(result, r)
if err != nil {
return err
Expand Down Expand Up @@ -212,7 +353,7 @@ func (c *SrvReportCmd) reportRoute(_ *fisk.ParseContext) error {
r.Account,
fmt.Sprintf("%s:%d", r.IP, r.Port),
f(uptime),
f(r.RTT),
c.parseRtt(r.RTT, 100*time.Millisecond),
f(r.NumSubs),
fiBytes(uint64(r.InBytes)),
fiBytes(uint64(r.OutBytes)),
Expand Down Expand Up @@ -297,14 +438,9 @@ func (c *SrvReportCmd) reportJetStream(_ *fisk.ParseContext) error {
return err
}

type jszr struct {
Data server.JSInfo `json:"data"`
Server server.ServerInfo `json:"server"`
}

var (
names []string
jszResponses []*jszr
jszResponses []*server.ServerAPIJszResponse
apiErrTotal uint64
apiTotal uint64
pendingTotal int
Expand All @@ -322,7 +458,7 @@ func (c *SrvReportCmd) reportJetStream(_ *fisk.ParseContext) error {
renderPending := iu.ServerMinVersion(nc, 2, 10, 21)
renderDomain := false
for _, r := range res {
response := jszr{}
response := &server.ServerAPIJszResponse{}

err = json.Unmarshal(r, &response)
if err != nil {
Expand All @@ -333,7 +469,7 @@ func (c *SrvReportCmd) reportJetStream(_ *fisk.ParseContext) error {
renderDomain = true
}

jszResponses = append(jszResponses, &response)
jszResponses = append(jszResponses, response)
}

sort.Slice(jszResponses, func(i, j int) bool {
Expand Down
17 changes: 8 additions & 9 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,19 @@ require (
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
github.com/klauspost/compress v1.17.11
github.com/mattn/go-isatty v0.0.20
github.com/nats-io/jsm.go v0.1.1-0.20241211112912-e379cb1c3877
github.com/nats-io/jwt/v2 v2.7.2
github.com/nats-io/nats-server/v2 v2.11.0-dev.0.20241127165413-cfaad68e19db
github.com/nats-io/jsm.go v0.1.1-0.20241211113853-2da637dcc792
github.com/nats-io/jwt/v2 v2.7.3
github.com/nats-io/nats-server/v2 v2.11.0-dev.0.20241214163630-5431acbed222
github.com/nats-io/nats.go v1.37.0
github.com/nats-io/nkeys v0.4.8
github.com/nats-io/nkeys v0.4.9
github.com/nats-io/nuid v1.0.1
github.com/prometheus/client_golang v1.20.5
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1
github.com/synadia-io/jwt-auth-builder.go v0.0.0-20240829124321-43722a8ce3ce
github.com/tylertreat/hdrhistogram-writer v0.0.0-20210816161836-2e440612a39f
golang.org/x/crypto v0.29.0
golang.org/x/crypto v0.31.0
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f
golang.org/x/term v0.26.0
golang.org/x/term v0.27.0
gopkg.in/gizak/termui.v1 v1.0.0-20151021151108-e62b5929642a
gopkg.in/yaml.v3 v3.0.1
)
Expand All @@ -42,7 +42,6 @@ require (
github.com/Masterminds/semver/v3 v3.2.1 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/goccy/go-json v0.10.3 // indirect
github.com/google/go-tpm v0.9.1 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gosuri/uilive v0.0.4 // indirect
Expand All @@ -64,8 +63,8 @@ require (
github.com/shopspring/decimal v1.4.0 // indirect
github.com/spf13/cast v1.7.0 // indirect
golang.org/x/net v0.31.0 // indirect
golang.org/x/sys v0.27.0 // indirect
golang.org/x/text v0.20.0 // indirect
golang.org/x/sys v0.28.0 // indirect
golang.org/x/text v0.21.0 // indirect
golang.org/x/time v0.8.0 // indirect
google.golang.org/protobuf v1.35.2 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
Expand Down
34 changes: 16 additions & 18 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,6 @@ github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA=
github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
Expand Down Expand Up @@ -106,16 +104,16 @@ github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zx
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/nats-io/jsm.go v0.1.1-0.20241211112912-e379cb1c3877 h1:Q9u7cz8jPvNZOvX9Z5TAk0G2To0iZOnNeUL4mVER7P8=
github.com/nats-io/jsm.go v0.1.1-0.20241211112912-e379cb1c3877/go.mod h1:5Wh2yAEPwB+sIAwS4MShJDw+ToZZmayZeqqK1zh+0xQ=
github.com/nats-io/jwt/v2 v2.7.2 h1:SCRjfDLJ2q8naXp8YlGJJS5/yj3wGSODFYVi4nnwVMw=
github.com/nats-io/jwt/v2 v2.7.2/go.mod h1:kB6QUmqHG6Wdrzj0KP2L+OX4xiTPBeV+NHVstFaATXU=
github.com/nats-io/nats-server/v2 v2.11.0-dev.0.20241127165413-cfaad68e19db h1:XSsKLcdTjNwRhhiPS2G193zgh7yCHjT5IRzRyTuI/Y0=
github.com/nats-io/nats-server/v2 v2.11.0-dev.0.20241127165413-cfaad68e19db/go.mod h1:nI8h87Ryi/zcaQcDLSSVbMfomhyck+0oDqxR7NoZX0Y=
github.com/nats-io/jsm.go v0.1.1-0.20241211113853-2da637dcc792 h1:CpciVWtRn7ftIfgETj99Z0qDWF0q0Fv9S7Tq9E3zvhI=
github.com/nats-io/jsm.go v0.1.1-0.20241211113853-2da637dcc792/go.mod h1:5Wh2yAEPwB+sIAwS4MShJDw+ToZZmayZeqqK1zh+0xQ=
github.com/nats-io/jwt/v2 v2.7.3 h1:6bNPK+FXgBeAqdj4cYQ0F8ViHRbi7woQLq4W29nUAzE=
github.com/nats-io/jwt/v2 v2.7.3/go.mod h1:GvkcbHhKquj3pkioy5put1wvPxs78UlZ7D/pY+BgZk4=
github.com/nats-io/nats-server/v2 v2.11.0-dev.0.20241214163630-5431acbed222 h1:ArcRZ6MaxOMdOrwuB46VRCVtoPysqROvjqUzxI6cxqY=
github.com/nats-io/nats-server/v2 v2.11.0-dev.0.20241214163630-5431acbed222/go.mod h1:Ky5GDRMam5300yCf1N+pD0apW7TqfVvTNgYEvbXtnE8=
github.com/nats-io/nats.go v1.37.0 h1:07rauXbVnnJvv1gfIyghFEo6lUcYRY0WXc3x7x0vUxE=
github.com/nats-io/nats.go v1.37.0/go.mod h1:Ubdu4Nh9exXdSz0RVWRFBbRfrbSxOYd26oF0wkWclB8=
github.com/nats-io/nkeys v0.4.8 h1:+wee30071y3vCZAYRsnrmIPaOe47A/SkK/UBDPdIV70=
github.com/nats-io/nkeys v0.4.8/go.mod h1:kqXRgRDPlGy7nGaEDMuYzmiJCIAAWDK0IMBtDmGD0nc=
github.com/nats-io/nkeys v0.4.9 h1:qe9Faq2Gxwi6RZnZMXfmGMZkg3afLLOtrU+gDZJ35b0=
github.com/nats-io/nkeys v0.4.9/go.mod h1:jcMqs+FLG+W5YO36OX6wFIFcmpdAns+w1Wm6D3I/evE=
github.com/nats-io/nsc/v2 v2.8.6-0.20231220104935-3f89317df670 h1:NQzs7g/+Z4kC4XsYsKCQlwRcM4Hk0VyKuz7F4zUgjvQ=
github.com/nats-io/nsc/v2 v2.8.6-0.20231220104935-3f89317df670/go.mod h1:Z2+aDD1PzpXk8kF1ro17cfGBzmBoWPbtvGW8hBssAdA=
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
Expand Down Expand Up @@ -161,8 +159,8 @@ github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5t
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ=
golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg=
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
Expand Down Expand Up @@ -195,18 +193,18 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU=
golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E=
golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg=
golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
Expand Down
Loading