github.com/evdatsion/aphelion-dpos-bft@v0.32.1/tools/tm-monitor/ton.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"os"
     7  	"text/tabwriter"
     8  	"time"
     9  
    10  	monitor "github.com/evdatsion/aphelion-dpos-bft/tools/tm-monitor/monitor"
    11  )
    12  
    13  const (
    14  	// Default refresh rate - 200ms
    15  	defaultRefreshRate = time.Millisecond * 200
    16  )
    17  
    18  // Ton - table of nodes.
    19  //
    20  // It produces the unordered list of nodes and updates it periodically.
    21  //
    22  // Default output is stdout, but it could be changed. Note if you want for
    23  // refresh to work properly, output must support [ANSI escape
    24  // codes](http://en.wikipedia.org/wiki/ANSI_escape_code).
    25  //
    26  // Ton was inspired by [Linux top
    27  // program](https://en.wikipedia.org/wiki/Top_(software)) as the name suggests.
    28  type Ton struct {
    29  	monitor *monitor.Monitor
    30  
    31  	RefreshRate time.Duration
    32  	Output      io.Writer
    33  	quit        chan struct{}
    34  }
    35  
    36  func NewTon(m *monitor.Monitor) *Ton {
    37  	return &Ton{
    38  		RefreshRate: defaultRefreshRate,
    39  		Output:      os.Stdout,
    40  		quit:        make(chan struct{}),
    41  		monitor:     m,
    42  	}
    43  }
    44  
    45  func (o *Ton) Start() {
    46  	clearScreen(o.Output)
    47  	o.Print()
    48  	go o.refresher()
    49  }
    50  
    51  func (o *Ton) Print() {
    52  	moveCursor(o.Output, 1, 1)
    53  	o.printHeader()
    54  	fmt.Println()
    55  	o.printTable()
    56  }
    57  
    58  func (o *Ton) Stop() {
    59  	close(o.quit)
    60  }
    61  
    62  func (o *Ton) printHeader() {
    63  	n := o.monitor.Network
    64  	fmt.Fprintf(o.Output, "%v up %.2f%%\n", n.StartTime(), n.Uptime())
    65  	fmt.Println()
    66  	fmt.Fprintf(o.Output, "Height: %d\n", n.Height)
    67  	fmt.Fprintf(o.Output, "Avg block time: %.3f ms\n", n.AvgBlockTime)
    68  	fmt.Fprintf(o.Output, "Avg tx throughput: %.0f per sec\n", n.AvgTxThroughput)
    69  	fmt.Fprintf(o.Output, "Avg block latency: %.3f ms\n", n.AvgBlockLatency)
    70  	fmt.Fprintf(o.Output, "Active nodes: %d/%d (health: %s) Validators: %d\n", n.NumNodesMonitoredOnline, n.NumNodesMonitored, n.GetHealthString(), n.NumValidators)
    71  }
    72  
    73  func (o *Ton) printTable() {
    74  	w := tabwriter.NewWriter(o.Output, 0, 0, 5, ' ', 0)
    75  	fmt.Fprintln(w, "NAME\tHEIGHT\tBLOCK LATENCY\tONLINE\tVALIDATOR\t")
    76  	for _, n := range o.monitor.Nodes {
    77  		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))
    78  	}
    79  	w.Flush()
    80  }
    81  
    82  // Internal loop for refreshing
    83  func (o *Ton) refresher() {
    84  	for {
    85  		select {
    86  		case <-o.quit:
    87  			return
    88  		case <-time.After(o.RefreshRate):
    89  			o.Print()
    90  		}
    91  	}
    92  }
    93  
    94  func clearScreen(w io.Writer) {
    95  	fmt.Fprint(w, "\033[2J")
    96  }
    97  
    98  func moveCursor(w io.Writer, x int, y int) {
    99  	fmt.Fprintf(w, "\033[%d;%dH", x, y)
   100  }