-
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.
config/config.go
Outdated
// 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.
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 change the function to take a mandatory path
or source
parameter and unconditionally add the source to the plugin models. The only place that should be conditional should be the printing.
Remember this is a public, exported function and we shouldn't change the signature too often. Having the plugin source in the model is a good thing so please add it.
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
config/config.go
Outdated
// 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. |
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.
@neelayu thanks for your update and sorry for this taking so long (due to holidays). I do have two minor comments in the code and a request to no go for the option pattern for the LoadConfigData
function. Let's change the function signature once and remove any room for errors.
config/plugin_printer.go
Outdated
|
||
type pluginNames []pluginPrinter | ||
|
||
func GetPluginSourcesTable(pluginNames []pluginPrinter) 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.
Please do not export this function.
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
go.mod
Outdated
require ( | ||
github.com/mattn/go-runewidth v0.0.16 // indirect | ||
github.com/rivo/uniseg v0.4.7 // indirect | ||
) | ||
|
||
require ( |
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 manually fuse the two requires.
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
13fe6a0
to
487823e
Compare
@srebhan I have enforced the func signature. Let me know. Thanks! |
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 |
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 a lot @neelayu!
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