Overhaul config <-> agent coupling. Put config in it's own package.
This commit is contained in:
parent
8dde60e869
commit
979e5f193a
16
CHANGELOG.md
16
CHANGELOG.md
|
@ -7,15 +7,31 @@ This only affects the kafka consumer _plugin_ (not the
|
||||||
output). There were a number of problems with the kafka plugin that led to it
|
output). There were a number of problems with the kafka plugin that led to it
|
||||||
only collecting data once at startup, so the kafka plugin was basically non-
|
only collecting data once at startup, so the kafka plugin was basically non-
|
||||||
functional.
|
functional.
|
||||||
|
- Plugins can now be specified as a list, and multiple plugin instances of the
|
||||||
|
same type can be specified, like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
[[plugins.cpu]]
|
||||||
|
percpu = false
|
||||||
|
totalcpu = true
|
||||||
|
|
||||||
|
[[plugins.cpu]]
|
||||||
|
percpu = true
|
||||||
|
totalcpu = false
|
||||||
|
drop = ["cpu_time"]
|
||||||
|
```
|
||||||
|
|
||||||
- Riemann output added
|
- Riemann output added
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
- [#379](https://github.com/influxdb/telegraf/pull/379): Riemann output, thanks @allenj!
|
- [#379](https://github.com/influxdb/telegraf/pull/379): Riemann output, thanks @allenj!
|
||||||
- [#375](https://github.com/influxdb/telegraf/pull/375): kafka_consumer service plugin.
|
- [#375](https://github.com/influxdb/telegraf/pull/375): kafka_consumer service plugin.
|
||||||
- [#392](https://github.com/influxdb/telegraf/pull/392): Procstat plugin can now accept pgrep -f pattern, thanks @ecarreras!
|
- [#392](https://github.com/influxdb/telegraf/pull/392): Procstat plugin can now accept pgrep -f pattern, thanks @ecarreras!
|
||||||
|
- [#383](https://github.com/influxdb/telegraf/pull/383): Specify plugins as a list.
|
||||||
|
|
||||||
### Bugfixes
|
### Bugfixes
|
||||||
- [#371](https://github.com/influxdb/telegraf/issues/371): Kafka consumer plugin not functioning.
|
- [#371](https://github.com/influxdb/telegraf/issues/371): Kafka consumer plugin not functioning.
|
||||||
|
- [#389](https://github.com/influxdb/telegraf/issues/389): NaN value panic
|
||||||
|
|
||||||
## v0.2.2 [2015-11-18]
|
## v0.2.2 [2015-11-18]
|
||||||
|
|
||||||
|
|
43
README.md
43
README.md
|
@ -110,37 +110,45 @@ you can configure that here.
|
||||||
|
|
||||||
This is a full working config that will output CPU data to an InfluxDB instance
|
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
|
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.
|
measurements at a 10s interval and will collect per-cpu data, dropping any
|
||||||
|
measurements which begin with `cpu_time`.
|
||||||
|
|
||||||
```
|
```
|
||||||
[tags]
|
[tags]
|
||||||
dc = "denver-1"
|
dc = "denver-1"
|
||||||
|
|
||||||
[agent]
|
[agent]
|
||||||
interval = "10s"
|
interval = "10s"
|
||||||
|
|
||||||
# OUTPUTS
|
# OUTPUTS
|
||||||
[outputs]
|
[outputs]
|
||||||
[[outputs.influxdb]]
|
[[outputs.influxdb]]
|
||||||
url = "http://192.168.59.103:8086" # required.
|
url = "http://192.168.59.103:8086" # required.
|
||||||
database = "telegraf" # required.
|
database = "telegraf" # required.
|
||||||
precision = "s"
|
precision = "s"
|
||||||
|
|
||||||
# PLUGINS
|
# PLUGINS
|
||||||
[cpu]
|
[plugins]
|
||||||
percpu = true
|
[[plugins.cpu]]
|
||||||
totalcpu = true
|
percpu = true
|
||||||
|
totalcpu = false
|
||||||
|
drop = ["cpu_time"]
|
||||||
```
|
```
|
||||||
|
|
||||||
Below is how to configure `tagpass` and `tagdrop` parameters (added in 0.1.5)
|
Below is how to configure `tagpass` and `tagdrop` parameters (added in 0.1.5)
|
||||||
|
|
||||||
```
|
```
|
||||||
# Don't collect CPU data for cpu6 & cpu7
|
[plugins]
|
||||||
[cpu.tagdrop]
|
[[plugins.cpu]]
|
||||||
|
percpu = true
|
||||||
|
totalcpu = false
|
||||||
|
drop = ["cpu_time"]
|
||||||
|
# Don't collect CPU data for cpu6 & cpu7
|
||||||
|
[plugins.cpu.tagdrop]
|
||||||
cpu = [ "cpu6", "cpu7" ]
|
cpu = [ "cpu6", "cpu7" ]
|
||||||
|
|
||||||
[disk]
|
[[plugins.disk]]
|
||||||
[disk.tagpass]
|
[plugins.disk.tagpass]
|
||||||
# tagpass conditions are OR, not AND.
|
# tagpass conditions are OR, not AND.
|
||||||
# If the (filesystem is ext4 or xfs) OR (the path is /opt or /home)
|
# If the (filesystem is ext4 or xfs) OR (the path is /opt or /home)
|
||||||
# then the metric passes
|
# then the metric passes
|
||||||
|
@ -148,6 +156,15 @@ Below is how to configure `tagpass` and `tagdrop` parameters (added in 0.1.5)
|
||||||
path = [ "/opt", "/home" ]
|
path = [ "/opt", "/home" ]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Additional plugins (or outputs) of the same type can be specified,
|
||||||
|
just define another instance in the config file:
|
||||||
|
|
||||||
|
```
|
||||||
|
[[plugins.cpu]]
|
||||||
|
percpu = false
|
||||||
|
totalcpu = true
|
||||||
|
```
|
||||||
|
|
||||||
## Supported Plugins
|
## Supported Plugins
|
||||||
|
|
||||||
**You can view usage instructions for each plugin by running**
|
**You can view usage instructions for each plugin by running**
|
||||||
|
|
|
@ -7,6 +7,8 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/influxdb/telegraf/internal/config"
|
||||||
|
|
||||||
"github.com/influxdb/influxdb/client/v2"
|
"github.com/influxdb/influxdb/client/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -27,12 +29,12 @@ type Accumulator interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAccumulator(
|
func NewAccumulator(
|
||||||
plugin *ConfiguredPlugin,
|
pluginConfig *config.PluginConfig,
|
||||||
points chan *client.Point,
|
points chan *client.Point,
|
||||||
) Accumulator {
|
) Accumulator {
|
||||||
acc := accumulator{}
|
acc := accumulator{}
|
||||||
acc.points = points
|
acc.points = points
|
||||||
acc.plugin = plugin
|
acc.pluginConfig = pluginConfig
|
||||||
return &acc
|
return &acc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,7 +47,7 @@ type accumulator struct {
|
||||||
|
|
||||||
debug bool
|
debug bool
|
||||||
|
|
||||||
plugin *ConfiguredPlugin
|
pluginConfig *config.PluginConfig
|
||||||
|
|
||||||
prefix string
|
prefix string
|
||||||
}
|
}
|
||||||
|
@ -104,8 +106,8 @@ func (ac *accumulator) AddFields(
|
||||||
measurement = ac.prefix + measurement
|
measurement = ac.prefix + measurement
|
||||||
}
|
}
|
||||||
|
|
||||||
if ac.plugin != nil {
|
if ac.pluginConfig != nil {
|
||||||
if !ac.plugin.ShouldPass(measurement) || !ac.plugin.ShouldTagsPass(tags) {
|
if !ac.pluginConfig.ShouldPass(measurement) || !ac.pluginConfig.ShouldTagsPass(tags) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
175
agent.go
175
agent.go
|
@ -6,30 +6,17 @@ import (
|
||||||
"log"
|
"log"
|
||||||
"math/big"
|
"math/big"
|
||||||
"os"
|
"os"
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/influxdb/telegraf/internal"
|
"github.com/influxdb/telegraf/internal"
|
||||||
|
"github.com/influxdb/telegraf/internal/config"
|
||||||
"github.com/influxdb/telegraf/outputs"
|
"github.com/influxdb/telegraf/outputs"
|
||||||
"github.com/influxdb/telegraf/plugins"
|
"github.com/influxdb/telegraf/plugins"
|
||||||
|
|
||||||
"github.com/influxdb/influxdb/client/v2"
|
"github.com/influxdb/influxdb/client/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
type runningOutput struct {
|
|
||||||
name string
|
|
||||||
output outputs.Output
|
|
||||||
}
|
|
||||||
|
|
||||||
type runningPlugin struct {
|
|
||||||
name string
|
|
||||||
filtername string
|
|
||||||
plugin plugins.Plugin
|
|
||||||
config *ConfiguredPlugin
|
|
||||||
}
|
|
||||||
|
|
||||||
// Agent runs telegraf and collects data based on the given config
|
// Agent runs telegraf and collects data based on the given config
|
||||||
type Agent struct {
|
type Agent struct {
|
||||||
|
|
||||||
|
@ -66,14 +53,11 @@ type Agent struct {
|
||||||
|
|
||||||
Tags map[string]string
|
Tags map[string]string
|
||||||
|
|
||||||
Config *Config
|
Config *config.Config
|
||||||
|
|
||||||
outputs []*runningOutput
|
|
||||||
plugins []*runningPlugin
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAgent returns an Agent struct based off the given Config
|
// NewAgent returns an Agent struct based off the given Config
|
||||||
func NewAgent(config *Config) (*Agent, error) {
|
func NewAgent(config *config.Config) (*Agent, error) {
|
||||||
agent := &Agent{
|
agent := &Agent{
|
||||||
Tags: make(map[string]string),
|
Tags: make(map[string]string),
|
||||||
Config: config,
|
Config: config,
|
||||||
|
@ -110,30 +94,30 @@ func NewAgent(config *Config) (*Agent, error) {
|
||||||
|
|
||||||
// Connect connects to all configured outputs
|
// Connect connects to all configured outputs
|
||||||
func (a *Agent) Connect() error {
|
func (a *Agent) Connect() error {
|
||||||
for _, o := range a.outputs {
|
for _, o := range a.Config.Outputs {
|
||||||
switch ot := o.output.(type) {
|
switch ot := o.Output.(type) {
|
||||||
case outputs.ServiceOutput:
|
case outputs.ServiceOutput:
|
||||||
if err := ot.Start(); err != nil {
|
if err := ot.Start(); err != nil {
|
||||||
log.Printf("Service for output %s failed to start, exiting\n%s\n",
|
log.Printf("Service for output %s failed to start, exiting\n%s\n",
|
||||||
o.name, err.Error())
|
o.Name, err.Error())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if a.Debug {
|
if a.Debug {
|
||||||
log.Printf("Attempting connection to output: %s\n", o.name)
|
log.Printf("Attempting connection to output: %s\n", o.Name)
|
||||||
}
|
}
|
||||||
err := o.output.Connect()
|
err := o.Output.Connect()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Failed to connect to output %s, retrying in 15s\n", o.name)
|
log.Printf("Failed to connect to output %s, retrying in 15s\n", o.Name)
|
||||||
time.Sleep(15 * time.Second)
|
time.Sleep(15 * time.Second)
|
||||||
err = o.output.Connect()
|
err = o.Output.Connect()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if a.Debug {
|
if a.Debug {
|
||||||
log.Printf("Successfully connected to output: %s\n", o.name)
|
log.Printf("Successfully connected to output: %s\n", o.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -142,9 +126,9 @@ func (a *Agent) Connect() error {
|
||||||
// Close closes the connection to all configured outputs
|
// Close closes the connection to all configured outputs
|
||||||
func (a *Agent) Close() error {
|
func (a *Agent) Close() error {
|
||||||
var err error
|
var err error
|
||||||
for _, o := range a.outputs {
|
for _, o := range a.Config.Outputs {
|
||||||
err = o.output.Close()
|
err = o.Output.Close()
|
||||||
switch ot := o.output.(type) {
|
switch ot := o.Output.(type) {
|
||||||
case outputs.ServiceOutput:
|
case outputs.ServiceOutput:
|
||||||
ot.Stop()
|
ot.Stop()
|
||||||
}
|
}
|
||||||
|
@ -152,67 +136,6 @@ func (a *Agent) Close() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadOutputs loads the agent's outputs
|
|
||||||
func (a *Agent) LoadOutputs(filters []string) ([]string, error) {
|
|
||||||
var names []string
|
|
||||||
|
|
||||||
for _, name := range a.Config.OutputsDeclared() {
|
|
||||||
// Trim the ID off the output name for filtering
|
|
||||||
filtername := strings.TrimRight(name, "-0123456789")
|
|
||||||
creator, ok := outputs.Outputs[filtername]
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("Undefined but requested output: %s", name)
|
|
||||||
}
|
|
||||||
|
|
||||||
if sliceContains(filtername, filters) || len(filters) == 0 {
|
|
||||||
output := creator()
|
|
||||||
|
|
||||||
err := a.Config.ApplyOutput(name, output)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
a.outputs = append(a.outputs, &runningOutput{name, output})
|
|
||||||
names = append(names, name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sort.Strings(names)
|
|
||||||
|
|
||||||
return names, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadPlugins loads the agent's plugins
|
|
||||||
func (a *Agent) LoadPlugins(filters []string) ([]string, error) {
|
|
||||||
var names []string
|
|
||||||
|
|
||||||
for _, name := range a.Config.PluginsDeclared() {
|
|
||||||
// Trim the ID off the output name for filtering
|
|
||||||
filtername := strings.TrimRight(name, "-0123456789")
|
|
||||||
creator, ok := plugins.Plugins[filtername]
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("Undefined but requested plugin: %s", name)
|
|
||||||
}
|
|
||||||
|
|
||||||
if sliceContains(filtername, filters) || len(filters) == 0 {
|
|
||||||
plugin := creator()
|
|
||||||
|
|
||||||
config, err := a.Config.ApplyPlugin(name, plugin)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
a.plugins = append(a.plugins,
|
|
||||||
&runningPlugin{name, filtername, plugin, config})
|
|
||||||
names = append(names, name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sort.Strings(names)
|
|
||||||
|
|
||||||
return names, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// gatherParallel runs the plugins that are using the same reporting interval
|
// gatherParallel runs the plugins that are using the same reporting interval
|
||||||
// as the telegraf agent.
|
// as the telegraf agent.
|
||||||
func (a *Agent) gatherParallel(pointChan chan *client.Point) error {
|
func (a *Agent) gatherParallel(pointChan chan *client.Point) error {
|
||||||
|
@ -220,23 +143,23 @@ func (a *Agent) gatherParallel(pointChan chan *client.Point) error {
|
||||||
|
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
counter := 0
|
counter := 0
|
||||||
for _, plugin := range a.plugins {
|
for _, plugin := range a.Config.Plugins {
|
||||||
if plugin.config.Interval != 0 {
|
if plugin.Config.Interval != 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
counter++
|
counter++
|
||||||
go func(plugin *runningPlugin) {
|
go func(plugin *config.RunningPlugin) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
|
||||||
acc := NewAccumulator(plugin.config, pointChan)
|
acc := NewAccumulator(plugin.Config, pointChan)
|
||||||
acc.SetDebug(a.Debug)
|
acc.SetDebug(a.Debug)
|
||||||
acc.SetPrefix(plugin.filtername + "_")
|
acc.SetPrefix(plugin.Name + "_")
|
||||||
acc.SetDefaultTags(a.Tags)
|
acc.SetDefaultTags(a.Tags)
|
||||||
|
|
||||||
if err := plugin.plugin.Gather(acc); err != nil {
|
if err := plugin.Plugin.Gather(acc); err != nil {
|
||||||
log.Printf("Error in plugin [%s]: %s", plugin.name, err)
|
log.Printf("Error in plugin [%s]: %s", plugin.Name, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
}(plugin)
|
}(plugin)
|
||||||
|
@ -254,27 +177,27 @@ func (a *Agent) gatherParallel(pointChan chan *client.Point) error {
|
||||||
// reporting interval.
|
// reporting interval.
|
||||||
func (a *Agent) gatherSeparate(
|
func (a *Agent) gatherSeparate(
|
||||||
shutdown chan struct{},
|
shutdown chan struct{},
|
||||||
plugin *runningPlugin,
|
plugin *config.RunningPlugin,
|
||||||
pointChan chan *client.Point,
|
pointChan chan *client.Point,
|
||||||
) error {
|
) error {
|
||||||
ticker := time.NewTicker(plugin.config.Interval)
|
ticker := time.NewTicker(plugin.Config.Interval)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
var outerr error
|
var outerr error
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
|
|
||||||
acc := NewAccumulator(plugin.config, pointChan)
|
acc := NewAccumulator(plugin.Config, pointChan)
|
||||||
acc.SetDebug(a.Debug)
|
acc.SetDebug(a.Debug)
|
||||||
acc.SetPrefix(plugin.filtername + "_")
|
acc.SetPrefix(plugin.Name + "_")
|
||||||
acc.SetDefaultTags(a.Tags)
|
acc.SetDefaultTags(a.Tags)
|
||||||
|
|
||||||
if err := plugin.plugin.Gather(acc); err != nil {
|
if err := plugin.Plugin.Gather(acc); err != nil {
|
||||||
log.Printf("Error in plugin [%s]: %s", plugin.name, err)
|
log.Printf("Error in plugin [%s]: %s", plugin.Name, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
elapsed := time.Since(start)
|
elapsed := time.Since(start)
|
||||||
log.Printf("Gathered metrics, (separate %s interval), from %s in %s\n",
|
log.Printf("Gathered metrics, (separate %s interval), from %s in %s\n",
|
||||||
plugin.config.Interval, plugin.name, elapsed)
|
plugin.Config.Interval, plugin.Name, elapsed)
|
||||||
|
|
||||||
if outerr != nil {
|
if outerr != nil {
|
||||||
return outerr
|
return outerr
|
||||||
|
@ -308,27 +231,27 @@ func (a *Agent) Test() error {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
for _, plugin := range a.plugins {
|
for _, plugin := range a.Config.Plugins {
|
||||||
acc := NewAccumulator(plugin.config, pointChan)
|
acc := NewAccumulator(plugin.Config, pointChan)
|
||||||
acc.SetDebug(true)
|
acc.SetDebug(true)
|
||||||
acc.SetPrefix(plugin.filtername + "_")
|
acc.SetPrefix(plugin.Name + "_")
|
||||||
|
|
||||||
fmt.Printf("* Plugin: %s, Collection 1\n", plugin.name)
|
fmt.Printf("* Plugin: %s, Collection 1\n", plugin.Name)
|
||||||
if plugin.config.Interval != 0 {
|
if plugin.Config.Interval != 0 {
|
||||||
fmt.Printf("* Internal: %s\n", plugin.config.Interval)
|
fmt.Printf("* Internal: %s\n", plugin.Config.Interval)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := plugin.plugin.Gather(acc); err != nil {
|
if err := plugin.Plugin.Gather(acc); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Special instructions for some plugins. cpu, for example, needs to be
|
// Special instructions for some plugins. cpu, for example, needs to be
|
||||||
// run twice in order to return cpu usage percentages.
|
// run twice in order to return cpu usage percentages.
|
||||||
switch plugin.filtername {
|
switch plugin.Name {
|
||||||
case "cpu", "mongodb":
|
case "cpu", "mongodb":
|
||||||
time.Sleep(500 * time.Millisecond)
|
time.Sleep(500 * time.Millisecond)
|
||||||
fmt.Printf("* Plugin: %s, Collection 2\n", plugin.name)
|
fmt.Printf("* Plugin: %s, Collection 2\n", plugin.Name)
|
||||||
if err := plugin.plugin.Gather(acc); err != nil {
|
if err := plugin.Plugin.Gather(acc); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -341,7 +264,7 @@ func (a *Agent) Test() error {
|
||||||
// Optionally takes a `done` channel to indicate that it is done writing.
|
// Optionally takes a `done` channel to indicate that it is done writing.
|
||||||
func (a *Agent) writeOutput(
|
func (a *Agent) writeOutput(
|
||||||
points []*client.Point,
|
points []*client.Point,
|
||||||
ro *runningOutput,
|
ro *config.RunningOutput,
|
||||||
shutdown chan struct{},
|
shutdown chan struct{},
|
||||||
wg *sync.WaitGroup,
|
wg *sync.WaitGroup,
|
||||||
) {
|
) {
|
||||||
|
@ -354,12 +277,12 @@ func (a *Agent) writeOutput(
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
err := ro.output.Write(points)
|
err := ro.Output.Write(points)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
// Write successful
|
// Write successful
|
||||||
elapsed := time.Since(start)
|
elapsed := time.Since(start)
|
||||||
log.Printf("Flushed %d metrics to output %s in %s\n",
|
log.Printf("Flushed %d metrics to output %s in %s\n",
|
||||||
len(points), ro.name, elapsed)
|
len(points), ro.Name, elapsed)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -371,12 +294,12 @@ func (a *Agent) writeOutput(
|
||||||
// No more retries
|
// No more retries
|
||||||
msg := "FATAL: Write to output [%s] failed %d times, dropping" +
|
msg := "FATAL: Write to output [%s] failed %d times, dropping" +
|
||||||
" %d metrics\n"
|
" %d metrics\n"
|
||||||
log.Printf(msg, ro.name, retries+1, len(points))
|
log.Printf(msg, ro.Name, retries+1, len(points))
|
||||||
return
|
return
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
// Sleep for a retry
|
// Sleep for a retry
|
||||||
log.Printf("Error in output [%s]: %s, retrying in %s",
|
log.Printf("Error in output [%s]: %s, retrying in %s",
|
||||||
ro.name, err.Error(), a.FlushInterval.Duration)
|
ro.Name, err.Error(), a.FlushInterval.Duration)
|
||||||
time.Sleep(a.FlushInterval.Duration)
|
time.Sleep(a.FlushInterval.Duration)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -392,7 +315,7 @@ func (a *Agent) flush(
|
||||||
wait bool,
|
wait bool,
|
||||||
) {
|
) {
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
for _, o := range a.outputs {
|
for _, o := range a.Config.Outputs {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go a.writeOutput(points, o, shutdown, &wg)
|
go a.writeOutput(points, o, shutdown, &wg)
|
||||||
}
|
}
|
||||||
|
@ -476,14 +399,14 @@ func (a *Agent) Run(shutdown chan struct{}) error {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
for _, plugin := range a.plugins {
|
for _, plugin := range a.Config.Plugins {
|
||||||
|
|
||||||
// Start service of any ServicePlugins
|
// Start service of any ServicePlugins
|
||||||
switch p := plugin.plugin.(type) {
|
switch p := plugin.Plugin.(type) {
|
||||||
case plugins.ServicePlugin:
|
case plugins.ServicePlugin:
|
||||||
if err := p.Start(); err != nil {
|
if err := p.Start(); err != nil {
|
||||||
log.Printf("Service for plugin %s failed to start, exiting\n%s\n",
|
log.Printf("Service for plugin %s failed to start, exiting\n%s\n",
|
||||||
plugin.name, err.Error())
|
plugin.Name, err.Error())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer p.Stop()
|
defer p.Stop()
|
||||||
|
@ -491,9 +414,9 @@ func (a *Agent) Run(shutdown chan struct{}) error {
|
||||||
|
|
||||||
// Special handling for plugins that have their own collection interval
|
// Special handling for plugins that have their own collection interval
|
||||||
// configured. Default intervals are handled below with gatherParallel
|
// configured. Default intervals are handled below with gatherParallel
|
||||||
if plugin.config.Interval != 0 {
|
if plugin.Config.Interval != 0 {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func(plugin *runningPlugin) {
|
go func(plugin *config.RunningPlugin) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
if err := a.gatherSeparate(shutdown, plugin, pointChan); err != nil {
|
if err := a.gatherSeparate(shutdown, plugin, pointChan); err != nil {
|
||||||
log.Printf(err.Error())
|
log.Printf(err.Error())
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/influxdb/telegraf/internal"
|
"github.com/influxdb/telegraf/internal"
|
||||||
|
"github.com/influxdb/telegraf/internal/config"
|
||||||
|
|
||||||
// needing to load the plugins
|
// needing to load the plugins
|
||||||
_ "github.com/influxdb/telegraf/plugins/all"
|
_ "github.com/influxdb/telegraf/plugins/all"
|
||||||
|
@ -14,49 +15,73 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestAgent_LoadPlugin(t *testing.T) {
|
func TestAgent_LoadPlugin(t *testing.T) {
|
||||||
|
c := config.NewConfig()
|
||||||
|
c.PluginFilters = []string{"mysql"}
|
||||||
|
c.LoadConfig("./internal/config/testdata/telegraf-agent.toml")
|
||||||
|
a, _ := NewAgent(c)
|
||||||
|
assert.Equal(t, 1, len(a.Config.Plugins))
|
||||||
|
|
||||||
// load a dedicated configuration file
|
c = config.NewConfig()
|
||||||
config, _ := LoadConfig("./testdata/telegraf-agent.toml")
|
c.PluginFilters = []string{"foo"}
|
||||||
a, _ := NewAgent(config)
|
c.LoadConfig("./internal/config/testdata/telegraf-agent.toml")
|
||||||
|
a, _ = NewAgent(c)
|
||||||
|
assert.Equal(t, 0, len(a.Config.Plugins))
|
||||||
|
|
||||||
pluginsEnabled, _ := a.LoadPlugins([]string{"mysql"}, config)
|
c = config.NewConfig()
|
||||||
assert.Equal(t, 1, len(pluginsEnabled))
|
c.PluginFilters = []string{"mysql", "foo"}
|
||||||
|
c.LoadConfig("./internal/config/testdata/telegraf-agent.toml")
|
||||||
|
a, _ = NewAgent(c)
|
||||||
|
assert.Equal(t, 1, len(a.Config.Plugins))
|
||||||
|
|
||||||
pluginsEnabled, _ = a.LoadPlugins([]string{"foo"}, config)
|
c = config.NewConfig()
|
||||||
assert.Equal(t, 0, len(pluginsEnabled))
|
c.PluginFilters = []string{"mysql", "redis"}
|
||||||
|
c.LoadConfig("./internal/config/testdata/telegraf-agent.toml")
|
||||||
|
a, _ = NewAgent(c)
|
||||||
|
assert.Equal(t, 2, len(a.Config.Plugins))
|
||||||
|
|
||||||
pluginsEnabled, _ = a.LoadPlugins([]string{"mysql", "foo"}, config)
|
c = config.NewConfig()
|
||||||
assert.Equal(t, 1, len(pluginsEnabled))
|
c.PluginFilters = []string{"mysql", "foo", "redis", "bar"}
|
||||||
|
c.LoadConfig("./internal/config/testdata/telegraf-agent.toml")
|
||||||
pluginsEnabled, _ = a.LoadPlugins([]string{"mysql", "redis"}, config)
|
a, _ = NewAgent(c)
|
||||||
assert.Equal(t, 2, len(pluginsEnabled))
|
assert.Equal(t, 2, len(a.Config.Plugins))
|
||||||
|
|
||||||
pluginsEnabled, _ = a.LoadPlugins([]string{"mysql", "foo", "redis", "bar"}, config)
|
|
||||||
assert.Equal(t, 2, len(pluginsEnabled))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAgent_LoadOutput(t *testing.T) {
|
func TestAgent_LoadOutput(t *testing.T) {
|
||||||
// load a dedicated configuration file
|
c := config.NewConfig()
|
||||||
config, _ := LoadConfig("./testdata/telegraf-agent.toml")
|
c.OutputFilters = []string{"influxdb"}
|
||||||
a, _ := NewAgent(config)
|
c.LoadConfig("./internal/config/testdata/telegraf-agent.toml")
|
||||||
|
a, _ := NewAgent(c)
|
||||||
|
assert.Equal(t, 2, len(a.Config.Outputs))
|
||||||
|
|
||||||
outputsEnabled, _ := a.LoadOutputs([]string{"influxdb"}, config)
|
c = config.NewConfig()
|
||||||
assert.Equal(t, 2, len(outputsEnabled))
|
c.OutputFilters = []string{}
|
||||||
|
c.LoadConfig("./internal/config/testdata/telegraf-agent.toml")
|
||||||
|
a, _ = NewAgent(c)
|
||||||
|
assert.Equal(t, 3, len(a.Config.Outputs))
|
||||||
|
|
||||||
outputsEnabled, _ = a.LoadOutputs([]string{}, config)
|
c = config.NewConfig()
|
||||||
assert.Equal(t, 3, len(outputsEnabled))
|
c.OutputFilters = []string{"foo"}
|
||||||
|
c.LoadConfig("./internal/config/testdata/telegraf-agent.toml")
|
||||||
|
a, _ = NewAgent(c)
|
||||||
|
assert.Equal(t, 0, len(a.Config.Outputs))
|
||||||
|
|
||||||
outputsEnabled, _ = a.LoadOutputs([]string{"foo"}, config)
|
c = config.NewConfig()
|
||||||
assert.Equal(t, 0, len(outputsEnabled))
|
c.OutputFilters = []string{"influxdb", "foo"}
|
||||||
|
c.LoadConfig("./internal/config/testdata/telegraf-agent.toml")
|
||||||
|
a, _ = NewAgent(c)
|
||||||
|
assert.Equal(t, 2, len(a.Config.Outputs))
|
||||||
|
|
||||||
outputsEnabled, _ = a.LoadOutputs([]string{"influxdb", "foo"}, config)
|
c = config.NewConfig()
|
||||||
assert.Equal(t, 2, len(outputsEnabled))
|
c.OutputFilters = []string{"influxdb", "kafka"}
|
||||||
|
c.LoadConfig("./internal/config/testdata/telegraf-agent.toml")
|
||||||
|
a, _ = NewAgent(c)
|
||||||
|
assert.Equal(t, 3, len(a.Config.Outputs))
|
||||||
|
|
||||||
outputsEnabled, _ = a.LoadOutputs([]string{"influxdb", "kafka"}, config)
|
c = config.NewConfig()
|
||||||
assert.Equal(t, 3, len(outputsEnabled))
|
c.OutputFilters = []string{"influxdb", "foo", "kafka", "bar"}
|
||||||
|
c.LoadConfig("./internal/config/testdata/telegraf-agent.toml")
|
||||||
outputsEnabled, _ = a.LoadOutputs([]string{"influxdb", "foo", "kafka", "bar"}, config)
|
a, _ = NewAgent(c)
|
||||||
assert.Equal(t, 3, len(outputsEnabled))
|
assert.Equal(t, 3, len(a.Config.Outputs))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAgent_ZeroJitter(t *testing.T) {
|
func TestAgent_ZeroJitter(t *testing.T) {
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/influxdb/telegraf"
|
"github.com/influxdb/telegraf"
|
||||||
|
"github.com/influxdb/telegraf/internal/config"
|
||||||
_ "github.com/influxdb/telegraf/outputs/all"
|
_ "github.com/influxdb/telegraf/outputs/all"
|
||||||
_ "github.com/influxdb/telegraf/plugins/all"
|
_ "github.com/influxdb/telegraf/plugins/all"
|
||||||
)
|
)
|
||||||
|
@ -56,13 +57,13 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if *fSampleConfig {
|
if *fSampleConfig {
|
||||||
telegraf.PrintSampleConfig(pluginFilters, outputFilters)
|
config.PrintSampleConfig(pluginFilters, outputFilters)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if *fUsage != "" {
|
if *fUsage != "" {
|
||||||
if err := telegraf.PrintPluginConfig(*fUsage); err != nil {
|
if err := config.PrintPluginConfig(*fUsage); err != nil {
|
||||||
if err2 := telegraf.PrintOutputConfig(*fUsage); err2 != nil {
|
if err2 := config.PrintOutputConfig(*fUsage); err2 != nil {
|
||||||
log.Fatalf("%s and %s", err, err2)
|
log.Fatalf("%s and %s", err, err2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -70,13 +71,15 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
config *telegraf.Config
|
c *config.Config
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
|
|
||||||
if *fConfig != "" {
|
if *fConfig != "" {
|
||||||
config = telegraf.NewConfig()
|
c = config.NewConfig()
|
||||||
err = config.LoadConfig(*fConfig)
|
c.OutputFilters = outputFilters
|
||||||
|
c.PluginFilters = pluginFilters
|
||||||
|
err = c.LoadConfig(*fConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -87,13 +90,19 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if *fConfigDirectory != "" {
|
if *fConfigDirectory != "" {
|
||||||
err = config.LoadDirectory(*fConfigDirectory)
|
err = c.LoadDirectory(*fConfigDirectory)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if len(c.Outputs) == 0 {
|
||||||
|
log.Fatalf("Error: no outputs found, did you provide a valid config file?")
|
||||||
|
}
|
||||||
|
if len(c.Plugins) == 0 {
|
||||||
|
log.Fatalf("Error: no plugins found, did you provide a valid config file?")
|
||||||
|
}
|
||||||
|
|
||||||
ag, err := telegraf.NewAgent(config)
|
ag, err := telegraf.NewAgent(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -102,24 +111,6 @@ func main() {
|
||||||
ag.Debug = true
|
ag.Debug = true
|
||||||
}
|
}
|
||||||
|
|
||||||
outputs, err := ag.LoadOutputs(outputFilters)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
if len(outputs) == 0 {
|
|
||||||
log.Printf("Error: no outputs found, did you provide a valid config file?")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
plugins, err := ag.LoadPlugins(pluginFilters)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
if len(plugins) == 0 {
|
|
||||||
log.Printf("Error: no plugins found, did you provide a valid config file?")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
if *fTest {
|
if *fTest {
|
||||||
err = ag.Test()
|
err = ag.Test()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -142,9 +133,9 @@ func main() {
|
||||||
}()
|
}()
|
||||||
|
|
||||||
log.Printf("Starting Telegraf (version %s)\n", Version)
|
log.Printf("Starting Telegraf (version %s)\n", Version)
|
||||||
log.Printf("Loaded outputs: %s", strings.Join(outputs, " "))
|
log.Printf("Loaded outputs: %s", strings.Join(c.OutputNames(), " "))
|
||||||
log.Printf("Loaded plugins: %s", strings.Join(plugins, " "))
|
log.Printf("Loaded plugins: %s", strings.Join(c.PluginNames(), " "))
|
||||||
log.Printf("Tags enabled: %s", config.ListTags())
|
log.Printf("Tags enabled: %s", c.ListTags())
|
||||||
|
|
||||||
if *fPidfile != "" {
|
if *fPidfile != "" {
|
||||||
f, err := os.Create(*fPidfile)
|
f, err := os.Create(*fPidfile)
|
||||||
|
|
307
config_test.go
307
config_test.go
|
@ -1,307 +0,0 @@
|
||||||
package telegraf
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/influxdb/telegraf/plugins"
|
|
||||||
"github.com/influxdb/telegraf/plugins/exec"
|
|
||||||
"github.com/influxdb/telegraf/plugins/memcached"
|
|
||||||
"github.com/influxdb/telegraf/plugins/procstat"
|
|
||||||
"github.com/naoina/toml"
|
|
||||||
"github.com/naoina/toml/ast"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"github.com/stretchr/testify/suite"
|
|
||||||
)
|
|
||||||
|
|
||||||
type subTest struct {
|
|
||||||
AField string
|
|
||||||
AnotherField int
|
|
||||||
}
|
|
||||||
type test struct {
|
|
||||||
StringField string
|
|
||||||
IntegerField int
|
|
||||||
FloatField float32
|
|
||||||
BooleansField bool `toml:"boolean_field"`
|
|
||||||
DatetimeField time.Time
|
|
||||||
ArrayField []string
|
|
||||||
TableArrayField []subTest
|
|
||||||
}
|
|
||||||
|
|
||||||
type MergeStructSuite struct {
|
|
||||||
suite.Suite
|
|
||||||
EmptyStruct *test
|
|
||||||
FullStruct *test
|
|
||||||
AnotherFullStruct *test
|
|
||||||
AllFields []string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *MergeStructSuite) SetupSuite() {
|
|
||||||
s.AllFields = []string{"string_field", "integer_field", "float_field",
|
|
||||||
"boolean_field", "date_time_field", "array_field", "table_array_field"}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *MergeStructSuite) SetupTest() {
|
|
||||||
s.EmptyStruct = &test{
|
|
||||||
ArrayField: []string{},
|
|
||||||
TableArrayField: []subTest{},
|
|
||||||
}
|
|
||||||
s.FullStruct = &test{
|
|
||||||
StringField: "one",
|
|
||||||
IntegerField: 1,
|
|
||||||
FloatField: 1.1,
|
|
||||||
BooleansField: false,
|
|
||||||
DatetimeField: time.Date(1963, time.August, 28, 17, 0, 0, 0, time.UTC),
|
|
||||||
ArrayField: []string{"one", "two", "three"},
|
|
||||||
TableArrayField: []subTest{
|
|
||||||
subTest{
|
|
||||||
AField: "one",
|
|
||||||
AnotherField: 1,
|
|
||||||
},
|
|
||||||
subTest{
|
|
||||||
AField: "two",
|
|
||||||
AnotherField: 2,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
s.AnotherFullStruct = &test{
|
|
||||||
StringField: "two",
|
|
||||||
IntegerField: 2,
|
|
||||||
FloatField: 2.2,
|
|
||||||
BooleansField: true,
|
|
||||||
DatetimeField: time.Date(1965, time.March, 25, 17, 0, 0, 0, time.UTC),
|
|
||||||
ArrayField: []string{"four", "five", "six"},
|
|
||||||
TableArrayField: []subTest{
|
|
||||||
subTest{
|
|
||||||
AField: "three",
|
|
||||||
AnotherField: 3,
|
|
||||||
},
|
|
||||||
subTest{
|
|
||||||
AField: "four",
|
|
||||||
AnotherField: 4,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *MergeStructSuite) TestEmptyMerge() {
|
|
||||||
err := mergeStruct(s.EmptyStruct, s.FullStruct, s.AllFields)
|
|
||||||
if err != nil {
|
|
||||||
s.T().Error(err)
|
|
||||||
}
|
|
||||||
s.Equal(s.FullStruct, s.EmptyStruct,
|
|
||||||
fmt.Sprintf("Full merge of %v onto an empty struct failed.", s.FullStruct))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *MergeStructSuite) TestFullMerge() {
|
|
||||||
result := &test{
|
|
||||||
StringField: "two",
|
|
||||||
IntegerField: 2,
|
|
||||||
FloatField: 2.2,
|
|
||||||
BooleansField: true,
|
|
||||||
DatetimeField: time.Date(1965, time.March, 25, 17, 0, 0, 0, time.UTC),
|
|
||||||
ArrayField: []string{"four", "five", "six"},
|
|
||||||
TableArrayField: []subTest{
|
|
||||||
subTest{
|
|
||||||
AField: "three",
|
|
||||||
AnotherField: 3,
|
|
||||||
},
|
|
||||||
subTest{
|
|
||||||
AField: "four",
|
|
||||||
AnotherField: 4,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
err := mergeStruct(s.FullStruct, s.AnotherFullStruct, s.AllFields)
|
|
||||||
if err != nil {
|
|
||||||
s.T().Error(err)
|
|
||||||
}
|
|
||||||
s.Equal(result, s.FullStruct,
|
|
||||||
fmt.Sprintf("Full merge of %v onto FullStruct failed.", s.AnotherFullStruct))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *MergeStructSuite) TestPartialMergeWithoutSlices() {
|
|
||||||
result := &test{
|
|
||||||
StringField: "two",
|
|
||||||
IntegerField: 1,
|
|
||||||
FloatField: 2.2,
|
|
||||||
BooleansField: false,
|
|
||||||
DatetimeField: time.Date(1965, time.March, 25, 17, 0, 0, 0, time.UTC),
|
|
||||||
ArrayField: []string{"one", "two", "three"},
|
|
||||||
TableArrayField: []subTest{
|
|
||||||
subTest{
|
|
||||||
AField: "one",
|
|
||||||
AnotherField: 1,
|
|
||||||
},
|
|
||||||
subTest{
|
|
||||||
AField: "two",
|
|
||||||
AnotherField: 2,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
err := mergeStruct(s.FullStruct, s.AnotherFullStruct,
|
|
||||||
[]string{"string_field", "float_field", "date_time_field"})
|
|
||||||
if err != nil {
|
|
||||||
s.T().Error(err)
|
|
||||||
}
|
|
||||||
s.Equal(result, s.FullStruct,
|
|
||||||
fmt.Sprintf("Partial merge without slices of %v onto FullStruct failed.",
|
|
||||||
s.AnotherFullStruct))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *MergeStructSuite) TestPartialMergeWithSlices() {
|
|
||||||
result := &test{
|
|
||||||
StringField: "two",
|
|
||||||
IntegerField: 1,
|
|
||||||
FloatField: 2.2,
|
|
||||||
BooleansField: false,
|
|
||||||
DatetimeField: time.Date(1965, time.March, 25, 17, 0, 0, 0, time.UTC),
|
|
||||||
ArrayField: []string{"one", "two", "three"},
|
|
||||||
TableArrayField: []subTest{
|
|
||||||
subTest{
|
|
||||||
AField: "three",
|
|
||||||
AnotherField: 3,
|
|
||||||
},
|
|
||||||
subTest{
|
|
||||||
AField: "four",
|
|
||||||
AnotherField: 4,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
err := mergeStruct(s.FullStruct, s.AnotherFullStruct,
|
|
||||||
[]string{"string_field", "float_field", "date_time_field", "table_array_field"})
|
|
||||||
if err != nil {
|
|
||||||
s.T().Error(err)
|
|
||||||
}
|
|
||||||
s.Equal(result, s.FullStruct,
|
|
||||||
fmt.Sprintf("Partial merge with slices of %v onto FullStruct failed.",
|
|
||||||
s.AnotherFullStruct))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestConfig_mergeStruct(t *testing.T) {
|
|
||||||
suite.Run(t, new(MergeStructSuite))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestConfig_parsePlugin(t *testing.T) {
|
|
||||||
data, err := ioutil.ReadFile("./testdata/single_plugin.toml")
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
tbl, err := toml.Parse(data)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
c := &Config{
|
|
||||||
plugins: make(map[string]plugins.Plugin),
|
|
||||||
pluginConfigurations: make(map[string]*ConfiguredPlugin),
|
|
||||||
pluginFieldsSet: make(map[string][]string),
|
|
||||||
pluginConfigurationFieldsSet: make(map[string][]string),
|
|
||||||
}
|
|
||||||
|
|
||||||
subtbl := tbl.Fields["memcached"].(*ast.Table)
|
|
||||||
err = c.parsePlugin("memcached", subtbl, 0)
|
|
||||||
|
|
||||||
memcached := plugins.Plugins["memcached"]().(*memcached.Memcached)
|
|
||||||
memcached.Servers = []string{"localhost"}
|
|
||||||
|
|
||||||
mConfig := &ConfiguredPlugin{
|
|
||||||
Name: "memcached",
|
|
||||||
Drop: []string{"other", "stuff"},
|
|
||||||
Pass: []string{"some", "strings"},
|
|
||||||
TagDrop: []TagFilter{
|
|
||||||
TagFilter{
|
|
||||||
Name: "badtag",
|
|
||||||
Filter: []string{"othertag"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
TagPass: []TagFilter{
|
|
||||||
TagFilter{
|
|
||||||
Name: "goodtag",
|
|
||||||
Filter: []string{"mytag"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Interval: 5 * time.Second,
|
|
||||||
}
|
|
||||||
|
|
||||||
assert.Equal(t, memcached, c.plugins["memcached-0"],
|
|
||||||
"Testdata did not produce a correct memcached struct.")
|
|
||||||
assert.Equal(t, mConfig, c.pluginConfigurations["memcached-0"],
|
|
||||||
"Testdata did not produce correct memcached metadata.")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestConfig_LoadDirectory(t *testing.T) {
|
|
||||||
c, err := LoadConfig("./testdata/telegraf-agent.toml")
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
err = c.LoadDirectory("./testdata/subconfig")
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
memcached := plugins.Plugins["memcached"]().(*memcached.Memcached)
|
|
||||||
memcached.Servers = []string{"192.168.1.1"}
|
|
||||||
|
|
||||||
mConfig := &ConfiguredPlugin{
|
|
||||||
Name: "memcached",
|
|
||||||
Drop: []string{"other", "stuff"},
|
|
||||||
Pass: []string{"some", "strings"},
|
|
||||||
TagDrop: []TagFilter{
|
|
||||||
TagFilter{
|
|
||||||
Name: "badtag",
|
|
||||||
Filter: []string{"othertag"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
TagPass: []TagFilter{
|
|
||||||
TagFilter{
|
|
||||||
Name: "goodtag",
|
|
||||||
Filter: []string{"mytag"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Interval: 5 * time.Second,
|
|
||||||
}
|
|
||||||
|
|
||||||
ex := plugins.Plugins["exec"]().(*exec.Exec)
|
|
||||||
ex.Commands = []*exec.Command{
|
|
||||||
&exec.Command{
|
|
||||||
Command: "/usr/bin/myothercollector --foo=bar",
|
|
||||||
Name: "myothercollector",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
eConfig := &ConfiguredPlugin{Name: "exec"}
|
|
||||||
|
|
||||||
pstat := plugins.Plugins["procstat"]().(*procstat.Procstat)
|
|
||||||
pstat.Specifications = []*procstat.Specification{
|
|
||||||
&procstat.Specification{
|
|
||||||
PidFile: "/var/run/grafana-server.pid",
|
|
||||||
},
|
|
||||||
&procstat.Specification{
|
|
||||||
PidFile: "/var/run/influxdb/influxd.pid",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
pConfig := &ConfiguredPlugin{Name: "procstat"}
|
|
||||||
|
|
||||||
assert.Equal(t, memcached, c.plugins["memcached-0"],
|
|
||||||
"Merged Testdata did not produce a correct memcached struct.")
|
|
||||||
assert.Equal(t, mConfig, c.pluginConfigurations["memcached-0"],
|
|
||||||
"Merged Testdata did not produce correct memcached metadata.")
|
|
||||||
|
|
||||||
assert.Equal(t, ex, c.plugins["exec-0"],
|
|
||||||
"Merged Testdata did not produce a correct exec struct.")
|
|
||||||
assert.Equal(t, eConfig, c.pluginConfigurations["exec-0"],
|
|
||||||
"Merged Testdata did not produce correct exec metadata.")
|
|
||||||
|
|
||||||
assert.Equal(t, pstat, c.plugins["procstat-0"],
|
|
||||||
"Merged Testdata did not produce a correct procstat struct.")
|
|
||||||
assert.Equal(t, pConfig, c.pluginConfigurations["procstat-0"],
|
|
||||||
"Merged Testdata did not produce correct procstat metadata.")
|
|
||||||
}
|
|
|
@ -1,4 +1,4 @@
|
||||||
package telegraf
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
@ -12,6 +12,7 @@ import (
|
||||||
|
|
||||||
"github.com/influxdb/telegraf/outputs"
|
"github.com/influxdb/telegraf/outputs"
|
||||||
"github.com/influxdb/telegraf/plugins"
|
"github.com/influxdb/telegraf/plugins"
|
||||||
|
|
||||||
"github.com/naoina/toml"
|
"github.com/naoina/toml"
|
||||||
"github.com/naoina/toml/ast"
|
"github.com/naoina/toml/ast"
|
||||||
)
|
)
|
||||||
|
@ -20,18 +21,22 @@ import (
|
||||||
// will be logging to, as well as all the plugins that the user has
|
// will be logging to, as well as all the plugins that the user has
|
||||||
// specified
|
// specified
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Tags map[string]string
|
Tags map[string]string
|
||||||
|
PluginFilters []string
|
||||||
|
OutputFilters []string
|
||||||
|
|
||||||
agent *ast.Table
|
Agent *ast.Table
|
||||||
plugins map[string]*ast.Table
|
Plugins []*RunningPlugin
|
||||||
outputs map[string]*ast.Table
|
Outputs []*RunningOutput
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConfig() *Config {
|
func NewConfig() *Config {
|
||||||
c := &Config{
|
c := &Config{
|
||||||
Tags: make(map[string]string),
|
Tags: make(map[string]string),
|
||||||
plugins: make(map[string]*ast.Table),
|
Plugins: make([]*RunningPlugin, 0),
|
||||||
outputs: make(map[string]*ast.Table),
|
Outputs: make([]*RunningOutput, 0),
|
||||||
|
PluginFilters: make([]string, 0),
|
||||||
|
OutputFilters: make([]string, 0),
|
||||||
}
|
}
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
@ -42,9 +47,20 @@ type TagFilter struct {
|
||||||
Filter []string
|
Filter []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConfiguredPlugin containing a name, interval, and drop/pass prefix lists
|
type RunningOutput struct {
|
||||||
|
Name string
|
||||||
|
Output outputs.Output
|
||||||
|
}
|
||||||
|
|
||||||
|
type RunningPlugin struct {
|
||||||
|
Name string
|
||||||
|
Plugin plugins.Plugin
|
||||||
|
Config *PluginConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
// PluginConfig containing a name, interval, and drop/pass prefix lists
|
||||||
// Also lists the tags to filter
|
// Also lists the tags to filter
|
||||||
type ConfiguredPlugin struct {
|
type PluginConfig struct {
|
||||||
Name string
|
Name string
|
||||||
|
|
||||||
Drop []string
|
Drop []string
|
||||||
|
@ -58,7 +74,7 @@ type ConfiguredPlugin struct {
|
||||||
|
|
||||||
// ShouldPass returns true if the metric should pass, false if should drop
|
// ShouldPass returns true if the metric should pass, false if should drop
|
||||||
// based on the drop/pass plugin parameters
|
// based on the drop/pass plugin parameters
|
||||||
func (cp *ConfiguredPlugin) ShouldPass(measurement string) bool {
|
func (cp *PluginConfig) ShouldPass(measurement string) bool {
|
||||||
if cp.Pass != nil {
|
if cp.Pass != nil {
|
||||||
for _, pat := range cp.Pass {
|
for _, pat := range cp.Pass {
|
||||||
if strings.HasPrefix(measurement, pat) {
|
if strings.HasPrefix(measurement, pat) {
|
||||||
|
@ -82,7 +98,7 @@ func (cp *ConfiguredPlugin) ShouldPass(measurement string) bool {
|
||||||
|
|
||||||
// ShouldTagsPass returns true if the metric should pass, false if should drop
|
// ShouldTagsPass returns true if the metric should pass, false if should drop
|
||||||
// based on the tagdrop/tagpass plugin parameters
|
// based on the tagdrop/tagpass plugin parameters
|
||||||
func (cp *ConfiguredPlugin) ShouldTagsPass(tags map[string]string) bool {
|
func (cp *PluginConfig) ShouldTagsPass(tags map[string]string) bool {
|
||||||
if cp.TagPass != nil {
|
if cp.TagPass != nil {
|
||||||
for _, pat := range cp.TagPass {
|
for _, pat := range cp.TagPass {
|
||||||
if tagval, ok := tags[pat.Name]; ok {
|
if tagval, ok := tags[pat.Name]; ok {
|
||||||
|
@ -112,138 +128,34 @@ func (cp *ConfiguredPlugin) ShouldTagsPass(tags map[string]string) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// ApplyOutput loads the toml config into the given interface
|
// Plugins returns a list of strings of the configured plugins.
|
||||||
func (c *Config) ApplyOutput(name string, v interface{}) error {
|
func (c *Config) PluginNames() []string {
|
||||||
if c.outputs[name] != nil {
|
var name []string
|
||||||
return toml.UnmarshalTable(c.outputs[name], v)
|
for _, plugin := range c.Plugins {
|
||||||
|
name = append(name, plugin.Name)
|
||||||
}
|
}
|
||||||
return nil
|
return name
|
||||||
|
}
|
||||||
|
|
||||||
|
// Outputs returns a list of strings of the configured plugins.
|
||||||
|
func (c *Config) OutputNames() []string {
|
||||||
|
var name []string
|
||||||
|
for _, output := range c.Outputs {
|
||||||
|
name = append(name, output.Name)
|
||||||
|
}
|
||||||
|
return name
|
||||||
}
|
}
|
||||||
|
|
||||||
// ApplyAgent loads the toml config into the given Agent object, overriding
|
// ApplyAgent loads the toml config into the given Agent object, overriding
|
||||||
// defaults (such as collection duration) with the values from the toml config.
|
// defaults (such as collection duration) with the values from the toml config.
|
||||||
func (c *Config) ApplyAgent(a *Agent) error {
|
func (c *Config) ApplyAgent(a interface{}) error {
|
||||||
if c.agent != nil {
|
if c.Agent != nil {
|
||||||
return toml.UnmarshalTable(c.agent, a)
|
return toml.UnmarshalTable(c.Agent, a)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ApplyPlugin takes defined plugin names and applies them to the given
|
|
||||||
// interface, returning a ConfiguredPlugin object in the end that can
|
|
||||||
// be inserted into a runningPlugin by the agent.
|
|
||||||
func (c *Config) ApplyPlugin(name string, v interface{}) (*ConfiguredPlugin, error) {
|
|
||||||
cp := &ConfiguredPlugin{Name: name}
|
|
||||||
|
|
||||||
if tbl, ok := c.plugins[name]; ok {
|
|
||||||
|
|
||||||
if node, ok := tbl.Fields["pass"]; ok {
|
|
||||||
if kv, ok := node.(*ast.KeyValue); ok {
|
|
||||||
if ary, ok := kv.Value.(*ast.Array); ok {
|
|
||||||
for _, elem := range ary.Value {
|
|
||||||
if str, ok := elem.(*ast.String); ok {
|
|
||||||
cp.Pass = append(cp.Pass, str.Value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if node, ok := tbl.Fields["drop"]; ok {
|
|
||||||
if kv, ok := node.(*ast.KeyValue); ok {
|
|
||||||
if ary, ok := kv.Value.(*ast.Array); ok {
|
|
||||||
for _, elem := range ary.Value {
|
|
||||||
if str, ok := elem.(*ast.String); ok {
|
|
||||||
cp.Drop = append(cp.Drop, str.Value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if node, ok := tbl.Fields["interval"]; ok {
|
|
||||||
if kv, ok := node.(*ast.KeyValue); ok {
|
|
||||||
if str, ok := kv.Value.(*ast.String); ok {
|
|
||||||
dur, err := time.ParseDuration(str.Value)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
cp.Interval = dur
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if node, ok := tbl.Fields["tagpass"]; ok {
|
|
||||||
if subtbl, ok := node.(*ast.Table); ok {
|
|
||||||
for name, val := range subtbl.Fields {
|
|
||||||
if kv, ok := val.(*ast.KeyValue); ok {
|
|
||||||
tagfilter := &TagFilter{Name: name}
|
|
||||||
if ary, ok := kv.Value.(*ast.Array); ok {
|
|
||||||
for _, elem := range ary.Value {
|
|
||||||
if str, ok := elem.(*ast.String); ok {
|
|
||||||
tagfilter.Filter = append(tagfilter.Filter, str.Value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cp.TagPass = append(cp.TagPass, *tagfilter)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if node, ok := tbl.Fields["tagdrop"]; ok {
|
|
||||||
if subtbl, ok := node.(*ast.Table); ok {
|
|
||||||
for name, val := range subtbl.Fields {
|
|
||||||
if kv, ok := val.(*ast.KeyValue); ok {
|
|
||||||
tagfilter := &TagFilter{Name: name}
|
|
||||||
if ary, ok := kv.Value.(*ast.Array); ok {
|
|
||||||
for _, elem := range ary.Value {
|
|
||||||
if str, ok := elem.(*ast.String); ok {
|
|
||||||
tagfilter.Filter = append(tagfilter.Filter, str.Value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cp.TagDrop = append(cp.TagDrop, *tagfilter)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
delete(tbl.Fields, "drop")
|
|
||||||
delete(tbl.Fields, "pass")
|
|
||||||
delete(tbl.Fields, "interval")
|
|
||||||
delete(tbl.Fields, "tagdrop")
|
|
||||||
delete(tbl.Fields, "tagpass")
|
|
||||||
return cp, toml.UnmarshalTable(tbl, v)
|
|
||||||
}
|
|
||||||
|
|
||||||
return cp, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// PluginsDeclared returns the name of all plugins declared in the config.
|
|
||||||
func (c *Config) PluginsDeclared() []string {
|
|
||||||
return declared(c.plugins)
|
|
||||||
}
|
|
||||||
|
|
||||||
// OutputsDeclared returns the name of all outputs declared in the config.
|
|
||||||
func (c *Config) OutputsDeclared() []string {
|
|
||||||
return declared(c.outputs)
|
|
||||||
}
|
|
||||||
|
|
||||||
func declared(endpoints map[string]*ast.Table) []string {
|
|
||||||
var names []string
|
|
||||||
|
|
||||||
for name := range endpoints {
|
|
||||||
names = append(names, name)
|
|
||||||
}
|
|
||||||
|
|
||||||
sort.Strings(names)
|
|
||||||
|
|
||||||
return names
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListTags returns a string of tags specified in the config,
|
// ListTags returns a string of tags specified in the config,
|
||||||
// line-protocol style
|
// line-protocol style
|
||||||
func (c *Config) ListTags() string {
|
func (c *Config) ListTags() string {
|
||||||
|
@ -258,14 +170,6 @@ func (c *Config) ListTags() string {
|
||||||
return strings.Join(tags, " ")
|
return strings.Join(tags, " ")
|
||||||
}
|
}
|
||||||
|
|
||||||
type hasConfig interface {
|
|
||||||
BasicConfig() string
|
|
||||||
}
|
|
||||||
|
|
||||||
type hasDescr interface {
|
|
||||||
Description() string
|
|
||||||
}
|
|
||||||
|
|
||||||
var header = `# Telegraf configuration
|
var header = `# Telegraf configuration
|
||||||
|
|
||||||
# Telegraf is entirely plugin driven. All metrics are gathered from the
|
# Telegraf is entirely plugin driven. All metrics are gathered from the
|
||||||
|
@ -353,15 +257,7 @@ func PrintSampleConfig(pluginFilters []string, outputFilters []string) {
|
||||||
for _, oname := range onames {
|
for _, oname := range onames {
|
||||||
creator := outputs.Outputs[oname]
|
creator := outputs.Outputs[oname]
|
||||||
output := creator()
|
output := creator()
|
||||||
|
printConfig(oname, output, "outputs")
|
||||||
fmt.Printf("\n# %s\n[[outputs.%s]]", output.Description(), oname)
|
|
||||||
|
|
||||||
config := output.SampleConfig()
|
|
||||||
if config == "" {
|
|
||||||
fmt.Printf("\n # no configuration\n")
|
|
||||||
} else {
|
|
||||||
fmt.Printf(config)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filter plugins
|
// Filter plugins
|
||||||
|
@ -386,13 +282,13 @@ func PrintSampleConfig(pluginFilters []string, outputFilters []string) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
printConfig(pname, plugin)
|
printConfig(pname, plugin, "plugins")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print Service Plugins
|
// Print Service Plugins
|
||||||
fmt.Printf(servicePluginHeader)
|
fmt.Printf(servicePluginHeader)
|
||||||
for name, plugin := range servPlugins {
|
for name, plugin := range servPlugins {
|
||||||
printConfig(name, plugin)
|
printConfig(name, plugin, "plugins")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -401,8 +297,8 @@ type printer interface {
|
||||||
SampleConfig() string
|
SampleConfig() string
|
||||||
}
|
}
|
||||||
|
|
||||||
func printConfig(name string, p printer) {
|
func printConfig(name string, p printer, op string) {
|
||||||
fmt.Printf("\n# %s\n[[plugins.%s]]", p.Description(), name)
|
fmt.Printf("\n# %s\n[[%s.%s]]", p.Description(), op, name)
|
||||||
config := p.SampleConfig()
|
config := p.SampleConfig()
|
||||||
if config == "" {
|
if config == "" {
|
||||||
fmt.Printf("\n # no configuration\n")
|
fmt.Printf("\n # no configuration\n")
|
||||||
|
@ -423,7 +319,7 @@ func sliceContains(name string, list []string) bool {
|
||||||
// PrintPluginConfig prints the config usage of a single plugin.
|
// PrintPluginConfig prints the config usage of a single plugin.
|
||||||
func PrintPluginConfig(name string) error {
|
func PrintPluginConfig(name string) error {
|
||||||
if creator, ok := plugins.Plugins[name]; ok {
|
if creator, ok := plugins.Plugins[name]; ok {
|
||||||
printConfig(name, creator())
|
printConfig(name, creator(), "plugins")
|
||||||
} else {
|
} else {
|
||||||
return errors.New(fmt.Sprintf("Plugin %s not found", name))
|
return errors.New(fmt.Sprintf("Plugin %s not found", name))
|
||||||
}
|
}
|
||||||
|
@ -433,7 +329,7 @@ func PrintPluginConfig(name string) error {
|
||||||
// PrintOutputConfig prints the config usage of a single output.
|
// PrintOutputConfig prints the config usage of a single output.
|
||||||
func PrintOutputConfig(name string) error {
|
func PrintOutputConfig(name string) error {
|
||||||
if creator, ok := outputs.Outputs[name]; ok {
|
if creator, ok := outputs.Outputs[name]; ok {
|
||||||
printConfig(name, creator())
|
printConfig(name, creator(), "outputs")
|
||||||
} else {
|
} else {
|
||||||
return errors.New(fmt.Sprintf("Output %s not found", name))
|
return errors.New(fmt.Sprintf("Output %s not found", name))
|
||||||
}
|
}
|
||||||
|
@ -461,7 +357,7 @@ func (c *Config) LoadDirectory(path string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadConfig loads the given config file and returns a *Config pointer
|
// LoadConfig loads the given config file and applies it to c
|
||||||
func (c *Config) LoadConfig(path string) error {
|
func (c *Config) LoadConfig(path string) error {
|
||||||
data, err := ioutil.ReadFile(path)
|
data, err := ioutil.ReadFile(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -481,7 +377,7 @@ func (c *Config) LoadConfig(path string) error {
|
||||||
|
|
||||||
switch name {
|
switch name {
|
||||||
case "agent":
|
case "agent":
|
||||||
c.agent = subTable
|
c.Agent = subTable
|
||||||
case "tags":
|
case "tags":
|
||||||
if err = toml.UnmarshalTable(subTable, c.Tags); err != nil {
|
if err = toml.UnmarshalTable(subTable, c.Tags); err != nil {
|
||||||
log.Printf("Could not parse [tags] config\n")
|
log.Printf("Could not parse [tags] config\n")
|
||||||
|
@ -491,11 +387,14 @@ func (c *Config) LoadConfig(path string) error {
|
||||||
for outputName, outputVal := range subTable.Fields {
|
for outputName, outputVal := range subTable.Fields {
|
||||||
switch outputSubTable := outputVal.(type) {
|
switch outputSubTable := outputVal.(type) {
|
||||||
case *ast.Table:
|
case *ast.Table:
|
||||||
c.outputs[outputName] = outputSubTable
|
if err = c.addOutput(outputName, outputSubTable); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
case []*ast.Table:
|
case []*ast.Table:
|
||||||
for id, t := range outputSubTable {
|
for _, t := range outputSubTable {
|
||||||
nameID := fmt.Sprintf("%s-%d", outputName, id)
|
if err = c.addOutput(outputName, t); err != nil {
|
||||||
c.outputs[nameID] = t
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("Unsupported config format: %s",
|
return fmt.Errorf("Unsupported config format: %s",
|
||||||
|
@ -506,11 +405,14 @@ func (c *Config) LoadConfig(path string) error {
|
||||||
for pluginName, pluginVal := range subTable.Fields {
|
for pluginName, pluginVal := range subTable.Fields {
|
||||||
switch pluginSubTable := pluginVal.(type) {
|
switch pluginSubTable := pluginVal.(type) {
|
||||||
case *ast.Table:
|
case *ast.Table:
|
||||||
c.plugins[pluginName] = pluginSubTable
|
if err = c.addPlugin(pluginName, pluginSubTable); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
case []*ast.Table:
|
case []*ast.Table:
|
||||||
for id, t := range pluginSubTable {
|
for _, t := range pluginSubTable {
|
||||||
nameID := fmt.Sprintf("%s-%d", pluginName, id)
|
if err = c.addPlugin(pluginName, t); err != nil {
|
||||||
c.plugins[nameID] = t
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("Unsupported config format: %s",
|
return fmt.Errorf("Unsupported config format: %s",
|
||||||
|
@ -520,8 +422,142 @@ func (c *Config) LoadConfig(path string) error {
|
||||||
// Assume it's a plugin for legacy config file support if no other
|
// Assume it's a plugin for legacy config file support if no other
|
||||||
// identifiers are present
|
// identifiers are present
|
||||||
default:
|
default:
|
||||||
c.plugins[name] = subTable
|
if err = c.addPlugin(name, subTable); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Config) addOutput(name string, table *ast.Table) error {
|
||||||
|
if len(c.OutputFilters) > 0 && !sliceContains(name, c.OutputFilters) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
creator, ok := outputs.Outputs[name]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("Undefined but requested output: %s", name)
|
||||||
|
}
|
||||||
|
o := creator()
|
||||||
|
|
||||||
|
if err := toml.UnmarshalTable(table, o); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
ro := &RunningOutput{
|
||||||
|
Name: name,
|
||||||
|
Output: o,
|
||||||
|
}
|
||||||
|
c.Outputs = append(c.Outputs, ro)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Config) addPlugin(name string, table *ast.Table) error {
|
||||||
|
if len(c.PluginFilters) > 0 && !sliceContains(name, c.PluginFilters) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
creator, ok := plugins.Plugins[name]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("Undefined but requested plugin: %s", name)
|
||||||
|
}
|
||||||
|
plugin := creator()
|
||||||
|
|
||||||
|
pluginConfig, err := applyPlugin(name, table, plugin)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
rp := &RunningPlugin{
|
||||||
|
Name: name,
|
||||||
|
Plugin: plugin,
|
||||||
|
Config: pluginConfig,
|
||||||
|
}
|
||||||
|
c.Plugins = append(c.Plugins, rp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// applyPlugin takes defined plugin names and applies them to the given
|
||||||
|
// interface, returning a PluginConfig object in the end that can
|
||||||
|
// be inserted into a runningPlugin by the agent.
|
||||||
|
func applyPlugin(name string, tbl *ast.Table, p plugins.Plugin) (*PluginConfig, error) {
|
||||||
|
cp := &PluginConfig{Name: name}
|
||||||
|
|
||||||
|
if node, ok := tbl.Fields["pass"]; ok {
|
||||||
|
if kv, ok := node.(*ast.KeyValue); ok {
|
||||||
|
if ary, ok := kv.Value.(*ast.Array); ok {
|
||||||
|
for _, elem := range ary.Value {
|
||||||
|
if str, ok := elem.(*ast.String); ok {
|
||||||
|
cp.Pass = append(cp.Pass, str.Value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if node, ok := tbl.Fields["drop"]; ok {
|
||||||
|
if kv, ok := node.(*ast.KeyValue); ok {
|
||||||
|
if ary, ok := kv.Value.(*ast.Array); ok {
|
||||||
|
for _, elem := range ary.Value {
|
||||||
|
if str, ok := elem.(*ast.String); ok {
|
||||||
|
cp.Drop = append(cp.Drop, str.Value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if node, ok := tbl.Fields["interval"]; ok {
|
||||||
|
if kv, ok := node.(*ast.KeyValue); ok {
|
||||||
|
if str, ok := kv.Value.(*ast.String); ok {
|
||||||
|
dur, err := time.ParseDuration(str.Value)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
cp.Interval = dur
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if node, ok := tbl.Fields["tagpass"]; ok {
|
||||||
|
if subtbl, ok := node.(*ast.Table); ok {
|
||||||
|
for name, val := range subtbl.Fields {
|
||||||
|
if kv, ok := val.(*ast.KeyValue); ok {
|
||||||
|
tagfilter := &TagFilter{Name: name}
|
||||||
|
if ary, ok := kv.Value.(*ast.Array); ok {
|
||||||
|
for _, elem := range ary.Value {
|
||||||
|
if str, ok := elem.(*ast.String); ok {
|
||||||
|
tagfilter.Filter = append(tagfilter.Filter, str.Value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cp.TagPass = append(cp.TagPass, *tagfilter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if node, ok := tbl.Fields["tagdrop"]; ok {
|
||||||
|
if subtbl, ok := node.(*ast.Table); ok {
|
||||||
|
for name, val := range subtbl.Fields {
|
||||||
|
if kv, ok := val.(*ast.KeyValue); ok {
|
||||||
|
tagfilter := &TagFilter{Name: name}
|
||||||
|
if ary, ok := kv.Value.(*ast.Array); ok {
|
||||||
|
for _, elem := range ary.Value {
|
||||||
|
if str, ok := elem.(*ast.String); ok {
|
||||||
|
tagfilter.Filter = append(tagfilter.Filter, str.Value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cp.TagDrop = append(cp.TagDrop, *tagfilter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(tbl.Fields, "drop")
|
||||||
|
delete(tbl.Fields, "pass")
|
||||||
|
delete(tbl.Fields, "interval")
|
||||||
|
delete(tbl.Fields, "tagdrop")
|
||||||
|
delete(tbl.Fields, "tagpass")
|
||||||
|
return cp, toml.UnmarshalTable(tbl, p)
|
||||||
|
}
|
|
@ -0,0 +1,118 @@
|
||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/influxdb/telegraf/plugins"
|
||||||
|
"github.com/influxdb/telegraf/plugins/exec"
|
||||||
|
"github.com/influxdb/telegraf/plugins/memcached"
|
||||||
|
"github.com/influxdb/telegraf/plugins/procstat"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestConfig_LoadSinglePlugin(t *testing.T) {
|
||||||
|
c := NewConfig()
|
||||||
|
c.LoadConfig("./testdata/single_plugin.toml")
|
||||||
|
|
||||||
|
memcached := plugins.Plugins["memcached"]().(*memcached.Memcached)
|
||||||
|
memcached.Servers = []string{"localhost"}
|
||||||
|
|
||||||
|
mConfig := &PluginConfig{
|
||||||
|
Name: "memcached",
|
||||||
|
Drop: []string{"other", "stuff"},
|
||||||
|
Pass: []string{"some", "strings"},
|
||||||
|
TagDrop: []TagFilter{
|
||||||
|
TagFilter{
|
||||||
|
Name: "badtag",
|
||||||
|
Filter: []string{"othertag"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
TagPass: []TagFilter{
|
||||||
|
TagFilter{
|
||||||
|
Name: "goodtag",
|
||||||
|
Filter: []string{"mytag"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Interval: 5 * time.Second,
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(t, memcached, c.Plugins[0].Plugin,
|
||||||
|
"Testdata did not produce a correct memcached struct.")
|
||||||
|
assert.Equal(t, mConfig, c.Plugins[0].Config,
|
||||||
|
"Testdata did not produce correct memcached metadata.")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConfig_LoadDirectory(t *testing.T) {
|
||||||
|
c := NewConfig()
|
||||||
|
err := c.LoadConfig("./testdata/single_plugin.toml")
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
err = c.LoadDirectory("./testdata/subconfig")
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
memcached := plugins.Plugins["memcached"]().(*memcached.Memcached)
|
||||||
|
memcached.Servers = []string{"localhost"}
|
||||||
|
|
||||||
|
mConfig := &PluginConfig{
|
||||||
|
Name: "memcached",
|
||||||
|
Drop: []string{"other", "stuff"},
|
||||||
|
Pass: []string{"some", "strings"},
|
||||||
|
TagDrop: []TagFilter{
|
||||||
|
TagFilter{
|
||||||
|
Name: "badtag",
|
||||||
|
Filter: []string{"othertag"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
TagPass: []TagFilter{
|
||||||
|
TagFilter{
|
||||||
|
Name: "goodtag",
|
||||||
|
Filter: []string{"mytag"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Interval: 5 * time.Second,
|
||||||
|
}
|
||||||
|
assert.Equal(t, memcached, c.Plugins[0].Plugin,
|
||||||
|
"Testdata did not produce a correct memcached struct.")
|
||||||
|
assert.Equal(t, mConfig, c.Plugins[0].Config,
|
||||||
|
"Testdata did not produce correct memcached metadata.")
|
||||||
|
|
||||||
|
ex := plugins.Plugins["exec"]().(*exec.Exec)
|
||||||
|
ex.Commands = []*exec.Command{
|
||||||
|
&exec.Command{
|
||||||
|
Command: "/usr/bin/myothercollector --foo=bar",
|
||||||
|
Name: "myothercollector",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
eConfig := &PluginConfig{Name: "exec"}
|
||||||
|
assert.Equal(t, ex, c.Plugins[1].Plugin,
|
||||||
|
"Merged Testdata did not produce a correct exec struct.")
|
||||||
|
assert.Equal(t, eConfig, c.Plugins[1].Config,
|
||||||
|
"Merged Testdata did not produce correct exec metadata.")
|
||||||
|
|
||||||
|
memcached.Servers = []string{"192.168.1.1"}
|
||||||
|
assert.Equal(t, memcached, c.Plugins[2].Plugin,
|
||||||
|
"Testdata did not produce a correct memcached struct.")
|
||||||
|
assert.Equal(t, mConfig, c.Plugins[2].Config,
|
||||||
|
"Testdata did not produce correct memcached metadata.")
|
||||||
|
|
||||||
|
pstat := plugins.Plugins["procstat"]().(*procstat.Procstat)
|
||||||
|
pstat.Specifications = []*procstat.Specification{
|
||||||
|
&procstat.Specification{
|
||||||
|
PidFile: "/var/run/grafana-server.pid",
|
||||||
|
},
|
||||||
|
&procstat.Specification{
|
||||||
|
PidFile: "/var/run/influxdb/influxd.pid",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
pConfig := &PluginConfig{Name: "procstat"}
|
||||||
|
|
||||||
|
assert.Equal(t, pstat, c.Plugins[3].Plugin,
|
||||||
|
"Merged Testdata did not produce a correct procstat struct.")
|
||||||
|
assert.Equal(t, pConfig, c.Plugins[3].Config,
|
||||||
|
"Merged Testdata did not produce correct procstat metadata.")
|
||||||
|
}
|
|
@ -1,9 +1,9 @@
|
||||||
[memcached]
|
[[plugins.memcached]]
|
||||||
servers = ["localhost"]
|
servers = ["localhost"]
|
||||||
pass = ["some", "strings"]
|
pass = ["some", "strings"]
|
||||||
drop = ["other", "stuff"]
|
drop = ["other", "stuff"]
|
||||||
interval = "5s"
|
interval = "5s"
|
||||||
[memcached.tagpass]
|
[plugins.memcached.tagpass]
|
||||||
goodtag = ["mytag"]
|
goodtag = ["mytag"]
|
||||||
[memcached.tagdrop]
|
[plugins.memcached.tagdrop]
|
||||||
badtag = ["othertag"]
|
badtag = ["othertag"]
|
|
@ -1,6 +1,6 @@
|
||||||
[exec]
|
[[plugins.exec]]
|
||||||
# specify commands via an array of tables
|
# specify commands via an array of tables
|
||||||
[[exec.commands]]
|
[[plugins.exec.commands]]
|
||||||
# the command to run
|
# the command to run
|
||||||
command = "/usr/bin/myothercollector --foo=bar"
|
command = "/usr/bin/myothercollector --foo=bar"
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
[memcached]
|
[[plugins.memcached]]
|
||||||
servers = ["192.168.1.1"]
|
servers = ["192.168.1.1"]
|
||||||
pass = ["some", "strings"]
|
pass = ["some", "strings"]
|
||||||
drop = ["other", "stuff"]
|
drop = ["other", "stuff"]
|
||||||
interval = "5s"
|
interval = "5s"
|
||||||
[memcached.tagpass]
|
[plugins.memcached.tagpass]
|
||||||
goodtag = ["mytag"]
|
goodtag = ["mytag"]
|
||||||
[memcached.tagdrop]
|
[plugins.memcached.tagdrop]
|
||||||
badtag = ["othertag"]
|
badtag = ["othertag"]
|
|
@ -0,0 +1,5 @@
|
||||||
|
[[plugins.procstat]]
|
||||||
|
[[plugins.procstat.specifications]]
|
||||||
|
pid_file = "/var/run/grafana-server.pid"
|
||||||
|
[[plugins.procstat.specifications]]
|
||||||
|
pid_file = "/var/run/influxdb/influxd.pid"
|
|
@ -88,13 +88,15 @@
|
||||||
# PLUGINS #
|
# PLUGINS #
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
|
[plugins]
|
||||||
|
|
||||||
# Read Apache status information (mod_status)
|
# Read Apache status information (mod_status)
|
||||||
[apache]
|
[[plugins.apache]]
|
||||||
# An array of Apache status URI to gather stats.
|
# An array of Apache status URI to gather stats.
|
||||||
urls = ["http://localhost/server-status?auto"]
|
urls = ["http://localhost/server-status?auto"]
|
||||||
|
|
||||||
# Read metrics about cpu usage
|
# Read metrics about cpu usage
|
||||||
[cpu]
|
[[plugins.cpu]]
|
||||||
# Whether to report per-cpu stats or not
|
# Whether to report per-cpu stats or not
|
||||||
percpu = true
|
percpu = true
|
||||||
# Whether to report total system cpu stats or not
|
# Whether to report total system cpu stats or not
|
||||||
|
@ -103,11 +105,11 @@ urls = ["http://localhost/server-status?auto"]
|
||||||
drop = ["cpu_time"]
|
drop = ["cpu_time"]
|
||||||
|
|
||||||
# Read metrics about disk usage by mount point
|
# Read metrics about disk usage by mount point
|
||||||
[disk]
|
[[plugins.disk]]
|
||||||
# no configuration
|
# no configuration
|
||||||
|
|
||||||
# Read metrics from one or many disque servers
|
# Read metrics from one or many disque servers
|
||||||
[disque]
|
[[plugins.disque]]
|
||||||
# An array of URI to gather stats about. Specify an ip or hostname
|
# An array of URI to gather stats about. Specify an ip or hostname
|
||||||
# with optional port and password. ie disque://localhost, disque://10.10.3.33:18832,
|
# with optional port and password. ie disque://localhost, disque://10.10.3.33:18832,
|
||||||
# 10.0.0.1:10000, etc.
|
# 10.0.0.1:10000, etc.
|
||||||
|
@ -116,7 +118,7 @@ urls = ["http://localhost/server-status?auto"]
|
||||||
servers = ["localhost"]
|
servers = ["localhost"]
|
||||||
|
|
||||||
# Read stats from one or more Elasticsearch servers or clusters
|
# Read stats from one or more Elasticsearch servers or clusters
|
||||||
[elasticsearch]
|
[[plugins.elasticsearch]]
|
||||||
# specify a list of one or more Elasticsearch servers
|
# specify a list of one or more Elasticsearch servers
|
||||||
servers = ["http://localhost:9200"]
|
servers = ["http://localhost:9200"]
|
||||||
|
|
||||||
|
@ -125,7 +127,7 @@ urls = ["http://localhost/server-status?auto"]
|
||||||
local = true
|
local = true
|
||||||
|
|
||||||
# Read flattened metrics from one or more commands that output JSON to stdout
|
# Read flattened metrics from one or more commands that output JSON to stdout
|
||||||
[exec]
|
[[plugins.exec]]
|
||||||
# specify commands via an array of tables
|
# specify commands via an array of tables
|
||||||
[[exec.commands]]
|
[[exec.commands]]
|
||||||
# the command to run
|
# the command to run
|
||||||
|
@ -135,7 +137,7 @@ urls = ["http://localhost/server-status?auto"]
|
||||||
name = "mycollector"
|
name = "mycollector"
|
||||||
|
|
||||||
# Read metrics of haproxy, via socket or csv stats page
|
# Read metrics of haproxy, via socket or csv stats page
|
||||||
[haproxy]
|
[[plugins.haproxy]]
|
||||||
# An array of address to gather stats about. Specify an ip on hostname
|
# An array of address to gather stats about. Specify an ip on hostname
|
||||||
# with optional port. ie localhost, 10.10.3.33:1936, etc.
|
# with optional port. ie localhost, 10.10.3.33:1936, etc.
|
||||||
#
|
#
|
||||||
|
@ -145,7 +147,7 @@ urls = ["http://localhost/server-status?auto"]
|
||||||
# servers = ["socket:/run/haproxy/admin.sock"]
|
# servers = ["socket:/run/haproxy/admin.sock"]
|
||||||
|
|
||||||
# Read flattened metrics from one or more JSON HTTP endpoints
|
# Read flattened metrics from one or more JSON HTTP endpoints
|
||||||
[httpjson]
|
[[plugins.httpjson]]
|
||||||
# Specify services via an array of tables
|
# Specify services via an array of tables
|
||||||
[[httpjson.services]]
|
[[httpjson.services]]
|
||||||
|
|
||||||
|
@ -167,11 +169,11 @@ urls = ["http://localhost/server-status?auto"]
|
||||||
threshold = "0.75"
|
threshold = "0.75"
|
||||||
|
|
||||||
# Read metrics about disk IO by device
|
# Read metrics about disk IO by device
|
||||||
[io]
|
[[plugins.io]]
|
||||||
# no configuration
|
# no configuration
|
||||||
|
|
||||||
# read metrics from a Kafka topic
|
# read metrics from a Kafka topic
|
||||||
[kafka_consumer]
|
[[plugins.kafka_consumer]]
|
||||||
# topic(s) to consume
|
# topic(s) to consume
|
||||||
topics = ["telegraf"]
|
topics = ["telegraf"]
|
||||||
# an array of Zookeeper connection strings
|
# an array of Zookeeper connection strings
|
||||||
|
@ -184,7 +186,7 @@ urls = ["http://localhost/server-status?auto"]
|
||||||
offset = "oldest"
|
offset = "oldest"
|
||||||
|
|
||||||
# Read metrics from a LeoFS Server via SNMP
|
# Read metrics from a LeoFS Server via SNMP
|
||||||
[leofs]
|
[[plugins.leofs]]
|
||||||
# An array of URI to gather stats about LeoFS.
|
# An array of URI to gather stats about LeoFS.
|
||||||
# Specify an ip or hostname with port. ie 127.0.0.1:4020
|
# Specify an ip or hostname with port. ie 127.0.0.1:4020
|
||||||
#
|
#
|
||||||
|
@ -192,7 +194,7 @@ urls = ["http://localhost/server-status?auto"]
|
||||||
servers = ["127.0.0.1:4021"]
|
servers = ["127.0.0.1:4021"]
|
||||||
|
|
||||||
# Read metrics from local Lustre service on OST, MDS
|
# Read metrics from local Lustre service on OST, MDS
|
||||||
[lustre2]
|
[[plugins.lustre2]]
|
||||||
# An array of /proc globs to search for Lustre stats
|
# An array of /proc globs to search for Lustre stats
|
||||||
# If not specified, the default will work on Lustre 2.5.x
|
# If not specified, the default will work on Lustre 2.5.x
|
||||||
#
|
#
|
||||||
|
@ -200,11 +202,11 @@ urls = ["http://localhost/server-status?auto"]
|
||||||
# mds_procfiles = ["/proc/fs/lustre/mdt/*/md_stats"]
|
# mds_procfiles = ["/proc/fs/lustre/mdt/*/md_stats"]
|
||||||
|
|
||||||
# Read metrics about memory usage
|
# Read metrics about memory usage
|
||||||
[mem]
|
[[plugins.mem]]
|
||||||
# no configuration
|
# no configuration
|
||||||
|
|
||||||
# Read metrics from one or many memcached servers
|
# Read metrics from one or many memcached servers
|
||||||
[memcached]
|
[[plugins.memcached]]
|
||||||
# An array of address to gather stats about. Specify an ip on hostname
|
# An array of address to gather stats about. Specify an ip on hostname
|
||||||
# with optional port. ie localhost, 10.0.0.1:11211, etc.
|
# with optional port. ie localhost, 10.0.0.1:11211, etc.
|
||||||
#
|
#
|
||||||
|
@ -212,7 +214,7 @@ urls = ["http://localhost/server-status?auto"]
|
||||||
servers = ["localhost"]
|
servers = ["localhost"]
|
||||||
|
|
||||||
# Read metrics from one or many MongoDB servers
|
# Read metrics from one or many MongoDB servers
|
||||||
[mongodb]
|
[[plugins.mongodb]]
|
||||||
# An array of URI to gather stats about. Specify an ip or hostname
|
# An array of URI to gather stats about. Specify an ip or hostname
|
||||||
# with optional port add password. ie mongodb://user:auth_key@10.10.3.30:27017,
|
# with optional port add password. ie mongodb://user:auth_key@10.10.3.30:27017,
|
||||||
# mongodb://10.10.3.33:18832, 10.0.0.1:10000, etc.
|
# mongodb://10.10.3.33:18832, 10.0.0.1:10000, etc.
|
||||||
|
@ -221,7 +223,7 @@ urls = ["http://localhost/server-status?auto"]
|
||||||
servers = ["127.0.0.1:27017"]
|
servers = ["127.0.0.1:27017"]
|
||||||
|
|
||||||
# Read metrics from one or many mysql servers
|
# Read metrics from one or many mysql servers
|
||||||
[mysql]
|
[[plugins.mysql]]
|
||||||
# specify servers via a url matching:
|
# specify servers via a url matching:
|
||||||
# [username[:password]@][protocol[(address)]]/[?tls=[true|false|skip-verify]]
|
# [username[:password]@][protocol[(address)]]/[?tls=[true|false|skip-verify]]
|
||||||
# e.g.
|
# e.g.
|
||||||
|
@ -232,7 +234,7 @@ urls = ["http://localhost/server-status?auto"]
|
||||||
servers = ["localhost"]
|
servers = ["localhost"]
|
||||||
|
|
||||||
# Read metrics about network interface usage
|
# Read metrics about network interface usage
|
||||||
[net]
|
[[plugins.net]]
|
||||||
# By default, telegraf gathers stats from any up interface (excluding loopback)
|
# By default, telegraf gathers stats from any up interface (excluding loopback)
|
||||||
# Setting interfaces will tell it to gather these explicit interfaces,
|
# Setting interfaces will tell it to gather these explicit interfaces,
|
||||||
# regardless of status.
|
# regardless of status.
|
||||||
|
@ -240,12 +242,12 @@ urls = ["http://localhost/server-status?auto"]
|
||||||
# interfaces = ["eth0", ... ]
|
# interfaces = ["eth0", ... ]
|
||||||
|
|
||||||
# Read Nginx's basic status information (ngx_http_stub_status_module)
|
# Read Nginx's basic status information (ngx_http_stub_status_module)
|
||||||
[nginx]
|
[[plugins.nginx]]
|
||||||
# An array of Nginx stub_status URI to gather stats.
|
# An array of Nginx stub_status URI to gather stats.
|
||||||
urls = ["http://localhost/status"]
|
urls = ["http://localhost/status"]
|
||||||
|
|
||||||
# Ping given url(s) and return statistics
|
# Ping given url(s) and return statistics
|
||||||
[ping]
|
[[plugins.ping]]
|
||||||
# urls to ping
|
# urls to ping
|
||||||
urls = ["www.google.com"] # required
|
urls = ["www.google.com"] # required
|
||||||
# number of pings to send (ping -c <COUNT>)
|
# number of pings to send (ping -c <COUNT>)
|
||||||
|
@ -258,7 +260,7 @@ urls = ["http://localhost/server-status?auto"]
|
||||||
interface = ""
|
interface = ""
|
||||||
|
|
||||||
# Read metrics from one or many postgresql servers
|
# Read metrics from one or many postgresql servers
|
||||||
[postgresql]
|
[[plugins.postgresql]]
|
||||||
# specify servers via an array of tables
|
# specify servers via an array of tables
|
||||||
[[postgresql.servers]]
|
[[postgresql.servers]]
|
||||||
|
|
||||||
|
@ -288,12 +290,12 @@ urls = ["http://localhost/server-status?auto"]
|
||||||
# address = "influx@remoteserver"
|
# address = "influx@remoteserver"
|
||||||
|
|
||||||
# Read metrics from one or many prometheus clients
|
# Read metrics from one or many prometheus clients
|
||||||
[prometheus]
|
[[plugins.prometheus]]
|
||||||
# An array of urls to scrape metrics from.
|
# An array of urls to scrape metrics from.
|
||||||
urls = ["http://localhost:9100/metrics"]
|
urls = ["http://localhost:9100/metrics"]
|
||||||
|
|
||||||
# Read metrics from one or many RabbitMQ servers via the management API
|
# Read metrics from one or many RabbitMQ servers via the management API
|
||||||
[rabbitmq]
|
[[plugins.rabbitmq]]
|
||||||
# Specify servers via an array of tables
|
# Specify servers via an array of tables
|
||||||
[[rabbitmq.servers]]
|
[[rabbitmq.servers]]
|
||||||
# name = "rmq-server-1" # optional tag
|
# name = "rmq-server-1" # optional tag
|
||||||
|
@ -306,7 +308,7 @@ urls = ["http://localhost/server-status?auto"]
|
||||||
# nodes = ["rabbit@node1", "rabbit@node2"]
|
# nodes = ["rabbit@node1", "rabbit@node2"]
|
||||||
|
|
||||||
# Read metrics from one or many redis servers
|
# Read metrics from one or many redis servers
|
||||||
[redis]
|
[[plugins.redis]]
|
||||||
# An array of URI to gather stats about. Specify an ip or hostname
|
# An array of URI to gather stats about. Specify an ip or hostname
|
||||||
# with optional port add password. ie redis://localhost, redis://10.10.3.33:18832,
|
# with optional port add password. ie redis://localhost, redis://10.10.3.33:18832,
|
||||||
# 10.0.0.1:10000, etc.
|
# 10.0.0.1:10000, etc.
|
||||||
|
@ -315,7 +317,7 @@ urls = ["http://localhost/server-status?auto"]
|
||||||
servers = ["localhost"]
|
servers = ["localhost"]
|
||||||
|
|
||||||
# Read metrics from one or many RethinkDB servers
|
# Read metrics from one or many RethinkDB servers
|
||||||
[rethinkdb]
|
[[plugins.rethinkdb]]
|
||||||
# An array of URI to gather stats about. Specify an ip or hostname
|
# An array of URI to gather stats about. Specify an ip or hostname
|
||||||
# with optional port add password. ie rethinkdb://user:auth_key@10.10.3.30:28105,
|
# with optional port add password. ie rethinkdb://user:auth_key@10.10.3.30:28105,
|
||||||
# rethinkdb://10.10.3.33:18832, 10.0.0.1:10000, etc.
|
# rethinkdb://10.10.3.33:18832, 10.0.0.1:10000, etc.
|
||||||
|
@ -324,9 +326,9 @@ urls = ["http://localhost/server-status?auto"]
|
||||||
servers = ["127.0.0.1:28015"]
|
servers = ["127.0.0.1:28015"]
|
||||||
|
|
||||||
# Read metrics about swap memory usage
|
# Read metrics about swap memory usage
|
||||||
[swap]
|
[[plugins.swap]]
|
||||||
# no configuration
|
# no configuration
|
||||||
|
|
||||||
# Read metrics about system load & uptime
|
# Read metrics about system load & uptime
|
||||||
[system]
|
[[plugins.system]]
|
||||||
# no configuration
|
# no configuration
|
|
@ -16,7 +16,7 @@ import (
|
||||||
|
|
||||||
const sampleConfig = `
|
const sampleConfig = `
|
||||||
# specify commands via an array of tables
|
# specify commands via an array of tables
|
||||||
[[exec.commands]]
|
[[plugins.exec.commands]]
|
||||||
# the command to run
|
# the command to run
|
||||||
command = "/usr/bin/mycollector --foo=bar"
|
command = "/usr/bin/mycollector --foo=bar"
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ func (c RealHTTPClient) MakeRequest(req *http.Request) (*http.Response, error) {
|
||||||
|
|
||||||
var sampleConfig = `
|
var sampleConfig = `
|
||||||
# Specify services via an array of tables
|
# Specify services via an array of tables
|
||||||
[[httpjson.services]]
|
[[plugins.httpjson.services]]
|
||||||
|
|
||||||
# a name for the service being polled
|
# a name for the service being polled
|
||||||
name = "webserver_stats"
|
name = "webserver_stats"
|
||||||
|
@ -69,7 +69,7 @@ var sampleConfig = `
|
||||||
# ]
|
# ]
|
||||||
|
|
||||||
# HTTP parameters (all values must be strings)
|
# HTTP parameters (all values must be strings)
|
||||||
[httpjson.services.parameters]
|
[plugins.httpjson.services.parameters]
|
||||||
event_type = "cpu_spike"
|
event_type = "cpu_spike"
|
||||||
threshold = "0.75"
|
threshold = "0.75"
|
||||||
`
|
`
|
||||||
|
|
|
@ -55,7 +55,7 @@ func (j *Jolokia) SampleConfig() string {
|
||||||
group = "as"
|
group = "as"
|
||||||
|
|
||||||
# List of servers exposing jolokia read service
|
# List of servers exposing jolokia read service
|
||||||
[[jolokia.servers]]
|
[[plugins.jolokia.servers]]
|
||||||
name = "stable"
|
name = "stable"
|
||||||
host = "192.168.103.2"
|
host = "192.168.103.2"
|
||||||
port = "8180"
|
port = "8180"
|
||||||
|
@ -63,20 +63,20 @@ func (j *Jolokia) SampleConfig() string {
|
||||||
# List of metrics collected on above servers
|
# List of metrics collected on above servers
|
||||||
# Each metric consists in a name, a jmx path and either a pass or drop slice attributes
|
# Each metric consists in a name, a jmx path and either a pass or drop slice attributes
|
||||||
# This collect all heap memory usage metrics
|
# This collect all heap memory usage metrics
|
||||||
[[jolokia.metrics]]
|
[[plugins.jolokia.metrics]]
|
||||||
name = "heap_memory_usage"
|
name = "heap_memory_usage"
|
||||||
jmx = "/java.lang:type=Memory/HeapMemoryUsage"
|
jmx = "/java.lang:type=Memory/HeapMemoryUsage"
|
||||||
|
|
||||||
|
|
||||||
# This drops the 'committed' value from Eden space measurement
|
# This drops the 'committed' value from Eden space measurement
|
||||||
[[jolokia.metrics]]
|
[[plugins.jolokia.metrics]]
|
||||||
name = "memory_eden"
|
name = "memory_eden"
|
||||||
jmx = "/java.lang:type=MemoryPool,name=PS Eden Space/Usage"
|
jmx = "/java.lang:type=MemoryPool,name=PS Eden Space/Usage"
|
||||||
drop = [ "committed" ]
|
drop = [ "committed" ]
|
||||||
|
|
||||||
|
|
||||||
# This passes only DaemonThreadCount and ThreadCount
|
# This passes only DaemonThreadCount and ThreadCount
|
||||||
[[jolokia.metrics]]
|
[[plugins.jolokia.metrics]]
|
||||||
name = "heap_threads"
|
name = "heap_threads"
|
||||||
jmx = "/java.lang:type=Threading"
|
jmx = "/java.lang:type=Threading"
|
||||||
pass = [
|
pass = [
|
||||||
|
|
|
@ -25,7 +25,7 @@ var ignoredColumns = map[string]bool{"datid": true, "datname": true, "stats_rese
|
||||||
|
|
||||||
var sampleConfig = `
|
var sampleConfig = `
|
||||||
# specify servers via an array of tables
|
# specify servers via an array of tables
|
||||||
[[postgresql.servers]]
|
[[plugins.postgresql.servers]]
|
||||||
|
|
||||||
# specify address via a url matching:
|
# specify address via a url matching:
|
||||||
# postgres://[pqgotest[:password]]@localhost[/dbname]?sslmode=[disable|verify-ca|verify-full]
|
# postgres://[pqgotest[:password]]@localhost[/dbname]?sslmode=[disable|verify-ca|verify-full]
|
||||||
|
@ -49,7 +49,7 @@ var sampleConfig = `
|
||||||
|
|
||||||
# databases = ["app_production", "blah_testing"]
|
# databases = ["app_production", "blah_testing"]
|
||||||
|
|
||||||
# [[postgresql.servers]]
|
# [[plugins.postgresql.servers]]
|
||||||
# address = "influx@remoteserver"
|
# address = "influx@remoteserver"
|
||||||
`
|
`
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ func NewProcstat() *Procstat {
|
||||||
}
|
}
|
||||||
|
|
||||||
var sampleConfig = `
|
var sampleConfig = `
|
||||||
[[procstat.specifications]]
|
[[plugins.procstat.specifications]]
|
||||||
prefix = "" # optional string to prefix measurements
|
prefix = "" # optional string to prefix measurements
|
||||||
# Must specify one of: pid_file, exe, or pattern
|
# Must specify one of: pid_file, exe, or pattern
|
||||||
# PID file to monitor process
|
# PID file to monitor process
|
||||||
|
|
|
@ -100,7 +100,7 @@ var gatherFunctions = []gatherFunc{gatherOverview, gatherNodes, gatherQueues}
|
||||||
|
|
||||||
var sampleConfig = `
|
var sampleConfig = `
|
||||||
# Specify servers via an array of tables
|
# Specify servers via an array of tables
|
||||||
[[rabbitmq.servers]]
|
[[plugins.rabbitmq.servers]]
|
||||||
# name = "rmq-server-1" # optional tag
|
# name = "rmq-server-1" # optional tag
|
||||||
# url = "http://localhost:15672"
|
# url = "http://localhost:15672"
|
||||||
# username = "guest"
|
# username = "guest"
|
||||||
|
|
|
@ -22,7 +22,7 @@ type TwemproxyInstance struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
var sampleConfig = `
|
var sampleConfig = `
|
||||||
[[twemproxy.instances]]
|
[[plugins.twemproxy.instances]]
|
||||||
# Twemproxy stats address and port (no scheme)
|
# Twemproxy stats address and port (no scheme)
|
||||||
addr = "localhost:22222"
|
addr = "localhost:22222"
|
||||||
# Monitor pool name
|
# Monitor pool name
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
[agent]
|
|
||||||
interval = "5s"
|
|
||||||
http = ":11213"
|
|
||||||
debug = true
|
|
||||||
|
|
||||||
[outputs]
|
|
||||||
[outputs.influxdb]
|
|
||||||
url = "http://localhost:8086"
|
|
||||||
username = "root"
|
|
||||||
password = "root"
|
|
||||||
database = "telegraf"
|
|
||||||
|
|
||||||
[tags]
|
|
||||||
dc = "us-phx-1"
|
|
||||||
|
|
||||||
[redis]
|
|
||||||
address = ":6379"
|
|
|
@ -1,5 +0,0 @@
|
||||||
[procstat]
|
|
||||||
[[procstat.specifications]]
|
|
||||||
pid_file = "/var/run/grafana-server.pid"
|
|
||||||
[[procstat.specifications]]
|
|
||||||
pid_file = "/var/run/influxdb/influxd.pid"
|
|
Loading…
Reference in New Issue