-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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
Add builder support for autodiscover and annotations builder #6408
Conversation
Since this is a community submitted pull request, a Jenkins build has not been kicked off automatically. Can an Elastic organization member please verify the contents of this patch and then kick off a build manually? |
return result | ||
} | ||
|
||
func ApplyConfigTemplate(event bus.Event, configs []*common.Config) []*common.Config { |
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.
exported function ApplyConfigTemplate should have comment or be unexported
var Registry = NewRegistry() | ||
|
||
// NewRegistry creates and returns a new Registry | ||
func NewRegistry() *registry { |
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.
exported func NewRegistry returns unexported type *autodiscover.registry, which can be annoying to use
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.
im not sure what to do about this :)
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.
This could return an interface implemented by *register, wdyt?
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.
register doesnt implement any interfaces at the moment. i think even mb registry and few others will have the same hound violation.
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.
works for me 😄
return result | ||
} | ||
|
||
func GetContainerAnnotationsWithPrefix(annotations map[string]string, prefix, container, key string) map[string]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.
exported function GetContainerAnnotationsWithPrefix should have comment or be unexported
return IsNoOp(annotations, fmt.Sprintf("%s.%s", prefix, container)) | ||
} | ||
|
||
func GetAnnotationsWithPrefix(annotations map[string]string, prefix, key string) map[string]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.
exported function GetAnnotationsWithPrefix should have comment or be unexported
return noop | ||
} | ||
|
||
func IsContainerNoOp(annotations map[string]string, prefix, container string) bool { |
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.
exported function IsContainerNoOp should have comment or be unexported
libbeat/autodiscover/builder.go
Outdated
return builder(c) | ||
} | ||
|
||
func (b Builders) GetConfig(event bus.Event) []*common.Config { |
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.
exported method Builders.GetConfig should have comment or be unexported
libbeat/autodiscover/builder.go
Outdated
|
||
type Builders []Builder | ||
|
||
type BuilderConstructor func(*common.Config) (Builder, 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.
exported type BuilderConstructor should have comment or be unexported
libbeat/autodiscover/builder.go
Outdated
CreateConfig(event bus.Event) []*common.Config | ||
} | ||
|
||
type Builders []Builder |
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.
exported type Builders should have comment or be unexported
libbeat/autodiscover/builder.go
Outdated
"github.com/elastic/beats/libbeat/logp" | ||
) | ||
|
||
type Builder interface { |
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.
exported type Builder should have comment or be unexported
filebeat/autodiscover/include.go
Outdated
package autodiscover | ||
|
||
import ( | ||
_ "github.com/elastic/beats/filebeat/autodiscover/builder/log_annotations" |
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.
a blank import should be only in a main or test package, or have a comment justifying it
105041b
to
e9e3a84
Compare
metricbeat/autodiscover/include.go
Outdated
package autodiscover | ||
|
||
import ( | ||
_ "github.com/elastic/beats/metricbeat/autodiscover/builder/metric_annotations" |
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.
a blank import should be only in a main or test package, or have a comment justifying it
func (m *metricAnnotations) getTimeout(annotations map[string]string, container string) string { | ||
if tout := builder.GetContainerAnnotationAsString(annotations, m.Prefix, container, timeout); tout != "" { | ||
return tout | ||
} else { |
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.
if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
func (m *metricAnnotations) getPeriod(annotations map[string]string, container string) string { | ||
if ival := builder.GetContainerAnnotationAsString(annotations, m.Prefix, container, period); ival != "" { | ||
return ival | ||
} else { |
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.
if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
// Prometheus stats can be explicitly configured if need be. | ||
if module == "prometheus" { | ||
return []string{"collector"} | ||
} else { |
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.
if block ends with a return statement, so drop this else and outdent its block
Prefix string | ||
} | ||
|
||
func NewMetricAnnotations(cfg *common.Config) (autodiscover.Builder, 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.
exported function NewMetricAnnotations should have comment or be unexported
ssl = "ssl" | ||
|
||
default_timeout = "3s" | ||
default_interval = "1m" |
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.
don't use underscores in Go names; const default_interval should be defaultInterval
timeout = "timeout" | ||
ssl = "ssl" | ||
|
||
default_timeout = "3s" |
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.
don't use underscores in Go names; const default_timeout should be defaultTimeout
@@ -0,0 +1,141 @@ | |||
package metric_annotations |
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.
don't use an underscore in package name
@@ -0,0 +1,11 @@ | |||
package metric_annotations |
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.
don't use an underscore in package name
Thank you for working on this @vjsamuel! 🎉 Sorry for the delay answering here. Builders interface is looking great! I have some thoughts/questions:
That's why I think we should introduce the concept of hints to Autodiscover events. The main idea is that each provider can fill a set of well-known hint fields, that builders can then use to build configurations from events coming from any provider. Example of a Docker event:
Putting the responsibility of extracting hints in the provider sounds good, as it will allow us to implement the hinting system in many platforms. What do you think? |
@exekias i have the graphite annotations builder coming up in a next PR once this structure is finalized and merged. hence simply |
We had a chat about this, code is looking great, we agreed on doing some changes:
|
func (m *metricAnnotations) getTimeout(hints common.MapStr) string { | ||
if tout := builder.GetHintString(hints, m.Key, timeout); tout != "" { | ||
return tout | ||
} else { |
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.
if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
func (m *metricAnnotations) getPeriod(hints common.MapStr) string { | ||
if ival := builder.GetHintString(hints, m.Key, period); ival != "" { | ||
return ival | ||
} else { |
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.
if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
Key string | ||
} | ||
|
||
// Build a new metrics annotation builder |
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.
comment on exported function NewMetricAnnotations should be of the form "NewMetricAnnotations ..."
libbeat/common/kubernetes/types.go
Outdated
return cID | ||
} | ||
|
||
// GetContainerID parses the container ID to get the actual ID 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.
comment on exported method PodContainerStatus.GetContainerIDWithRuntime should be of the form "GetContainerIDWithRuntime ..."
} | ||
} | ||
|
||
func (c *Config) Validate() { |
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.
exported method Config.Validate should have comment or be unexported
} | ||
} | ||
|
||
func (c *Config) Validate() { |
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.
exported method Config.Validate should have comment or be unexported
hIface, ok := event["hints"] | ||
if !ok { | ||
return config | ||
} else { |
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.
if block ends with a return statement, so drop this else and outdent its block
Config []*common.Config | ||
} | ||
|
||
// Construct a log annotations builder |
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.
comment on exported function NewLogAnnotations should be of the form "NewLogAnnotations ..."
@@ -0,0 +1,98 @@ | |||
package log_annotations |
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.
don't use an underscore in package name
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.
This is getting in shape!, I left a few comments, let's discuss them.
@@ -10,6 +10,8 @@ import ( | |||
"github.com/elastic/beats/libbeat/common/bus" | |||
|
|||
"github.com/stretchr/testify/assert" | |||
|
|||
"github.com/elastic/beats/libbeat/autodiscover/template" |
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.
this import should go with the rest of github.com/elastic/beats/libbeat/
) | ||
|
||
func init() { | ||
autodiscover.Registry.AddBuilder("log.annotations", NewLogAnnotations) |
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.
Perhaps it should be just logs
?
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 thought of the same. will change it as well.
libbeat/autodiscover/builder.go
Outdated
} | ||
|
||
// ConstructBuilder reads provider configuration and instatiate one | ||
func (r *registry) ConstructBuilder(c *common.Config) (Builder, 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 we normally use Create
word for constructors
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 previous constructor for provider was BuildProvider
. It seemed redundant to have BuildBuilder
. Thats why I made this as Construct. I ll change.
libbeat/autodiscover/provider.go
Outdated
providers: make(map[string]ProviderBuilder, 0), | ||
} | ||
} | ||
type ProviderBuilder func(bus.Bus, *template.Mapper, Builders, *common.Config) (Provider, 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.
What if the provider doesn't support builders? (for instance, it doesn't give you any hints). I'm more comfortable with the current approach, letting the provider decide what it supports (templates, builders...) and plug it in.
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. sure. i will revert this guy. makes it easier for submitting more PRs in parallel :)
"id": containerIDs[c.Name], | ||
"name": c.Name, | ||
"image": c.Image, | ||
// Without this check there would be overlapping configurations with and without ports. |
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'm ok with this change but could you open it in a separate PR? this one could grow a lot
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 have removed this. i will add it in once this PR is merged.
@@ -154,6 +155,44 @@ func (p *Provider) publish(event bus.Event) { | |||
// Try to match a config | |||
if config := p.templates.GetConfig(event); config != nil { | |||
event["config"] = config | |||
} else { |
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.
this code path should be similar p.templates.GetConfig
, I would extract all the logic to generate hints from the event, and then call p.builders.GetConfig
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.
it may be a bit difficult as handling is provider specific unlike templates. WDYT?
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
df2ed5e
to
df06112
Compare
df06112
to
dd889e9
Compare
labelMap := common.MapStr{} | ||
for k, v := range container.Labels { | ||
labelMap[k] = v | ||
} |
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 did you remove this? this was a fix introduced a few days ago, if labels is not a MapStr autodiscover conditions won't work on 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.
Thank you so much @vjsamuel! 🎉 🎉 let's get this in, we may want to rethink some config options, but we can do it in followup PRs
jenkins, test it please |
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.
This PR adds builder support for Beats autodiscover along with an annotations builder for filebeat and metricbeat.
Prefix for logs would be
co.elastic.logs/
andco.elastic.metrics/
for metrics. Sample config:the
log.annotations
takes a list of templatized configurations that can be used to build input configs. The default is a simple docker input.Annotations that are accepted for logs are
/disable
which would disable the input creation and hence log tailing,/include_lines
,/exclude_lines
,/multiline.*
where*
would bepattern
,negate
,match
etc.If
co.elastic.logs/*
is used then the annotation is honored at a pod level. If `co.elastic.logs./* is used then it is honored at the container level. The latter always takes precedence.The
metric.annotations
builder can be used to auto discover metric endpoints. Sample annotation set:Sample config:
This would spin up a prometheus collector metricset. Other supported annotations are:
co.elastic.metrics.<container>/*
can be used to configure entries at a container level.The annotations builder are provider agnostic hence both docker and kubernetes can leverage the same. Both providers will pass to the builder a provider agnostic
bus.Event
which has:Test cases are still WIP. Kindly review the overall structure as it is a big change. The above said will be added to the same PR to complete the builder flow for polling use-cases.