-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
feat: cli: lotus info cmd #9233
Merged
Merged
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
ab61f4b
`lotus info` cmd
rjan90 683900b
make docsgen-cli
rjan90 8a45e8c
Handle "Default address not set" better
rjan90 870c2f9
Move newline
rjan90 818153a
Put SyncBasefeeCheck in function
rjan90 a31b8a1
Update cli/info.go
rjan90 ab06998
make gen happy
rjan90 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,230 @@ | ||
package cli | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"math" | ||
"os" | ||
"sort" | ||
"strings" | ||
"text/tabwriter" | ||
"time" | ||
|
||
"github.com/dustin/go-humanize" | ||
"github.com/fatih/color" | ||
"github.com/urfave/cli/v2" | ||
|
||
"github.com/filecoin-project/go-fil-markets/storagemarket" | ||
"github.com/filecoin-project/go-state-types/big" | ||
|
||
"github.com/filecoin-project/lotus/api/v1api" | ||
"github.com/filecoin-project/lotus/build" | ||
"github.com/filecoin-project/lotus/chain/types" | ||
) | ||
|
||
var infoCmd = &cli.Command{ | ||
Name: "info", | ||
Usage: "Print node info", | ||
Action: infoCmdAct, | ||
} | ||
|
||
func infoCmdAct(cctx *cli.Context) error { | ||
fullapi, acloser, err := GetFullNodeAPIV1(cctx) | ||
if err != nil { | ||
return err | ||
} | ||
defer acloser() | ||
ctx := ReqContext(cctx) | ||
|
||
network, err := fullapi.StateGetNetworkParams(ctx) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
fmt.Printf("Network: %s\n", network.NetworkName) | ||
fmt.Print("Chain: ") | ||
err = SyncBasefeeCheck(ctx, fullapi) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
status, err := fullapi.NodeStatus(ctx, true) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
fmt.Printf(" [epoch %s]\n", color.MagentaString(("%d"), status.SyncStatus.Epoch)) | ||
fmt.Printf("Peers to: [publish messages %d] [publish blocks %d]\n", status.PeerStatus.PeersToPublishMsgs, status.PeerStatus.PeersToPublishBlocks) | ||
|
||
//Chain health calculated as percentage: amount of blocks in last finality / very healthy amount of blocks in a finality (900 epochs * 5 blocks per tipset) | ||
health := (100 * (900 * status.ChainStatus.BlocksPerTipsetLastFinality) / (900 * 5)) | ||
switch { | ||
case health > 85: | ||
fmt.Printf("Chain health: %.f%% [%s]\n", health, color.GreenString("healthy")) | ||
case health < 85: | ||
fmt.Printf("Chain health: %.f%% [%s]\n", health, color.RedString("unhealthy")) | ||
} | ||
|
||
fmt.Println() | ||
|
||
addr, err := fullapi.WalletDefaultAddress(ctx) | ||
magik6k marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if err == nil { | ||
fmt.Printf("Default address: \n") | ||
balance, err := fullapi.WalletBalance(ctx, addr) | ||
if err != nil { | ||
return err | ||
} | ||
fmt.Printf(" %s [%s]\n", addr.String(), types.FIL(balance).Short()) | ||
} else { | ||
fmt.Printf("Default address: address not set\n") | ||
} | ||
fmt.Println() | ||
|
||
addrs, err := fullapi.WalletList(ctx) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
totalBalance := big.Zero() | ||
for _, addr := range addrs { | ||
totbal, err := fullapi.WalletBalance(ctx, addr) | ||
if err != nil { | ||
return err | ||
} | ||
totalBalance = big.Add(totalBalance, totbal) | ||
} | ||
|
||
switch { | ||
case len(addrs) <= 1: | ||
fmt.Printf("Wallet: %v address\n", len(addrs)) | ||
case len(addrs) > 1: | ||
fmt.Printf("Wallet: %v addresses\n", len(addrs)) | ||
} | ||
fmt.Printf(" Total balance: %s\n", types.FIL(totalBalance).Short()) | ||
|
||
mbLockedSum := big.Zero() | ||
mbAvailableSum := big.Zero() | ||
for _, addr := range addrs { | ||
mbal, err := fullapi.StateMarketBalance(ctx, addr, types.EmptyTSK) | ||
if err != nil { | ||
if strings.Contains(err.Error(), "actor not found") { | ||
continue | ||
} else { | ||
return err | ||
} | ||
} | ||
mbLockedSum = big.Add(mbLockedSum, mbal.Locked) | ||
mbAvailableSum = big.Add(mbAvailableSum, mbal.Escrow) | ||
} | ||
|
||
fmt.Printf(" Market locked: %s\n", types.FIL(mbLockedSum).Short()) | ||
fmt.Printf(" Market available: %s\n", types.FIL(mbAvailableSum).Short()) | ||
|
||
fmt.Println() | ||
|
||
chs, err := fullapi.PaychList(ctx) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
switch { | ||
case len(chs) <= 1: | ||
fmt.Printf("Payment Channels: %v channel\n", len(chs)) | ||
case len(chs) > 1: | ||
fmt.Printf("Payment Channels: %v channels\n", len(chs)) | ||
} | ||
fmt.Println() | ||
|
||
localDeals, err := fullapi.ClientListDeals(ctx) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
var totalSize uint64 | ||
byState := map[storagemarket.StorageDealStatus][]uint64{} | ||
for _, deal := range localDeals { | ||
totalSize += deal.Size | ||
byState[deal.State] = append(byState[deal.State], deal.Size) | ||
} | ||
|
||
fmt.Printf("Deals: %d, %s\n", len(localDeals), types.SizeStr(types.NewInt(totalSize))) | ||
|
||
type stateStat struct { | ||
state storagemarket.StorageDealStatus | ||
count int | ||
bytes uint64 | ||
} | ||
|
||
stateStats := make([]stateStat, 0, len(byState)) | ||
for state, deals := range byState { | ||
if state == storagemarket.StorageDealActive { | ||
state = math.MaxUint64 // for sort | ||
} | ||
|
||
st := stateStat{ | ||
state: state, | ||
count: len(deals), | ||
} | ||
for _, b := range deals { | ||
st.bytes += b | ||
} | ||
|
||
stateStats = append(stateStats, st) | ||
} | ||
|
||
sort.Slice(stateStats, func(i, j int) bool { | ||
return int64(stateStats[i].state) < int64(stateStats[j].state) | ||
}) | ||
|
||
for _, st := range stateStats { | ||
if st.state == math.MaxUint64 { | ||
st.state = storagemarket.StorageDealActive | ||
} | ||
fmt.Printf(" %s: %d deals, %s\n", storagemarket.DealStates[st.state], st.count, types.SizeStr(types.NewInt(st.bytes))) | ||
} | ||
|
||
fmt.Println() | ||
|
||
tw := tabwriter.NewWriter(os.Stdout, 6, 6, 2, ' ', 0) | ||
|
||
s, err := fullapi.NetBandwidthStats(ctx) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
fmt.Printf("Bandwidth:\n") | ||
fmt.Fprintf(tw, "\tTotalIn\tTotalOut\tRateIn\tRateOut\n") | ||
fmt.Fprintf(tw, "\t%s\t%s\t%s/s\t%s/s\n", humanize.Bytes(uint64(s.TotalIn)), humanize.Bytes(uint64(s.TotalOut)), humanize.Bytes(uint64(s.RateIn)), humanize.Bytes(uint64(s.RateOut))) | ||
return tw.Flush() | ||
|
||
} | ||
|
||
func SyncBasefeeCheck(ctx context.Context, fullapi v1api.FullNode) error { | ||
head, err := fullapi.ChainHead(ctx) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
switch { | ||
case time.Now().Unix()-int64(head.MinTimestamp()) < int64(build.BlockDelaySecs*3/2): // within 1.5 epochs | ||
fmt.Printf("[%s]", color.GreenString("sync ok")) | ||
case time.Now().Unix()-int64(head.MinTimestamp()) < int64(build.BlockDelaySecs*5): // within 5 epochs | ||
fmt.Printf("[%s]", color.YellowString("sync slow (%s behind)", time.Now().Sub(time.Unix(int64(head.MinTimestamp()), 0)).Truncate(time.Second))) | ||
default: | ||
fmt.Printf("[%s]", color.RedString("sync behind! (%s behind)", time.Now().Sub(time.Unix(int64(head.MinTimestamp()), 0)).Truncate(time.Second))) | ||
} | ||
basefee := head.MinTicketBlock().ParentBaseFee | ||
gasCol := []color.Attribute{color.FgBlue} | ||
switch { | ||
case basefee.GreaterThan(big.NewInt(7000_000_000)): // 7 nFIL | ||
gasCol = []color.Attribute{color.BgRed, color.FgBlack} | ||
case basefee.GreaterThan(big.NewInt(3000_000_000)): // 3 nFIL | ||
gasCol = []color.Attribute{color.FgRed} | ||
case basefee.GreaterThan(big.NewInt(750_000_000)): // 750 uFIL | ||
gasCol = []color.Attribute{color.FgYellow} | ||
case basefee.GreaterThan(big.NewInt(100_000_000)): // 100 uFIL | ||
gasCol = []color.Attribute{color.FgGreen} | ||
} | ||
fmt.Printf(" [basefee %s]", color.New(gasCol...).Sprint(types.FIL(basefee).Short())) | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For setting the threshold - what % do we see on mainnet?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Its been hovering around 4.8 - 4.9 blocks on average in the last finality on mainnet while I have been monitoring it, so around 96% - 98%
Could maybe try to get some historical avarages as well for setting the threshold of what is unhealthy more realistic.