009841706db73acc344bca58b5f1ebc27f86b7a9
[pstop.git] / i_s / pl_by_user.go
1 package i_s
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 username      |Run Time   %age|Sleeping      %|Conn Actv|Hosts DBs|Sel Ins Upd Del Oth|
42 xxxxxxxxxxxxxx|hh:mm:ss 100.0%|hh:mm:ss 100.0%|9999 9999|9999  999|999 999 999 999 999|
43 */
44
45 func (r *pl_by_user_row) headings() string {
46         return fmt.Sprintf("%-14s|%-8s %6s|%-8s %6s|%4s %4s|%5s %3s|%3s %3s %3s %3s %3s|",
47                 "User", "Run Time", "%", "Sleeping", "%", "Conn", "Actv", "Hosts", "DBs", "Sel", "Ins", "Upd", "Del", "Oth")
48 }
49
50 // generate a printable result
51 func (r *pl_by_user_row) row_content(totals pl_by_user_row) string {
52         var u string
53         if len(r.username) == 0 {
54                 u = ""
55         } else if len(r.username) > 14 {
56                 u = r.username[0:14]
57         } else {
58                 u = r.username
59         }
60         return fmt.Sprintf("%-14s|%8s %6s|%8s %6s|%4s %4s|%5s %3s|%3s %3s %3s %3s %3s|",
61                 u,
62                 lib.FormatSeconds(r.runtime),
63                 lib.FormatPct(lib.MyDivide(r.runtime, totals.runtime)),
64                 lib.FormatSeconds(r.sleeptime),
65                 lib.FormatPct(lib.MyDivide(r.sleeptime, totals.sleeptime)),
66                 lib.FormatCounter(int(r.connections), 4),
67                 lib.FormatCounter(int(r.active), 4),
68                 lib.FormatCounter(int(r.hosts), 5),
69                 lib.FormatCounter(int(r.dbs), 3),
70                 lib.FormatCounter(int(r.selects), 3),
71                 lib.FormatCounter(int(r.inserts), 3),
72                 lib.FormatCounter(int(r.updates), 3),
73                 lib.FormatCounter(int(r.deletes), 3),
74                 lib.FormatCounter(int(r.other), 3))
75 }
76
77 // generate a row of totals from a table
78 func (t pl_by_user_rows) totals() pl_by_user_row {
79         var totals pl_by_user_row
80         totals.username = "Totals"
81
82         for i := range t {
83                 totals.runtime += t[i].runtime
84                 totals.sleeptime += t[i].sleeptime
85                 totals.connections += t[i].connections
86                 totals.active += t[i].active
87                 //      totals.hosts += t[i].hosts      This needs to be done differently to get the total number of distinct hosts
88                 //      totals.dbs += t[i].dbs          This needs to be done differently to get the total number of distinct dbs
89                 totals.selects += t[i].selects
90                 totals.inserts += t[i].inserts
91                 totals.updates += t[i].updates
92                 totals.deletes += t[i].deletes
93                 totals.other += t[i].other
94         }
95
96         return totals
97 }
98
99 func (t pl_by_user_rows) Headings() string {
100         var r pl_by_user_row
101         return r.headings()
102 }
103
104 // describe a whole row
105 func (r pl_by_user_row) String() string {
106         return fmt.Sprintf("%v %v %v %v %v %v %v %v %v %v", r.username, r.runtime, r.connections, r.sleeptime, r.active, r.hosts, r.dbs, r.selects, r.inserts, r.updates, r.deletes, r.other)
107 }
108
109 // total time is runtime + sleeptime
110 func (r pl_by_user_row) total_time() uint64 {
111         return r.runtime + r.sleeptime
112 }
113
114 // describe a whole table
115 func (t pl_by_user_rows) String() string {
116         s := ""
117         for i := range t {
118                 s = s + t[i].String() + "\n"
119         }
120         return s
121 }
122
123 // for sorting
124 type ByRunTime pl_by_user_rows
125
126 func (t ByRunTime) Len() int      { return len(t) }
127 func (t ByRunTime) Swap(i, j int) { t[i], t[j] = t[j], t[i] }
128 func (t ByRunTime) Less(i, j int) bool {
129         return (t[i].total_time() > t[j].total_time()) ||
130                 ((t[i].total_time() == t[j].total_time()) && (t[i].connections > t[j].connections)) ||
131                 ((t[i].total_time() == t[j].total_time()) && (t[i].connections == t[j].connections) && (t[i].username < t[j].username))
132 }
133
134 func (t pl_by_user_rows) Sort() {
135         sort.Sort(ByRunTime(t))
136 }
137
138 func (t pl_by_user_rows) emptyRowContent() string {
139         var r pl_by_user_row
140         return r.row_content(r)
141 }