-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Make DataType a separate type within Component #10069
Make DataType a separate type within Component #10069
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #10069 +/- ##
==========================================
- Coverage 91.65% 91.63% -0.02%
==========================================
Files 356 356
Lines 16843 16855 +12
==========================================
+ Hits 15437 15445 +8
- Misses 1063 1067 +4
Partials 343 343 ☔ View full report in Codecov by Sentry. |
func mustNewDataType(strType string) DataType { | ||
return MustNewType(strType) | ||
} | ||
type DataType 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 prefer to use a struct here to disallow users to create new DataType's
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.
Hmmm... I understand that's a risk. I've tried to mitigate it with the logic in pipelines/config.go that make sure its a member of signalNameToDataType.
Do you think its still worth wrapping it in a struct?
@@ -109,18 +109,23 @@ func callValidateIfPossible(v reflect.Value) error { | |||
return nil | |||
} | |||
|
|||
// Type is the component type as it is used in the config. | |||
type Type struct { | |||
type Type 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.
Why is this needed?
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.
In order to keep ID basically the same, we make Type an interface and implement it with ComponentType and DataType
e6b47a3
to
38a2e96
Compare
} | ||
|
||
// ComponentType is the component type as it is used in the config. | ||
type ComponentType struct { //revive:disable-line:exported |
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 is the linter directive needed?
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 linter doesn't like it when type FooBar is in a package Foo. It thinks Foo/FooBar is annoying to pronounce. I think in this case having component/ComponentType is a good exemption.
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 agree with the linter here. The difference between component.Type
and component.ComponentType
is very not obvious at a glance.
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.
// DataTypeFromSignal takes in a string of a datatype, and returns a DataType and a bool. | ||
// The bool is set to true if the string corresponds to a supported DataType, else it is False. | ||
// if there is a matching DataType, it returns the matching DataType enum. If not, it returns an empty string. | ||
func DataTypeFromSignal(s string) (DataType, 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.
I would instead implement UnmarshalText
for 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.
good idea!
# These lines will be padded with 2 spaces and then inserted directly into the document. | ||
# Use pipe (|) for multiline entries. | ||
subtext: | | ||
Creates ComponentType and DataType - ComponentType represents the names of components and DataType is an enum for Traces,Logs, and Metrics (and future signal types!). |
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.
ComponentType represents the names of components
I think we need to be very precise here not to overload the words type or name. Currently, for components we use ID to refer to type[/name]
. So when you say "names of components", I think this should actually say Type of component. It may be helpful to give a couple clear examples for users as well. "The type of component, e.g. otlp
, filelog
"
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 great feedback - my use of the word name didn't account for name actually being embedded within ID
@@ -109,18 +110,26 @@ func callValidateIfPossible(v reflect.Value) error { | |||
return nil | |||
} | |||
|
|||
// Type is the component type as it is used in the config. | |||
type Type struct { | |||
// Type represents the names of receivers (otlp, filelog, etc), |
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.
Same here
} | ||
|
||
// ComponentType is the component type as it is used in the config. | ||
type ComponentType struct { //revive:disable-line:exported |
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 agree with the linter here. The difference between component.Type
and component.ComponentType
is very not obvious at a glance.
func mustNewDataType(strType string) DataType { | ||
return MustNewType(strType) | ||
} | ||
type DataType 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.
If we're going to rework all of this, it would make sense to me to move data type into a different package, since things other than components can be types.
This PR seems to add complexity but I'm not clear what the benefit is. The original issue suggested moving DataType (logs, metrics, traces) out of the Component package, which I agree with. IMO, if we're reworking this, the most intuitive model is to have |
<!--Ex. Fixing a bug - Describe the bug and how this fixes the issue. Ex. Adding a feature - Explain what this achieves.--> #### Description `newBaseExporter` needs a `DataType` - up until now we've been passing in a `Type`. In preparation of splitting `DataType` and `Type`, pass in a real `DataType`. <!-- Issue number if applicable --> #### Link to tracking issue related to #9429 In preparation for #10069
A |
…#10128) <!--Ex. Fixing a bug - Describe the bug and how this fixes the issue. Ex. Adding a feature - Explain what this achieves.--> #### Description In an upcoming PR, I change Type to be an interface. This means the zero value of Type will be nil - which will cause this test to fail. Initializing ID instead of relying on the zero value fixes this <!-- Issue number if applicable --> #### Link to tracking issue related to #9429 <!--Please delete paragraphs that you did not use before submitting.--> In preparation for #10069
Ah, you're right, crossed wires. My suggested alternative was hastily written. I am primarily concerned about the proposal to have both |
I totally agree! I have a followup PR planned where I will move it out. Didn't make sense for me to do it all in one PR. I also plan to rename it to
I can totally see the concern here - |
**Description:** <Describe what has changed.> In open-telemetry/opentelemetry-collector#10069, I am making Type an interface. This means the zero value of Type will be nil - which will cause this test to fail. Initializing ID instead of relying on the zero value fixes this --------- Co-authored-by: Pablo Baeyens <pbaeyens31+github@gmail.com> Co-authored-by: Bogdan Drutu <bogdandrutu@gmail.com>
I think something I should have done in the beginning is lay out the problem and how I arrived at this solution: If we want to make DataType its own type - we have to adjust Type somehow. As Pablo said:
We have to somehow change either ID or Type to make this work. I considered a few options:
I hope this explains how I decided on approach 3. Is this approach something that everyone agrees with? If we can get to consensus on the overall approach I can finish iterating on this PR and get it to a mergeable state. |
**Description:** <Describe what has changed.> In open-telemetry/opentelemetry-collector#10069, I am making Type an interface. This means the zero value of Type will be nil - which will cause this test to fail. Initializing ID instead of relying on the zero value fixes this --------- Co-authored-by: Pablo Baeyens <pbaeyens31+github@gmail.com> Co-authored-by: Bogdan Drutu <bogdandrutu@gmail.com>
From the Collector stability discussion, we decided to first focus in if the approach of having an interface and two types that implement said interface (the type for component types and the type for signal types) makes sense, and decide on what names to use for said types/interfaces later. |
This feels like a pretty confusing topic, so I'm gonna try to define a bunch of terms for use in this comment. Currently we have the following important terms:
With those terms defined, I want to poke at why we use Importantly I think these two identifiers need their own naming restrictions. A I feel we'd really benefit from stopping the use of With this solution we have no more overlap between names and no mixing of concepts in the structs. I will admit that I only took a brief look through |
@TylerHelmuth's analysis makes sense to me. There is commonality in the structure of
I could be forgetting some details but I think it may be less complicated than the changes in this PR. |
I also think that the implementation of a |
Hey @TylerHelmuth, thanks for the comprehensive feedback! I can implement this other option - there will be a bunch of changes in pipeline and connector code as well as perhaps some API changes - but this is probably the right time to make those changes! You also make a good point of the pipeline API silently accepting I think it'll be better if I close this PR and open a different PR for this change. |
I agree with this! My original plan was to
I will say I'm not sure |
…etry#10127) <!--Ex. Fixing a bug - Describe the bug and how this fixes the issue. Ex. Adding a feature - Explain what this achieves.--> #### Description `newBaseExporter` needs a `DataType` - up until now we've been passing in a `Type`. In preparation of splitting `DataType` and `Type`, pass in a real `DataType`. <!-- Issue number if applicable --> #### Link to tracking issue related to open-telemetry#9429 In preparation for open-telemetry#10069
…open-telemetry#10128) <!--Ex. Fixing a bug - Describe the bug and how this fixes the issue. Ex. Adding a feature - Explain what this achieves.--> #### Description In an upcoming PR, I change Type to be an interface. This means the zero value of Type will be nil - which will cause this test to fail. Initializing ID instead of relying on the zero value fixes this <!-- Issue number if applicable --> #### Link to tracking issue related to open-telemetry#9429 <!--Please delete paragraphs that you did not use before submitting.--> In preparation for open-telemetry#10069
Addresses #9429
There were several approaches to implementing this, but I decided to make Type an interface that continues to be embedded in ID.
I split Type into ComponentType and DataType - ComponentType represents the names of components and DataType is an enum for Traces, Logs, and Metrics.
This keeps ID with the same basic API, which eases this transition. The largest change is
NewType
will automatically create a DataType instead of ComponentType for the strings "traces", "logs", and "metrics". In addition, ID's zero value now contains a null value for Type - since it is now an interface.