Sensibly format rows with table name on the right.
[pstop.git] / i_s / processlist / pl_by_user.go
1 package processlist
2
3 import (
4         "fmt"
5         "sort"
6
7         "github.com/sjmudd/pstop/lib"
8 )
9
10 /*
11 root@localhost [i_s]> show create table i_s\G
12 *************************** 1. row ***************************
13 CREATE TEMPORARY TABLE `PROCESSLIST` (
14         `ID` bigint(21) unsigned NOT NULL DEFAULT '0',
15         `USER` varchar(16) NOT NULL DEFAULT '',
16         `HOST` varchar(64) NOT NULL DEFAULT '',
17         `DB` varchar(64) DEFAULT NULL, `COMMAND` varchar(16) NOT NULL DEFAULT '', `TIME` int(7) NOT NULL DEFAULT '0', `STATE` varchar(64) DEFAULT NULL,
18         `INFO` longtext
19 ) ENGINE=MyISAM DEFAULT CHARSET=utf8
20 1 row in set (0.02 sec)
21 */
22
23 // a summary row of information taken from information_schema.processlist
24 type pl_by_user_row struct {
25         username    string
26         runtime     uint64
27         sleeptime   uint64
28         connections uint64
29         active      uint64
30         hosts       uint64
31         dbs         uint64
32         selects     uint64
33         inserts     uint64
34         updates     uint64
35         deletes     uint64
36         other       uint64
37 }
38 type pl_by_user_rows []pl_by_user_row
39
40 /*
41 Run Time   %age|Sleeping      %|Conn Actv|Hosts DBs|Sel Ins Upd Del Oth|username
42 hh:mm:ss 100.0%|hh:mm:ss 100.0%|9999 9999|9999  999|999 999 999 999 999|xxxxxxxxxxxxxx
43 */
44
45 func (r *pl_by_user_row) headings() string {
46         return fmt.Sprintf("%-8s %6s|%-8s %6s|%4s %4s|%5s %3s|%3s %3s %3s %3s %3s|%s",
47                 "Run Time", "%", "Sleeping", "%", "Conn", "Actv", "Hosts", "DBs", "Sel", "Ins", "Upd", "Del", "Oth", "User")
48 }
49
50 // generate a printable result
51 func (r *pl_by_user_row) row_content(totals pl_by_user_row) string {
52         return fmt.Sprintf("%8s %6s|%8s %6s|%4s %4s|%5s %3s|%3s %3s %3s %3s %3s|%s",
53                 lib.FormatSeconds(r.runtime),
54                 lib.FormatPct(lib.MyDivide(r.runtime, totals.runtime)),
55                 lib.FormatSeconds(r.sleeptime),
56                 lib.FormatPct(lib.MyDivide(r.sleeptime, totals.sleeptime)),
57                 lib.FormatCounter(int(r.connections), 4),
58                 lib.FormatCounter(int(r.active), 4),
59                 lib.FormatCounter(int(r.hosts), 5),
60                 lib.FormatCounter(int(r.dbs), 3),
61                 lib.FormatCounter(int(r.selects), 3),
62                 lib.FormatCounter(int(r.inserts), 3),
63                 lib.FormatCounter(int(r.updates), 3),
64                 lib.FormatCounter(int(r.deletes), 3),
65                 lib.FormatCounter(int(r.other), 3),
66                 r.username)
67 }
68
69 // generate a row of totals from a table
70 func (t pl_by_user_rows) totals() pl_by_user_row {
71         var totals pl_by_user_row
72         totals.username = "Totals"
73
74         for i := range t {
75                 totals.runtime += t[i].runtime
76                 totals.sleeptime += t[i].sleeptime
77                 totals.connections += t[i].connections
78                 totals.active += t[i].active
79                 //      totals.hosts += t[i].hosts      This needs to be done differently to get the total number of distinct hosts
80                 //      totals.dbs += t[i].dbs          This needs to be done differently to get the total number of distinct dbs
81                 totals.selects += t[i].selects
82                 totals.inserts += t[i].inserts
83                 totals.updates += t[i].updates
84                 totals.deletes += t[i].deletes
85                 totals.other += t[i].other
86         }
87
88         return totals
89 }
90
91 func (t pl_by_user_rows) Headings() string {
92         var r pl_by_user_row
93         return r.headings()
94 }
95
96 // describe a whole row
97 func (r pl_by_user_row) String() string {
98         return fmt.Sprintf("%v %v %v %v %v %v %v %v %v %v", r.runtime, r.connections, r.sleeptime, r.active, r.hosts, r.dbs, r.selects, r.inserts, r.updates, r.deletes, r.other, r.username)
99 }
100
101 // total time is runtime + sleeptime
102 func (r pl_by_user_row) total_time() uint64 {
103         return r.runtime + r.sleeptime
104 }
105
106 // describe a whole table
107 func (t pl_by_user_rows) String() string {
108         s := ""
109         for i := range t {
110                 s = s + t[i].String() + "\n"
111         }
112         return s
113 }
114
115 // for sorting
116 type ByRunTime pl_by_user_rows
117
118 func (t ByRunTime) Len() int      { return len(t) }
119 func (t ByRunTime) Swap(i, j int) { t[i], t[j] = t[j], t[i] }
120 func (t ByRunTime) Less(i, j int) bool {
121         return (t[i].total_time() > t[j].total_time()) ||
122                 ((t[i].total_time() == t[j].total_time()) && (t[i].connections > t[j].connections)) ||
123                 ((t[i].total_time() == t[j].total_time()) && (t[i].connections == t[j].connections) && (t[i].username < t[j].username))
124 }
125
126 func (t pl_by_user_rows) Sort() {
127         sort.Sort(ByRunTime(t))
128 }
129
130 func (t pl_by_user_rows) emptyRowContent() string {
131         var r pl_by_user_row
132         return r.row_content(r)
133 }