Merge pull request #4108 from filecoin-project/feat/nice-sectorslist
Improve miner sectors list UX
This commit is contained in:
commit
7699f195f1
@ -1423,7 +1423,7 @@ func toChannelOutput(useColor bool, otherPartyColumn string, channel lapi.DataTr
|
||||
otherPartyColumn: otherParty,
|
||||
"Root Cid": rootCid,
|
||||
"Initiated?": initiated,
|
||||
"Transferred": channel.Transferred,
|
||||
"Transferred": units.BytesSize(float64(channel.Transferred)),
|
||||
"Voucher": voucher,
|
||||
"Message": channel.Message,
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/hako/durafmt"
|
||||
"github.com/ipfs/go-cid"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
@ -36,11 +37,11 @@ func parseTipSet(ctx context.Context, api api.FullNode, vals []string) (*types.T
|
||||
func EpochTime(curr, e abi.ChainEpoch) string {
|
||||
switch {
|
||||
case curr > e:
|
||||
return fmt.Sprintf("%d (%s ago)", e, time.Second*time.Duration(int64(build.BlockDelaySecs)*int64(curr-e)))
|
||||
return fmt.Sprintf("%d (%s ago)", e, durafmt.Parse(time.Second*time.Duration(int64(build.BlockDelaySecs)*int64(curr-e))).LimitFirstN(2))
|
||||
case curr == e:
|
||||
return fmt.Sprintf("%d (now)", e)
|
||||
case curr < e:
|
||||
return fmt.Sprintf("%d (in %s)", e, time.Second*time.Duration(int64(build.BlockDelaySecs)*int64(e-curr)))
|
||||
return fmt.Sprintf("%d (in %s)", e, durafmt.Parse(time.Second*time.Duration(int64(build.BlockDelaySecs)*int64(e-curr))).LimitFirstN(2))
|
||||
}
|
||||
|
||||
panic("math broke")
|
||||
|
@ -5,19 +5,22 @@ import (
|
||||
"os"
|
||||
"sort"
|
||||
"strconv"
|
||||
"text/tabwriter"
|
||||
"time"
|
||||
|
||||
"github.com/docker/go-units"
|
||||
"github.com/fatih/color"
|
||||
"github.com/urfave/cli/v2"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/go-state-types/big"
|
||||
|
||||
miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/lib/tablewriter"
|
||||
|
||||
lcli "github.com/filecoin-project/lotus/cli"
|
||||
sealing "github.com/filecoin-project/lotus/extern/storage-sealing"
|
||||
@ -144,8 +147,19 @@ var sectorsListCmd = &cli.Command{
|
||||
Name: "show-removed",
|
||||
Usage: "show removed sectors",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "color",
|
||||
Aliases: []string{"c"},
|
||||
Value: true,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "fast",
|
||||
Usage: "don't show on-chain info for better performance",
|
||||
},
|
||||
},
|
||||
Action: func(cctx *cli.Context) error {
|
||||
color.NoColor = !cctx.Bool("color")
|
||||
|
||||
nodeApi, closer, err := lcli.GetStorageMinerAPI(cctx)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -170,7 +184,12 @@ var sectorsListCmd = &cli.Command{
|
||||
return err
|
||||
}
|
||||
|
||||
activeSet, err := fullApi.StateMinerActiveSectors(ctx, maddr, types.EmptyTSK)
|
||||
head, err := fullApi.ChainHead(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
activeSet, err := fullApi.StateMinerActiveSectors(ctx, maddr, head.Key())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -179,7 +198,7 @@ var sectorsListCmd = &cli.Command{
|
||||
activeIDs[info.SectorNumber] = struct{}{}
|
||||
}
|
||||
|
||||
sset, err := fullApi.StateMinerSectors(ctx, maddr, nil, types.EmptyTSK)
|
||||
sset, err := fullApi.StateMinerSectors(ctx, maddr, nil, head.Key())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -192,12 +211,26 @@ var sectorsListCmd = &cli.Command{
|
||||
return list[i] < list[j]
|
||||
})
|
||||
|
||||
w := tabwriter.NewWriter(os.Stdout, 8, 4, 1, ' ', 0)
|
||||
tw := tablewriter.New(
|
||||
tablewriter.Col("ID"),
|
||||
tablewriter.Col("State"),
|
||||
tablewriter.Col("OnChain"),
|
||||
tablewriter.Col("Active"),
|
||||
tablewriter.Col("Expiration"),
|
||||
tablewriter.Col("Deals"),
|
||||
tablewriter.Col("DealWeight"),
|
||||
tablewriter.NewLineCol("Error"),
|
||||
tablewriter.NewLineCol("EarlyExpiration"))
|
||||
|
||||
fast := cctx.Bool("fast")
|
||||
|
||||
for _, s := range list {
|
||||
st, err := nodeApi.SectorsStatus(ctx, s, false)
|
||||
st, err := nodeApi.SectorsStatus(ctx, s, !fast)
|
||||
if err != nil {
|
||||
fmt.Fprintf(w, "%d:\tError: %s\n", s, err)
|
||||
tw.Write(map[string]interface{}{
|
||||
"ID": s,
|
||||
"Error": err,
|
||||
})
|
||||
continue
|
||||
}
|
||||
|
||||
@ -205,20 +238,60 @@ var sectorsListCmd = &cli.Command{
|
||||
_, inSSet := commitedIDs[s]
|
||||
_, inASet := activeIDs[s]
|
||||
|
||||
_, _ = fmt.Fprintf(w, "%d: %s\tsSet: %s\tactive: %s\ttktH: %d\tseedH: %d\tdeals: %v\t toUpgrade:%t\n",
|
||||
s,
|
||||
st.State,
|
||||
yesno(inSSet),
|
||||
yesno(inASet),
|
||||
st.Ticket.Epoch,
|
||||
st.Seed.Epoch,
|
||||
st.Deals,
|
||||
st.ToUpgrade,
|
||||
)
|
||||
dw := .0
|
||||
if st.Expiration-st.Activation > 0 {
|
||||
dw = float64(big.Div(st.DealWeight, big.NewInt(int64(st.Expiration-st.Activation))).Uint64())
|
||||
}
|
||||
|
||||
var deals int
|
||||
for _, deal := range st.Deals {
|
||||
if deal != 0 {
|
||||
deals++
|
||||
}
|
||||
}
|
||||
|
||||
exp := st.Expiration
|
||||
if st.OnTime > 0 && st.OnTime < exp {
|
||||
exp = st.OnTime // Can be different when the sector was CC upgraded
|
||||
}
|
||||
|
||||
m := map[string]interface{}{
|
||||
"ID": s,
|
||||
"State": color.New(stateOrder[sealing.SectorState(st.State)].col).Sprint(st.State),
|
||||
"OnChain": yesno(inSSet),
|
||||
"Active": yesno(inASet),
|
||||
}
|
||||
|
||||
if deals > 0 {
|
||||
m["Deals"] = color.GreenString("%d", deals)
|
||||
} else {
|
||||
m["Deals"] = color.BlueString("CC")
|
||||
if st.ToUpgrade {
|
||||
m["Deals"] = color.CyanString("CC(upgrade)")
|
||||
}
|
||||
}
|
||||
|
||||
if !fast {
|
||||
if !inSSet {
|
||||
m["Expiration"] = "n/a"
|
||||
} else {
|
||||
m["Expiration"] = lcli.EpochTime(head.Height(), exp)
|
||||
|
||||
if !fast && deals > 0 {
|
||||
m["DealWeight"] = units.BytesSize(dw)
|
||||
}
|
||||
|
||||
if st.Early > 0 {
|
||||
m["EarlyExpiration"] = color.YellowString(lcli.EpochTime(head.Height(), st.Early))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tw.Write(m)
|
||||
}
|
||||
}
|
||||
|
||||
return w.Flush()
|
||||
return tw.Flush(os.Stdout)
|
||||
},
|
||||
}
|
||||
|
||||
@ -447,7 +520,7 @@ var sectorsUpdateCmd = &cli.Command{
|
||||
|
||||
func yesno(b bool) string {
|
||||
if b {
|
||||
return "YES"
|
||||
return color.GreenString("YES")
|
||||
}
|
||||
return "NO"
|
||||
return color.RedString("NO")
|
||||
}
|
||||
|
1
go.mod
1
go.mod
@ -46,6 +46,7 @@ require (
|
||||
github.com/google/uuid v1.1.1
|
||||
github.com/gorilla/mux v1.7.4
|
||||
github.com/gorilla/websocket v1.4.2
|
||||
github.com/hako/durafmt v0.0.0-20200710122514-c0fb7b4da026
|
||||
github.com/hannahhoward/go-pubsub v0.0.0-20200423002714-8d62886cc36e
|
||||
github.com/hashicorp/go-multierror v1.1.0
|
||||
github.com/hashicorp/golang-lru v0.5.4
|
||||
|
2
go.sum
2
go.sum
@ -417,6 +417,8 @@ github.com/gxed/go-shellwords v1.0.3/go.mod h1:N7paucT91ByIjmVJHhvoarjoQnmsi3Jd3
|
||||
github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU=
|
||||
github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48=
|
||||
github.com/gxed/pubsub v0.0.0-20180201040156-26ebdf44f824/go.mod h1:OiEWyHgK+CWrmOlVquHaIK1vhpUJydC9m0Je6mhaiNE=
|
||||
github.com/hako/durafmt v0.0.0-20200710122514-c0fb7b4da026 h1:BpJ2o0OR5FV7vrkDYfXYVJQeMNWa8RhklZOpW2ITAIQ=
|
||||
github.com/hako/durafmt v0.0.0-20200710122514-c0fb7b4da026/go.mod h1:5Scbynm8dF1XAPwIwkGPqzkM/shndPm79Jd1003hTjE=
|
||||
github.com/hannahhoward/cbor-gen-for v0.0.0-20200817222906-ea96cece81f1 h1:F9k+7wv5OIk1zcq23QpdiL0hfDuXPjuOmMNaC6fgQ0Q=
|
||||
github.com/hannahhoward/cbor-gen-for v0.0.0-20200817222906-ea96cece81f1/go.mod h1:jvfsLIxk0fY/2BKSQ1xf2406AKA5dwMmKKv0ADcOfN8=
|
||||
github.com/hannahhoward/go-pubsub v0.0.0-20200423002714-8d62886cc36e h1:3YKHER4nmd7b5qy5t0GWDTwSn4OyRgfAXSmo6VnryBY=
|
||||
|
@ -12,6 +12,7 @@ import (
|
||||
type Column struct {
|
||||
Name string
|
||||
SeparateLine bool
|
||||
Lines int
|
||||
}
|
||||
|
||||
type TableWriter struct {
|
||||
@ -50,6 +51,7 @@ cloop:
|
||||
for i, column := range w.cols {
|
||||
if column.Name == col {
|
||||
byColID[i] = fmt.Sprint(val)
|
||||
w.cols[i].Lines++
|
||||
continue cloop
|
||||
}
|
||||
}
|
||||
@ -58,6 +60,7 @@ cloop:
|
||||
w.cols = append(w.cols, Column{
|
||||
Name: col,
|
||||
SeparateLine: false,
|
||||
Lines: 1,
|
||||
})
|
||||
}
|
||||
|
||||
@ -77,7 +80,11 @@ func (w *TableWriter) Flush(out io.Writer) error {
|
||||
|
||||
w.rows = append([]map[int]string{header}, w.rows...)
|
||||
|
||||
for col := range w.cols {
|
||||
for col, c := range w.cols {
|
||||
if c.Lines == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, row := range w.rows {
|
||||
val, found := row[col]
|
||||
if !found {
|
||||
@ -94,9 +101,13 @@ func (w *TableWriter) Flush(out io.Writer) error {
|
||||
cols := make([]string, len(w.cols))
|
||||
|
||||
for ci, col := range w.cols {
|
||||
if col.Lines == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
e, _ := row[ci]
|
||||
pad := colLengths[ci] - cliStringLength(e) + 2
|
||||
if !col.SeparateLine {
|
||||
if !col.SeparateLine && col.Lines > 0 {
|
||||
e = e + strings.Repeat(" ", pad)
|
||||
if _, err := fmt.Fprint(out, e); err != nil {
|
||||
return err
|
||||
|
Loading…
Reference in New Issue
Block a user