-
Notifications
You must be signed in to change notification settings - Fork 5.6k
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
base: master
Are you sure you want to change the base?
Conversation
@neelayu I really like this! Can we please make the flag being something like Furthermore, please fix the linter issues. |
39f3020
to
c885748
Compare
@srebhan Thanks. I have made the changes. The test failure seems unrelated to my change though. |
There was a problem hiding this 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 |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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...
There was a problem hiding this comment.
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 | ||
} |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
// 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) | ||
} |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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...
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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... ;-)
There was a problem hiding this comment.
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.
config/plugin_printer.go
Outdated
// 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 { |
There was a problem hiding this comment.
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. :-)
There was a problem hiding this comment.
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 :)
There was a problem hiding this comment.
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. :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @srebhan
config/plugin_printer.go
Outdated
// 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 { |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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
// 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) | ||
} |
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
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.
6c83f2d
to
f066526
Compare
@neelayu you need to update the |
@srebhan Not sure why it is asking me to remove them again?
|
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. ;-) |
e0ec63d
to
13fe6a0
Compare
Thanks @srebhan. |
Download PR build artifacts for linux_amd64.tar.gz, darwin_arm64.tar.gz, and windows_amd64.zip. 📦 Click here to get additional PR build artifactsArtifact URLs |
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: falseIf required, we can eliminate this flag.
Sample output on telegraf init
Checklist
Related issues
resolves #16269