diff --git a/cli/net.go b/cli/net.go index 5248a1410..2846b8511 100644 --- a/cli/net.go +++ b/cli/net.go @@ -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 }, } diff --git a/cmd/lotus-miner/sealing.go b/cmd/lotus-miner/sealing.go index 6ee10dacc..21e672e38 100644 --- a/cmd/lotus-miner/sealing.go +++ b/cmd/lotus-miner/sealing.go @@ -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))