fix merge conflicts, update import paths

This commit is contained in:
JP 2015-08-13 18:57:05 -05:00
commit 3145a732f2
14 changed files with 313 additions and 133 deletions

View File

@ -1,4 +1,10 @@
## v0.1.5 [unreleased] ## v0.1.6 [unreleased]
### Features
### Bugfixes
## v0.1.5 [2015-08-13]
### Features ### Features
- [#54](https://github.com/influxdb/telegraf/pull/54): MongoDB plugin. Thanks @jipperinbham! - [#54](https://github.com/influxdb/telegraf/pull/54): MongoDB plugin. Thanks @jipperinbham!
@ -15,6 +21,8 @@
- [#103](https://github.com/influxdb/telegraf/pull/103): Filter by metric tags. Thanks @srfraser! - [#103](https://github.com/influxdb/telegraf/pull/103): Filter by metric tags. Thanks @srfraser!
- [#106](https://github.com/influxdb/telegraf/pull/106): Options to filter plugins on startup. Thanks @zepouet! - [#106](https://github.com/influxdb/telegraf/pull/106): Options to filter plugins on startup. Thanks @zepouet!
- [#107](https://github.com/influxdb/telegraf/pull/107): Multiple outputs beyong influxdb. Thanks @jipperinbham! - [#107](https://github.com/influxdb/telegraf/pull/107): Multiple outputs beyong influxdb. Thanks @jipperinbham!
- [#108](https://github.com/influxdb/telegraf/issues/108): Support setting per-CPU and total-CPU gathering.
- [#111](https://github.com/influxdb/telegraf/pull/111): Report CPU Usage in cpu plugin. Thanks @jpalay!
### Bugfixes ### Bugfixes
- [#85](https://github.com/influxdb/telegraf/pull/85): Fix GetLocalHost testutil function for mac users - [#85](https://github.com/influxdb/telegraf/pull/85): Fix GetLocalHost testutil function for mac users

128
README.md
View File

@ -18,9 +18,14 @@ writing new plugins.
### Linux packages for Debian/Ubuntu and RHEL/CentOS: ### Linux packages for Debian/Ubuntu and RHEL/CentOS:
NOTE: version 0.1.5 has introduced some breaking changes! A 0.1.5 telegraf
agent is NOT backwards-compatible with a config file from 0.1.4 and below.
That being said, the difference is not huge, see below for an example on
how to setup the new config file.
``` ```
http://get.influxdb.org/telegraf/telegraf_0.1.4_amd64.deb http://get.influxdb.org/telegraf/telegraf_0.1.5_amd64.deb
http://get.influxdb.org/telegraf/telegraf-0.1.4-1.x86_64.rpm http://get.influxdb.org/telegraf/telegraf-0.1.5-1.x86_64.rpm
``` ```
### OSX via Homebrew: ### OSX via Homebrew:
@ -35,22 +40,10 @@ brew install telegraf
* Run `telegraf -sample-config > telegraf.toml` to create an initial configuration * Run `telegraf -sample-config > telegraf.toml` to create an initial configuration
* Edit the configuration to match your needs * Edit the configuration to match your needs
* Run `telegraf -config telegraf.toml -test` to output one full measurement sample to STDOUT * Run `telegraf -config telegraf.toml -test` to output one full measurement sample to STDOUT
* Run `telegraf -config telegraf.toml` to gather and send metrics to InfluxDB * Run `telegraf -config telegraf.toml` to gather and send metrics to configured outputs.
* Run `telegraf -config telegraf.toml -filter system:swap` to enable only two plugins described into config file * Run `telegraf -config telegraf.toml -filter system:swap`
to enable only the system & swap plugins defined in the config.
### Telegraf Usage
```telegraf --help```
* -config="": configuration file to load
* -debug=false: show metrics as they're generated to stdout
* -filter="": filter the plugins to enable, separator is :
* -httptest.serve="": if non-empty, httptest.NewServer serves on this address and blocks
* -pidfile="": file to write our pid to
* -sample-config=false: print out full sample configuration
* -test=false: gather metrics, print them out, and exit
* -version=false: display the version
## Telegraf Options ## Telegraf Options
Telegraf has a few options you can configure under the `agent` section of the Telegraf has a few options you can configure under the `agent` section of the
@ -66,6 +59,62 @@ unit parser, ie "10s" for 10 seconds or "5m" for 5 minutes.
* **debug**: Set to true to gather and send metrics to STDOUT as well as * **debug**: Set to true to gather and send metrics to STDOUT as well as
InfluxDB. InfluxDB.
## Plugin Options
There are 5 configuration options that are configurable per plugin:
* **pass**: An array of strings that is used to filter metrics generated by the
current plugin. Each string in the array is tested as a prefix against metric names
and if it matches, the metric is emitted.
* **drop**: The inverse of pass, if a metric name matches, it is not emitted.
* **tagpass**: tag names and arrays of strings that are used to filter metrics by
the current plugin. Each string in the array is tested as an exact match against
the tag name, and if it matches the metric is emitted.
* **tagdrop**: The inverse of tagpass. If a tag matches, the metric is not emitted.
This is tested on metrics that have passed the tagpass test.
* **interval**: How often to gather this metric. Normal plugins use a single
global interval, but if one particular plugin should be run less or more often,
you can configure that here.
### Plugin Configuration Examples
This is a full working config that will output CPU data to an InfluxDB instance
at 192.168.59.103:8086, tagging measurements with dc="Denver-1". It will output
measurements at a 10s interval and will collect totalcpu & percpu data.
```
[outputs]
[outputs.influxdb]
url = "http://192.168.59.103:8086" # required.
database = "telegraf" # required.
[tags]
dc = "denver-1"
[agent]
interval = "10s"
# PLUGINS
[cpu]
percpu = true
totalcpu = true
```
Below is how to configure `tagpass` parameters (added in 0.1.5)
```
# Don't collect CPU data for cpu6 & cpu7
[cpu.tagdrop]
cpu = [ "cpu6", "cpu7" ]
[disk]
[disk.tagpass]
# tagpass conditions are OR, not AND.
# If the (filesystem is ext4 or xfs) OR (the path is /opt or /home)
# then the metric passes
fstype = [ "ext4", "xfs" ]
path = [ "/opt", "/home" ]
```
## Supported Plugins ## Supported Plugins
Telegraf currently has support for collecting metrics from: Telegraf currently has support for collecting metrics from:
@ -87,51 +136,6 @@ Telegraf currently has support for collecting metrics from:
We'll be adding support for many more over the coming months. Read on if you We'll be adding support for many more over the coming months. Read on if you
want to add support for another service or third-party API. want to add support for another service or third-party API.
## Plugin Options
There are 3 configuration options that are configurable per plugin:
* **pass**: An array of strings that is used to filter metrics generated by the
current plugin. Each string in the array is tested as a prefix against metric names
and if it matches, the metric is emitted.
* **drop**: The inverse of pass, if a metric name matches, it is not emitted.
* **tagpass**: tag names and arrays of strings that are used to filter metrics by
the current plugin. Each string in the array is tested as an exact match against
the tag name, and if it matches the metric is emitted.
* **tagdrop**: The inverse of tagpass. If a tag matches, the metric is not emitted.
This is tested on metrics that have passed the tagpass test.
* **interval**: How often to gather this metric. Normal plugins use a single
global interval, but if one particular plugin should be run less or more often,
you can configure that here.
### Plugin Configuration Examples
```
# Read metrics about disk usage by mount point
[disk]
interval = "1m" # Run at a 1 minute interval instead of the default
[disk.tagpass]
# These tag conditions are OR, not AND.
# If the (filesystem is ext4 or xfs) or (the path is /opt or /home) then the metric passes
fstype = [ "ext4", "xfs" ]
path = [ "/opt", "/home" ]
[postgresql]
[postgresql.tagdrop]
# Don't report stats about the database name 'testdatabase'
db = [ "testdatabase" ]
```
```
[disk]
# Don't report stats about the following filesystem types
[disk.tagdrop]
fstype = [ "nfs", "tmpfs", "ecryptfs" ]
```
## Plugins ## Plugins
This section is for developers that want to create new collection plugins. This section is for developers that want to create new collection plugins.

View File

@ -13,11 +13,11 @@ test:
# install binaries # install binaries
- go install ./... - go install ./...
# Go fmt should pass all files # Go fmt should pass all files
- "[ `git ls-files | grep '.go$' | xargs gofmt -l 2>&1 | wc -l` -eq 0 ]" - "[ `git ls-files | grep '.go$' | xargs gofmt -l | tee /tmp/foo | wc -l` -eq 0 ] || (cat /tmp/foo; exit 1)"
- go vet ./... - go vet ./...
- golint . - "[ `golint . | tee /tmp/foo | wc -l` == 0 ] || (cat /tmp/foo; exit 1)"
- golint testutil/... - "[ `golint testutil/... | tee /tmp/foo | wc -l` == 0 ] || (cat /tmp/foo; exit 1)"
- golint cmd/... - "[ `golint cmd/... | tee /tmp/foo | wc -l` == 0 ] || (cat /tmp/foo; exit 1)"
override: override:
- make test-short - make test-short
post: post:

View File

@ -8,9 +8,9 @@ import (
"os/signal" "os/signal"
"strings" "strings"
"github.com/influxdb/telegraf"
_ "github.com/influxdb/telegraf/outputs/all"
_ "github.com/influxdb/telegraf/plugins/all" _ "github.com/influxdb/telegraf/plugins/all"
"github.com/jipperinbham/telegraf"
_ "github.com/jipperinbham/telegraf/outputs/all"
) )
var fDebug = flag.Bool("debug", false, "show metrics as they're generated to stdout") var fDebug = flag.Bool("debug", false, "show metrics as they're generated to stdout")
@ -22,7 +22,7 @@ var fPidfile = flag.String("pidfile", "", "file to write our pid to")
var fPLuginsFilter = flag.String("filter", "", "filter the plugins to enable, separator is :") var fPLuginsFilter = flag.String("filter", "", "filter the plugins to enable, separator is :")
// Telegraf version // Telegraf version
var Version = "0.1.5-dev" var Version = "0.1.6-dev"
func main() { func main() {
flag.Parse() flag.Parse()
@ -48,7 +48,9 @@ func main() {
log.Fatal(err) log.Fatal(err)
} }
} else { } else {
config = telegraf.DefaultConfig() fmt.Println("Usage: Telegraf")
flag.PrintDefaults()
return
} }
ag, err := telegraf.NewAgent(config) ag, err := telegraf.NewAgent(config)
@ -65,7 +67,7 @@ func main() {
log.Fatal(err) log.Fatal(err)
} }
if len(outputs) == 0 { if len(outputs) == 0 {
log.Printf("Error: no outputs found, did you provide a config file?") log.Printf("Error: no outputs found, did you provide a valid config file?")
os.Exit(1) os.Exit(1)
} }
@ -74,7 +76,7 @@ func main() {
log.Fatal(err) log.Fatal(err)
} }
if len(plugins) == 0 { if len(plugins) == 0 {
log.Printf("Error: no plugins found, did you provide a config file?") log.Printf("Error: no plugins found, did you provide a valid config file?")
os.Exit(1) os.Exit(1)
} }
@ -116,7 +118,7 @@ func main() {
log.Printf("Agent Config: Interval:%s, Debug:%#v, Hostname:%#v\n", log.Printf("Agent Config: Interval:%s, Debug:%#v, Hostname:%#v\n",
ag.Interval, ag.Debug, ag.Hostname) ag.Interval, ag.Debug, ag.Hostname)
} }
log.Printf("Tags enabled: %v", config.ListTags()) log.Printf("Tags enabled: %s", config.ListTags())
if *fPidfile != "" { if *fPidfile != "" {
f, err := os.Create(*fPidfile) f, err := os.Create(*fPidfile)

View File

@ -51,7 +51,7 @@ func (c *Config) Outputs() map[string]*ast.Table {
return c.outputs return c.outputs
} }
// The name of a tag, and the values on which to filter // TagFilter is the name of a tag, and the values on which to filter
type TagFilter struct { type TagFilter struct {
Name string Name string
Filter []string Filter []string
@ -253,11 +253,6 @@ func declared(endpoints map[string]*ast.Table) []string {
return names return names
} }
// DefaultConfig returns an empty default configuration
func DefaultConfig() *Config {
return &Config{}
}
var errInvalidConfig = errors.New("invalid configuration") var errInvalidConfig = errors.New("invalid configuration")
// LoadConfig loads the given config file and returns a *Config pointer // LoadConfig loads the given config file and returns a *Config pointer

View File

@ -1,6 +1,6 @@
package all package all
import ( import (
_ "github.com/influxdb/telegraf/outputs/datadog"
_ "github.com/influxdb/telegraf/outputs/influxdb" _ "github.com/influxdb/telegraf/outputs/influxdb"
_ "github.com/jipperinbham/telegraf/outputs/datadog"
) )

View File

@ -224,7 +224,7 @@ EOF
if [ $# -ne 1 ]; then if [ $# -ne 1 ]; then
usage 1 usage 1
elif [ $1 == "-h" ]; then elif [ "$1" == "-h" ]; then
usage 0 usage 0
else else
VERSION=$1 VERSION=$1
@ -232,11 +232,11 @@ fi
echo -e "\nStarting package process...\n" echo -e "\nStarting package process...\n"
if [ $CIRCLE_BRANCH == "" ]; then if [ "$CIRCLE_BRANCH" == "" ]; then
check_gvm check_gvm
fi fi
check_gopath check_gopath
if [ $CIRCLE_BRANCH == "" ]; then if [ "$CIRCLE_BRANCH" == "" ]; then
check_clean_tree check_clean_tree
update_tree update_tree
fi fi
@ -282,7 +282,7 @@ generate_postinstall_script $VERSION
########################################################################### ###########################################################################
# Create the actual packages. # Create the actual packages.
if [ $CIRCLE_BRANCH == "" ]; then if [ "$CIRCLE_BRANCH" == "" ]; then
echo -n "Commence creation of $ARCH packages, version $VERSION? [Y/n] " echo -n "Commence creation of $ARCH packages, version $VERSION? [Y/n] "
read response read response
response=`echo $response | tr 'A-Z' 'a-z'` response=`echo $response | tr 'A-Z' 'a-z'`
@ -323,7 +323,7 @@ echo "Debian package created successfully."
########################################################################### ###########################################################################
# Offer to tag the repo. # Offer to tag the repo.
if [ $CIRCLE_BRANCH == "" ]; then if [ "$CIRCLE_BRANCH" == "" ]; then
echo -n "Tag source tree with v$VERSION and push to repo? [y/N] " echo -n "Tag source tree with v$VERSION and push to repo? [y/N] "
read response read response
response=`echo $response | tr 'A-Z' 'a-z'` response=`echo $response | tr 'A-Z' 'a-z'`
@ -347,7 +347,7 @@ fi
########################################################################### ###########################################################################
# Offer to publish the packages. # Offer to publish the packages.
if [ $CIRCLE_BRANCH == "" ]; then if [ "$CIRCLE_BRANCH" == "" ]; then
echo -n "Publish packages to S3? [y/N] " echo -n "Publish packages to S3? [y/N] "
read response read response
response=`echo $response | tr 'A-Z' 'a-z'` response=`echo $response | tr 'A-Z' 'a-z'`

View File

@ -4,29 +4,51 @@ import (
"fmt" "fmt"
"github.com/influxdb/telegraf/plugins" "github.com/influxdb/telegraf/plugins"
"github.com/influxdb/telegraf/plugins/system/ps/cpu"
) )
type CPUStats struct { type CPUStats struct {
ps PS ps PS
lastStats []cpu.CPUTimesStat
PerCPU bool `toml:"percpu"`
TotalCPU bool `toml:"totalcpu"`
}
func NewCPUStats(ps PS) *CPUStats {
return &CPUStats{
ps: ps,
}
} }
func (_ *CPUStats) Description() string { func (_ *CPUStats) Description() string {
return "Read metrics about cpu usage" return "Read metrics about cpu usage"
} }
func (_ *CPUStats) SampleConfig() string { return "" } var sampleConfig = `
# Whether to report per-cpu stats or not
percpu = true
# Whether to report total system cpu stats or not
totalcpu = true`
func (_ *CPUStats) SampleConfig() string {
return sampleConfig
}
func (s *CPUStats) Gather(acc plugins.Accumulator) error { func (s *CPUStats) Gather(acc plugins.Accumulator) error {
times, err := s.ps.CPUTimes() times, err := s.ps.CPUTimes(s.PerCPU, s.TotalCPU)
if err != nil { if err != nil {
return fmt.Errorf("error getting CPU info: %s", err) return fmt.Errorf("error getting CPU info: %s", err)
} }
for _, cts := range times { for i, cts := range times {
tags := map[string]string{ tags := map[string]string{
"cpu": cts.CPU, "cpu": cts.CPU,
} }
busy, total := busyAndTotalCpuTime(cts)
// Add total cpu numbers
add(acc, "user", cts.User, tags) add(acc, "user", cts.User, tags)
add(acc, "system", cts.System, tags) add(acc, "system", cts.System, tags)
add(acc, "idle", cts.Idle, tags) add(acc, "idle", cts.Idle, tags)
@ -38,11 +60,54 @@ func (s *CPUStats) Gather(acc plugins.Accumulator) error {
add(acc, "guest", cts.Guest, tags) add(acc, "guest", cts.Guest, tags)
add(acc, "guestNice", cts.GuestNice, tags) add(acc, "guestNice", cts.GuestNice, tags)
add(acc, "stolen", cts.Stolen, tags) add(acc, "stolen", cts.Stolen, tags)
add(acc, "busy", busy, tags)
// Add in percentage
if len(s.lastStats) == 0 {
// If it's the 1st gather, can't get CPU stats yet
continue
}
lastCts := s.lastStats[i]
lastBusy, lastTotal := busyAndTotalCpuTime(lastCts)
busyDelta := busy - lastBusy
totalDelta := total - lastTotal
if totalDelta < 0 {
return fmt.Errorf("Error: current total CPU time is less than previous total CPU time")
}
if totalDelta == 0 {
continue
}
add(acc, "percentageUser", 100*(cts.User-lastCts.User)/totalDelta, tags)
add(acc, "percentageSystem", 100*(cts.System-lastCts.System)/totalDelta, tags)
add(acc, "percentageIdle", 100*(cts.Idle-lastCts.Idle)/totalDelta, tags)
add(acc, "percentageNice", 100*(cts.Nice-lastCts.Nice)/totalDelta, tags)
add(acc, "percentageIowait", 100*(cts.Iowait-lastCts.Iowait)/totalDelta, tags)
add(acc, "percentageIrq", 100*(cts.Irq-lastCts.Irq)/totalDelta, tags)
add(acc, "percentageSoftirq", 100*(cts.Softirq-lastCts.Softirq)/totalDelta, tags)
add(acc, "percentageSteal", 100*(cts.Steal-lastCts.Steal)/totalDelta, tags)
add(acc, "percentageGuest", 100*(cts.Guest-lastCts.Guest)/totalDelta, tags)
add(acc, "percentageGuestNice", 100*(cts.GuestNice-lastCts.GuestNice)/totalDelta, tags)
add(acc, "percentageStolen", 100*(cts.Stolen-lastCts.Stolen)/totalDelta, tags)
add(acc, "percentageBusy", 100*busyDelta/totalDelta, tags)
} }
s.lastStats = times
return nil return nil
} }
func busyAndTotalCpuTime(t cpu.CPUTimesStat) (float64, float64) {
busy := t.User + t.System + t.Nice + t.Iowait + t.Irq + t.Softirq + t.Steal +
t.Guest + t.GuestNice + t.Stolen
return busy, busy + t.Idle
}
func init() { func init() {
plugins.Add("cpu", func() plugins.Plugin { plugins.Add("cpu", func() plugins.Plugin {
return &CPUStats{ps: &systemPS{}} return &CPUStats{ps: &systemPS{}}

View File

@ -21,7 +21,7 @@ func (m *MockPS) LoadAvg() (*load.LoadAvgStat, error) {
return r0, r1 return r0, r1
} }
func (m *MockPS) CPUTimes() ([]cpu.CPUTimesStat, error) { func (m *MockPS) CPUTimes(perCPU, totalCPU bool) ([]cpu.CPUTimesStat, error) {
ret := m.Called() ret := m.Called()
r0 := ret.Get(0).([]cpu.CPUTimesStat) r0 := ret.Get(0).([]cpu.CPUTimesStat)

View File

@ -25,7 +25,7 @@ type DockerContainerStat struct {
type PS interface { type PS interface {
LoadAvg() (*load.LoadAvgStat, error) LoadAvg() (*load.LoadAvgStat, error)
CPUTimes() ([]cpu.CPUTimesStat, error) CPUTimes(perCPU, totalCPU bool) ([]cpu.CPUTimesStat, error)
DiskUsage() ([]*disk.DiskUsageStat, error) DiskUsage() ([]*disk.DiskUsageStat, error)
NetIO() ([]net.NetIOCountersStat, error) NetIO() ([]net.NetIOCountersStat, error)
DiskIO() (map[string]disk.DiskIOCountersStat, error) DiskIO() (map[string]disk.DiskIOCountersStat, error)
@ -49,8 +49,23 @@ func (s *systemPS) LoadAvg() (*load.LoadAvgStat, error) {
return load.LoadAvg() return load.LoadAvg()
} }
func (s *systemPS) CPUTimes() ([]cpu.CPUTimesStat, error) { func (s *systemPS) CPUTimes(perCPU, totalCPU bool) ([]cpu.CPUTimesStat, error) {
return cpu.CPUTimes(true) var cpuTimes []cpu.CPUTimesStat
if perCPU {
if perCPUTimes, err := cpu.CPUTimes(true); err == nil {
cpuTimes = append(cpuTimes, perCPUTimes...)
} else {
return nil, err
}
}
if totalCPU {
if totalCPUTimes, err := cpu.CPUTimes(false); err == nil {
cpuTimes = append(cpuTimes, totalCPUTimes...)
} else {
return nil, err
}
}
return cpuTimes, nil
} }
func (s *systemPS) DiskUsage() ([]*disk.DiskUsageStat, error) { func (s *systemPS) DiskUsage() ([]*disk.DiskUsageStat, error) {

View File

@ -85,18 +85,11 @@ func perCPUTimes() ([]CPUTimesStat, error) {
} }
c := CPUTimesStat{ c := CPUTimesStat{
CPU: fmt.Sprintf("cpu%d", i), CPU: fmt.Sprintf("cpu%d", i),
User: float64(cpu_ticks[C.CPU_STATE_USER]) / ClocksPerSec, User: float64(cpu_ticks[C.CPU_STATE_USER]) / ClocksPerSec,
System: float64(cpu_ticks[C.CPU_STATE_SYSTEM]) / ClocksPerSec, System: float64(cpu_ticks[C.CPU_STATE_SYSTEM]) / ClocksPerSec,
Nice: float64(cpu_ticks[C.CPU_STATE_NICE]) / ClocksPerSec, Nice: float64(cpu_ticks[C.CPU_STATE_NICE]) / ClocksPerSec,
Idle: float64(cpu_ticks[C.CPU_STATE_IDLE]) / ClocksPerSec, Idle: float64(cpu_ticks[C.CPU_STATE_IDLE]) / ClocksPerSec,
Iowait: -1,
Irq: -1,
Softirq: -1,
Steal: -1,
Guest: -1,
GuestNice: -1,
Stolen: -1,
} }
ret = append(ret, c) ret = append(ret, c)
@ -119,18 +112,11 @@ func allCPUTimes() ([]CPUTimesStat, error) {
} }
c := CPUTimesStat{ c := CPUTimesStat{
CPU: "cpu-total", CPU: "cpu-total",
User: float64(cpuload.cpu_ticks[C.CPU_STATE_USER]) / ClocksPerSec, User: float64(cpuload.cpu_ticks[C.CPU_STATE_USER]) / ClocksPerSec,
System: float64(cpuload.cpu_ticks[C.CPU_STATE_SYSTEM]) / ClocksPerSec, System: float64(cpuload.cpu_ticks[C.CPU_STATE_SYSTEM]) / ClocksPerSec,
Nice: float64(cpuload.cpu_ticks[C.CPU_STATE_NICE]) / ClocksPerSec, Nice: float64(cpuload.cpu_ticks[C.CPU_STATE_NICE]) / ClocksPerSec,
Idle: float64(cpuload.cpu_ticks[C.CPU_STATE_IDLE]) / ClocksPerSec, Idle: float64(cpuload.cpu_ticks[C.CPU_STATE_IDLE]) / ClocksPerSec,
Iowait: -1,
Irq: -1,
Softirq: -1,
Steal: -1,
Guest: -1,
GuestNice: -1,
Stolen: -1,
} }
return []CPUTimesStat{c}, nil return []CPUTimesStat{c}, nil

View File

@ -1,6 +1,8 @@
package system package system
import ( import (
"fmt"
"reflect"
"testing" "testing"
"github.com/influxdb/telegraf/plugins/system/ps/cpu" "github.com/influxdb/telegraf/plugins/system/ps/cpu"
@ -44,6 +46,21 @@ func TestSystemStats_GenerateStats(t *testing.T) {
Stolen: 0.051, Stolen: 0.051,
} }
cts2 := cpu.CPUTimesStat{
CPU: "cpu0",
User: 11.4, // increased by 8.3
System: 10.9, // increased by 2.7
Idle: 158.8699, // increased by 78.7699 (for total increase of 100)
Nice: 2.5, // increased by 1.2
Iowait: 0.7, // increased by 0.5
Irq: 1.2, // increased by 1.1
Softirq: 0.31, // increased by 0.2
Steal: 0.0002, // increased by 0.0001
Guest: 12.9, // increased by 4.8
GuestNice: 2.524, // increased by 2.2
Stolen: 0.281, // increased by 0.23
}
mps.On("CPUTimes").Return([]cpu.CPUTimesStat{cts}, nil) mps.On("CPUTimes").Return([]cpu.CPUTimesStat{cts}, nil)
du := &disk.DiskUsageStat{ du := &disk.DiskUsageStat{
@ -171,26 +188,72 @@ func TestSystemStats_GenerateStats(t *testing.T) {
assert.True(t, acc.CheckValue("load5", 1.5)) assert.True(t, acc.CheckValue("load5", 1.5))
assert.True(t, acc.CheckValue("load15", 0.8)) assert.True(t, acc.CheckValue("load15", 0.8))
cs := &CPUStats{ps: &mps} cs := NewCPUStats(&mps)
cputags := map[string]string{ cputags := map[string]string{
"cpu": "cpu0", "cpu": "cpu0",
} }
preCPUPoints := len(acc.Points)
err = cs.Gather(&acc)
require.NoError(t, err)
numCPUPoints := len(acc.Points) - preCPUPoints
expectedCPUPoints := 12
assert.Equal(t, numCPUPoints, expectedCPUPoints)
// Computed values are checked with delta > 0 becasue of floating point arithmatic
// imprecision
assertContainsTaggedFloat(t, acc, "user", 3.1, 0, cputags)
assertContainsTaggedFloat(t, acc, "system", 8.2, 0, cputags)
assertContainsTaggedFloat(t, acc, "idle", 80.1, 0, cputags)
assertContainsTaggedFloat(t, acc, "nice", 1.3, 0, cputags)
assertContainsTaggedFloat(t, acc, "iowait", 0.2, 0, cputags)
assertContainsTaggedFloat(t, acc, "irq", 0.1, 0, cputags)
assertContainsTaggedFloat(t, acc, "softirq", 0.11, 0, cputags)
assertContainsTaggedFloat(t, acc, "steal", 0.0001, 0, cputags)
assertContainsTaggedFloat(t, acc, "guest", 8.1, 0, cputags)
assertContainsTaggedFloat(t, acc, "guestNice", 0.324, 0, cputags)
assertContainsTaggedFloat(t, acc, "stolen", 0.051, 0, cputags)
assertContainsTaggedFloat(t, acc, "busy", 21.4851, 0.0005, cputags)
mps2 := MockPS{}
mps2.On("CPUTimes").Return([]cpu.CPUTimesStat{cts2}, nil)
cs.ps = &mps2
// Should have added cpu percentages too
err = cs.Gather(&acc) err = cs.Gather(&acc)
require.NoError(t, err) require.NoError(t, err)
assert.True(t, acc.CheckTaggedValue("user", 3.1, cputags)) numCPUPoints = len(acc.Points) - (preCPUPoints + numCPUPoints)
assert.True(t, acc.CheckTaggedValue("system", 8.2, cputags)) expectedCPUPoints = 24
assert.True(t, acc.CheckTaggedValue("idle", 80.1, cputags)) assert.Equal(t, numCPUPoints, expectedCPUPoints)
assert.True(t, acc.CheckTaggedValue("nice", 1.3, cputags))
assert.True(t, acc.CheckTaggedValue("iowait", 0.2, cputags)) assertContainsTaggedFloat(t, acc, "user", 11.4, 0, cputags)
assert.True(t, acc.CheckTaggedValue("irq", 0.1, cputags)) assertContainsTaggedFloat(t, acc, "system", 10.9, 0, cputags)
assert.True(t, acc.CheckTaggedValue("softirq", 0.11, cputags)) assertContainsTaggedFloat(t, acc, "idle", 158.8699, 0, cputags)
assert.True(t, acc.CheckTaggedValue("steal", 0.0001, cputags)) assertContainsTaggedFloat(t, acc, "nice", 2.5, 0, cputags)
assert.True(t, acc.CheckTaggedValue("guest", 8.1, cputags)) assertContainsTaggedFloat(t, acc, "iowait", 0.7, 0, cputags)
assert.True(t, acc.CheckTaggedValue("guestNice", 0.324, cputags)) assertContainsTaggedFloat(t, acc, "irq", 1.2, 0, cputags)
assert.True(t, acc.CheckTaggedValue("stolen", 0.051, cputags)) assertContainsTaggedFloat(t, acc, "softirq", 0.31, 0, cputags)
assertContainsTaggedFloat(t, acc, "steal", 0.0002, 0, cputags)
assertContainsTaggedFloat(t, acc, "guest", 12.9, 0, cputags)
assertContainsTaggedFloat(t, acc, "guestNice", 2.524, 0, cputags)
assertContainsTaggedFloat(t, acc, "stolen", 0.281, 0, cputags)
assertContainsTaggedFloat(t, acc, "busy", 42.7152, 0.0005, cputags)
assertContainsTaggedFloat(t, acc, "percentageUser", 8.3, 0.0005, cputags)
assertContainsTaggedFloat(t, acc, "percentageSystem", 2.7, 0.0005, cputags)
assertContainsTaggedFloat(t, acc, "percentageIdle", 78.7699, 0.0005, cputags)
assertContainsTaggedFloat(t, acc, "percentageNice", 1.2, 0.0005, cputags)
assertContainsTaggedFloat(t, acc, "percentageIowait", 0.5, 0.0005, cputags)
assertContainsTaggedFloat(t, acc, "percentageIrq", 1.1, 0.0005, cputags)
assertContainsTaggedFloat(t, acc, "percentageSoftirq", 0.2, 0.0005, cputags)
assertContainsTaggedFloat(t, acc, "percentageSteal", 0.0001, 0.0005, cputags)
assertContainsTaggedFloat(t, acc, "percentageGuest", 4.8, 0.0005, cputags)
assertContainsTaggedFloat(t, acc, "percentageGuestNice", 2.2, 0.0005, cputags)
assertContainsTaggedFloat(t, acc, "percentageStolen", 0.23, 0.0005, cputags)
assertContainsTaggedFloat(t, acc, "percentageBusy", 21.2301, 0.0005, cputags)
err = (&DiskStats{&mps}).Gather(&acc) err = (&DiskStats{&mps}).Gather(&acc)
require.NoError(t, err) require.NoError(t, err)
@ -319,3 +382,44 @@ func TestSystemStats_GenerateStats(t *testing.T) {
assert.True(t, acc.CheckTaggedValue("total_active_file", uint64(26), dockertags)) assert.True(t, acc.CheckTaggedValue("total_active_file", uint64(26), dockertags))
assert.True(t, acc.CheckTaggedValue("total_unevictable", uint64(27), dockertags)) assert.True(t, acc.CheckTaggedValue("total_unevictable", uint64(27), dockertags))
} }
// Asserts that a given accumulator contains a measurment of type float64 with
// specific tags within a certain distance of a given expected value. Asserts a failure
// if the measurement is of the wrong type, or if no matching measurements are found
//
// Paramaters:
// t *testing.T : Testing object to use
// acc testutil.Accumulator: Accumulator to examine
// measurement string : Name of the measurement to examine
// expectedValue float64 : Value to search for within the measurement
// delta float64 : Maximum acceptable distance of an accumulated value
// from the expectedValue parameter. Useful when
// floating-point arithmatic imprecision makes looking
// for an exact match impractical
// tags map[string]string : Tag set the found measurement must have. Set to nil to
// ignore the tag set.
func assertContainsTaggedFloat(
t *testing.T,
acc testutil.Accumulator,
measurement string,
expectedValue float64,
delta float64,
tags map[string]string,
) {
for _, pt := range acc.Points {
if pt.Measurement == measurement {
if (tags == nil) || reflect.DeepEqual(pt.Tags, tags) {
if value, ok := pt.Values["value"].(float64); ok {
if (value >= expectedValue-delta) && (value <= expectedValue+delta) {
// Found the point, return without failing
return
}
} else {
assert.Fail(t, fmt.Sprintf("Measurement \"%s\" does not have type float64", measurement))
}
}
}
}
assert.Fail(t, fmt.Sprintf("Could not find measurement \"%s\" with requested tags within %f of %f", measurement, delta, expectedValue))
}

View File

@ -11,7 +11,7 @@ password = "root"
database = "telegraf" database = "telegraf"
[tags] [tags]
dc = "us-phx-1" } dc = "us-phx-1"
[redis] [redis]
address = ":6379" address = ":6379"

View File

@ -57,7 +57,8 @@ database = "telegraf" # required.
# Read metrics about cpu usage # Read metrics about cpu usage
[cpu] [cpu]
# no configuration totalcpu = true
percpu = false
# Read metrics about disk usage by mount point # Read metrics about disk usage by mount point
[disk] [disk]