telegraf/plugins/inputs/mock/mock.go

163 lines
3.4 KiB
Go

package mock
import (
"math"
"math/rand"
"time"
"github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/plugins/inputs"
)
type Mock struct {
counter int64
MetricName string `toml:"metric_name"`
Tags map[string]string `toml:"tags"`
Random []*random `toml:"random"`
Step []*step `toml:"step"`
Stock []*stock `toml:"stock"`
SineWave []*sineWave `toml:"sine_wave"`
}
type random struct {
Name string `toml:"name"`
Min float64 `toml:"min"`
Max float64 `toml:"max"`
}
type sineWave struct {
Name string `toml:"name"`
Amplitude float64 `toml:"amplitude"`
Period float64 `toml:"period"`
}
type step struct {
latest float64
Name string `toml:"name"`
Start float64 `toml:"min"`
Step float64 `toml:"max"`
}
type stock struct {
latest float64
Name string `toml:"name"`
Price float64 `toml:"price"`
Volatility float64 `toml:"volatility"`
}
const sampleConfig = `
## Set the metric name to use for reporting
metric_name = "mock"
## Optional string key-value pairs of tags to add to all metrics
# [inputs.mock.tags]
# "key" = "value"
## One or more mock data fields *must* be defined.
##
## [[inputs.mock.random]]
## name = "rand"
## min = 1.0
## max = 6.0
## [[inputs.mock.sine_wave]]
## name = "wave"
## amplitude = 1.0
## period = 0.5
## [[inputs.mock.step]]
## name = "plus_one"
## start = 0.0
## step = 1.0
## [[inputs.mock.stock]]
## name = "abc"
## price = 50.00
## volatility = 0.2
`
func (m *Mock) SampleConfig() string {
return sampleConfig
}
func (m *Mock) Description() string {
return "Generate metrics for test and demonstration purposes"
}
func (m *Mock) Init() error {
rand.Seed(time.Now().UnixNano())
return nil
}
func (m *Mock) Gather(acc telegraf.Accumulator) error {
fields := make(map[string]interface{})
m.generateRandomFloat64(fields)
m.generateStockPrice(fields)
m.generateSineWave(fields)
m.generateStep(fields)
tags := make(map[string]string)
for key, value := range m.Tags {
tags[key] = value
}
acc.AddFields(m.MetricName, fields, tags)
m.counter++
return nil
}
// Generate random value between min and max, inclusivly
func (m *Mock) generateRandomFloat64(fields map[string]interface{}) {
for _, random := range m.Random {
fields[random.Name] = random.Min + rand.Float64()*(random.Max-random.Min)
}
}
// Create sine waves
func (m *Mock) generateSineWave(fields map[string]interface{}) {
for _, field := range m.SineWave {
fields[field.Name] = math.Sin((float64(m.counter) * field.Period * math.Pi)) * field.Amplitude
}
}
// Begin at start value and then add step value every tick
func (m *Mock) generateStep(fields map[string]interface{}) {
for _, step := range m.Step {
if m.counter == 0 {
step.latest = step.Start
} else {
step.latest += step.Step
}
fields[step.Name] = step.latest
}
}
// Begin at start price and then generate random value
func (m *Mock) generateStockPrice(fields map[string]interface{}) {
for _, stock := range m.Stock {
if stock.latest == 0.0 {
stock.latest = stock.Price
} else {
noise := 2 * (rand.Float64() - 0.5)
stock.latest = stock.latest + (stock.latest * stock.Volatility * noise)
// avoid going below zero
if stock.latest < 1.0 {
stock.latest = 1.0
}
}
fields[stock.Name] = stock.latest
}
}
func init() {
inputs.Add("mock", func() telegraf.Input {
return &Mock{}
})
}