forked from lesovsky/pgcenter
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathauxinfo.go
158 lines (145 loc) · 4.26 KB
/
auxinfo.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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
// Package top -- auxiliary (aux) stats is not displayed by default and can be enabled if needed.
// Aux stats includes diskstat, nicstat and logtail.
package top
import (
"fmt"
"github.com/jroimartin/gocui"
"github.com/lesovsky/pgcenter/lib/stat"
"os"
)
type auxType int
const (
auxNone auxType = iota
auxDiskstat
auxNicstat
auxLogtail
)
// Prepares aux stat - open or close dedicated 'view' in which stats are displayed, create stats containers or open log.
func showAux(auxtype auxType) func(g *gocui.Gui, _ *gocui.View) error {
return func(g *gocui.Gui, v *gocui.View) error {
// Close 'view' if passed type of aux stats are already displayed
if ctx.aux == auxtype {
closeAuxView(g, v)
return nil
}
// If other type of aux stats are already displayed, ignore it and open 'view' for new aux stats. For diskstat/nicstat
// get number of devices and create appropriate storages. For logtail, a logfile have to be opened. In the end,
// set passed 'auxtype' in the context and aux stats can be displayed in the statsLoop().
switch auxtype {
case auxDiskstat:
if err := openAuxView(g, v); err != nil {
return err
}
nlines, err := stat.CountLines(stat.ProcDiskstats, conn, conninfo.ConnLocal)
if err != nil {
printCmdline(g, err.Error())
closeAuxView(g, nil)
}
stats.Iostat.New(nlines)
ctx.aux = auxtype
printCmdline(g, "Show diskstats")
doUpdate <- 1
case auxNicstat:
if err := openAuxView(g, v); err != nil {
return err
}
nlines, err := stat.CountLines(stat.ProcNetdevFile, conn, conninfo.ConnLocal)
if err != nil {
printCmdline(g, err.Error())
closeAuxView(g, nil)
}
stats.Nicstat.New(nlines)
ctx.aux = auxtype
printCmdline(g, "Show nicstat")
doUpdate <- 1
case auxLogtail:
if !conninfo.ConnLocal {
printCmdline(g, "Log tail is not supported for remote hosts")
return nil
}
pgLog.Size = 0
pgLog.Path, _ = readLogPath()
// Check the logfile isn't an empty
if info, err := os.Stat(pgLog.Path); err == nil && info.Size() == 0 {
printCmdline(g, "Empty logfile")
return nil
} else if err != nil {
printCmdline(g, "Failed to stat logfile: %s", err)
return nil
}
if err := pgLog.Open(); err != nil {
printCmdline(g, "Failed to open %s", pgLog.Path)
return nil
}
if err := openAuxView(g, v); err != nil {
return err
}
ctx.aux = auxtype
printCmdline(g, "Show logtail")
doUpdate <- 1
}
return nil
}
}
// Depending on current AUXTYPE read specific stats: Diskstat, Nicstat. Logtail AUXTYPE processed separately.
func getAuxStat(g *gocui.Gui) {
switch ctx.aux {
case auxDiskstat:
ndev, err := stat.CountLines(stat.ProcDiskstats, conn, conninfo.ConnLocal)
if err != nil {
printCmdline(g, err.Error())
closeAuxView(g, nil)
}
// If number of devices is changed, re-create stats container
if ndev != len(stats.CurrDiskstats) {
stats.Iostat.New(ndev)
}
// Read stats
if err := stats.CurrDiskstats.Read(conn, conninfo.ConnLocal); err != nil {
printCmdline(g, err.Error())
closeAuxView(g, nil)
} else {
stats.DiffDiskstats.Diff(stats.CurrDiskstats, stats.PrevDiskstats)
copy(stats.PrevDiskstats, stats.CurrDiskstats)
}
case auxNicstat:
ndev, err := stat.CountLines(stat.ProcNetdevFile, conn, conninfo.ConnLocal)
if err != nil {
printCmdline(g, err.Error())
closeAuxView(g, nil)
}
// If number of interfaces is changed, re-create stats container
if ndev != len(stats.CurrNetdevs) {
stats.Nicstat.New(ndev)
}
// Read stats
if err := stats.CurrNetdevs.Read(conn, conninfo.ConnLocal); err != nil {
printCmdline(g, err.Error())
closeAuxView(g, nil)
} else {
stats.DiffNetdevs.Diff(stats.CurrNetdevs, stats.PrevNetdevs)
copy(stats.PrevNetdevs, stats.CurrNetdevs)
}
case auxNone:
// do nothing
}
}
// Open 'gocui' object for aux stats
func openAuxView(g *gocui.Gui, _ *gocui.View) error {
maxX, maxY := g.Size()
if v, err := g.SetView("aux", -1, 3*maxY/5-1, maxX-1, maxY-1); err != nil {
if err != gocui.ErrUnknownView {
return fmt.Errorf("set aux view on layout failed: %s", err)
}
v.Frame = false
}
return nil
}
// Close 'gocui' object
func closeAuxView(g *gocui.Gui, _ *gocui.View) error {
if ctx.aux > auxNone {
g.DeleteView("aux")
ctx.aux = auxNone
}
return nil
}