Skip to content

Commit

Permalink
Merge pull request #5767 from filecoin-project/feat/node-status-api
Browse files Browse the repository at this point in the history
node status api
  • Loading branch information
vyzo authored Mar 16, 2021
2 parents a54c6bf + 522ffab commit 4498354
Show file tree
Hide file tree
Showing 9 changed files with 239 additions and 7 deletions.
5 changes: 5 additions & 0 deletions api/api_full.go
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,11 @@ type FullNode interface {
PaychVoucherList(context.Context, address.Address) ([]*paych.SignedVoucher, error)
PaychVoucherSubmit(context.Context, address.Address, *paych.SignedVoucher, []byte, []byte) (cid.Cid, error)

// MethodGroup: Node
// These methods are general node management and status commands

NodeStatus(ctx context.Context, inclChainStatus bool) (NodeStatus, error)

// CreateBackup creates node backup onder the specified file name. The
// method requires that the lotus daemon is running with the
// LOTUS_BACKUP_BASE_PATH environment variable set to some path, and that
Expand Down
7 changes: 6 additions & 1 deletion api/apistruct/struct.go
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,8 @@ type FullNodeStruct struct {
PaychVoucherList func(context.Context, address.Address) ([]*paych.SignedVoucher, error) `perm:"write"`
PaychVoucherSubmit func(context.Context, address.Address, *paych.SignedVoucher, []byte, []byte) (cid.Cid, error) `perm:"sign"`

CreateBackup func(ctx context.Context, fpath string) error `perm:"admin"`
CreateBackup func(ctx context.Context, fpath string) error `perm:"admin"`
NodeStatus func(context.Context, bool) (api.NodeStatus, error) `perm:"read"`
}
}

Expand Down Expand Up @@ -1260,6 +1261,10 @@ func (c *FullNodeStruct) CreateBackup(ctx context.Context, fpath string) error {
return c.Internal.CreateBackup(ctx, fpath)
}

func (c *FullNodeStruct) NodeStatus(ctx context.Context, inclChainStatus bool) (api.NodeStatus, error) {
return c.Internal.NodeStatus(ctx, inclChainStatus)
}

// StorageMinerStruct

func (c *StorageMinerStruct) ActorAddress(ctx context.Context) (address.Address, error) {
Expand Down
15 changes: 15 additions & 0 deletions api/mocks/mock_full.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 21 additions & 0 deletions api/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,3 +115,24 @@ type ConnMgrInfo struct {
Tags map[string]int
Conns map[string]time.Time
}

type NodeStatus struct {
SyncStatus NodeSyncStatus
PeerStatus NodePeerStatus
ChainStatus NodeChainStatus
}

type NodeSyncStatus struct {
Epoch uint64
Behind uint64
}

type NodePeerStatus struct {
PeersToPublishMsgs int
PeersToPublishBlocks int
}

type NodeChainStatus struct {
BlocksPerTipsetLast100 float64
BlocksPerTipsetLastFinality float64
}
1 change: 1 addition & 0 deletions cli/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ var Commands = []*cli.Command{
WithCategory("developer", fetchParamCmd),
WithCategory("network", netCmd),
WithCategory("network", syncCmd),
WithCategory("status", statusCmd),
pprofCmd,
VersionCmd,
}
Expand Down
60 changes: 60 additions & 0 deletions cli/status.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package cli

import (
"fmt"

"github.com/urfave/cli/v2"

"github.com/filecoin-project/lotus/build"
)

var statusCmd = &cli.Command{
Name: "status",
Usage: "Check node status",
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "chain",
Usage: "include chain health status",
},
},

Action: func(cctx *cli.Context) error {
apic, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := ReqContext(cctx)

inclChainStatus := cctx.Bool("chain")

status, err := apic.NodeStatus(ctx, inclChainStatus)
if err != nil {
return err
}

fmt.Printf("Sync Epoch: %d\n", status.SyncStatus.Epoch)
fmt.Printf("Epochs Behind: %d\n", status.SyncStatus.Behind)
fmt.Printf("Peers to Publish Messages: %d\n", status.PeerStatus.PeersToPublishMsgs)
fmt.Printf("Peers to Publish Blocks: %d\n", status.PeerStatus.PeersToPublishBlocks)

if inclChainStatus && status.SyncStatus.Epoch > uint64(build.Finality) {
var ok100, okFin string
if status.ChainStatus.BlocksPerTipsetLast100 >= 4.75 {
ok100 = "[OK]"
} else {
ok100 = "[UNHEALTHY]"
}
if status.ChainStatus.BlocksPerTipsetLastFinality >= 4.75 {
okFin = "[OK]"
} else {
okFin = "[UNHEALTHY]"
}

fmt.Printf("Blocks per TipSet in last 100 epochs: %f %s\n", status.ChainStatus.BlocksPerTipsetLast100, ok100)
fmt.Printf("Blocks per TipSet in last finality: %f %s\n", status.ChainStatus.BlocksPerTipsetLastFinality, okFin)
}

return nil
},
}
36 changes: 36 additions & 0 deletions documentation/en/api-methods.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@
* [NetPeerInfo](#NetPeerInfo)
* [NetPeers](#NetPeers)
* [NetPubsubScores](#NetPubsubScores)
* [Node](#Node)
* [NodeStatus](#NodeStatus)
* [Paych](#Paych)
* [PaychAllocateLane](#PaychAllocateLane)
* [PaychAvailableFunds](#PaychAvailableFunds)
Expand Down Expand Up @@ -2938,6 +2940,40 @@ Inputs: `null`

Response: `null`

## Node
These methods are general node management and status commands


### NodeStatus
There are not yet any comments for this method.

Perms: read

Inputs:
```json
[
true
]
```

Response:
```json
{
"SyncStatus": {
"Epoch": 42,
"Behind": 42
},
"PeerStatus": {
"PeersToPublishMsgs": 123,
"PeersToPublishBlocks": 123
},
"ChainStatus": {
"BlocksPerTipsetLast100": 12.3,
"BlocksPerTipsetLastFinality": 12.3
}
}
```

## Paych
The Paych methods are for interacting with and managing payment channels

Expand Down
82 changes: 81 additions & 1 deletion node/impl/full.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,21 @@ package impl

import (
"context"
"time"

"github.com/libp2p/go-libp2p-core/peer"

logging "github.com/ipfs/go-log/v2"

"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/node/impl/client"
"github.com/filecoin-project/lotus/node/impl/common"
"github.com/filecoin-project/lotus/node/impl/full"
"github.com/filecoin-project/lotus/node/impl/market"
"github.com/filecoin-project/lotus/node/impl/paych"
"github.com/filecoin-project/lotus/node/modules/dtypes"
"github.com/filecoin-project/lotus/node/modules/lp2p"
)

var log = logging.Logger("node")
Expand All @@ -30,11 +35,86 @@ type FullNodeAPI struct {
full.SyncAPI
full.BeaconAPI

DS dtypes.MetadataDS
DS dtypes.MetadataDS
NetworkName dtypes.NetworkName
}

func (n *FullNodeAPI) CreateBackup(ctx context.Context, fpath string) error {
return backup(n.DS, fpath)
}

func (n *FullNodeAPI) NodeStatus(ctx context.Context, inclChainStatus bool) (status api.NodeStatus, err error) {
curTs, err := n.ChainHead(ctx)
if err != nil {
return status, err
}

status.SyncStatus.Epoch = uint64(curTs.Height())
timestamp := time.Unix(int64(curTs.MinTimestamp()), 0)
delta := time.Since(timestamp).Seconds()
status.SyncStatus.Behind = uint64(delta / 30)

// get peers in the messages and blocks topics
peersMsgs := make(map[peer.ID]struct{})
peersBlocks := make(map[peer.ID]struct{})

for _, p := range n.PubSub.ListPeers(build.MessagesTopic(n.NetworkName)) {
peersMsgs[p] = struct{}{}
}

for _, p := range n.PubSub.ListPeers(build.BlocksTopic(n.NetworkName)) {
peersBlocks[p] = struct{}{}
}

// get scores for all connected and recent peers
scores, err := n.NetPubsubScores(ctx)
if err != nil {
return status, err
}

for _, score := range scores {
if score.Score.Score > lp2p.PublishScoreThreshold {
_, inMsgs := peersMsgs[score.ID]
if inMsgs {
status.PeerStatus.PeersToPublishMsgs++
}

_, inBlocks := peersBlocks[score.ID]
if inBlocks {
status.PeerStatus.PeersToPublishBlocks++
}
}
}

if inclChainStatus && status.SyncStatus.Epoch > uint64(build.Finality) {
blockCnt := 0
ts := curTs

for i := 0; i < 100; i++ {
blockCnt += len(ts.Blocks())
tsk := ts.Parents()
ts, err = n.ChainGetTipSet(ctx, tsk)
if err != nil {
return status, err
}
}

status.ChainStatus.BlocksPerTipsetLast100 = float64(blockCnt) / 100

for i := 100; i < int(build.Finality); i++ {
blockCnt += len(ts.Blocks())
tsk := ts.Parents()
ts, err = n.ChainGetTipSet(ctx, tsk)
if err != nil {
return status, err
}
}

status.ChainStatus.BlocksPerTipsetLastFinality = float64(blockCnt) / float64(build.Finality)

}

return status, nil
}

var _ api.FullNode = &FullNodeAPI{}
19 changes: 14 additions & 5 deletions node/modules/lp2p/pubsub.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,15 @@ func init() {
pubsub.GossipSubHistoryLength = 10
pubsub.GossipSubGossipFactor = 0.1
}

const (
GossipScoreThreshold = -500
PublishScoreThreshold = -1000
GraylistScoreThreshold = -2500
AcceptPXScoreThreshold = 1000
OpportunisticGraftScoreThreshold = 3.5
)

func ScoreKeeper() *dtypes.ScoreKeeper {
return new(dtypes.ScoreKeeper)
}
Expand Down Expand Up @@ -256,11 +265,11 @@ func GossipSub(in GossipIn) (service *pubsub.PubSub, err error) {
Topics: topicParams,
},
&pubsub.PeerScoreThresholds{
GossipThreshold: -500,
PublishThreshold: -1000,
GraylistThreshold: -2500,
AcceptPXThreshold: 1000,
OpportunisticGraftThreshold: 3.5,
GossipThreshold: GossipScoreThreshold,
PublishThreshold: PublishScoreThreshold,
GraylistThreshold: GraylistScoreThreshold,
AcceptPXThreshold: AcceptPXScoreThreshold,
OpportunisticGraftThreshold: OpportunisticGraftScoreThreshold,
},
),
pubsub.WithPeerScoreInspect(in.Sk.Update, 10*time.Second),
Expand Down

0 comments on commit 4498354

Please sign in to comment.