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

Add singleton flags to factories and standardize attributes #12057

Conversation

djaglowski
Copy link
Member

This PR is an extension of #11344 that addresses #11814.

Major changes:

  • Add a Metadata() method to receiver.Factory, exporter.Factory and connector.Factory (processor.Factory excluded intentionally as described in Loggers for shared components should not report signal type. #11814). These Metadata() methods return Metadata structs, which act similarly to consumer.Capabilities in that they are intended as a set of information which describes the components which the factory produces.
  • Remodels each component's as a proper go.opentelemetry.io/otel/attribute.Set. This set is used as the ID in the graph, but also as the set of attributes that creates the logger. In the future, the set will be automatically used to describe other aspects of the collector's own telemetry.
  • The logger fields are changed to match those described in the component telemetry RFC.

Minor changes:

  • Unknown component types are detected earlier in the startup process. (When the graph is being assembled, rather than when the components of the graph are being instantiated.) This is necessary so that we can obtain the Metadata from the appropriate factory. There is a minor user facing change in that the error message is not wrapped in a "could not build" prefix. I moved the processors to this pattern as well in order to match the other components.

@djaglowski djaglowski requested review from mx-psi, dmathieu and a team as code owners January 8, 2025 19:47
@djaglowski djaglowski changed the title Singleton flags and attributes Add singleton flags to factories and standardize attributes Jan 8, 2025
@djaglowski djaglowski marked this pull request as draft January 8, 2025 19:47
@djaglowski
Copy link
Member Author

If desired, I believe I can split this PR into several smaller PRs. However, I wanted to put this version up in order to show the overall picture.

@djaglowski djaglowski force-pushed the singleton-flags-and-attributes branch 2 times, most recently from 0717a5d to 79e1bcb Compare January 8, 2025 20:00
Copy link

codecov bot commented Jan 8, 2025

Codecov Report

Attention: Patch coverage is 98.31224% with 4 lines in your changes missing coverage. Please review.

Project coverage is 91.88%. Comparing base (dcc866c) to head (02f5e8f).
Report is 62 commits behind head on main.

Files with missing lines Patch % Lines
service/internal/graph/exporter.go 92.59% 2 Missing ⚠️
service/internal/graph/receiver.go 95.23% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #12057      +/-   ##
==========================================
+ Coverage   91.72%   91.88%   +0.15%     
==========================================
  Files         463      465       +2     
  Lines       24821    25430     +609     
==========================================
+ Hits        22767    23366     +599     
- Misses       1672     1675       +3     
- Partials      382      389       +7     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@djaglowski
Copy link
Member Author

djaglowski commented Jan 10, 2025

I discovered when adding tests that singleton connectors will introduce broader changes into the way we build the graph, since we're wrapping each instance as a specific type of consumer. I've not been able to get it working yet but either way, the additional complexity seems not worth for now. I believe there are some reasons why singleton connectors would be useful but I'm going to propose for now that singleton instances are supported only for receivers and exporters. In the future we can try to add singleton connectors.

@djaglowski djaglowski force-pushed the singleton-flags-and-attributes branch 5 times, most recently from 32b1ba7 to 90a4238 Compare January 10, 2025 20:02
@djaglowski djaglowski force-pushed the singleton-flags-and-attributes branch from 90a4238 to 6a38f9c Compare January 10, 2025 20:49
@djaglowski djaglowski force-pushed the singleton-flags-and-attributes branch 2 times, most recently from bb19bc7 to 9fc517f Compare January 10, 2025 21:15
github-merge-queue bot pushed a commit that referenced this pull request Jan 10, 2025
This PR just cleans up some naming in the `testcomponents` package, so
that no component kind has a monopoly on the generic version of a
variable or function name.

Subset of #12057
@djaglowski djaglowski force-pushed the singleton-flags-and-attributes branch from 9fc517f to 7772955 Compare January 10, 2025 21:30
Copy link
Member

@mx-psi mx-psi left a comment

Choose a reason for hiding this comment

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

The approach makes sense to me, just one question about naming

exporter/exporter.go Show resolved Hide resolved
Copy link
Member

@mx-psi mx-psi left a comment

Choose a reason for hiding this comment

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

Looks good to me.

One thing I don't like about Capabilities is that a component developer can accidentally 'lie' about their component, which can also happen here. I don't see a great way to do this here without introducing a lot more API, so this seems reasonable enough

@djaglowski djaglowski force-pushed the singleton-flags-and-attributes branch from 256d7c9 to c498d3e Compare January 16, 2025 17:53
@djaglowski djaglowski marked this pull request as ready for review January 16, 2025 19:59
@jade-guiton-dd
Copy link
Contributor

Do you have ideas for making the new attributes available to components for use in spans and metrics? (Adding the attribute.Set in the TelemetrySettings for example?)

@djaglowski
Copy link
Member Author

djaglowski commented Jan 17, 2025

Do you have ideas for making the new attributes available to components for use in spans and metrics? (Adding the attribute.Set in the TelemetrySettings for example?)

It is the next thing I intend to look into once this is merged. Either as you suggested, or maybe it's possible to save them into the Meter/Tracer providers in some way?

github-merge-queue bot pushed a commit that referenced this pull request Jan 20, 2025
Subset of #12057

This PR adds a test to validate the expected number of instances of each
component. This framework becomes more useful once singleton components
are explicitly supported.
github-merge-queue bot pushed a commit that referenced this pull request Jan 20, 2025
This PR creates a new internal package which defines the correct set of
attributes for each kind of component.

This is a subset of #12057 which is broken off in order to reduce the
overall size of that PR. As such, this package will not actually be used
until #12057 is merged.
@djaglowski djaglowski force-pushed the singleton-flags-and-attributes branch 2 times, most recently from 98fe10f to c72b516 Compare January 21, 2025 15:03
@mx-psi
Copy link
Member

mx-psi commented Jan 23, 2025

I will merge this on Monday unless somebody comments, cc @open-telemetry/collector-approvers

Copy link
Member

@songy23 songy23 left a comment

Choose a reason for hiding this comment

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

LGTM

@mx-psi mx-psi requested a review from dmitryax January 27, 2025 16:09
@mx-psi
Copy link
Member

mx-psi commented Jan 27, 2025

@dmitryax will take a look at this before we merge it

@sfc-gh-bdrutu
Copy link

sfc-gh-bdrutu commented Jan 27, 2025

I have a feedback we discuss in the otel collector stability meeting (which may be already address, but want to make sure is documented): We should be able to have internal telemetry (logs/traces/metrics) annotated with the signal type that produces them, so if I fail to parse a message I should know that is the "metrics" pipeline that failed.

PS: What I think we discussed is exactly against #11814.

I do understand that from a "status" perspective if the main shared gRPC server fails is a fail of all components, but if a message is logged when I process the logs I should know that is about logs.

@djaglowski
Copy link
Member Author

I have a feedback we discuss in the otel collector stability meeting (which may be already address, but want to make sure is documented): We should be able to have internal telemetry (logs/traces/metrics) annotated with the signal type that produces them, so if I fail to parse a message I should know that is the "metrics" pipeline that failed.

PS: What I think we discussed is exactly against #11814.

I do understand that from a "status" perspective if the main shared gRPC server fails is a fail of all components, but if a message is logged when I process the logs I should know that is about logs.

I mostly agree with you but I think we need to look at this as two layers:

  1. Provide a set of attributes which identifies the instance, and also is correct when describing the instance as a whole.
  2. Encourage (or enforce in some way) that signal-specific telemetry is additionally attributed to the signal type.

I think this PR solves (1) and allows for (2) to be a best/recommended practice. (e.g. otlp receiver has a logger w/o signal attribute, but should use zap.String("otel.signal", "logs") where appropriate.

We can consider ways to make (2) automatic/natural later, but I think this PR is a big improvement over the current state of things where we incorrectly attribute all logs to the same signal (whichever was created first).

exporter/exporter.go Outdated Show resolved Hide resolved
@bogdandrutu
Copy link
Member

I do understand the underlying problem you try to solve, but I think this will come with the downside that the signal specific part of the component is not handled correctly (or has to be handled by manually annotating the signal tag to the telemetry).

In reality we don't need to share the entire component, but we need to share a "sub-component" which indeed is signal agnostic, for example the "http.Server" part of a receiver. This sub-component is then wrapped in signal specific logic.

The current approach is to treat the entire component as shared and not have the Signal annotation available, probably later will manually add that (this is my expectation since I don't see any other way to do this).

I would rather go with a different approach which will be to add a concept of a "core/share" component to the factory.

@djaglowski
Copy link
Member Author

I'm curious to hear more about your idea but my immediate thoughts:

  1. You cannot effectively prevent component authors from making the whole component a singleton. So we might as well allow it and work with it. (Maybe could detect and fail when CreateX and CreateY return the same struct, but this can always be subverted by adding one more layer of abstraction.)
  2. While I would also like to eliminate correctness concerns, omitting a signal attribute when it could have been included is a trivial problem to fix. It won't ever be implemented perfectly across all components but will trend upward very quickly.
  3. What you're proposing will require substantial refactoring to several important components, each of which will have unique design changes and corresponding correctness challenges. I doubt you or I have the time to do this and even if we did it would delay the addition of several useful observability signals from the collector by additional months.

@djaglowski
Copy link
Member Author

I think this will come with the downside that the signal specific part of the component is not handled correctly (or has to be handled by manually annotating the signal tag to the telemetry).

I agree this is a downside, but your proposal leaves the same problem in place. It reduces the scope of the problem slightly at the cost of a lot of refactoring, but fundamentally the same problem remains. Any shared sub-component may have good reason to report telemetry that pertains to one specific signal, so how does the shared sub-component manage this? This still leaves us with manually annotating the signal tag to the telemetry.

@djaglowski djaglowski force-pushed the singleton-flags-and-attributes branch from c72b516 to 02f5e8f Compare January 29, 2025 21:00
@dmitryax
Copy link
Member

dmitryax commented Jan 30, 2025

What if we just add another field to component.TelemetrySettings, let's call it SharedLogger (same as Logger but without the signal attribute), which can be used by the shared parts of the components while Logger will be kept to signal specific code parts? memory_limiter processor needs that as well.

It's hard to be convinced that this new public API (Metadata) is required. It feels like just passing a boolean flag back to the factory. It's supposed to be connected to the fact that sharedComponent is used, but there is nothing to support that connection.

@djaglowski
Copy link
Member Author

I'm closing this as I no longer believe that adding notions of shared/singleton parts is a realistic solution to all the novel cases. New proposal here: #12217

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

Successfully merging this pull request may close these issues.

7 participants