perfmonger 0.10.1 → 0.12.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.
Files changed (45) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +3 -0
  3. data/.travis.yml +9 -8
  4. data/HOWTO.md +0 -1
  5. data/NEWS +47 -3
  6. data/README.md +77 -27
  7. data/Rakefile +20 -9
  8. data/core/Makefile +10 -18
  9. data/core/build.sh +2 -2
  10. data/core/perfmonger-player.go +90 -40
  11. data/core/perfmonger-plot-formatter.go +18 -4
  12. data/core/perfmonger-recorder.go +22 -2
  13. data/core/perfmonger-summarizer.go +20 -14
  14. data/core/perfmonger-viewer.go +164 -0
  15. data/core/subsystem/Makefile +4 -0
  16. data/core/subsystem/perfmonger_linux.go +95 -0
  17. data/core/subsystem/perfmonger_linux_test.go +40 -0
  18. data/core/subsystem/stat.go +70 -0
  19. data/core/subsystem/stat_test.go +9 -0
  20. data/core/subsystem/usage.go +223 -66
  21. data/core/subsystem/usage_test.go +62 -32
  22. data/{bin → exe}/perfmonger +0 -0
  23. data/lib/perfmonger/command/fingerprint.rb +26 -1
  24. data/lib/perfmonger/command/live.rb +19 -0
  25. data/lib/perfmonger/command/play.rb +16 -0
  26. data/lib/perfmonger/command/plot.rb +25 -9
  27. data/lib/perfmonger/command/record.rb +1 -1
  28. data/lib/perfmonger/command/record_option.rb +16 -0
  29. data/lib/perfmonger/command/server.rb +1 -1
  30. data/lib/perfmonger/version.rb +1 -1
  31. data/misc/werker-box/Dockerfile +34 -0
  32. data/misc/werker-box/build-push.sh +7 -0
  33. data/perfmonger.gemspec +2 -1
  34. data/spec/data/busy100.pgr.played +3 -3
  35. data/spec/fingerprint_spec.rb +1 -1
  36. data/spec/live_spec.rb +2 -3
  37. data/spec/perfmonger_spec.rb +1 -1
  38. data/spec/play_spec.rb +1 -1
  39. data/spec/plot_spec.rb +16 -1
  40. data/spec/record_spec.rb +10 -1
  41. data/spec/spec_helper.rb +28 -3
  42. data/spec/stat_spec.rb +2 -2
  43. data/spec/summary_spec.rb +1 -1
  44. data/wercker.yml +29 -16
  45. metadata +28 -10
@@ -1,6 +1,7 @@
1
1
  package subsystem
2
2
 
3
3
  import (
4
+ "log"
4
5
  "os"
5
6
  "testing"
6
7
  )
@@ -71,3 +72,42 @@ func TestReadNetStat(t *testing.T) {
71
72
  t.Error("Device 'lo' not found.")
72
73
  }
73
74
  }
75
+
76
+ func TestReadMemStat(t *testing.T) {
77
+ var err error
78
+ var stat_record *StatRecord = nil
79
+
80
+ err = ReadMemStat(stat_record)
81
+ if err == nil {
82
+ t.Errorf("Error should not be returned with non-nil *StatRecord.")
83
+ }
84
+
85
+ _, err = os.Stat("/proc/meminfo")
86
+ if err != nil {
87
+ t.Skip("/proc/meminfo is not present.")
88
+ }
89
+
90
+ stat_record = NewStatRecord()
91
+ err = ReadMemStat(stat_record)
92
+ if err != nil {
93
+ log.Print(err)
94
+ t.Error("Error should not be returned with valid *StatRecord.")
95
+ return
96
+ }
97
+ if stat_record.Mem == nil {
98
+ t.Error("stat_record.Mem should not be nil")
99
+ return
100
+ }
101
+
102
+ if stat_record.Mem.MemTotal == 0 {
103
+ t.Error("Cannot read MemTotal correctly")
104
+ return
105
+ }
106
+
107
+ mem := stat_record.Mem
108
+
109
+ if (mem.MemFree + mem.Cached + mem.Buffers) > mem.MemTotal {
110
+ t.Error("Inconsistent meminfo values")
111
+ return
112
+ }
113
+ }
@@ -102,6 +102,38 @@ type NetStat struct {
102
102
  Entries []*NetStatEntry
103
103
  }
104
104
 
105
+ // all values are recorded in KB
106
+ type MemStat struct {
107
+ MemTotal int64
108
+ MemFree int64
109
+ Buffers int64
110
+ Cached int64
111
+ SwapCached int64
112
+ Active int64
113
+ Inactive int64
114
+ SwapTotal int64
115
+ SwapFree int64
116
+ Dirty int64
117
+ Writeback int64
118
+ AnonPages int64
119
+ Mapped int64
120
+ Shmem int64
121
+ Slab int64
122
+ SReclaimable int64
123
+ SUnreclaim int64
124
+ KernelStack int64
125
+ PageTables int64
126
+ NFS_Unstable int64
127
+ Bounce int64
128
+ CommitLimit int64
129
+ Committed_AS int64
130
+ AnonHugePages int64
131
+ HugePages_Total int64
132
+ HugePages_Free int64
133
+ HugePages_Rsvd int64
134
+ HugePages_Surp int64
135
+ }
136
+
105
137
  type StatRecord struct {
106
138
  Time time.Time
107
139
  Cpu *CpuStat
@@ -110,6 +142,7 @@ type StatRecord struct {
110
142
  Disk *DiskStat
111
143
  Softirq *SoftIrqStat
112
144
  Net *NetStat
145
+ Mem *MemStat
113
146
  }
114
147
 
115
148
  func (core_stat *CpuCoreStat) Clear() {
@@ -219,6 +252,42 @@ func NewNetStat() *NetStat {
219
252
  return new(NetStat)
220
253
  }
221
254
 
255
+ func NewMemStat() *MemStat {
256
+ return new(MemStat)
257
+ }
258
+
259
+ func (entry *MemStat) Clear() {
260
+ entry.MemTotal = 0
261
+ entry.MemFree = 0
262
+ entry.Buffers = 0
263
+ entry.Cached = 0
264
+ entry.SwapCached = 0
265
+ entry.Active = 0
266
+ entry.Inactive = 0
267
+ entry.SwapTotal = 0
268
+ entry.SwapFree = 0
269
+ entry.Dirty = 0
270
+ entry.Writeback = 0
271
+ entry.AnonPages = 0
272
+ entry.Mapped = 0
273
+ entry.Shmem = 0
274
+ entry.Slab = 0
275
+ entry.SReclaimable = 0
276
+ entry.NFS_Unstable = 0
277
+ entry.SUnreclaim = 0
278
+ entry.KernelStack = 0
279
+ entry.PageTables = 0
280
+ entry.NFS_Unstable = 0
281
+ entry.Bounce = 0
282
+ entry.CommitLimit = 0
283
+ entry.Committed_AS = 0
284
+ entry.AnonHugePages = 0
285
+ entry.HugePages_Total = 0
286
+ entry.HugePages_Free = 0
287
+ entry.HugePages_Rsvd = 0
288
+ entry.HugePages_Surp = 0
289
+ }
290
+
222
291
  func NewStatRecord() *StatRecord {
223
292
  return &StatRecord{
224
293
  time.Now(),
@@ -228,6 +297,7 @@ func NewStatRecord() *StatRecord {
228
297
  nil,
229
298
  nil,
230
299
  nil,
300
+ nil,
231
301
  }
232
302
  }
233
303
 
@@ -262,6 +262,14 @@ func TestNewNetStat(t *testing.T) {
262
262
  }
263
263
  }
264
264
 
265
+ func TestNewMemStat(t *testing.T) {
266
+ memstat := NewMemStat()
267
+
268
+ if memstat == nil {
269
+ t.Error("failed to create MemStat")
270
+ }
271
+ }
272
+
265
273
  func TestNewStatRecord(t *testing.T) {
266
274
  stat_record := NewStatRecord()
267
275
 
@@ -278,4 +286,5 @@ func TestNewStatRecord(t *testing.T) {
278
286
  checkFieldIsNil("Disk")
279
287
  checkFieldIsNil("Softirq")
280
288
  checkFieldIsNil("Net")
289
+ checkFieldIsNil("Mem")
281
290
  }
@@ -2,12 +2,13 @@ package subsystem
2
2
 
3
3
  import (
4
4
  "bytes"
5
- "encoding/json"
6
5
  "errors"
7
6
  "fmt"
8
7
  "regexp"
9
8
  "sort"
10
9
  "time"
10
+
11
+ projson "github.com/hayamiz/go-projson"
11
12
  )
12
13
 
13
14
  type CpuCoreUsage struct {
@@ -84,25 +85,56 @@ type NetUsageEntry struct {
84
85
 
85
86
  type NetUsage map[string]*NetUsageEntry
86
87
 
87
- func (ccusage *CpuCoreUsage) WriteJsonTo(buf *bytes.Buffer) {
88
- buf.WriteString(
89
- fmt.Sprintf(`{"usr":%.2f,"nice":%.2f,"sys":%.2f,"idle":%.2f,"iowait":%.2f,"hardirq":%.2f,"softirq":%.2f,"steal":%.2f,"guest":%.2f,"guestnice":%.2f}`,
90
- ccusage.User, ccusage.Nice, ccusage.Sys, ccusage.Idle, ccusage.Iowait,
91
- ccusage.Hardirq, ccusage.Softirq, ccusage.Steal, ccusage.Guest, ccusage.GuestNice))
88
+ type MemUsage struct {
89
+ mem *MemStat
92
90
  }
93
91
 
94
- func (cusage *CpuUsage) WriteJsonTo(buf *bytes.Buffer) {
95
- buf.WriteString(
96
- fmt.Sprintf(`{"num_core":%d,"all":`, cusage.NumCore))
97
- cusage.All.WriteJsonTo(buf)
98
- buf.WriteString(`,"cores":[`)
99
- for idx, ccusage := range cusage.CoreUsages {
100
- if idx > 0 {
101
- buf.WriteString(",")
102
- }
103
- ccusage.WriteJsonTo(buf)
92
+ var UseColor = false
93
+
94
+ func SetUseColor(use_color bool) {
95
+ UseColor = use_color
96
+ }
97
+
98
+ func (ccusage *CpuCoreUsage) WriteJsonTo(printer *projson.JsonPrinter) {
99
+ printer.BeginObject()
100
+ printer.PutKey("usr")
101
+ printer.PutFloatFmt(ccusage.User, "%.2f")
102
+ printer.PutKey("nice")
103
+ printer.PutFloatFmt(ccusage.Nice, "%.2f")
104
+ printer.PutKey("sys")
105
+ printer.PutFloatFmt(ccusage.Sys, "%.2f")
106
+ printer.PutKey("idle")
107
+ printer.PutFloatFmt(ccusage.Idle, "%.2f")
108
+ printer.PutKey("iowait")
109
+ printer.PutFloatFmt(ccusage.Iowait, "%.2f")
110
+ printer.PutKey("hardirq")
111
+ printer.PutFloatFmt(ccusage.Hardirq, "%.2f")
112
+ printer.PutKey("softirq")
113
+ printer.PutFloatFmt(ccusage.Softirq, "%.2f")
114
+ printer.PutKey("steal")
115
+ printer.PutFloatFmt(ccusage.Steal, "%.2f")
116
+ printer.PutKey("guest")
117
+ printer.PutFloatFmt(ccusage.Guest, "%.2f")
118
+ printer.PutKey("guestnice")
119
+ printer.PutFloatFmt(ccusage.GuestNice, "%.2f")
120
+ printer.FinishObject()
121
+ }
122
+
123
+ func (cusage *CpuUsage) WriteJsonTo(printer *projson.JsonPrinter) {
124
+ printer.BeginObject()
125
+ printer.PutKey("num_core")
126
+ printer.PutInt(cusage.NumCore)
127
+ printer.PutKey("all")
128
+
129
+ cusage.All.WriteJsonTo(printer)
130
+
131
+ printer.PutKey("cores")
132
+ printer.BeginArray()
133
+ for _, ccusage := range cusage.CoreUsages {
134
+ ccusage.WriteJsonTo(printer)
104
135
  }
105
- buf.WriteString(`]}`)
136
+ printer.FinishArray()
137
+ printer.FinishObject()
106
138
  }
107
139
 
108
140
  func GetCpuCoreUsage(c1 *CpuCoreStat, c2 *CpuCoreStat) (*CpuCoreUsage, error) {
@@ -225,35 +257,68 @@ func GetInterruptUsage(t1 time.Time, i1 *InterruptStat, t2 time.Time, i2 *Interr
225
257
  return usage, nil
226
258
  }
227
259
 
228
- func (intr_usage *InterruptUsage) WriteJsonTo(buf *bytes.Buffer) {
229
- buf.WriteString("{")
230
- buf.WriteString(`"core_dev_intr":[`)
231
- for idx, core_usage := range intr_usage.CoreIntrUsages {
232
- if idx > 0 {
233
- buf.WriteString(",")
234
- }
235
- fmt.Fprintf(buf, "%.2f", core_usage.Device)
260
+ func (intr_usage *InterruptUsage) WriteJsonTo(printer *projson.JsonPrinter) {
261
+ printer.BeginObject()
262
+ printer.PutKey("core_dev_intr")
263
+ printer.BeginArray()
264
+ for _, core_usage := range intr_usage.CoreIntrUsages {
265
+ printer.PutFloatFmt(core_usage.Device, "%.2f")
236
266
  }
237
- buf.WriteString(`],"core_sys_intr":[`)
238
- for idx, core_usage := range intr_usage.CoreIntrUsages {
239
- if idx > 0 {
240
- buf.WriteString(",")
241
- }
242
- fmt.Fprintf(buf, "%.2f", core_usage.System)
267
+ printer.FinishArray()
268
+
269
+ printer.PutKey("core_sys_intr")
270
+ printer.BeginArray()
271
+ for _, core_usage := range intr_usage.CoreIntrUsages {
272
+ printer.PutFloatFmt(core_usage.System, "%.2f")
243
273
  }
244
- buf.WriteString("]")
245
- buf.WriteString("}")
274
+ printer.FinishArray()
275
+ printer.FinishObject()
246
276
  }
247
277
 
248
- func (duentry *DiskUsageEntry) WriteJsonTo(buf *bytes.Buffer) {
249
- fmt.Fprintf(buf,
250
- `{"riops":%.2f,"wiops":%.2f,"rkbyteps":%.2f,"wkbyteps":%.2f,"rlatency":%.3f,"wlatency":%.3f,"rsize":%.2f,"wsize":%.2f,"qlen":%.2f}`,
251
- duentry.RdIops, duentry.WrIops, duentry.RdSecps/2.0, duentry.WrSecps/2.0,
252
- duentry.RdLatency, duentry.WrLatency,
253
- duentry.AvgRdSize, duentry.AvgWrSize, duentry.ReqQlen)
278
+ func (duentry *DiskUsageEntry) WriteJsonTo(printer *projson.JsonPrinter) {
279
+ printer.BeginObject()
280
+ printer.PutKey("riops")
281
+ printer.PutFloatFmt(duentry.RdIops, "%.2f")
282
+ printer.PutKey("wiops")
283
+ printer.PutFloatFmt(duentry.WrIops, "%.2f")
284
+ printer.PutKey("rkbyteps")
285
+ printer.PutFloatFmt(duentry.RdSecps/2.0, "%.2f")
286
+ printer.PutKey("wkbyteps")
287
+ printer.PutFloatFmt(duentry.WrSecps/2.0, "%.2f")
288
+ printer.PutKey("rlatency")
289
+ printer.PutFloatFmt(duentry.RdLatency, "%.3f")
290
+ printer.PutKey("wlatency")
291
+ printer.PutFloatFmt(duentry.WrLatency, "%.3f")
292
+ printer.PutKey("rsize")
293
+ printer.PutFloatFmt(duentry.AvgRdSize, "%.2f")
294
+ printer.PutKey("wsize")
295
+ printer.PutFloatFmt(duentry.AvgWrSize, "%.2f")
296
+ printer.PutKey("qlen")
297
+ printer.PutFloatFmt(duentry.ReqQlen, "%.2f")
298
+ printer.FinishObject()
254
299
  }
255
300
 
256
- func (dusage *DiskUsage) WriteJsonTo(buf *bytes.Buffer) {
301
+ func strarrayToString(arr []string) string {
302
+ buf := bytes.NewBuffer([]byte{})
303
+
304
+ fmt.Fprintf(buf, "[")
305
+ for i, elem := range arr {
306
+ if i > 0 {
307
+ fmt.Fprintf(buf, ",")
308
+ }
309
+
310
+ if UseColor {
311
+ fmt.Fprintf(buf, "\033[35m\"%s\"\033[0m", elem)
312
+ } else {
313
+ fmt.Fprintf(buf, "\"%s\"", elem)
314
+ }
315
+ }
316
+ fmt.Fprintf(buf, "]")
317
+
318
+ return buf.String()
319
+ }
320
+
321
+ func (dusage *DiskUsage) WriteJsonTo(printer *projson.JsonPrinter) {
257
322
  var devices []string
258
323
 
259
324
  for device, _ := range *dusage {
@@ -263,23 +328,24 @@ func (dusage *DiskUsage) WriteJsonTo(buf *bytes.Buffer) {
263
328
  }
264
329
  sort.Strings(devices)
265
330
 
266
- bytes, err := json.Marshal(devices)
267
- if err != nil {
268
- panic(err)
331
+ printer.BeginObject()
332
+ printer.PutKey("devices")
333
+ printer.BeginArray()
334
+ for _, device := range devices {
335
+ printer.PutString(device)
269
336
  }
270
- fmt.Fprintf(buf, `{"devices":%s`, string(bytes))
337
+ printer.FinishArray()
271
338
 
272
339
  devices = append(devices, "total")
273
340
 
274
341
  for _, device := range devices {
275
342
  usage := (*dusage)[device]
276
- buf.WriteString(`,"`)
277
- buf.WriteString(device)
278
- buf.WriteString(`":`)
279
- usage.WriteJsonTo(buf)
343
+
344
+ printer.PutKey(device)
345
+ usage.WriteJsonTo(printer)
280
346
  }
281
347
 
282
- buf.WriteByte('}')
348
+ printer.FinishObject()
283
349
  }
284
350
 
285
351
  func avgDelta(v int64, w int64, interval float64) float64 {
@@ -470,7 +536,7 @@ func GetNetUsage(t1 time.Time, d1 *NetStat, t2 time.Time, d2 *NetStat) (*NetUsag
470
536
  return net_usage, nil
471
537
  }
472
538
 
473
- func (nusage *NetUsage) WriteJsonTo(buf *bytes.Buffer) {
539
+ func (nusage *NetUsage) WriteJsonTo(printer *projson.JsonPrinter) {
474
540
  var devices []string
475
541
 
476
542
  for device, _ := range *nusage {
@@ -480,30 +546,121 @@ func (nusage *NetUsage) WriteJsonTo(buf *bytes.Buffer) {
480
546
  }
481
547
  sort.Strings(devices)
482
548
 
483
- bytes, err := json.Marshal(devices)
484
- if err != nil {
485
- panic(err)
549
+ printer.BeginObject()
550
+ printer.PutKey("devices")
551
+ printer.BeginArray()
552
+ for _, device := range devices {
553
+ printer.PutString(device)
486
554
  }
487
- fmt.Fprintf(buf, `{"devices":%s`, string(bytes))
555
+ printer.FinishArray()
488
556
 
489
557
  devices = append(devices, "total")
490
558
 
491
559
  for _, device := range devices {
492
560
  usage := (*nusage)[device]
493
- buf.WriteString(`,"`)
494
- buf.WriteString(device)
495
- buf.WriteString(`":`)
496
- usage.WriteJsonTo(buf)
561
+
562
+ printer.PutKey(device)
563
+ usage.WriteJsonTo(printer)
564
+ }
565
+
566
+ printer.FinishObject()
567
+ }
568
+
569
+ func GetMemUsage(mem *MemStat) (*MemUsage, error) {
570
+ if mem == nil {
571
+ return nil, errors.New("invalid memstat")
497
572
  }
498
573
 
499
- buf.WriteByte('}')
574
+ musage := new(MemUsage)
575
+ musage.mem = mem
576
+
577
+ return musage, nil
578
+ }
579
+
580
+ func (musage *MemUsage) WriteJsonTo(printer *projson.JsonPrinter) {
581
+ printer.BeginObject()
582
+
583
+ printer.PutKey("mem_total")
584
+ printer.PutInt64(musage.mem.MemTotal)
585
+ printer.PutKey("mem_used")
586
+ printer.PutInt64(musage.mem.MemTotal - musage.mem.MemFree - musage.mem.Buffers - musage.mem.Cached - musage.mem.SReclaimable)
587
+ printer.PutKey("mem_free")
588
+ printer.PutInt64(musage.mem.MemFree)
589
+ printer.PutKey("buffers")
590
+ printer.PutInt64(musage.mem.Buffers)
591
+ printer.PutKey("cached")
592
+ printer.PutInt64(musage.mem.Cached)
593
+ printer.PutKey("swap_cached")
594
+ printer.PutInt64(musage.mem.SwapCached)
595
+ printer.PutKey("active")
596
+ printer.PutInt64(musage.mem.Active)
597
+ printer.PutKey("inactive")
598
+ printer.PutInt64(musage.mem.Inactive)
599
+ printer.PutKey("swap_total")
600
+ printer.PutInt64(musage.mem.SwapTotal)
601
+ printer.PutKey("swap_free")
602
+ printer.PutInt64(musage.mem.SwapFree)
603
+ printer.PutKey("dirty")
604
+ printer.PutInt64(musage.mem.Dirty)
605
+ printer.PutKey("writeback")
606
+ printer.PutInt64(musage.mem.Writeback)
607
+ printer.PutKey("anon_pages")
608
+ printer.PutInt64(musage.mem.AnonPages)
609
+ printer.PutKey("mapped")
610
+ printer.PutInt64(musage.mem.Mapped)
611
+ printer.PutKey("shmem")
612
+ printer.PutInt64(musage.mem.Shmem)
613
+ printer.PutKey("slab")
614
+ printer.PutInt64(musage.mem.Slab)
615
+ printer.PutKey("s_reclaimable")
616
+ printer.PutInt64(musage.mem.SReclaimable)
617
+ printer.PutKey("s_unreclaim")
618
+ printer.PutInt64(musage.mem.SUnreclaim)
619
+ printer.PutKey("kernel_stack")
620
+ printer.PutInt64(musage.mem.KernelStack)
621
+ printer.PutKey("page_tables")
622
+ printer.PutInt64(musage.mem.PageTables)
623
+ printer.PutKey("nfs_unstable")
624
+ printer.PutInt64(musage.mem.NFS_Unstable)
625
+ printer.PutKey("bounce")
626
+ printer.PutInt64(musage.mem.Bounce)
627
+ printer.PutKey("commit_limit")
628
+ printer.PutInt64(musage.mem.CommitLimit)
629
+ printer.PutKey("committed_as")
630
+ printer.PutInt64(musage.mem.Committed_AS)
631
+ printer.PutKey("anon_huge_pages")
632
+ printer.PutInt64(musage.mem.AnonHugePages)
633
+ printer.PutKey("huge_pages_total")
634
+ printer.PutInt64(musage.mem.HugePages_Total)
635
+ printer.PutKey("huge_pages_free")
636
+ printer.PutInt64(musage.mem.HugePages_Free)
637
+ printer.PutKey("huge_pages_rsvd")
638
+ printer.PutInt64(musage.mem.HugePages_Rsvd)
639
+ printer.PutKey("huge_pages_surp")
640
+ printer.PutInt64(musage.mem.HugePages_Surp)
641
+
642
+ printer.FinishObject()
500
643
  }
501
644
 
502
- func (entry *NetUsageEntry) WriteJsonTo(buf *bytes.Buffer) {
503
- buf.WriteString(
504
- fmt.Sprintf(`{"rxkbyteps":%.2f,"rxpktps":%.2f,"rxerrps":%.2f,"rxdropps":%.2f,"txkbyteps":%.2f,"txpktps":%.2f,"txerrps":%.2f,"txdropps":%.2f}`,
505
- entry.RxBytesPerSec/1024.0, entry.RxPacketsPerSec,
506
- entry.RxErrorsPerSec, entry.RxDropsPerSec,
507
- entry.TxBytesPerSec/1024.0, entry.TxPacketsPerSec,
508
- entry.TxErrorsPerSec, entry.TxDropsPerSec))
645
+ func (entry *NetUsageEntry) WriteJsonTo(printer *projson.JsonPrinter) {
646
+ printer.BeginObject()
647
+
648
+ printer.PutKey("rxkbyteps")
649
+ printer.PutFloatFmt(entry.RxBytesPerSec/1024.0, "%.2f")
650
+ printer.PutKey("rxpktps")
651
+ printer.PutFloatFmt(entry.RxPacketsPerSec, "%.2f")
652
+ printer.PutKey("rxerrps")
653
+ printer.PutFloatFmt(entry.RxErrorsPerSec, "%.2f")
654
+ printer.PutKey("rxdropps")
655
+ printer.PutFloatFmt(entry.RxDropsPerSec, "%.2f")
656
+ printer.PutKey("txkbyteps")
657
+ printer.PutFloatFmt(entry.TxBytesPerSec/1024.0, "%.2f")
658
+ printer.PutKey("txpktps")
659
+ printer.PutFloatFmt(entry.TxPacketsPerSec, "%.2f")
660
+ printer.PutKey("txerrps")
661
+ printer.PutFloatFmt(entry.TxErrorsPerSec, "%.2f")
662
+ printer.PutKey("txdropps")
663
+ printer.PutFloatFmt(entry.TxDropsPerSec, "%.2f")
664
+
665
+ printer.FinishObject()
509
666
  }