-
Notifications
You must be signed in to change notification settings - Fork 651
Design document for otelhttpconv package #6859
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
base: main
Are you sure you want to change the base?
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #6859 +/- ##
=====================================
Coverage 75.6% 75.6%
=====================================
Files 207 207
Lines 19354 19354
=====================================
+ Hits 14643 14646 +3
+ Misses 4275 4273 -2
+ Partials 436 435 -1 🚀 New features to boost your workflow:
|
cc @akats7 @scorpionknifes as code owners of HTTP implementations |
Co-authored-by: Robert Pająk <[email protected]>
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.
Could you add an example for a certain existing HTTP instrumentation to describe how otelhttpconv
is actually being used in HTTP instrumentation? This could also give other authors more clues about how to leverage otelhttpconv
to reduce code repetition.
I've added a sample implementation of an |
Co-authored-by: Sam Xie <[email protected]>
|
||
// NewResponseWrapper wraps additional data into the http.ResponseWriter, | ||
// such as duration, status code and quantity of bytes read. | ||
rww := otelhttpconv.NewResponseWrapper(w) |
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.
Isn't this coupled to otelhttpconv.NewHTTPConv
?
Are we sure that it would work with other custom semantic conventions?
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 this goes with your other comment. If we make the body and response wrapper structs and internalize their logic then, this will indeed change.
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.
So, even with structs for the wrappers, I think this design makes sense.
Building a response wrapper from an HTTPConv
would be strange, as then each implementations would need to know how to build a wrapper as well.
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.
as then each implementations would need to know how to build a wrapper as well.
But wouldn't the wrapper functionalities by detriment by what httpconv.Record
is supposed to do? I feel like those structures are coupled to each other. E.g. I guess that for some httpconv
the reponse needs BytesWritten
but for other it is unnecessary.
|
||
// Client provides an interface for HTTP client instrumentations to set the | ||
// proper semantic convention attributes and metrics into their data. | ||
type Client 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.
I think it would be good to have some "Rationale" or/and "Rejected Proposals" explaining the pros and cons behind the decision making.
For instance, why cannot we simply have a function a struct more or less like
func RecordClient(r *http.Request, params RecordClientParameters)
type RecordClientParameters struct {
Tracer trace.Tracer
Meter metric.Meter
Error error
Response *http.Response
Duration time.Time
}
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've added an Alternatives
section.
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.
It would be nice to have a working prototype as a separate draft PR.
I intend to do that. But I'd rather have the spec stabilize first, to avoid rewriting it several times. |
These interfaces are kept relatively simple on purpose, so they can be used as | ||
foundations if folks wish to extend them with their own actual implementations. |
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.
What would be a problem to use a struct
? They can still be used as foundations. The users can always create their own interfaces if they need to support different implementation.
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.
How would you do that?
If we provide the following API:
otelhttp.NewTransport(http.DefaultTransport, otelhttp.WithHTTPConv(myCustomImplementation{}))
And otelhttp.WithHTTPConv
takes a struct, you can't extend it. It has to be our implementation.
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.
otelhttp
would define the interface as this is the package that accepts input and not otelhttpconv
which provides an implementation.
otelhttp
should not expose otelhttpconv
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.
Let's discuss this during today's SIG meeting. We have different views here.
While otelhttp would definitely use this package, the idea here is that other packages which currently use the generated semconv
package would too.
Then, they need the types exposed.
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.
Let's discuss this during today's SIG meeting. We have different views here.
👍
the idea here is that other packages which currently use the generated semconv package would too.
Sure but these can be struct
and not interface
.
Once stable, we will not be able to change those interfaces anymore (adding, | ||
renaming or deleting methods), as that would break backwards compatibility with | ||
implementations. |
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.
Then what is our plan if we would like to add a new functionality?
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 as for the interfaces in the SDK. We either introduce a new interface, or we release a v2.
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.
With a struct we could simply add new fields/method.
|
||
### Implementations | ||
|
||
We will provide one official implementation of the described interfaces. |
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.
What is the point of exposing an interface if we want to provide only one implementation?
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.
So that folks can provide their own implementation.
Also, I do mention that we may provide additional implementations later on, for unstable conventions for example.
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 places where we want to allow passing custom implementations should define the interface (e.g. otelhttp
). otelhttpconv
does not accept any custom implementation.
Reference: https://go.dev/wiki/CodeReviewComments#interfaces
To be honest, I am not even sure if we need to support custom semantic conventions (we never did that).
tracer: otel.Tracer("http"), | ||
propagators: otel.GetTextMapPropagator(), | ||
meter: otel.Meter("http"), | ||
httpconv: otelhttpconv.NewHTTPConv(otel.Tracer("httpconv"), otel.Meter("httpconv")), |
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.
NewHTTPConv
is not defined in the design.
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.
Sorry, that seemed clear to me. It creates an instance of our official implementation of the interface.
Since the implementation itself isn't in the design, I didn't add this method.
### Compatibility | ||
|
||
These interfaces are kept relatively simple on purpose, so they can be used as | ||
foundations if folks wish to extend them with their own actual implementations. |
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.
Do we really want to support custom semconv implementations?
I think it is an overkill (and footgun). Shouldn't we just focus on OTel SemConv?
People not happy with OTel SemConv can create their own instrumentation libraries.
I propose that otelhttpconv
has "concrete" implementations (functions, structs).
If we want to ever provide customization of semconv, I would rather add it on the instrumentation library layer as this is the API that the user is interacting with. otelhttpconv
should be used "internally" by instrumentation libraries.
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 being able to support custom semantic conventions is just a side effect of the modularity. The real interesting thing here would be to be able to support unstable semantic conventions, with no breaking changes on the code that supports stable ones.
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 find it hard to evaluate without code and examples.
Unstable semantic conventions could be also controlled by env vars.
This provides a design document for a new instrumentation,
otelhttpconv
that would serve as a meta instrumentation for all HTTP packages to more easily share their behavior.