forked from tendermint/tendermint
-
Notifications
You must be signed in to change notification settings - Fork 2
/
ton.go
100 lines (86 loc) · 2.32 KB
/
ton.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
package main
import (
"fmt"
"io"
"os"
"text/tabwriter"
"time"
monitor "github.com/tendermint/tendermint/tools/tm-monitor/monitor"
)
const (
// Default refresh rate - 200ms
defaultRefreshRate = time.Millisecond * 200
)
// Ton - table of nodes.
//
// It produces the unordered list of nodes and updates it periodically.
//
// Default output is stdout, but it could be changed. Note if you want for
// refresh to work properly, output must support [ANSI escape
// codes](http://en.wikipedia.org/wiki/ANSI_escape_code).
//
// Ton was inspired by [Linux top
// program](https://en.wikipedia.org/wiki/Top_(software)) as the name suggests.
type Ton struct {
monitor *monitor.Monitor
RefreshRate time.Duration
Output io.Writer
quit chan struct{}
}
func NewTon(m *monitor.Monitor) *Ton {
return &Ton{
RefreshRate: defaultRefreshRate,
Output: os.Stdout,
quit: make(chan struct{}),
monitor: m,
}
}
func (o *Ton) Start() {
clearScreen(o.Output)
o.Print()
go o.refresher()
}
func (o *Ton) Print() {
moveCursor(o.Output, 1, 1)
o.printHeader()
fmt.Println()
o.printTable()
}
func (o *Ton) Stop() {
close(o.quit)
}
func (o *Ton) printHeader() {
n := o.monitor.Network
fmt.Fprintf(o.Output, "%v up %.2f%%\n", n.StartTime(), n.Uptime())
fmt.Println()
fmt.Fprintf(o.Output, "Height: %d\n", n.Height)
fmt.Fprintf(o.Output, "Avg block time: %.3f ms\n", n.AvgBlockTime)
fmt.Fprintf(o.Output, "Avg tx throughput: %.0f per sec\n", n.AvgTxThroughput)
fmt.Fprintf(o.Output, "Avg block latency: %.3f ms\n", n.AvgBlockLatency)
fmt.Fprintf(o.Output, "Active nodes: %d/%d (health: %s) Validators: %d\n", n.NumNodesMonitoredOnline, n.NumNodesMonitored, n.GetHealthString(), n.NumValidators)
}
func (o *Ton) printTable() {
w := tabwriter.NewWriter(o.Output, 0, 0, 5, ' ', 0)
fmt.Fprintln(w, "NAME\tHEIGHT\tBLOCK LATENCY\tONLINE\tVALIDATOR\t")
for _, n := range o.monitor.Nodes {
fmt.Fprintln(w, fmt.Sprintf("%s\t%d\t%.3f ms\t%v\t%v\t", n.Name, n.Height, n.BlockLatency, n.Online, n.IsValidator))
}
w.Flush()
}
// Internal loop for refreshing
func (o *Ton) refresher() {
for {
select {
case <-o.quit:
return
case <-time.After(o.RefreshRate):
o.Print()
}
}
}
func clearScreen(w io.Writer) {
fmt.Fprint(w, "\033[2J")
}
func moveCursor(w io.Writer, x int, y int) {
fmt.Fprintf(w, "\033[%d;%dH", x, y)
}