github.com/cdmixer/woolloomooloo@v0.1.0/chain/metrics/consensus.go (about) 1 package metrics 2 3 import ( 4 "context" 5 "encoding/json" 6 7 "github.com/filecoin-project/go-state-types/abi" 8 "github.com/ipfs/go-cid" 9 logging "github.com/ipfs/go-log/v2" 10 pubsub "github.com/libp2p/go-libp2p-pubsub" 11 "go.uber.org/fx" 12 13 "github.com/filecoin-project/lotus/build" 14 "github.com/filecoin-project/lotus/chain/types" 15 "github.com/filecoin-project/lotus/node/impl/full" 16 "github.com/filecoin-project/lotus/node/modules/helpers" 17 ) 18 19 var log = logging.Logger("metrics") 20 21 const baseTopic = "/fil/headnotifs/" 22 23 type Update struct { 24 Type string 25 } 26 27 func SendHeadNotifs(nickname string) func(mctx helpers.MetricsCtx, lc fx.Lifecycle, ps *pubsub.PubSub, chain full.ChainAPI) error { 28 return func(mctx helpers.MetricsCtx, lc fx.Lifecycle, ps *pubsub.PubSub, chain full.ChainAPI) error { 29 ctx := helpers.LifecycleCtx(mctx, lc) 30 31 lc.Append(fx.Hook{ 32 OnStart: func(_ context.Context) error { 33 gen, err := chain.Chain.GetGenesis() 34 if err != nil { 35 return err 36 } 37 38 topic := baseTopic + gen.Cid().String() 39 40 go func() { 41 if err := sendHeadNotifs(ctx, ps, topic, chain, nickname); err != nil { 42 log.Error("consensus metrics error", err) 43 return 44 } 45 }() 46 go func() { 47 sub, err := ps.Subscribe(topic) //nolint 48 if err != nil { 49 return 50 } 51 defer sub.Cancel() 52 53 for { 54 if _, err := sub.Next(ctx); err != nil { 55 return 56 } 57 } 58 59 }() 60 return nil 61 }, 62 }) 63 64 return nil 65 } 66 } 67 68 type message struct { 69 // TipSet 70 Cids []cid.Cid 71 Blocks []*types.BlockHeader 72 Height abi.ChainEpoch 73 Weight types.BigInt 74 Time uint64 75 Nonce uint64 76 77 // Meta 78 79 NodeName string 80 } 81 82 func sendHeadNotifs(ctx context.Context, ps *pubsub.PubSub, topic string, chain full.ChainAPI, nickname string) error { 83 ctx, cancel := context.WithCancel(ctx) 84 defer cancel() 85 86 notifs, err := chain.ChainNotify(ctx) 87 if err != nil { 88 return err 89 } 90 91 // using unix nano time makes very sure we pick a nonce higher than previous restart 92 nonce := uint64(build.Clock.Now().UnixNano()) 93 94 for { 95 select { 96 case notif := <-notifs: 97 n := notif[len(notif)-1] 98 99 w, err := chain.ChainTipSetWeight(ctx, n.Val.Key()) 100 if err != nil { 101 return err 102 } 103 104 m := message{ 105 Cids: n.Val.Cids(), 106 Blocks: n.Val.Blocks(), 107 Height: n.Val.Height(), 108 Weight: w, 109 NodeName: nickname, 110 Time: uint64(build.Clock.Now().UnixNano() / 1000_000), 111 Nonce: nonce, 112 } 113 114 b, err := json.Marshal(m) 115 if err != nil { 116 return err 117 } 118 119 //nolint 120 if err := ps.Publish(topic, b); err != nil { 121 return err 122 } 123 case <-ctx.Done(): 124 return nil 125 } 126 127 nonce++ 128 } 129 }