Skip to content

Commit

Permalink
Revert "use the external library to collect CPU usage on darwin"
Browse files Browse the repository at this point in the history
This reverts commit cf53f71.
  • Loading branch information
itchyny committed Oct 16, 2017
1 parent 55b1605 commit aaa596d
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 33 deletions.
2 changes: 1 addition & 1 deletion command/command_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func interfaceGenerator() spec.InterfaceGenerator {
func metricsGenerators(conf *config.Config) []metrics.Generator {
generators := []metrics.Generator{
&metricsDarwin.Loadavg5Generator{},
&metricsDarwin.CPUUsageGenerator{Interval: metricsInterval},
&metricsDarwin.CPUUsageGenerator{},
&metricsDarwin.MemoryGenerator{},
&metrics.FilesystemGenerator{IgnoreRegexp: conf.Filesystems.Ignore.Regexp, UseMountpoint: conf.Filesystems.UseMountpoint},
&metricsDarwin.InterfaceGenerator{Interval: metricsInterval},
Expand Down
51 changes: 31 additions & 20 deletions metrics/darwin/cpuusage.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,51 +3,62 @@
package darwin

import (
"errors"
"time"
"fmt"
"os/exec"
"strconv"
"strings"

"github.com/mackerelio/go-osstat/cpu"
"github.com/mackerelio/golib/logging"
"github.com/mackerelio/mackerel-agent/metrics"
)

// CPUUsageGenerator XXX
type CPUUsageGenerator struct {
Interval time.Duration
}

var cpuUsageLogger = logging.GetLogger("metrics.cpuUsage")

var iostatFieldToMetricName = []string{"user", "system", "idle"}

// Generate returns current CPU usage of the host.
// Keys below are expected:
// - cpu.user.percentage
// - cpu.system.percentage
// - cpu.idle.percentage
func (g *CPUUsageGenerator) Generate() (metrics.Values, error) {
before, err := cpu.Get()

// $ iostat -n0 -c2
// cpu load average
// us sy id 1m 5m 15m
// 13 7 81 1.93 2.23 2.65
// 13 7 81 1.93 2.23 2.65
iostatBytes, err := exec.Command("iostat", "-n0", "-c2").Output()
if err != nil {
cpuUsageLogger.Errorf("failed to get cpu statistics: %s", err)
cpuUsageLogger.Errorf("Failed to invoke iostat: %s", err)
return nil, err
}

time.Sleep(g.Interval)
iostat := string(iostatBytes)
lines := strings.Split(iostat, "\n")
if len(lines) != 5 {
return nil, fmt.Errorf("iostat result malformed: [%q]", iostat)
}

after, err := cpu.Get()
if err != nil {
cpuUsageLogger.Errorf("failed to get cpu statistics: %s", err)
return nil, err
fields := strings.Fields(lines[3])
if len(fields) < len(iostatFieldToMetricName) {
return nil, fmt.Errorf("iostat result malformed: [%q]", iostat)
}

if before.Total == after.Total {
err := errors.New("cpu total counter did not change")
cpuUsageLogger.Errorf("%s", err)
return nil, err
cpuUsage := make(map[string]float64, len(iostatFieldToMetricName))

for i, n := range iostatFieldToMetricName {
value, err := strconv.ParseFloat(fields[i], 64)
if err != nil {
return nil, err
}

cpuUsage["cpu."+n+".percentage"] = value
}

cpuUsage := make(map[string]float64, 3)
total := float64(after.Total - before.Total)
cpuUsage["cpu.user.percentage"] = float64(after.User-before.User) / total * 100.0
cpuUsage["cpu.system.percentage"] = float64(after.System-before.System) / total * 100.0
cpuUsage["cpu.idle.percentage"] = float64(after.Idle-before.Idle) / total * 100.0
return metrics.Values(cpuUsage), nil
}
18 changes: 6 additions & 12 deletions metrics/darwin/cpuusage_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,20 @@

package darwin

import (
"testing"
"time"
)
import "testing"

func TestCPUUsageGenerator_Generate(t *testing.T) {
g := &CPUUsageGenerator{1 * time.Second}
g := &CPUUsageGenerator{}
values, err := g.Generate()

if err != nil {
t.Errorf("error should not have occurred: %s", err)
}

metricNames := []string{"cpu.user.percentage", "cpu.system.percentage", "cpu.idle.percentage"}

for _, name := range metricNames {
if v, ok := values[name]; !ok {
t.Errorf("cpu should has %s", name)
} else {
t.Logf("cpu '%s' collected: %+v", name, v)
metricName := []string{"cpu.user.percentage", "cpu.system.percentage", "cpu.idle.percentage"}
for _, n := range metricName {
if _, ok := values[n]; !ok {
t.Errorf("should have '%s': %v", n, values)
}
}
}

0 comments on commit aaa596d

Please sign in to comment.