-
Notifications
You must be signed in to change notification settings - Fork 451
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
Replace pulling metrics port with using direct config #2856
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix' | ||
change_type: enhancement | ||
|
||
# The name of the component, or a single word describing the area of concern, (e.g. collector, target allocator, auto-instrumentation, opamp, github action) | ||
component: collector | ||
|
||
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). | ||
note: Changes metric port logic to use intermediary struct. | ||
|
||
# One or more tracking issues related to the change | ||
issues: [2603] | ||
|
||
# (Optional) One or more lines of additional information to render under the primary note. | ||
# These lines will be padded with 2 spaces and then inserted directly into the document. | ||
# Use pipe (|) for multiline entries. | ||
subtext: |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,10 +30,10 @@ type AnyConfig struct { | |
} | ||
|
||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. | ||
func (in *AnyConfig) DeepCopyInto(out *AnyConfig) { | ||
*out = *in | ||
if in.Object != nil { | ||
in, out := &in.Object, &out.Object | ||
func (c *AnyConfig) DeepCopyInto(out *AnyConfig) { | ||
*out = *c | ||
if c.Object != nil { | ||
in, out := &c.Object, &out.Object | ||
*out = make(map[string]interface{}, len(*in)) | ||
for key, val := range *in { | ||
(*out)[key] = val | ||
|
@@ -42,12 +42,12 @@ func (in *AnyConfig) DeepCopyInto(out *AnyConfig) { | |
} | ||
|
||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AnyConfig. | ||
func (in *AnyConfig) DeepCopy() *AnyConfig { | ||
if in == nil { | ||
func (c *AnyConfig) DeepCopy() *AnyConfig { | ||
if c == nil { | ||
return nil | ||
} | ||
out := new(AnyConfig) | ||
in.DeepCopyInto(out) | ||
c.DeepCopyInto(out) | ||
return out | ||
} | ||
|
||
|
@@ -88,7 +88,7 @@ type Config struct { | |
} | ||
|
||
// Yaml encodes the current object and returns it as a string. | ||
func (c Config) Yaml() (string, error) { | ||
func (c *Config) Yaml() (string, error) { | ||
var buf bytes.Buffer | ||
yamlEncoder := yaml.NewEncoder(&buf) | ||
yamlEncoder.SetIndent(2) | ||
|
@@ -98,16 +98,8 @@ func (c Config) Yaml() (string, error) { | |
return buf.String(), nil | ||
} | ||
|
||
type Service struct { | ||
Extensions *[]string `json:"extensions,omitempty" yaml:"extensions,omitempty"` | ||
// +kubebuilder:pruning:PreserveUnknownFields | ||
Telemetry *AnyConfig `json:"telemetry,omitempty" yaml:"telemetry,omitempty"` | ||
// +kubebuilder:pruning:PreserveUnknownFields | ||
Pipelines AnyConfig `json:"pipelines" yaml:"pipelines"` | ||
} | ||
|
||
// Returns null objects in the config. | ||
func (c Config) nullObjects() []string { | ||
func (c *Config) nullObjects() []string { | ||
var nullKeys []string | ||
if nulls := hasNullValue(c.Receivers.Object); len(nulls) > 0 { | ||
nullKeys = append(nullKeys, addPrefix("receivers.", nulls)...) | ||
|
@@ -135,6 +127,57 @@ func (c Config) nullObjects() []string { | |
return nullKeys | ||
} | ||
|
||
type Service struct { | ||
Extensions *[]string `json:"extensions,omitempty" yaml:"extensions,omitempty"` | ||
// +kubebuilder:pruning:PreserveUnknownFields | ||
Telemetry *AnyConfig `json:"telemetry,omitempty" yaml:"telemetry,omitempty"` | ||
// +kubebuilder:pruning:PreserveUnknownFields | ||
Pipelines AnyConfig `json:"pipelines" yaml:"pipelines"` | ||
} | ||
|
||
// MetricsConfig comes from the collector. | ||
type MetricsConfig struct { | ||
// Level is the level of telemetry metrics, the possible values are: | ||
// - "none" indicates that no telemetry data should be collected; | ||
// - "basic" is the recommended and covers the basics of the service telemetry. | ||
// - "normal" adds some other indicators on top of basic. | ||
// - "detailed" adds dimensions and views to the previous levels. | ||
Level string `json:"level,omitempty" yaml:"level,omitempty"` | ||
|
||
// Address is the [address]:port that metrics exposition should be bound to. | ||
Address string `json:"address,omitempty" yaml:"address,omitempty"` | ||
} | ||
|
||
// Telemetry is an intermediary type that allows for easy access to the collector's telemetry settings. | ||
type Telemetry struct { | ||
Metrics MetricsConfig `json:"metrics,omitempty" yaml:"metrics,omitempty"` | ||
|
||
// Resource specifies user-defined attributes to include with all emitted telemetry. | ||
// Note that some attributes are added automatically (e.g. service.version) even | ||
// if they are not specified here. In order to suppress such attributes the | ||
// attribute must be specified in this map with null YAML value (nil string pointer). | ||
Resource map[string]*string `json:"resource,omitempty" yaml:"resource,omitempty"` | ||
} | ||
|
||
// GetTelemetry serves as a helper function to access the fields we care about in the underlying telemetry struct. | ||
// This exists to avoid needing to worry extra fields in the telemetry struct. | ||
func (s *Service) GetTelemetry() *Telemetry { | ||
if s.Telemetry == nil { | ||
return nil | ||
} | ||
// Convert map to JSON bytes | ||
jsonData, err := json.Marshal(s.Telemetry) | ||
if err != nil { | ||
return nil | ||
} | ||
t := &Telemetry{} | ||
// Unmarshal JSON into the provided struct | ||
if err := json.Unmarshal(jsonData, t); err != nil { | ||
return nil | ||
} | ||
Comment on lines
+169
to
+177
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you think we should check this in the admission webhook, so we can be reasonably sure it works? Or is it better to be more permissive and then simply ignore functionality that depends on this value? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think its better to be permissive IMO, it's much closer to what we do today (i.e. it's fine if someone doesn't set this)... I think we could maybe introduce a "strict" operator mode as part of this issue's resolution There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was thinking about the situation where the parsing fails, that is, the format is inconsistent with what we expect. I think, other than a breaking change in the respective collector core package, this would be safe to do. With that said, breaking changes in collector core packages can happen, and it'd be unfortunate for us to need to always do a breaking change in the CRD as a result. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah I think once everything in the collector is marked stable we could do this... they're working on it! |
||
return t | ||
} | ||
|
||
func hasNullValue(cfg map[string]interface{}) []string { | ||
var nullKeys []string | ||
for k, v := range cfg { | ||
|
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
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 wonder if we should have a method on Config to convert it to a more constrained and strictly typed struct containing only information we make use of in the operator. Not a request to do it in this PR, just a thought.
On a separate note, should we cache this to avoid the marshalling and unmarshalling whenever it's accessed?
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 that feels like a good follow up to this – both of those are things we should figure out after we simplify all of the methods that use only maps and strings. Caching would get simpler if we only pass around that constrained struct (because we would probably only create it once)