Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(agent): Print plugins source information #16270

Open
wants to merge 11 commits into
base: master
Choose a base branch
from

Conversation

neelayu
Copy link
Contributor

@neelayu neelayu commented Dec 6, 2024

Summary

Print the source information for the plugins.

Put this feature behind a flag to preserve backward compatibility in systems relying on Loaded inputs, Outputs strings for validations.
Flag introduced: --print-plugin-config-source Default: false

If required, we can eliminate this flag.

Sample output on telegraf init

2024-12-06T19:05:36Z I! Loaded inputs: cpu disk (2x) internal interrupts mem (2x) net (3x)
+--------------+------------------------------------------------------+
| Name         | Source(s)                                            |
+--------------+------------------------------------------------------+
| net (3x)     | /Users/user-of-unix/telegraf/configs1/config3.conf   |
|              | /Users/user-of-unix/telegraf/configs1/config1.conf   |
|              | /Users/user-of-unix/telegraf/configs1/config2.conf   |
+--------------+------------------------------------------------------+
| disk (2x)    | /Users/user-of-unix/telegraf/configs1/config2.conf   |
|              | /Users/user-of-unix/telegraf/configs1/config2.conf   |
+--------------+------------------------------------------------------+
| mem (2x)     | /Users/user-of-unix/telegraf/configs1/config4.conf   |
|              | /Users/user-of-unix/telegraf/configs1/config2.conf   |
+--------------+------------------------------------------------------+
| internal     | /Users/user-of-unix/telegraf/configs1/config2.conf   |
+--------------+------------------------------------------------------+
| interrupts   | /Users/user-of-unix/telegraf/configs1/config2.conf   |
+--------------+------------------------------------------------------+
| cpu          | /Users/user-of-unix/telegraf/configs1/config5.conf   |
+--------------+------------------------------------------------------+

Checklist

  • No AI generated code was used in this PR

Related issues

resolves #16269

@telegraf-tiger telegraf-tiger bot added the feat Improvement on an existing feature such as adding a new setting/mode to an existing plugin label Dec 6, 2024
@srebhan
Copy link
Member

srebhan commented Dec 9, 2024

@neelayu I really like this! Can we please make the flag being something like --print-plugin-config-source or --print-plugin-origin? This would be a bit more speaking I think and avoids the next flag being called --even-newer-plugin-print-behavior. ;-)

Furthermore, please fix the linter issues.

@srebhan srebhan self-assigned this Dec 9, 2024
@neelayu
Copy link
Contributor Author

neelayu commented Dec 10, 2024

@srebhan Thanks. I have made the changes. The test failure seems unrelated to my change though.

Copy link
Member

@srebhan srebhan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @neelayu for the update. Some more comments from my side.

config/config.go Outdated
@@ -74,7 +77,8 @@ type Config struct {
OutputFilters []string
SecretStoreFilters []string

SecretStores map[string]telegraf.SecretStore
SecretStores map[string]telegraf.SecretStore
secretStoreSource []secretStoreConfig
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not using a map[string]string mapping the name to the source?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had considered using a map[string]string, but it will not help if have multiple secretstores with the same names. In that case it would be map[string][]string.

The SecretStore map on line 80 stores ID to underlying interface and hence it works.

Let me know your thoughts.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok I see, but I would use map[string][]string in this case to collect the sources for the same type and print them in groups...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ack. I've made the change.

config/config.go Outdated
func getPluginPrintString(plugins pluginNames) string {
output := PluginNameCounts(plugins)
if PrintPluginConfigSource {
return output + plugins.String()
}

return output
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please merge this back to the *Names() functions! Stripping this out to save the if is not worth it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

config/config.go Outdated
Comment on lines 318 to 321
// InputNames returns a string of configured inputs.
func (c *Config) InputNames() string {
plugins := make(pluginNames, 0, len(c.Inputs))
for _, input := range c.Inputs {
name = append(name, input.Config.Name)
plugins = append(plugins, pluginPrinter{
name: input.Config.Name,
source: input.Config.Source,
})
}
return PluginNameCounts(name)
return getPluginPrintString(plugins)
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about keeping this as is and add a function InputNamesWithSources() and call this in telegraf.go? Same for the other plugin types. This simplifies the code I think and we can keep the short printing in telegraf.go and add printing the sources.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense. However, can you clarify the following-

We print short form as we do currently. But with this PR, we also print the source table. If that is the case, do we require the flag that I introduced? My intention of introducing the flag was to ensure no regressions on systems already using telegraf and checking for strings like Loaded inputs

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We currently print a line for all loaded inputs etc. This can then still be there and use InputNames().

Then after that "header" we can print the more detailed information you add if --print-plugin-source... is provided. Keeping those lines will ensure that we don't break users if they rely on that header...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made the changes.

// LoadConfigData loads TOML-formatted config data
func (c *Config) LoadConfigData(data []byte) error {
func (c *Config) LoadConfigData(data []byte, opts ...cfgDataOption) error {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you should just pass the source here. If we ever want to add other flags we can still refactor this later.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason for introducing functional ops pattern was to prevent breaking other files calling this func. And there are about 50+ across 20+ files.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see your point but my fear is that people might forget about adding the source in future changes and we will not notice. You might keep this as is but I really would feel better if we enforce providing a source... ;-)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am inclined to keep this as-is for this PR. I can open up a second one to enforce the func signature change. Let me know your thoughts.

Comment on lines 51 to 59
// GetPluginTableContent prints a bordered ASCII table.
//
// Inputs:
//
// headers: slice of strings containing the headers of the table
// data: slice of slices of strings containing the data to be printed
//
// Reference: https://github.com/olekukonko/tablewriter
func GetPluginTableContent(headers []string, data [][]any) string {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think using https://github.com/jedib0t/go-pretty here is the better alternative. :-)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. This one is a popular library. But since I wanted something lightweight. Hence, I considered writing it using the above as reference. If Telegraf authors are okay with adding a new library, I can do it :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I'd rather add a dependency than stuffing in code here. :-)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Copy link
Contributor Author

@neelayu neelayu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @srebhan

Comment on lines 51 to 59
// GetPluginTableContent prints a bordered ASCII table.
//
// Inputs:
//
// headers: slice of strings containing the headers of the table
// data: slice of slices of strings containing the data to be printed
//
// Reference: https://github.com/olekukonko/tablewriter
func GetPluginTableContent(headers []string, data [][]any) string {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. This one is a popular library. But since I wanted something lightweight. Hence, I considered writing it using the above as reference. If Telegraf authors are okay with adding a new library, I can do it :)

config/config.go Outdated
@@ -74,7 +77,8 @@ type Config struct {
OutputFilters []string
SecretStoreFilters []string

SecretStores map[string]telegraf.SecretStore
SecretStores map[string]telegraf.SecretStore
secretStoreSource []secretStoreConfig
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had considered using a map[string]string, but it will not help if have multiple secretstores with the same names. In that case it would be map[string][]string.

The SecretStore map on line 80 stores ID to underlying interface and hence it works.

Let me know your thoughts.

config/config.go Outdated
Comment on lines 318 to 321
// InputNames returns a string of configured inputs.
func (c *Config) InputNames() string {
plugins := make(pluginNames, 0, len(c.Inputs))
for _, input := range c.Inputs {
name = append(name, input.Config.Name)
plugins = append(plugins, pluginPrinter{
name: input.Config.Name,
source: input.Config.Source,
})
}
return PluginNameCounts(name)
return getPluginPrintString(plugins)
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense. However, can you clarify the following-

We print short form as we do currently. But with this PR, we also print the source table. If that is the case, do we require the flag that I introduced? My intention of introducing the flag was to ensure no regressions on systems already using telegraf and checking for strings like Loaded inputs

// LoadConfigData loads TOML-formatted config data
func (c *Config) LoadConfigData(data []byte) error {
func (c *Config) LoadConfigData(data []byte, opts ...cfgDataOption) error {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason for introducing functional ops pattern was to prevent breaking other files calling this func. And there are about 50+ across 20+ files.

@srebhan
Copy link
Member

srebhan commented Dec 20, 2024

@neelayu you need to update the /docs/LICENSE_OF_DEPENDENCIES.md file with the new dependencies' license information. Please check make check-deps for what needs to be done!

@neelayu
Copy link
Contributor Author

neelayu commented Dec 20, 2024

@srebhan
I believe I have already added them here https://github.com/influxdata/telegraf/pull/16270/files#diff-2afa363df9dd5dc9cbf8b97542633fda73bf1747a7959b0da02e518a976db745R460

Not sure why it is asking me to remove them again?

--- /tmp/tmp.3FJLxju4ZG/LICENSE_OF_DEPENDENCIES.md      2024-12-16 06:45:42.992042502 +0000
+++ /tmp/tmp.3FJLxju4ZG/HEAD    2024-12-16 06:45:42.992042502 +0000
@@ -233,0 +234 @@
+github.com/jedib0t/go-pretty
@@ -259,0 +261 @@
+github.com/mattn/go-runewidth
@@ -333,0 +336 @@
+github.com/rivo/uniseg
@@ -455,3 +457,0 @@
-github.com/jedib0t/go-pretty
-github.com/mattn/go-runewidth
-github.com/rivo/uniseg


The docs/LICENSE_OF_DEPENDENCIES.md file does not contain the expected entries.

Lines prefixed with '+' should be added to LICENSE_OF_DEPENDENCIES.md and '-'
lines should be removed.

Include a link to the appropriate licenses for any additions.

@srebhan
Copy link
Member

srebhan commented Dec 20, 2024

Seems like you got the positions wrong. The entries are in lexicographic order so you also need to insert the lines in the right places. ;-)

@neelayu
Copy link
Contributor Author

neelayu commented Dec 20, 2024

Thanks @srebhan.
Made the changes now

@telegraf-tiger
Copy link
Contributor

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/agent feat Improvement on an existing feature such as adding a new setting/mode to an existing plugin
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Show loaded plugins source information(http or file)
2 participants