perfmonger 0.6.1 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -13
- data/.gitignore +6 -0
- data/.tachikoma.yml +1 -0
- data/.travis.yml +18 -6
- data/Gemfile +1 -3
- data/Guardfile +26 -0
- data/NEWS +21 -0
- data/README.md +8 -9
- data/Rakefile +33 -1
- data/core/Makefile +23 -0
- data/core/build.sh +48 -0
- data/core/perfmonger-player.go +165 -0
- data/core/perfmonger-recorder.go +296 -0
- data/core/perfmonger-summarizer.go +207 -0
- data/core/subsystem/Makefile +3 -0
- data/core/subsystem/perfmonger.go +60 -0
- data/core/subsystem/perfmonger_darwin.go +22 -0
- data/core/subsystem/perfmonger_linux.go +292 -0
- data/core/subsystem/perfmonger_linux_test.go +73 -0
- data/core/subsystem/stat.go +214 -0
- data/core/subsystem/stat_test.go +281 -0
- data/core/subsystem/usage.go +410 -0
- data/core/subsystem/usage_test.go +496 -0
- data/lib/exec/operationBinding.rb.svn-base +59 -0
- data/lib/exec/perfmonger-player_darwin_amd64 +0 -0
- data/lib/exec/perfmonger-player_linux_386 +0 -0
- data/lib/exec/perfmonger-player_linux_amd64 +0 -0
- data/lib/exec/perfmonger-recorder_darwin_amd64 +0 -0
- data/lib/exec/perfmonger-recorder_linux_386 +0 -0
- data/lib/exec/perfmonger-recorder_linux_amd64 +0 -0
- data/lib/exec/perfmonger-summarizer_darwin_amd64 +0 -0
- data/lib/exec/perfmonger-summarizer_linux_386 +0 -0
- data/lib/exec/perfmonger-summarizer_linux_amd64 +0 -0
- data/lib/exec/perfmonger-summary_linux_386 +0 -0
- data/lib/exec/perfmonger-summary_linux_amd64 +0 -0
- data/lib/perfmonger/cli.rb +8 -3
- data/lib/perfmonger/command/core.rb +62 -0
- data/lib/perfmonger/command/live.rb +39 -0
- data/lib/perfmonger/command/play.rb +56 -0
- data/lib/perfmonger/command/plot.rb +30 -22
- data/lib/perfmonger/command/record.rb +3 -2
- data/lib/perfmonger/command/record_option.rb +40 -59
- data/lib/perfmonger/command/server.rb +7 -2
- data/lib/perfmonger/command/stat.rb +2 -2
- data/lib/perfmonger/command/stat_option.rb +1 -1
- data/lib/perfmonger/command/summary.rb +11 -326
- data/lib/perfmonger/version.rb +1 -3
- data/lib/perfmonger.rb +3 -0
- data/misc/_perfmonger +128 -0
- data/misc/perfmonger-completion.bash +49 -0
- data/perfmonger.gemspec +6 -5
- data/spec/data/busy100.pgr +0 -0
- data/spec/fingerprint_spec.rb +35 -0
- data/spec/live_spec.rb +25 -0
- data/spec/perfmonger_spec.rb +37 -0
- data/spec/play_spec.rb +21 -0
- data/spec/plot_spec.rb +42 -0
- data/spec/record_spec.rb +15 -0
- data/spec/spec_helper.rb +33 -0
- data/spec/stat_spec.rb +15 -0
- data/spec/summary_spec.rb +51 -0
- data/spec/support/aruba.rb +11 -0
- data/wercker.yml +59 -0
- metadata +117 -45
- data/ext/perfmonger/extconf.rb +0 -19
- data/ext/perfmonger/perfmonger.h +0 -58
- data/ext/perfmonger/perfmonger_record.c +0 -754
- data/ext/perfmonger/sysstat/common.c +0 -627
- data/ext/perfmonger/sysstat/common.h +0 -207
- data/ext/perfmonger/sysstat/ioconf.c +0 -515
- data/ext/perfmonger/sysstat/ioconf.h +0 -84
- data/ext/perfmonger/sysstat/iostat.c +0 -1100
- data/ext/perfmonger/sysstat/iostat.h +0 -121
- data/ext/perfmonger/sysstat/libsysstat.h +0 -19
- data/ext/perfmonger/sysstat/mpstat.c +0 -953
- data/ext/perfmonger/sysstat/mpstat.h +0 -79
- data/ext/perfmonger/sysstat/rd_stats.c +0 -2388
- data/ext/perfmonger/sysstat/rd_stats.h +0 -651
- data/ext/perfmonger/sysstat/sysconfig.h +0 -13
- data/test/run-test.sh +0 -39
- data/test/spec/bin_spec.rb +0 -37
- data/test/spec/data/2devices.expected +0 -42
- data/test/spec/data/2devices.output +0 -42
- data/test/spec/spec_helper.rb +0 -20
- data/test/spec/summary_spec.rb +0 -193
- data/test/test-perfmonger.c +0 -145
- data/test/test.h +0 -9
@@ -0,0 +1,292 @@
|
|
1
|
+
// +build linux
|
2
|
+
|
3
|
+
package subsystem
|
4
|
+
|
5
|
+
import (
|
6
|
+
"bufio"
|
7
|
+
"errors"
|
8
|
+
"fmt"
|
9
|
+
"io"
|
10
|
+
"os"
|
11
|
+
"runtime"
|
12
|
+
)
|
13
|
+
|
14
|
+
type PlatformHeader LinuxHeader
|
15
|
+
|
16
|
+
func NewPlatformHeader() *LinuxHeader {
|
17
|
+
header := new(LinuxHeader)
|
18
|
+
header.Devices = make(map[string]LinuxDevice)
|
19
|
+
|
20
|
+
header.getDevsParts()
|
21
|
+
|
22
|
+
return header
|
23
|
+
}
|
24
|
+
|
25
|
+
func (header *LinuxHeader) getDevsParts() {
|
26
|
+
f, err := os.Open("/proc/diskstats")
|
27
|
+
if err != nil {
|
28
|
+
panic(err)
|
29
|
+
}
|
30
|
+
defer f.Close()
|
31
|
+
scan := bufio.NewScanner(f)
|
32
|
+
for scan.Scan() {
|
33
|
+
var major, minor int
|
34
|
+
var name string
|
35
|
+
c, err := fmt.Sscanf(scan.Text(), "%d %d %s", &major, &minor, &name)
|
36
|
+
if err != nil {
|
37
|
+
panic(err)
|
38
|
+
}
|
39
|
+
if c != 3 {
|
40
|
+
continue
|
41
|
+
}
|
42
|
+
|
43
|
+
header.DevsParts = append(header.DevsParts, name)
|
44
|
+
|
45
|
+
if isDevice(name) {
|
46
|
+
header.Devices[name] = LinuxDevice{
|
47
|
+
name, getPartitions(name),
|
48
|
+
}
|
49
|
+
}
|
50
|
+
}
|
51
|
+
}
|
52
|
+
|
53
|
+
func isDevice(name string) bool {
|
54
|
+
stat, err := os.Stat(fmt.Sprintf("/sys/block/%s", name))
|
55
|
+
if err == nil && stat.IsDir() {
|
56
|
+
return true
|
57
|
+
}
|
58
|
+
|
59
|
+
return false
|
60
|
+
}
|
61
|
+
|
62
|
+
func getPartitions(name string) []string {
|
63
|
+
var dir *os.File
|
64
|
+
var fis []os.FileInfo
|
65
|
+
var err error
|
66
|
+
var parts = []string{}
|
67
|
+
|
68
|
+
dir, err = os.Open(fmt.Sprintf("/sys/block/%s", name))
|
69
|
+
if err != nil {
|
70
|
+
panic(err)
|
71
|
+
}
|
72
|
+
fis, err = dir.Readdir(0)
|
73
|
+
if err != nil {
|
74
|
+
panic(err)
|
75
|
+
}
|
76
|
+
for _, fi := range fis {
|
77
|
+
_, err := os.Stat(fmt.Sprintf("/sys/block/%s/%s/stat", name, fi.Name()))
|
78
|
+
if err == nil {
|
79
|
+
// partition exists
|
80
|
+
parts = append(parts, fi.Name())
|
81
|
+
}
|
82
|
+
}
|
83
|
+
|
84
|
+
return parts
|
85
|
+
}
|
86
|
+
|
87
|
+
func ReadCpuStat(record *StatRecord) error {
|
88
|
+
f, ferr := os.Open("/proc/stat")
|
89
|
+
if ferr != nil {
|
90
|
+
return ferr
|
91
|
+
}
|
92
|
+
defer f.Close()
|
93
|
+
|
94
|
+
if record.Cpu == nil {
|
95
|
+
record.Cpu = NewCpuStat(runtime.NumCPU())
|
96
|
+
} else {
|
97
|
+
record.Cpu.Clear()
|
98
|
+
}
|
99
|
+
|
100
|
+
if record.Proc == nil {
|
101
|
+
record.Proc = NewProcStat()
|
102
|
+
} else {
|
103
|
+
record.Proc.Clear()
|
104
|
+
}
|
105
|
+
|
106
|
+
scan := bufio.NewScanner(f)
|
107
|
+
for scan.Scan() {
|
108
|
+
var err error
|
109
|
+
var cpu string
|
110
|
+
line := scan.Text()
|
111
|
+
if line[0:4] == "cpu " {
|
112
|
+
_, err = fmt.Sscanf(line,
|
113
|
+
"%s %d %d %d %d %d %d %d %d %d %d",
|
114
|
+
&cpu,
|
115
|
+
&record.Cpu.All.User,
|
116
|
+
&record.Cpu.All.Nice,
|
117
|
+
&record.Cpu.All.Sys,
|
118
|
+
&record.Cpu.All.Idle,
|
119
|
+
&record.Cpu.All.Iowait,
|
120
|
+
&record.Cpu.All.Hardirq,
|
121
|
+
&record.Cpu.All.Softirq,
|
122
|
+
&record.Cpu.All.Steal,
|
123
|
+
&record.Cpu.All.Guest,
|
124
|
+
&record.Cpu.All.GuestNice)
|
125
|
+
if err != nil {
|
126
|
+
return err
|
127
|
+
}
|
128
|
+
} else if line[0:3] == "cpu" {
|
129
|
+
var n_core int
|
130
|
+
var core_stat *CpuCoreStat
|
131
|
+
// assume n_core < 10000
|
132
|
+
_, err = fmt.Sscanf(line[3:7], "%d", &n_core)
|
133
|
+
if err != nil {
|
134
|
+
return err
|
135
|
+
}
|
136
|
+
|
137
|
+
core_stat = &record.Cpu.CoreStats[n_core]
|
138
|
+
_, err = fmt.Sscanf(line,
|
139
|
+
"%s %d %d %d %d %d %d %d %d %d %d",
|
140
|
+
&cpu,
|
141
|
+
&core_stat.User,
|
142
|
+
&core_stat.Nice,
|
143
|
+
&core_stat.Sys,
|
144
|
+
&core_stat.Idle,
|
145
|
+
&core_stat.Iowait,
|
146
|
+
&core_stat.Hardirq,
|
147
|
+
&core_stat.Softirq,
|
148
|
+
&core_stat.Steal,
|
149
|
+
&core_stat.Guest,
|
150
|
+
&core_stat.GuestNice)
|
151
|
+
if err != nil {
|
152
|
+
return err
|
153
|
+
}
|
154
|
+
} else if line[0:5] == "ctxt " {
|
155
|
+
_, err = fmt.Sscanf(line[4:], "%d", &record.Proc.ContextSwitch)
|
156
|
+
if err != nil {
|
157
|
+
return err
|
158
|
+
}
|
159
|
+
} else if line[0:10] == "processes " {
|
160
|
+
_, err = fmt.Sscanf(line[10:], "%d", &record.Proc.Fork)
|
161
|
+
if err != nil {
|
162
|
+
return err
|
163
|
+
}
|
164
|
+
}
|
165
|
+
}
|
166
|
+
|
167
|
+
return nil
|
168
|
+
}
|
169
|
+
|
170
|
+
func ReadDiskStats(record *StatRecord, targets *map[string]bool) error {
|
171
|
+
if record == nil {
|
172
|
+
return errors.New("Valid *StatRecord is required.")
|
173
|
+
}
|
174
|
+
|
175
|
+
f, ferr := os.Open("/proc/diskstats")
|
176
|
+
if ferr != nil {
|
177
|
+
panic(ferr)
|
178
|
+
}
|
179
|
+
defer f.Close()
|
180
|
+
|
181
|
+
if record.Disk == nil {
|
182
|
+
record.Disk = NewDiskStat()
|
183
|
+
} else {
|
184
|
+
record.Disk.Clear()
|
185
|
+
}
|
186
|
+
|
187
|
+
scan := bufio.NewScanner(f)
|
188
|
+
|
189
|
+
var num_items int
|
190
|
+
var err error
|
191
|
+
for scan.Scan() {
|
192
|
+
var rdmerge_or_rdsec int64
|
193
|
+
var rdsec_or_wrios int64
|
194
|
+
var rdticks_or_wrsec int64
|
195
|
+
|
196
|
+
line := scan.Text()
|
197
|
+
entry := NewDiskStatEntry()
|
198
|
+
|
199
|
+
num_items, err = fmt.Sscanf(line,
|
200
|
+
"%d %d %s %d %d %d %d %d %d %d %d %d %d %d",
|
201
|
+
&entry.Major, &entry.Minor, &entry.Name,
|
202
|
+
&entry.RdIos, &rdmerge_or_rdsec, &rdsec_or_wrios, &rdticks_or_wrsec,
|
203
|
+
&entry.WrIos, &entry.WrMerges, &entry.WrSectors, &entry.WrTicks,
|
204
|
+
&entry.IosPgr, &entry.TotalTicks, &entry.ReqTicks)
|
205
|
+
if err != nil {
|
206
|
+
return err
|
207
|
+
}
|
208
|
+
|
209
|
+
if num_items == 14 {
|
210
|
+
entry.RdMerges = rdmerge_or_rdsec
|
211
|
+
entry.RdSectors = rdsec_or_wrios
|
212
|
+
entry.RdTicks = rdticks_or_wrsec
|
213
|
+
} else if num_items == 7 {
|
214
|
+
entry.RdSectors = rdmerge_or_rdsec
|
215
|
+
entry.WrIos = rdsec_or_wrios
|
216
|
+
entry.WrSectors = rdticks_or_wrsec
|
217
|
+
} else {
|
218
|
+
continue
|
219
|
+
}
|
220
|
+
|
221
|
+
if entry.RdIos == 0 && entry.WrIos == 0 {
|
222
|
+
continue
|
223
|
+
}
|
224
|
+
|
225
|
+
if targets != nil {
|
226
|
+
if _, ok := (*targets)[entry.Name]; !ok {
|
227
|
+
// device not in targets
|
228
|
+
continue
|
229
|
+
}
|
230
|
+
} else {
|
231
|
+
if !isDevice(entry.Name) {
|
232
|
+
continue
|
233
|
+
}
|
234
|
+
}
|
235
|
+
|
236
|
+
record.Disk.Entries = append(record.Disk.Entries, entry)
|
237
|
+
}
|
238
|
+
|
239
|
+
return nil
|
240
|
+
}
|
241
|
+
|
242
|
+
func ReadNetStat(record *StatRecord) error {
|
243
|
+
if record == nil {
|
244
|
+
return errors.New("Valid *StatRecord is required.")
|
245
|
+
}
|
246
|
+
|
247
|
+
net_stat := NewNetStat()
|
248
|
+
|
249
|
+
f, err := os.Open("/proc/net/dev")
|
250
|
+
if err != nil {
|
251
|
+
return err
|
252
|
+
}
|
253
|
+
defer f.Close()
|
254
|
+
scanner := bufio.NewScanner(f)
|
255
|
+
|
256
|
+
for scanner.Scan() {
|
257
|
+
line := scanner.Text()
|
258
|
+
switch {
|
259
|
+
case line[0:7] == "Inter-|":
|
260
|
+
continue
|
261
|
+
case line[0:7] == " face |":
|
262
|
+
continue
|
263
|
+
}
|
264
|
+
|
265
|
+
e := NewNetStatEntry()
|
266
|
+
|
267
|
+
var devname string
|
268
|
+
n, err := fmt.Sscanf(line,
|
269
|
+
"%s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d", &devname,
|
270
|
+
&e.RxBytes, &e.RxPackets, &e.RxErrors, &e.RxDrops,
|
271
|
+
&e.RxFifo, &e.RxFrame, &e.RxCompressed, &e.RxMulticast,
|
272
|
+
&e.TxBytes, &e.TxPackets, &e.TxErrors, &e.TxDrops,
|
273
|
+
&e.TxFifo, &e.TxFrame, &e.TxCompressed, &e.TxMulticast)
|
274
|
+
if err == io.EOF {
|
275
|
+
break
|
276
|
+
} else if err != nil {
|
277
|
+
return err
|
278
|
+
}
|
279
|
+
if n != 17 {
|
280
|
+
continue
|
281
|
+
}
|
282
|
+
|
283
|
+
// trim trailing ":" from devname
|
284
|
+
e.Name = devname[0 : len(devname)-1]
|
285
|
+
|
286
|
+
net_stat.Entries = append(net_stat.Entries, e)
|
287
|
+
}
|
288
|
+
|
289
|
+
record.Net = net_stat
|
290
|
+
|
291
|
+
return nil
|
292
|
+
}
|
@@ -0,0 +1,73 @@
|
|
1
|
+
package subsystem
|
2
|
+
|
3
|
+
import (
|
4
|
+
"os"
|
5
|
+
"testing"
|
6
|
+
)
|
7
|
+
|
8
|
+
func TestReadDiskStat(t *testing.T) {
|
9
|
+
var err error
|
10
|
+
var stat_record *StatRecord = nil
|
11
|
+
|
12
|
+
err = ReadDiskStats(stat_record, nil)
|
13
|
+
if err == nil {
|
14
|
+
t.Errorf("Error should be returned with nil *StatRecord.")
|
15
|
+
}
|
16
|
+
|
17
|
+
_, err = os.Stat("/proc/diskstats")
|
18
|
+
if err != nil {
|
19
|
+
t.Skip("/proc/diskstats is not present.")
|
20
|
+
}
|
21
|
+
|
22
|
+
stat_record = NewStatRecord()
|
23
|
+
err = ReadDiskStats(stat_record, nil)
|
24
|
+
if err != nil {
|
25
|
+
t.Error("Error should not be returned with valid *StatRecord")
|
26
|
+
}
|
27
|
+
if stat_record.Disk == nil {
|
28
|
+
t.Error("stat_record.Disk should not be nil")
|
29
|
+
return
|
30
|
+
}
|
31
|
+
if len(stat_record.Disk.Entries) == 0 {
|
32
|
+
t.Error("No device found.")
|
33
|
+
}
|
34
|
+
}
|
35
|
+
|
36
|
+
func TestReadNetStat(t *testing.T) {
|
37
|
+
var err error
|
38
|
+
var stat_record *StatRecord = nil
|
39
|
+
|
40
|
+
err = ReadNetStat(stat_record)
|
41
|
+
if err == nil {
|
42
|
+
t.Errorf("Error should be returned with nil *StatRecord.")
|
43
|
+
}
|
44
|
+
|
45
|
+
_, err = os.Stat("/proc/net/dev")
|
46
|
+
if err != nil {
|
47
|
+
t.Skip("/proc/net/dev is not present.")
|
48
|
+
}
|
49
|
+
|
50
|
+
stat_record = NewStatRecord()
|
51
|
+
err = ReadNetStat(stat_record)
|
52
|
+
if err != nil {
|
53
|
+
t.Error("Error should not be returned with valid *StatRecord.")
|
54
|
+
}
|
55
|
+
if stat_record.Net == nil {
|
56
|
+
t.Error("stat_record.Net should not be nil")
|
57
|
+
return
|
58
|
+
}
|
59
|
+
if len(stat_record.Net.Entries) == 0 {
|
60
|
+
t.Error("No net device found, though every linux host should have 'lo'.")
|
61
|
+
}
|
62
|
+
// search 'lo'
|
63
|
+
lo_found := false
|
64
|
+
for _, entry := range stat_record.Net.Entries {
|
65
|
+
if entry.Name == "lo" {
|
66
|
+
lo_found = true
|
67
|
+
break
|
68
|
+
}
|
69
|
+
}
|
70
|
+
if !lo_found {
|
71
|
+
t.Error("Device 'lo' not found.")
|
72
|
+
}
|
73
|
+
}
|
@@ -0,0 +1,214 @@
|
|
1
|
+
package subsystem
|
2
|
+
|
3
|
+
import "time"
|
4
|
+
|
5
|
+
//
|
6
|
+
// Record
|
7
|
+
//
|
8
|
+
|
9
|
+
type CpuCoreStat struct {
|
10
|
+
User int64
|
11
|
+
Nice int64
|
12
|
+
Sys int64
|
13
|
+
Idle int64
|
14
|
+
Iowait int64
|
15
|
+
Hardirq int64
|
16
|
+
Softirq int64
|
17
|
+
Steal int64
|
18
|
+
Guest int64
|
19
|
+
GuestNice int64
|
20
|
+
}
|
21
|
+
|
22
|
+
type CpuStat struct {
|
23
|
+
All CpuCoreStat
|
24
|
+
NumCore int
|
25
|
+
CoreStats []CpuCoreStat
|
26
|
+
}
|
27
|
+
|
28
|
+
type ProcStat struct {
|
29
|
+
ContextSwitch int64
|
30
|
+
Fork int64
|
31
|
+
}
|
32
|
+
|
33
|
+
type SoftIrqStat struct {
|
34
|
+
Hi int64
|
35
|
+
Timer int64
|
36
|
+
NetTx int64
|
37
|
+
NetRx int64
|
38
|
+
Block int64
|
39
|
+
BlockIopoll int64
|
40
|
+
Tasklet int64
|
41
|
+
Sched int64
|
42
|
+
Hrtimer int64
|
43
|
+
Rcu int64
|
44
|
+
}
|
45
|
+
|
46
|
+
type DiskStatEntry struct {
|
47
|
+
Major uint
|
48
|
+
Minor uint
|
49
|
+
Name string
|
50
|
+
RdIos int64
|
51
|
+
RdMerges int64
|
52
|
+
RdSectors int64
|
53
|
+
RdTicks int64
|
54
|
+
WrIos int64
|
55
|
+
WrMerges int64
|
56
|
+
WrSectors int64
|
57
|
+
WrTicks int64
|
58
|
+
IosPgr int64
|
59
|
+
TotalTicks int64
|
60
|
+
ReqTicks int64
|
61
|
+
}
|
62
|
+
|
63
|
+
type DiskStat struct {
|
64
|
+
Entries []*DiskStatEntry
|
65
|
+
}
|
66
|
+
|
67
|
+
type NetStatEntry struct {
|
68
|
+
Name string
|
69
|
+
RxBytes int64
|
70
|
+
RxPackets int64
|
71
|
+
RxErrors int64
|
72
|
+
RxDrops int64
|
73
|
+
RxFifo int64
|
74
|
+
RxFrame int64
|
75
|
+
RxCompressed int64
|
76
|
+
RxMulticast int64
|
77
|
+
TxBytes int64
|
78
|
+
TxPackets int64
|
79
|
+
TxErrors int64
|
80
|
+
TxDrops int64
|
81
|
+
TxFifo int64
|
82
|
+
TxFrame int64
|
83
|
+
TxCompressed int64
|
84
|
+
TxMulticast int64
|
85
|
+
}
|
86
|
+
|
87
|
+
type NetStat struct {
|
88
|
+
Entries []*NetStatEntry
|
89
|
+
}
|
90
|
+
|
91
|
+
type StatRecord struct {
|
92
|
+
Time time.Time
|
93
|
+
Cpu *CpuStat
|
94
|
+
Proc *ProcStat
|
95
|
+
Disk *DiskStat
|
96
|
+
Softirq *SoftIrqStat
|
97
|
+
Net *NetStat
|
98
|
+
}
|
99
|
+
|
100
|
+
func (core_stat *CpuCoreStat) Clear() {
|
101
|
+
core_stat.User = 0
|
102
|
+
core_stat.Nice = 0
|
103
|
+
core_stat.Sys = 0
|
104
|
+
core_stat.Iowait = 0
|
105
|
+
core_stat.Steal = 0
|
106
|
+
core_stat.Hardirq = 0
|
107
|
+
core_stat.Softirq = 0
|
108
|
+
core_stat.Guest = 0
|
109
|
+
core_stat.GuestNice = 0
|
110
|
+
core_stat.Idle = 0
|
111
|
+
}
|
112
|
+
|
113
|
+
func (core_stat *CpuCoreStat) Uptime() int64 {
|
114
|
+
// Don't take Guest because User include Guest
|
115
|
+
return core_stat.User +
|
116
|
+
core_stat.Nice +
|
117
|
+
core_stat.Sys +
|
118
|
+
core_stat.Iowait +
|
119
|
+
core_stat.Steal +
|
120
|
+
core_stat.Hardirq +
|
121
|
+
core_stat.Softirq +
|
122
|
+
core_stat.Idle
|
123
|
+
}
|
124
|
+
|
125
|
+
func NewCpuStat(num_core int) *CpuStat {
|
126
|
+
if num_core < 1 {
|
127
|
+
return nil
|
128
|
+
}
|
129
|
+
|
130
|
+
cpu_stat := new(CpuStat)
|
131
|
+
|
132
|
+
cpu_stat.NumCore = num_core
|
133
|
+
cpu_stat.CoreStats = make([]CpuCoreStat, num_core)
|
134
|
+
|
135
|
+
return cpu_stat
|
136
|
+
}
|
137
|
+
|
138
|
+
func (cpu_stat *CpuStat) Clear() {
|
139
|
+
cpu_stat.All.Clear()
|
140
|
+
for idx, _ := range cpu_stat.CoreStats {
|
141
|
+
cpu_stat.CoreStats[idx].Clear()
|
142
|
+
}
|
143
|
+
}
|
144
|
+
|
145
|
+
func NewProcStat() *ProcStat {
|
146
|
+
return &ProcStat{0, 0}
|
147
|
+
}
|
148
|
+
|
149
|
+
func (proc_stat *ProcStat) Clear() {
|
150
|
+
proc_stat.ContextSwitch = 0
|
151
|
+
proc_stat.Fork = 0
|
152
|
+
}
|
153
|
+
|
154
|
+
func NewDiskStatEntry() *DiskStatEntry {
|
155
|
+
return new(DiskStatEntry)
|
156
|
+
}
|
157
|
+
|
158
|
+
func NewDiskStat() *DiskStat {
|
159
|
+
return &DiskStat{[]*DiskStatEntry{}}
|
160
|
+
}
|
161
|
+
|
162
|
+
func (disk_stat *DiskStat) Clear() {
|
163
|
+
disk_stat.Entries = []*DiskStatEntry{}
|
164
|
+
}
|
165
|
+
|
166
|
+
func (sirq_stat *SoftIrqStat) Clear() {
|
167
|
+
sirq_stat.Hi = 0
|
168
|
+
sirq_stat.Timer = 0
|
169
|
+
sirq_stat.NetTx = 0
|
170
|
+
sirq_stat.NetRx = 0
|
171
|
+
sirq_stat.Block = 0
|
172
|
+
sirq_stat.BlockIopoll = 0
|
173
|
+
sirq_stat.Tasklet = 0
|
174
|
+
sirq_stat.Sched = 0
|
175
|
+
sirq_stat.Hrtimer = 0
|
176
|
+
sirq_stat.Rcu = 0
|
177
|
+
}
|
178
|
+
|
179
|
+
func NewNetStatEntry() *NetStatEntry {
|
180
|
+
return new(NetStatEntry)
|
181
|
+
}
|
182
|
+
|
183
|
+
func (entry *NetStatEntry) Clear() {
|
184
|
+
entry.Name = ""
|
185
|
+
entry.RxBytes = 0
|
186
|
+
entry.RxPackets = 0
|
187
|
+
entry.RxErrors = 0
|
188
|
+
entry.RxDrops = 0
|
189
|
+
entry.TxBytes = 0
|
190
|
+
entry.TxPackets = 0
|
191
|
+
entry.TxErrors = 0
|
192
|
+
entry.TxDrops = 0
|
193
|
+
}
|
194
|
+
|
195
|
+
func NewNetStat() *NetStat {
|
196
|
+
return new(NetStat)
|
197
|
+
}
|
198
|
+
|
199
|
+
func NewStatRecord() *StatRecord {
|
200
|
+
return &StatRecord{
|
201
|
+
time.Now(),
|
202
|
+
nil,
|
203
|
+
nil,
|
204
|
+
nil,
|
205
|
+
nil,
|
206
|
+
nil,
|
207
|
+
}
|
208
|
+
}
|
209
|
+
|
210
|
+
func (rec *StatRecord) Clear() {
|
211
|
+
rec.Cpu.Clear()
|
212
|
+
rec.Proc.Clear()
|
213
|
+
rec.Disk.Clear()
|
214
|
+
}
|