feat: cli: Nicer net stat

This commit is contained in:
Łukasz Magiera 2022-06-02 16:53:58 +02:00
parent 6b68071d2f
commit 3de6856058
2 changed files with 98 additions and 24 deletions

View File

@ -4,6 +4,7 @@ import (
"context"
"encoding/json"
"fmt"
"math"
"os"
"sort"
"strings"
@ -11,9 +12,11 @@ import (
"time"
"github.com/dustin/go-humanize"
"github.com/fatih/color"
"github.com/urfave/cli/v2"
"golang.org/x/xerrors"
"github.com/libp2p/go-libp2p-core/network"
"github.com/libp2p/go-libp2p-core/peer"
protocol "github.com/libp2p/go-libp2p-core/protocol"
"github.com/multiformats/go-multiaddr"
@ -701,9 +704,34 @@ var NetBlockListCmd = &cli.Command{
},
}
var BarCols = float64(64)
func BarString(total, y, g float64) string {
yBars := int(math.Round(y / total * BarCols))
gBars := int(math.Round(g / total * BarCols))
if yBars < 0 {
yBars = 0
}
if gBars < 0 {
gBars = 0
}
eBars := int(BarCols) - yBars - gBars
var barString = color.YellowString(strings.Repeat("|", yBars)) +
color.GreenString(strings.Repeat("|", gBars))
if eBars >= 0 {
barString += strings.Repeat(" ", eBars)
}
return barString
}
var NetStatCmd = &cli.Command{
Name: "stat",
Usage: "Report resource usage for a scope",
Name: "stat",
Usage: "Report resource usage for a scope",
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "json",
},
},
ArgsUsage: "scope",
Description: `Report resource usage for a scope.
@ -731,11 +759,72 @@ var NetStatCmd = &cli.Command{
result, err := api.NetStat(ctx, scope)
if err != nil {
return err
return xerrors.Errorf("get stat: %w", err)
}
enc := json.NewEncoder(os.Stdout)
return enc.Encode(result)
if cctx.Bool("json") {
enc := json.NewEncoder(os.Stdout)
return enc.Encode(result)
}
printScope := func(stat *network.ScopeStat, scope string) {
if stat == nil {
return
}
limit, err := api.NetLimit(ctx, scope)
if err != nil {
fmt.Printf("error: %s\n", color.RedString("%s", err))
}
fmt.Printf("%s\n", scope)
fmt.Printf("\tmemory: [%s] %s/%s\n", BarString(float64(limit.Memory), 0, float64(stat.Memory)),
types.SizeStr(types.NewInt(uint64(stat.Memory))),
types.SizeStr(types.NewInt(uint64(limit.Memory))))
fmt.Printf("\tstreams in: [%s] %d/%d\n", BarString(float64(limit.StreamsInbound), 0, float64(stat.NumStreamsInbound)), stat.NumStreamsInbound, limit.StreamsInbound)
fmt.Printf("\tstreams out: [%s] %d/%d\n", BarString(float64(limit.StreamsOutbound), 0, float64(stat.NumStreamsOutbound)), stat.NumStreamsOutbound, limit.StreamsOutbound)
fmt.Printf("\tconn in: [%s] %d/%d\n", BarString(float64(limit.ConnsInbound), 0, float64(stat.NumConnsInbound)), stat.NumConnsInbound, limit.ConnsInbound)
fmt.Printf("\tconn out: [%s] %d/%d\n", BarString(float64(limit.ConnsOutbound), 0, float64(stat.NumConnsOutbound)), stat.NumConnsOutbound, limit.ConnsOutbound)
fmt.Printf("\tfile desc: [%s] %d/%d\n", BarString(float64(limit.FD), 0, float64(stat.NumFD)), stat.NumFD, limit.FD)
fmt.Println()
}
printScope(result.System, "system")
printScope(result.Transient, "transient")
printScopes := func(name string, st map[string]network.ScopeStat) {
type namedStat struct {
name string
stat network.ScopeStat
}
stats := make([]namedStat, 0, len(st))
for n, stat := range st {
stats = append(stats, namedStat{
name: n,
stat: stat,
})
}
sort.Slice(stats, func(i, j int) bool {
if stats[i].stat.Memory == stats[j].stat.Memory {
return stats[i].name < stats[j].name
}
return stats[i].stat.Memory > stats[j].stat.Memory
})
for _, stat := range stats {
printScope(&stat.stat, name+stat.name)
}
}
printScopes("svc:", result.Services)
printScopes("proto:", result.Protocols)
printScopes("peer:", result.Peers)
return nil
},
}

View File

@ -5,7 +5,6 @@ import (
"encoding/json"
"fmt"
"io"
"math"
"net/http"
"os"
"sort"
@ -42,20 +41,6 @@ var sealingCmd = &cli.Command{
},
}
var barCols = float64(64)
func barString(total, y, g float64) string {
yBars := int(math.Round(y / total * barCols))
gBars := int(math.Round(g / total * barCols))
eBars := int(barCols) - yBars - gBars
var barString = color.YellowString(strings.Repeat("|", yBars)) +
color.GreenString(strings.Repeat("|", gBars))
if eBars >= 0 {
barString += strings.Repeat(" ", eBars)
}
return barString
}
func workersCmd(sealing bool) *cli.Command {
return &cli.Command{
Name: "workers",
@ -170,7 +155,7 @@ func workersCmd(sealing bool) *cli.Command {
// CPU use
fmt.Printf("\tCPU: [%s] %d/%d core(s) in use\n",
barString(float64(stat.Info.Resources.CPUs), 0, float64(stat.CpuUse)), stat.CpuUse, stat.Info.Resources.CPUs)
lcli.BarString(float64(stat.Info.Resources.CPUs), 0, float64(stat.CpuUse)), stat.CpuUse, stat.Info.Resources.CPUs)
// RAM use
@ -181,7 +166,7 @@ func workersCmd(sealing bool) *cli.Command {
if ramUsed > ramTasks {
ramReserved = ramUsed - ramTasks
}
ramBar := barString(float64(ramTotal), float64(ramReserved), float64(ramTasks))
ramBar := lcli.BarString(float64(ramTotal), float64(ramReserved), float64(ramTasks))
fmt.Printf("\tRAM: [%s] %d%% %s/%s\n", ramBar,
(ramTasks+ramReserved)*100/stat.Info.Resources.MemPhysical,
@ -197,7 +182,7 @@ func workersCmd(sealing bool) *cli.Command {
if vmemUsed > vmemTasks {
vmemReserved = vmemUsed - vmemTasks
}
vmemBar := barString(float64(vmemTotal), float64(vmemReserved), float64(vmemTasks))
vmemBar := lcli.BarString(float64(vmemTotal), float64(vmemReserved), float64(vmemTasks))
fmt.Printf("\tVMEM: [%s] %d%% %s/%s\n", vmemBar,
(vmemTasks+vmemReserved)*100/vmemTotal,
@ -207,7 +192,7 @@ func workersCmd(sealing bool) *cli.Command {
// GPU use
if len(stat.Info.Resources.GPUs) > 0 {
gpuBar := barString(float64(len(stat.Info.Resources.GPUs)), 0, stat.GpuUsed)
gpuBar := lcli.BarString(float64(len(stat.Info.Resources.GPUs)), 0, stat.GpuUsed)
fmt.Printf("\tGPU: [%s] %.f%% %.2f/%d gpu(s) in use\n", color.GreenString(gpuBar),
stat.GpuUsed*100/float64(len(stat.Info.Resources.GPUs)),
stat.GpuUsed, len(stat.Info.Resources.GPUs))