diff --git a/chain/sync.go b/chain/sync.go index f5f915183..d04feab9c 100644 --- a/chain/sync.go +++ b/chain/sync.go @@ -23,6 +23,7 @@ import ( "github.com/libp2p/go-libp2p-core/peer" cbg "github.com/whyrusleeping/cbor-gen" "github.com/whyrusleeping/pubsub" + "go.opencensus.io/stats" "go.opencensus.io/trace" "golang.org/x/xerrors" @@ -38,6 +39,7 @@ import ( "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/lib/sigs" + "github.com/filecoin-project/lotus/metrics" ) var log = logging.Logger("chain") @@ -394,6 +396,9 @@ func (syncer *Syncer) Sync(ctx context.Context, maybeHead *types.TipSet) error { ) } + // Record current network chain height when sync is called + stats.Record(ctx, metrics.ChainHeight.M(int64(maybeHead.Height()))) + if syncer.store.GetHeaviestTipSet().ParentWeight().GreaterThan(maybeHead.ParentWeight()) { return nil } @@ -1038,6 +1043,8 @@ func (syncer *Syncer) syncMessagesAndCheckState(ctx context.Context, headers []* return xerrors.Errorf("message processing failed: %w", err) } + // Set current node sync height + stats.Record(ctx, metrics.ChainNodeHeight.M(int64(fts.TipSet().Height()))) ss.SetHeight(fts.TipSet().Height()) return nil diff --git a/cmd/lotus/daemon.go b/cmd/lotus/daemon.go index 2d2759cf4..ad3a3b823 100644 --- a/cmd/lotus/daemon.go +++ b/cmd/lotus/daemon.go @@ -24,6 +24,7 @@ import ( "github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/vm" + "github.com/filecoin-project/lotus/metrics" "github.com/filecoin-project/lotus/node" "github.com/filecoin-project/lotus/node/modules" "github.com/filecoin-project/lotus/node/modules/testing" @@ -36,12 +37,6 @@ const ( preSealedSectorsFlag = "genesis-presealed-sectors" ) -var ( - lotusInfo = stats.Int64("info", "Arbitrary counter to tag lotus info to", stats.UnitDimensionless) - version, _ = tag.NewKey("version") - commit, _ = tag.NewKey("commit") -) - // DaemonCmd is the `go-lotus daemon` command var DaemonCmd = &cli.Command{ Name: "daemon", @@ -99,7 +94,7 @@ var DaemonCmd = &cli.Command{ defer pprof.StopCPUProfile() } - ctx, _ := tag.New(context.Background(), tag.Insert(version, build.BuildVersion), tag.Insert(commit, build.CurrentCommit)) + ctx, _ := tag.New(context.Background(), tag.Insert(metrics.Version, build.BuildVersion), tag.Insert(metrics.Commit, build.CurrentCommit)) { dir, err := homedir.Expand(cctx.String("repo")) if err != nil { @@ -180,21 +175,15 @@ var DaemonCmd = &cli.Command{ return xerrors.Errorf("initializing node: %w", err) } - // We are using this metric to tag info about lotus even though - // it doesn't contain any actual metrics + // Register all metric views if err = view.Register( - &view.View{ - Name: "info", - Description: "Lotus node information", - Measure: lotusInfo, - Aggregation: view.LastValue(), - TagKeys: []tag.Key{version, commit}, - }, + metrics.DefaultViews..., ); err != nil { log.Fatalf("Cannot register the view: %v", err) } + // Set the metric to one so it is published to the exporter - stats.Record(ctx, lotusInfo.M(1)) + stats.Record(ctx, metrics.LotusInfo.M(1)) endpoint, err := r.APIEndpoint() if err != nil { diff --git a/lib/jsonrpc/handler.go b/lib/jsonrpc/handler.go index 0edc25fa9..b42b9d925 100644 --- a/lib/jsonrpc/handler.go +++ b/lib/jsonrpc/handler.go @@ -9,6 +9,9 @@ import ( "io" "reflect" + "github.com/filecoin-project/lotus/metrics" + "go.opencensus.io/stats" + "go.opencensus.io/tag" "go.opencensus.io/trace" "go.opencensus.io/trace/propagation" "golang.org/x/xerrors" @@ -151,12 +154,15 @@ func (handlers) getSpan(ctx context.Context, req request) (context.Context, *tra } func (h handlers) handle(ctx context.Context, req request, w func(func(io.Writer)), rpcError rpcErrFunc, done func(keepCtx bool), chOut chanOut) { + // Not sure if we need to sanitize the incoming req.Method or not. ctx, span := h.getSpan(ctx, req) + ctx, _ = tag.New(context.Background(), tag.Insert(metrics.RPCMethod, req.Method)) defer span.End() handler, ok := h[req.Method] if !ok { rpcError(w, &req, rpcMethodNotFound, fmt.Errorf("method '%s' not found", req.Method)) + stats.Record(ctx, metrics.RPCInvalidMethod.M(1)) done(false) return } @@ -201,6 +207,7 @@ func (h handlers) handle(ctx context.Context, req request, w func(func(io.Writer if req.ID == nil { return // notification } + stats.Record(ctx, metrics.RPCRequestSuccess.M(1)) /////////////////// @@ -245,5 +252,6 @@ func (h handlers) handle(ctx context.Context, req request, w func(func(io.Writer log.Error(err) return } + stats.Record(ctx, metrics.RPCResponseSuccess.M(1)) }) } diff --git a/metrics/metrics.go b/metrics/metrics.go new file mode 100644 index 000000000..5e1b78f93 --- /dev/null +++ b/metrics/metrics.go @@ -0,0 +1,64 @@ +package metrics + +import ( + "go.opencensus.io/stats" + "go.opencensus.io/stats/view" + "go.opencensus.io/tag" +) + +// Global Tags +var ( + Version, _ = tag.NewKey("version") + Commit, _ = tag.NewKey("commit") + RPCMethod, _ = tag.NewKey("method") +) + +// Measures +var ( + LotusInfo = stats.Int64("info", "Arbitrary counter to tag lotus info to", stats.UnitDimensionless) + ChainHeight = stats.Int64("chain/height", "Current Height of the chain", stats.UnitDimensionless) + ChainNodeHeight = stats.Int64("chain/node_height", "Current Height of the node", stats.UnitDimensionless) + PeerCount = stats.Int64("peer/count", "Current number of FIL peers", stats.UnitDimensionless) + RPCInvalidMethod = stats.Int64("rpc/invalid_method", "Total number of invalid RPC methods called", stats.UnitDimensionless) + RPCRequestSuccess = stats.Int64("rpc/request_success", "Total number of successful requests handled", stats.UnitDimensionless) + RPCResponseSuccess = stats.Int64("rpc/response_success", "Total number of succeessful responses handled", stats.UnitDimensionless) +) + +// DefaultViews is an array of Consensus views for metric gathering purposes +var DefaultViews = []*view.View{ + &view.View{ + Name: "info", + Description: "Lotus node information", + Measure: LotusInfo, + Aggregation: view.LastValue(), + TagKeys: []tag.Key{Version, Commit}, + }, + &view.View{ + Measure: ChainHeight, + Aggregation: view.LastValue(), + }, + &view.View{ + Measure: ChainNodeHeight, + Aggregation: view.LastValue(), + }, + // All RPC related metrics should at the very least tag the RPCMethod + &view.View{ + Measure: RPCInvalidMethod, + Aggregation: view.Count(), + TagKeys: []tag.Key{RPCMethod}, + }, + &view.View{ + Measure: RPCRequestSuccess, + Aggregation: view.Count(), + TagKeys: []tag.Key{RPCMethod}, + }, + &view.View{ + Measure: RPCResponseSuccess, + Aggregation: view.Count(), + TagKeys: []tag.Key{RPCMethod}, + }, + &view.View{ + Measure: PeerCount, + Aggregation: view.LastValue(), + }, +} diff --git a/peermgr/peermgr.go b/peermgr/peermgr.go index e1b41e14d..490f2b229 100644 --- a/peermgr/peermgr.go +++ b/peermgr/peermgr.go @@ -5,7 +5,9 @@ import ( "sync" "time" + "github.com/filecoin-project/lotus/metrics" "github.com/filecoin-project/lotus/node/modules/dtypes" + "go.opencensus.io/stats" "go.uber.org/fx" host "github.com/libp2p/go-libp2p-core/host" @@ -115,6 +117,7 @@ func (pmgr *PeerMgr) Run(ctx context.Context) { } else if pcount > pmgr.maxFilPeers { log.Debug("peer count about threshold: %d > %d", pcount, pmgr.maxFilPeers) } + stats.Record(ctx, metrics.PeerCount.M(int64(pmgr.getPeerCount()))) } } }