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

Experimental go 1.8 plugin support #3217

Merged
merged 1 commit into from
Jan 13, 2017
Merged

Experimental go 1.8 plugin support #3217

merged 1 commit into from
Jan 13, 2017

Conversation

urso
Copy link

@urso urso commented Dec 19, 2016

This PR introduces support for loadable plugins to beats. Requires linux, go1.8 beta2+, cgo. If any is missing, the API is still valid, but plugin loading is disabled (CLI flag is missing as well).

Shared libraries export a bundle of plugins in global Bundle variable of type map[string][]interface{}. The string key is the plugin module type, individual plugins are loadable for.

Beats modules supporting plugin support have to register a module type before startup via plugin.RegisterLoader. In addition modules must provide a Plugin function for building a valid type-correct bundle with correct module type key. See outputs.Plugin and processors.Plugin as example.
Alternatively a solution with Bundle of type []interface{} or interface{} might be possible too (no potential naming collisions). Loading can use reflection and/or type switches. This might work, by passing all loadable plugins to all module loaders. With public API as is, this implementation detail can be easily applied later without enforcing any changes on plugin writers.

Every plugin is a valid bundle itself. Use plugin.Bundle to flatten and combine multiple bundles/plugins into one bundle.

Bundles can be loaded from command line only. Use -plugin <path> to load a plugin.

Versioning: the plugin loader does no explicit version checks. A possible solution is to have plugin.Bundle include a version and be strict (e.g. on major version). On the other hand, the compiler already hashes all packages. The runtime already ensures no plugin with failing hash-check can be used.

thisnPR adds plugin support for:

  • libbout outputs
  • libbeat processors
  • packetbeat protocol analyzers
  • heartbeat monitors
  • metricbeat modules

@urso urso added the discuss Issue needs further discussion. label Dec 19, 2016
@tsg
Copy link
Contributor

tsg commented Dec 21, 2016

On the other hand, the compiler already hashes all packages. The runtime already ensures no plugin with failing hash-check can be used.

That means that the exact same libbeat version needs to be used when compiling both the Beat and the plugin?

@urso
Copy link
Author

urso commented Dec 21, 2016

Right. Plus compiler version, as runtime is also included in plugin.

@@ -155,6 +156,10 @@ func (b *Beat) launch(bt Creator) error {
return err
}

if err := plugin.Initialize(); err != nil {
Copy link
Member

Choose a reason for hiding this comment

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

Can we "hide" this behind a config option something like plugins.enabled: false? This make sure nothing happens by default and will make it easier to mark this experimential. Especially as it is not supported on all platforms and only go 1.8.

Copy link
Author

Choose a reason for hiding this comment

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

Plugins are loadable from CLI only using the -plugin setting. No config file support yet, as feature is very experimental.

Only if plugin support is available, the flag will be available. The Initialize function is implemented in cli.go. In case no plugin support is available cli_stub.go will be used (empty function).

This behavior close enough?

Copy link
Member

Choose a reason for hiding this comment

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

The behaviour is the same. It's just that with a undocument config option, not even the initialize code would be execute. I would still prefer to have an additional config option :-)

constr Constructor
}

var pluginKey = "libbeat-processor"
Copy link
Member

Choose a reason for hiding this comment

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

should we use the dot notation for the keys as we do in most other places? Means libbeat.processor

Copy link
Author

Choose a reason for hiding this comment

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

It doesn't really matter, as the pluginKey is private to the package providing a plugin type. It's only required for them to be 'unique'. We could even use a generated UUID.

@andrewkroh
Copy link
Member

jenkins, test it

- requires linux, go1.8 and cgo
- plugins export a `Bundle` symbol of type `map[string][]interface{}`.
  The `key` is special to every pluggable module in beats
- all pluggable beats modules provide a `PluginX` function to create a valid
  bundle
- using `plugin.Bundle`, multiple bundles can be combined into one. A bundle
  can contain plugins for different beats and be loaded by all these different
  beats.
- plugins can be loaded via CLI only using the `-plugin <path>` flag
- add plugin support for:
  - libbeat outputs
  - libbeat processors
  - packetbeat protocol analyzers
  - metricbeat modules
  - heartbeat monitors

See PR elastic#3217 for more details
@ruflin ruflin merged commit 760290f into elastic:master Jan 13, 2017
@urso urso deleted the exp/plugins branch February 19, 2019 18:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
discuss Issue needs further discussion. review v6.0.0-GA
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants