diff --git a/agent.go b/agent.go index 7e537f0c4..b671df106 100644 --- a/agent.go +++ b/agent.go @@ -24,9 +24,10 @@ type runningOutput struct { } type runningPlugin struct { - name string - plugin plugins.Plugin - config *ConfiguredPlugin + name string + filtername string + plugin plugins.Plugin + config *ConfiguredPlugin } // Agent runs telegraf and collects data based on the given config @@ -176,9 +177,11 @@ func (a *Agent) LoadPlugins(filters []string, config *Config) ([]string, error) var names []string for name, plugin := range config.PluginsDeclared() { - if sliceContains(name, filters) || len(filters) == 0 { + // Trim the ID off the output name for filtering + filtername := strings.TrimRight(name, "-0123456789") + if sliceContains(filtername, filters) || len(filters) == 0 { config := config.GetPluginConfig(name) - a.plugins = append(a.plugins, &runningPlugin{name, plugin, config}) + a.plugins = append(a.plugins, &runningPlugin{name, filtername, plugin, config}) names = append(names, name) } } @@ -207,7 +210,7 @@ func (a *Agent) gatherParallel(pointChan chan *client.Point) error { acc := NewAccumulator(plugin.config, pointChan) acc.SetDebug(a.Debug) - acc.SetPrefix(plugin.name + "_") + acc.SetPrefix(plugin.filtername + "_") acc.SetDefaultTags(a.Tags) if err := plugin.plugin.Gather(acc); err != nil { @@ -240,7 +243,7 @@ func (a *Agent) gatherSeparate( acc := NewAccumulator(plugin.config, pointChan) acc.SetDebug(a.Debug) - acc.SetPrefix(plugin.name + "_") + acc.SetPrefix(plugin.filtername + "_") acc.SetDefaultTags(a.Tags) if err := plugin.plugin.Gather(acc); err != nil { @@ -286,7 +289,7 @@ func (a *Agent) Test() error { for _, plugin := range a.plugins { acc := NewAccumulator(plugin.config, pointChan) acc.SetDebug(true) - acc.SetPrefix(plugin.name + "_") + acc.SetPrefix(plugin.filtername + "_") fmt.Printf("* Plugin: %s, Collection 1\n", plugin.name) if plugin.config.Interval != 0 { @@ -299,7 +302,7 @@ func (a *Agent) Test() error { // Special instructions for some plugins. cpu, for example, needs to be // run twice in order to return cpu usage percentages. - switch plugin.name { + switch plugin.filtername { case "cpu", "mongodb": time.Sleep(500 * time.Millisecond) fmt.Printf("* Plugin: %s, Collection 2\n", plugin.name) diff --git a/config.go b/config.go index 2e9677c87..8df49347d 100644 --- a/config.go +++ b/config.go @@ -236,6 +236,8 @@ var pluginHeader = ` ############################################################################### # PLUGINS # ############################################################################### + +[plugins] ` var servicePluginHeader = ` @@ -311,7 +313,7 @@ type printer interface { } func printConfig(name string, p printer) { - fmt.Printf("\n# %s\n[%s]", p.Description(), name) + fmt.Printf("\n# %s\n[[plugins.%s]]", p.Description(), name) config := p.SampleConfig() if config == "" { fmt.Printf("\n # no configuration\n") @@ -540,8 +542,34 @@ func LoadConfig(path string) (*Config, error) { outputName) } } + case "plugins": + for pluginName, pluginVal := range subTable.Fields { + switch pluginSubTable := pluginVal.(type) { + case *ast.Table: + err = c.parsePlugin(pluginName, pluginSubTable, 0) + if err != nil { + log.Printf("Could not parse config for plugin: %s\n", + pluginName) + return nil, err + } + case []*ast.Table: + for id, t := range pluginSubTable { + err = c.parsePlugin(pluginName, t, id) + if err != nil { + log.Printf("Could not parse config for plugin: %s\n", + pluginName) + return nil, err + } + } + default: + return nil, fmt.Errorf("Unsupported config format: %s", + pluginName) + } + } + // Assume it's a plugin for legacy config file support if no other + // identifiers are present default: - err = c.parsePlugin(name, subTable) + err = c.parsePlugin(name, subTable, 0) if err != nil { return nil, err } @@ -590,7 +618,7 @@ func (c *Config) parseOutput(name string, outputAst *ast.Table, id int) error { } // Parse a plugin config, plus plugin meta-config, out of the given *ast.Table. -func (c *Config) parsePlugin(name string, pluginAst *ast.Table) error { +func (c *Config) parsePlugin(name string, pluginAst *ast.Table, id int) error { creator, ok := plugins.Plugins[name] if !ok { return fmt.Errorf("Undefined but requested plugin: %s", name) @@ -682,13 +710,14 @@ func (c *Config) parsePlugin(name string, pluginAst *ast.Table) error { delete(pluginAst.Fields, "interval") delete(pluginAst.Fields, "tagdrop") delete(pluginAst.Fields, "tagpass") - c.pluginFieldsSet[name] = extractFieldNames(pluginAst) - c.pluginConfigurationFieldsSet[name] = cpFields + nameID := fmt.Sprintf("%s-%d", name, id) + c.pluginFieldsSet[nameID] = extractFieldNames(pluginAst) + c.pluginConfigurationFieldsSet[nameID] = cpFields err := toml.UnmarshalTable(pluginAst, plugin) if err != nil { return err } - c.plugins[name] = plugin - c.pluginConfigurations[name] = cp + c.plugins[nameID] = plugin + c.pluginConfigurations[nameID] = cp return nil } diff --git a/config_test.go b/config_test.go index 2801d22de..89b678b7b 100644 --- a/config_test.go +++ b/config_test.go @@ -206,7 +206,7 @@ func TestConfig_parsePlugin(t *testing.T) { } subtbl := tbl.Fields["memcached"].(*ast.Table) - err = c.parsePlugin("memcached", subtbl) + err = c.parsePlugin("memcached", subtbl, 0) memcached := plugins.Plugins["memcached"]().(*memcached.Memcached) memcached.Servers = []string{"localhost"} @@ -230,9 +230,9 @@ func TestConfig_parsePlugin(t *testing.T) { Interval: 5 * time.Second, } - assert.Equal(t, memcached, c.plugins["memcached"], + assert.Equal(t, memcached, c.plugins["memcached-0"], "Testdata did not produce a correct memcached struct.") - assert.Equal(t, mConfig, c.pluginConfigurations["memcached"], + assert.Equal(t, mConfig, c.pluginConfigurations["memcached-0"], "Testdata did not produce correct memcached metadata.") } @@ -290,18 +290,18 @@ func TestConfig_LoadDirectory(t *testing.T) { pConfig := &ConfiguredPlugin{Name: "procstat"} - assert.Equal(t, memcached, c.plugins["memcached"], + assert.Equal(t, memcached, c.plugins["memcached-0"], "Merged Testdata did not produce a correct memcached struct.") - assert.Equal(t, mConfig, c.pluginConfigurations["memcached"], + assert.Equal(t, mConfig, c.pluginConfigurations["memcached-0"], "Merged Testdata did not produce correct memcached metadata.") - assert.Equal(t, ex, c.plugins["exec"], + assert.Equal(t, ex, c.plugins["exec-0"], "Merged Testdata did not produce a correct exec struct.") - assert.Equal(t, eConfig, c.pluginConfigurations["exec"], + assert.Equal(t, eConfig, c.pluginConfigurations["exec-0"], "Merged Testdata did not produce correct exec metadata.") - assert.Equal(t, pstat, c.plugins["procstat"], + assert.Equal(t, pstat, c.plugins["procstat-0"], "Merged Testdata did not produce a correct procstat struct.") - assert.Equal(t, pConfig, c.pluginConfigurations["procstat"], + assert.Equal(t, pConfig, c.pluginConfigurations["procstat-0"], "Merged Testdata did not produce correct procstat metadata.") }