-
Notifications
You must be signed in to change notification settings - Fork 2
/
tendermint.go
127 lines (105 loc) · 3 KB
/
tendermint.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package monitor
import (
"fmt"
"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/server"
tmcli "github.com/fibonacci-chain/fbc/libs/tendermint/rpc/client"
tmhttp "github.com/fibonacci-chain/fbc/libs/tendermint/rpc/client/http"
"github.com/spf13/viper"
"strings"
"sync"
)
const (
loopBackAddr = "tcp://127.0.0.1"
)
var (
tmMonitor *TendermintMonitor
initTmMonitor sync.Once
)
// GetTendermintMonitor gets the global instance of TendermintMonitor
func GetTendermintMonitor() *TendermintMonitor {
initTmMonitor.Do(func() {
tmMonitor = NewTendermintMonitor(viper.GetString(server.FlagLocalRpcPort))
})
return tmMonitor
}
// TendermintMonitor - structure of monitor for block/mempool monitoring
type TendermintMonitor struct {
enable bool
rpcClient tmcli.Client
status tendermintStatus
}
// NewTendermintMonitor creates a new instance of TendermintMonitor
func NewTendermintMonitor(portInput string) *TendermintMonitor {
if len(portInput) == 0 {
// disable the tendermint monitor
return &TendermintMonitor{
enable: false,
}
}
rpcCli, err := tmhttp.New(fmt.Sprintf("%s:%d", loopBackAddr, ParsePort(portInput)), "/websocket")
if err != nil {
panic(fmt.Sprintf("fail to init a rpc client in tendermint monitor: %s", err.Error()))
}
return &TendermintMonitor{
enable: true,
rpcClient: rpcCli,
}
}
// reset resets the status of TendermintMonitor
func (tm *TendermintMonitor) reset() {
tm.status.blockSize = -1
tm.status.uncomfirmedTxNum = -1
tm.status.uncormfirmedTxTotalSize = -1
}
// Run starts monitoring
func (tm *TendermintMonitor) Run(height int64) error {
// TendermintMonitor disabled
if !tm.enable {
return nil
}
tm.reset()
err := tm.getTendermintStatus(height)
if err != nil {
return err
}
return nil
}
// GetResultString gets the format string result
func (tm *TendermintMonitor) GetResultString() string {
// TendermintMonitor disabled
if !tm.enable {
return ""
}
return fmt.Sprintf(",BlockSize<%.2fKB>, MemPoolTx<%d>, MemPoolSize<%.2fKB>,",
float64(tm.status.blockSize)/1024,
tm.status.uncomfirmedTxNum,
float64(tm.status.uncormfirmedTxTotalSize)/1024)
}
type tendermintStatus struct {
blockSize int
uncomfirmedTxNum int
uncormfirmedTxTotalSize int64
}
func (tm *TendermintMonitor) getTendermintStatus(height int64) error {
block, err := tm.rpcClient.Block(&height)
if err != nil {
return fmt.Errorf("failed to query block on height %d", height)
}
uncomfirmedRes, err := tm.rpcClient.NumUnconfirmedTxs()
if err != nil {
return fmt.Errorf("failed to query mempool result on height %d", height)
}
// update status
tm.status.blockSize = block.Block.Size()
tm.status.uncomfirmedTxNum = uncomfirmedRes.Total
tm.status.uncormfirmedTxTotalSize = uncomfirmedRes.TotalBytes
return nil
}
// CombineMonitorsRes combines all the monitors' results
func CombineMonitorsRes(res ...string) string {
var builder strings.Builder
for _, r := range res {
builder.WriteString(r)
}
return strings.Trim(strings.TrimSpace(builder.String()), ",")
}