-
Notifications
You must be signed in to change notification settings - Fork 890
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
Capture policy regarding non-exposure of generated Protobuf structs in the end user API #3420
Comments
Another thing is that adding new methods on a service will generate backwards incompatible code for languages like golang where that means adding a new func to an interface. |
I think this is an argument in favour of prohibiting addition of new methods to the services since it breaks existing implementations. I think this prohibition is necessary regardless of what we decide about this non-exposure policy. I think it can be discussed separately. |
@open-telemetry/specs-approvers please comment. |
Not sure I buy this argument. Do we really have such complex data structures exposed via APIs where this duplication matters? Another strike against proto is it bloats the library right at the API level. What if your company does not use protobuf at all? Why should that be a dependency just to use the API? |
Yes, we do. You potentially can expose the entire Protobuf definiiton. This is exactly what Collector codebase does. It wraps all of OTLP Protobuf definitions in a set of new data structures called My argument that doing this (wrapping) should be a choice and not a forced policy since it is a non-trivial amount of work.
This is a good argument. |
I added this to the Downsides list in the description. |
I'm not sure this is accurate. I'm not aware of any place in the API that would take a dependency on generated protobuf types. This would relate to the SDK and likely only the OTLP exporter. |
@Aneurysm9 I'd argue even at the general SDK level this is undesirable. If we have a good SDK design, it should not force people to re-implement the API from scratch just because they want a custom exporter. But I agree that at some point this may no longer apply, and the specific complaint 1 was about OTLP exporter, which is always coupled w/ protobuf. |
Another downside of exposing proto-generated-types without wrapping those is that it couples to the:
For instance in Go there are two popular libraries (packages): github.com/golang/protobuf/proto which is deprecated and google.golang.org/protobuf... but who knows if there won't be v2 in future? A breaking change in the library may be also a breaking change of the OTel library (indirect/transitive API breaking change).
While most people is the most popular protoc plugins for generating code, nothing prevents them from creating their own plugins to generate code. E.g. https://rotemtam.com/2021/03/22/creating-a-protoc-plugin-to-gen-go-code/ Also I am not sure if the plugins have strict stability guarantees. For instance check https://github.com/golang/protobuf#compatibility:
EDIT: Also I now noticed https://github.com/open-telemetry/opentelemetry-proto/blob/main/README.md#stability-definition As rule of thumb, I think that libraries should avoid accepting and returning types that are not "under control" (of course there are exceptions like standard library types, and... other exceptions 😄). I always felt that it is a "general guideline". |
I know you've already heard this: I think the primary issue here is protocol buffer library generation DOES NOT guarantee stability on changes where the protocol buffer wire format would have been stable. To @tigrannajaryan's point, pdata is an investment in a "stable" API that can serialize to proto format. Java, e.g. did the same thing, and has its own codegen that basically creates constants usable for writing serializers. (There's actually a couple reasons to custom-serialize OTLP, particularly important is not having to shuffle your data in memory to create the Resource->Scope->Signal hierarchy). Personally, I'd be ok asking for all SiGs to avoid exposing proto generated classes for two reasons:
However, I agree with @tigrannajaryan that forcing this seems a bit too much. |
This is unstated, so please correct me if I'm wrong, but this seems to be trying to prevent issues with the proto changing under an exporter. It does not look like any SIG has exposed the proto in the SDK but instead has some internal format that is used. The API that exposes this in go is contained within the OTLP exporter, which is going to have a dependency on the proto in some way, shape, or form, so we will not be able to prevent the inclusion of protobufs. If that is the goal of this request, I don't think it would be enough not to have the protobuf in the public API. One way to prevent what happened is to prevent the exporter from using a different version of the proto than what it was written for. This would essentially require that the exporter can't depend on an external generation of the proto (e.g. |
@MrAlias I think this policy should only apply to the API package, i.e. to the API that end user programs are calling. There there is a good reason to avoid exposing the generated Protobufs and bringing the Protobuf library as a transitive dependency. I think it is extremely important for the API package and Noop implementation to remain very lightweight, bring very few dependencies. Doing otherwise can be very harmful for adoption of "OpenTelemetry instrumentation as-a-first-class feature of all software" philosophy. I think this same policy must apply to the interface between the API package and SDK package otherwise we loose the long-term plug-ability of the SDK. A breaking change in the generated proto will result in a breaking change in this interface and will make impossible to upgrade to newer versions of the SDK. I think this plug-ability is also an important feature of OpenTelemetry that we must maintain. Everything else? I don't think we need the same hard restriction. The SDK's interface that is supposed to be callable by end user for configurability for example doesn't need such restriction. Even if it breaks (very rarely), it is ok to require the user to fix their code. I also do not think this restriction should apply to other helper libraries (e.g. OpAMP Go). |
The only place the Go implementation exposes this dependency is in the trace We have not exposed this for the metric That said, we could deprecate the interface if we feel it necessary. |
FYI all and @open-telemetry/specs-approvers, OpAMP Workgroup chose to guarantee generated code compatibility for its 1.0, primarily because there is no separation of API and SDK there and OpAMP Workgroup believes hiding Protobuf-generated code in OpAMP implementation is not necessary (and would create a ton of unnecessary work to add wrappers). This is just an FYI. I don't think OpAMP decision should influence our decision for Otel API libraries, where we have a different situation (most notably the API that needs to be a lightweight noop). |
I think this issue belongs to the spec repo, since it is a requirement for Otel API, not for OTLP or for protos. Moving. |
@tigrannajaryan this was fixed in go and I don't think it's affecting any other languages. Do you think this is still needed? |
I think we can close it. |
This is related to open-telemetry/opentelemetry-go#3455 which requests Go SDK to stop exposing the generated code in the API.
We don't have a policy or clarification anywhere that explains why this is prohibited.
My initial thoughts is that allowing has this benefit:
Downside:
@bogdandrutu I would like to hear your thoughts on this topic since you have a strong opinion about this.
The text was updated successfully, but these errors were encountered: