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

[pkg/stanza] add buildInfo for operator(#21794) #26664

Conversation

yutingcaicyt
Copy link
Contributor

@yutingcaicyt yutingcaicyt commented Sep 13, 2023

Description:
For adding the telemetry for filelog receiver, the related info (CreateSettings) needs to be delivered from factory to operator. So I add a BuildInfoInternal struct to do this first. And then the operators have the ability to add the metrics themselves.

Link to tracking Issue: #21794

Copy link
Member

@djaglowski djaglowski left a comment

Choose a reason for hiding this comment

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

Thanks for putting this together @yutingcaicyt.

I think this demonstrates what the plumbing may look like, which is helpful. I've left a few comments about this.

However, before we move forward with anything, I'd really like to see what it looks like to actually use the new parameters that we're passing through. This will help to validate what we actually need to pass through and also to inform how we should manage the addition complexity.

@@ -16,6 +17,11 @@ type Config struct {
Builder
}

type BuildInfoInternal struct {
Logger *zap.SugaredLogger
CreateSettings *rcvr.CreateSettings
Copy link
Member

Choose a reason for hiding this comment

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

I think in the end we cannot directly use receiver.CreateSettings because there are legitimate use cases for this codebase outside of receivers.

The struct contains several fields. Do you know which of these we actually need?

type CreateSettings struct {
	// ID returns the ID of the component that will be created.
	ID component.ID

	component.TelemetrySettings

	// BuildInfo can be used by components for informational purposes.
	BuildInfo component.BuildInfo
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

From my understanding, we need "ID" and "component.TelemetrySettings" to add the telemetry into the operator.

@@ -16,6 +17,11 @@ type Config struct {
Builder
}

type BuildInfoInternal struct {
Copy link
Member

Choose a reason for hiding this comment

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

Depending on how many individual parts of CreateSettings we need, I may be preferable to pass in each parameter separately, rather than have a wrapper like this.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I agree to only pass the parts of CreateSettings that we need, but I think a wrapper is also needed. I raised some questions in the comment below.

func (c Config) Build(logger *zap.SugaredLogger) (operator.Operator, error) {
inputOperator, err := c.InputConfig.Build(logger)
func (c Config) Build(buildInfo *operator.BuildInfoInternal) (operator.Operator, error) {
inputOperator, err := c.InputConfig.Build(buildInfo.Logger)
Copy link
Member

Choose a reason for hiding this comment

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

Many operators rely on these composable helper structs. It's hard to say without seeing how we are using the CreateSettings, but I suspect we should pass it through and have the shared structs manage as much of the additional complexity as possible.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In my opinion, shared structs do introduce some additional complexity, but they can also facilitate iteration or refactoring. Take the example of adding telemetry, we may need another temporary parameter like "useOtel" If we have the struct, the parameter can easily pass it through without modifying all implementations of the "Builder" interface. Or there will be other parameters that need to be passed through for some new features in the future. Without the struct, all these changes would be very difficult. How do you think about these situations?

Copy link
Member

Choose a reason for hiding this comment

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

I can appreciate the utility of what you are suggesting but I think there is a tradeoff that we have additional complexity which may never be needed. Generally in this repo we strongly prefer to include only what is necessary, even though it occasionally means we need to make a change later.

Copy link
Contributor Author

@yutingcaicyt yutingcaicyt Sep 15, 2023

Choose a reason for hiding this comment

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

So you mean that we can change the interface like this?

func (c Config) Build(logger *zap.SugaredLogger, ID component.ID, settings component.TelemetrySettings, telemetryUseOtel bool) (operator.Operator, error)

Does this really reduce much complexity compared to using struct?

Copy link
Member

Choose a reason for hiding this comment

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

So you mean that we can change the interface like this?

func (c Config) Build(logger *zap.SugaredLogger, ID component.ID, settings component.TelemetrySettings, telemetryUseOtel bool) (operator.Operator, error)

If in the future we have a need for additional parameters, they will either be required or optional. If they are required, this will be a breaking change anyways. If they are optional (or have reasonable defaults), then there are other ways to handle this beside breaking the signature. We can add variadic options or alternate signatures.

Does this really reduce much complexity compared to using struct?

Why do functions allow multiple parameters? Obviously there are tradeoffs regarding complexity.

In any case, I will continue to push for minimal complexity in the current implementation. To that end, I think we are two steps ahead of ourselves because we haven't even demonstrated how any of the proposed parameters will actually be used.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, let's first determine what parameters need to be passed. For creating the telemetry, the "component.TelemetrySettings" is needed to get the "metricsLevel" and "MeterProvider". The "ID" of the component is also needed to set the attribute of the metric. So I think "component.TelemetrySettings" and "ID" are required parameters. And I noticed that the internal metric of the collector will use this "UseOtelForInternalMetricsfeatureGate" to determine whether to use otel, if we follow the rule, a parameter "useOtel bool" is optional. In conclusion, "component.TelemetrySettings" and "ID" are required, "useOtel" is opional. WDYT?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Member

Choose a reason for hiding this comment

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

Please update the PR to demonstrate usage of the parameters.

@yutingcaicyt yutingcaicyt force-pushed the feature/addlogdelaymetric branch from 9f046c4 to a34ba3e Compare September 26, 2023 02:46
@yutingcaicyt
Copy link
Contributor Author

I added some parameters and explaination to the function.

@yutingcaicyt
Copy link
Contributor Author

@djaglowski

Copy link
Member

@djaglowski djaglowski left a comment

Choose a reason for hiding this comment

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

I've mentioned all of the following elsewhere but to reiterate my requested changes:

  1. Demonstrate actual usage of the information which you propose to pass through. Concrete usage will validate that we actually need these and inform the design process.
  2. Pass the necessary info through to helper structs so that we can centralize management. e.g. InputConfig.Build.
  3. BuildInfoInternal struct is likely unnecessary. We can reassess when items 1 and 2 are completed.

@yutingcaicyt yutingcaicyt force-pushed the feature/addlogdelaymetric branch from a34ba3e to aa57ee7 Compare October 10, 2023 07:38
@yutingcaicyt yutingcaicyt force-pushed the feature/addlogdelaymetric branch from aa57ee7 to 53fa50f Compare October 10, 2023 07:48
@yutingcaicyt
Copy link
Contributor Author

I understand what you mean, but every change to the interface requires a huge amount of work, so I want to wait until we confirm the parameters passed before making unified changes.
I have added a metric example, which includes the parameters used. In general, I think CreateSettings and telemetryUseOtel are needed. All properties in createSettings may be used by metric, and telemetryUseOtel is used to control otel or openCensus to enable.
So I think only the two parameters need to be passed through.

type fileConsumerTelemetry struct {
level configtelemetry.Level
detailed bool
useOtel bool
Copy link
Member

Choose a reason for hiding this comment

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

@open-telemetry/collector-approvers, do we expect to support a useOtel throughout the collector? Would it be reasonable to assume we're using OTel in new instrumentation at this point?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Do we need to discuss this here? I feel that whether to use otel should be unified throughout the project.

Copy link
Member

Choose a reason for hiding this comment

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

I'd like a decision. I'll bring it up at Wednesday's SIG

Copy link
Member

Choose a reason for hiding this comment

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

Discussed this in SIG today. The consensus from core maintainers is to support only OpenCensus metrics for now. We plan to provide a bridge once open-telemetry/opentelemetry-collector#7454 is complete. Therefore, let's remove the flag.

Copy link
Contributor

github-actions bot commented Nov 2, 2023

This PR was marked stale due to lack of activity. It will be closed in 14 days.

@github-actions github-actions bot added the Stale label Nov 2, 2023
Copy link
Contributor

Closed as inactive. Feel free to reopen if this PR is still being worked on.

@github-actions github-actions bot closed this Nov 16, 2023
@yutingcaicyt
Copy link
Contributor Author

I'm sorry that I haven't dealt with this PR for a long time due to some personal issues. To confirm that the changes are valid, I want to know whether opencensus is still used by default.

@djaglowski
Copy link
Member

I'm sorry that I haven't dealt with this PR for a long time due to some personal issues. To confirm that the changes are valid, I want to know whether opencensus is still used by default.

@codeboten, could you advise here?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants