-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Changes from 13 commits
03848cd
dcece16
3985797
78519a7
0264ff2
cdd368a
88fee9c
6a72d0e
c1f040b
554abb8
708a18d
52e2091
38a2e96
c6b2623
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,28 @@ | ||
# Use this changelog template to create an entry for release notes. | ||
|
||
# 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. otlpreceiver) | ||
component: component | ||
|
||
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). | ||
note: "Change Type to an interface, introduce the new types ComponentType and DataType now implement it." | ||
|
||
# One or more tracking issues or pull requests related to the change | ||
issues: [9429] | ||
|
||
# (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: | | ||
Creates ComponentType and DataType - ComponentType represents the names of components and DataType is an enum for Traces,Logs, and Metrics (and future signal types!). | ||
|
||
NewType will now 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." | ||
|
||
# Optional: The change log or logs in which this entry should be included. | ||
# e.g. '[user]' or '[user, api]' | ||
# Include 'user' if the change is relevant to end users. | ||
# Include 'api' if there is a change to a library API. | ||
# Default: '[user]' | ||
change_logs: ['api'] |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,7 @@ | |
package component // import "go.opentelemetry.io/collector/component" | ||
|
||
import ( | ||
"encoding" | ||
"fmt" | ||
"reflect" | ||
"regexp" | ||
|
@@ -109,18 +110,26 @@ | |
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 commentThe reason will be displayed to describe this comment to others. Learn more. Same here |
||
// processors (batch, memory_limit, etc), or exporters (debug, rabbitmq) | ||
// It also includes the DataType - things like "metrics", "traces", "logs" | ||
type Type interface { | ||
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. Why is this needed? 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. In order to keep ID basically the same, we make Type an interface and implement it with ComponentType and DataType
ankitpatel96 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
fmt.Stringer | ||
encoding.TextMarshaler | ||
} | ||
|
||
// 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 commentThe 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 commentThe 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 commentThe reason will be displayed to describe this comment to others. Learn more. I agree with the linter here. The difference between 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. |
||
name string | ||
} | ||
|
||
// String returns the string representation of the type. | ||
func (t Type) String() string { | ||
func (t ComponentType) String() string { | ||
return t.name | ||
} | ||
|
||
// MarshalText marshals returns the Type name. | ||
func (t Type) MarshalText() ([]byte, error) { | ||
func (t ComponentType) MarshalText() ([]byte, error) { | ||
return []byte(t.name), nil | ||
} | ||
|
||
|
@@ -135,14 +144,18 @@ | |
// - have at least one character, | ||
// - start with an ASCII alphabetic character and | ||
// - can only contain ASCII alphanumeric characters and '_'. | ||
// If the type string is a supported DataType, one is returned. Otherwise, a ComponentType is returned. | ||
func NewType(ty string) (Type, error) { | ||
if len(ty) == 0 { | ||
return Type{}, fmt.Errorf("id must not be empty") | ||
return ComponentType{}, fmt.Errorf("id must not be empty") | ||
} | ||
if !typeRegexp.MatchString(ty) { | ||
return Type{}, fmt.Errorf("invalid character(s) in type %q", ty) | ||
return ComponentType{}, fmt.Errorf("invalid character(s) in type %q", ty) | ||
} | ||
return Type{name: ty}, nil | ||
if dataType, ok := DataTypeFromSignal(ty); ok { | ||
return dataType, nil | ||
} | ||
return ComponentType{name: ty}, nil | ||
} | ||
|
||
// MustNewType creates a type. It panics if the type is invalid. | ||
|
@@ -160,20 +173,40 @@ | |
|
||
// DataType is a special Type that represents the data types supported by the collector. We currently support | ||
// collecting metrics, traces and logs, this can expand in the future. | ||
type DataType = Type | ||
|
||
func mustNewDataType(strType string) DataType { | ||
return MustNewType(strType) | ||
} | ||
type DataType string | ||
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 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 commentThe 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? 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. 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. |
||
|
||
// Currently supported data types. Add new data types here when new types are supported in the future. | ||
var ( | ||
// DataTypeTraces is the data type tag for traces. | ||
DataTypeTraces = mustNewDataType("traces") | ||
DataTypeTraces DataType = "traces" | ||
|
||
// DataTypeMetrics is the data type tag for metrics. | ||
DataTypeMetrics = mustNewDataType("metrics") | ||
DataTypeMetrics DataType = "metrics" | ||
|
||
// DataTypeLogs is the data type tag for logs. | ||
DataTypeLogs = mustNewDataType("logs") | ||
DataTypeLogs DataType = "logs" | ||
|
||
signalNameToDataType = map[string]DataType{ | ||
"logs": DataTypeLogs, | ||
"metrics": DataTypeMetrics, | ||
"traces": DataTypeTraces, | ||
} | ||
) | ||
|
||
func (dt DataType) String() string { | ||
return string(dt) | ||
} | ||
func (dt DataType) MarshalText() (text []byte, err error) { | ||
return []byte(dt), nil | ||
} | ||
|
||
// 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 commentThe reason will be displayed to describe this comment to others. Learn more. I would instead implement 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. good idea! |
||
val, ok := signalNameToDataType[s] | ||
if !ok { | ||
return "", ok | ||
} | ||
return val, ok | ||
} |
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 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