From f4d9667cb9c0577d960d3a46280e6952d029e6e0 Mon Sep 17 00:00:00 2001 From: Kyle Brandt Date: Thu, 3 Dec 2015 10:48:52 -0500 Subject: [PATCH] cmd/scollector: Covert gauges to counters for os.cpu --- cmd/scollector/collectors/collectors.go | 14 ++++++ cmd/scollector/collectors/snmp_cisco.go | 61 +++++++++++++++++++------ cmd/scollector/collectors/snmp_sys.go | 4 +- cmd/scollector/collectors/vsphere.go | 17 +++++-- 4 files changed, 74 insertions(+), 22 deletions(-) diff --git a/cmd/scollector/collectors/collectors.go b/cmd/scollector/collectors/collectors.go index d171e44d2c..650b89b217 100644 --- a/cmd/scollector/collectors/collectors.go +++ b/cmd/scollector/collectors/collectors.go @@ -325,3 +325,17 @@ func skipMetric(index string) bool { } return true } + +type tsIntegrator func(int64, float64) float64 + +func getTsIntegrator() tsIntegrator { + var total float64 + var lastTimestamp int64 + return func(timestamp int64, v float64) float64 { + if lastTimestamp > 0 { + total += v * float64(timestamp-lastTimestamp) + } + lastTimestamp = timestamp + return total + } +} diff --git a/cmd/scollector/collectors/snmp_cisco.go b/cmd/scollector/collectors/snmp_cisco.go index d5a007125c..c32502df57 100644 --- a/cmd/scollector/collectors/snmp_cisco.go +++ b/cmd/scollector/collectors/snmp_cisco.go @@ -2,6 +2,7 @@ package collectors import ( "fmt" + "strconv" "time" "bosun.org/cmd/scollector/conf" @@ -13,14 +14,6 @@ import ( func SNMPCisco(cfg conf.SNMP) { mib := conf.MIB{ BaseOid: "1.3.6.1.4.1.9.9", - Metrics: []conf.MIBMetric{ - { - Metric: "cisco.cpu", - Oid: ".109.1.1.1.1.6", - FallbackOid: ".109.1.1.1.1.6.1", - Unit: metadata.Pct, - }, - }, Trees: []conf.MIBTree{ { BaseOid: ".48.1.1.1", @@ -40,12 +33,50 @@ func SNMPCisco(cfg conf.SNMP) { }, }, } - - collectors = append(collectors, &IntervalCollector{ - F: func() (opentsdb.MultiDataPoint, error) { - return GenericSnmp(cfg, mib) + cpuIntegrator := getTsIntegrator() + collectors = append(collectors, + &IntervalCollector{ + F: func() (opentsdb.MultiDataPoint, error) { + return GenericSnmp(cfg, mib) + }, + Interval: time.Second * 30, + name: fmt.Sprintf("snmp-cisco-%s", cfg.Host), + }, + &IntervalCollector{ + F: func() (opentsdb.MultiDataPoint, error) { + return c_cisco_cpu(cfg.Host, cfg.Community, cpuIntegrator) + }, + Interval: time.Second * 30, + name: fmt.Sprintf("snmp-cisco-cpu-%s", cfg.Host), }, - Interval: time.Second * 30, - name: fmt.Sprintf("snmp-cisco-%s", cfg.Host), - }) + ) +} + +const ( + cpmCPUTotal5secRev = ".1.3.6.1.4.1.9.9.109.1.1.1.1.6" +) + +func c_cisco_cpu(host, community string, cpuIntegrator tsIntegrator) (opentsdb.MultiDataPoint, error) { + var md opentsdb.MultiDataPoint + cpuRaw, err := snmp_subtree(host, community, cpmCPUTotal5secRev) + if err != nil { + return md, err + } + tags := opentsdb.TagSet{"host": host} + cpu := make(map[string]int) + for k, v := range cpuRaw { + pct, err := strconv.Atoi(fmt.Sprintf("%v", v)) + if err != nil { + return md, err + } + cpu[k] = pct + } + if len(cpu) > 1 { + return md, fmt.Errorf("expected only one cpu when monitoring cisco cpu via cpmCPUTotal5secRev") + } + for _, pct := range cpu { + Add(&md, "cisco.cpu", pct, tags, metadata.Gauge, metadata.Pct, "") + Add(&md, osCPU, cpuIntegrator(time.Now().Unix(), float64(pct)), tags, metadata.Counter, metadata.Pct, "") + } + return md, nil } diff --git a/cmd/scollector/collectors/snmp_sys.go b/cmd/scollector/collectors/snmp_sys.go index 9d60656451..fa93a9fe6a 100644 --- a/cmd/scollector/collectors/snmp_sys.go +++ b/cmd/scollector/collectors/snmp_sys.go @@ -16,14 +16,14 @@ const sysUpTime = ".1.3.6.1.2.1.1.3.0" // "The time (in hundredths of a second) func SNMPSys(cfg conf.SNMP) { collectors = append(collectors, &IntervalCollector{ F: func() (opentsdb.MultiDataPoint, error) { - return c_snmp_sys(cfg.Community, cfg.Host) + return c_snmp_sys(cfg.Host, cfg.Community) }, Interval: time.Minute * 1, name: fmt.Sprintf("snmp-sys-%s", cfg.Host), }) } -func c_snmp_sys(community, host string) (opentsdb.MultiDataPoint, error) { +func c_snmp_sys(host, community string) (opentsdb.MultiDataPoint, error) { var md opentsdb.MultiDataPoint uptime, err := snmp_oid(host, community, sysUpTime) if err != nil { diff --git a/cmd/scollector/collectors/vsphere.go b/cmd/scollector/collectors/vsphere.go index 68d3663e89..68fc0e7e7a 100644 --- a/cmd/scollector/collectors/vsphere.go +++ b/cmd/scollector/collectors/vsphere.go @@ -6,6 +6,7 @@ import ( "fmt" "io" "strconv" + "time" "bosun.org/metadata" "bosun.org/opentsdb" @@ -19,22 +20,23 @@ func Vsphere(user, pwd, host string) error { if host == "" || user == "" || pwd == "" { return fmt.Errorf("empty Host, User, or Password in Vsphere") } + cpuIntegrators := make(map[string]tsIntegrator) collectors = append(collectors, &IntervalCollector{ F: func() (opentsdb.MultiDataPoint, error) { - return c_vsphere(user, pwd, host) + return c_vsphere(user, pwd, host, cpuIntegrators) }, name: fmt.Sprintf("vsphere-%s", host), }) return nil } -func c_vsphere(user, pwd, host string) (opentsdb.MultiDataPoint, error) { +func c_vsphere(user, pwd, host string, cpuIntegrators map[string]tsIntegrator) (opentsdb.MultiDataPoint, error) { v, err := vsphere.Connect(host, user, pwd) if err != nil { return nil, err } var md opentsdb.MultiDataPoint - if err := vsphereHost(v, &md); err != nil { + if err := vsphereHost(v, &md, cpuIntegrators); err != nil { return nil, err } if err := vsphereDatastore(v, &md); err != nil { @@ -111,7 +113,7 @@ type HostSystemIdentificationInfo struct { } `xml:"identifierType"` } -func vsphereHost(v *vsphere.Vsphere, md *opentsdb.MultiDataPoint) error { +func vsphereHost(v *vsphere.Vsphere, md *opentsdb.MultiDataPoint, cpuIntegrators map[string]tsIntegrator) error { res, err := v.Info("HostSystem", []string{ "name", "summary.hardware.cpuMhz", @@ -205,7 +207,12 @@ func vsphereHost(v *vsphere.Vsphere, md *opentsdb.MultiDataPoint) error { if cpuMhz > 0 && cpuUse > 0 && cpuCores > 0 { cpuTotal := cpuMhz * cpuCores Add(md, "vsphere.cpu", cpuTotal-cpuUse, opentsdb.TagSet{"host": name, "type": "idle"}, metadata.Gauge, metadata.MHz, "") - Add(md, "vsphere.cpu.pct", float64(cpuUse)/float64(cpuTotal)*100, tags, metadata.Gauge, metadata.Pct, "") + pct := float64(cpuUse) / float64(cpuTotal) * 100 + Add(md, "vsphere.cpu.pct", pct, tags, metadata.Gauge, metadata.Pct, "") + if _, ok := cpuIntegrators[name]; !ok { + cpuIntegrators[name] = getTsIntegrator() + } + Add(md, osCPU, cpuIntegrators[name](time.Now().Unix(), pct), tags, metadata.Counter, metadata.Pct, "") } } return Error