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 WithRouteTagMiddleware function to otelhttp package #4017

Closed
wants to merge 19 commits into from

Conversation

terev
Copy link

@terev terev commented Jun 22, 2023

This new function simplifies usage of this utility by users of third party router packages.

@terev terev requested a review from a team June 22, 2023 08:02
@terev terev requested review from Aneurysm9 and dmathieu as code owners June 22, 2023 08:02
CHANGELOG.md Outdated Show resolved Hide resolved
instrumentation/net/http/otelhttp/handler.go Show resolved Hide resolved
Co-authored-by: Damien Mathieu <42@dmathieu.com>
@pellared
Copy link
Member

pellared commented Jun 22, 2023

This new function simplifies usage of this utility within third party router packages.

Could you please provide examples? You can even consider adding "test examples".

EDIT: I think if we document how to use it with: gorilla/mux, echo, chi. We could even consider deprecating the otelmux, otelecho (or rewriting to use the same codebase).

@codecov
Copy link

codecov bot commented Jun 22, 2023

Codecov Report

Merging #4017 (efd7ba7) into main (9a582bd) will decrease coverage by 0.2%.
The diff coverage is 25.0%.

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##            main   #4017     +/-   ##
=======================================
- Coverage   79.2%   79.0%   -0.2%     
=======================================
  Files        165     165             
  Lines      10318   10349     +31     
=======================================
+ Hits        8176    8182      +6     
- Misses      2006    2030     +24     
- Partials     136     137      +1     
Impacted Files Coverage Δ
...hub.com/emicklei/go-restful/otelrestful/restful.go 90.5% <0.0%> (-9.5%) ⬇️
...ation/github.com/gin-gonic/gin/otelgin/gintrace.go 79.1% <0.0%> (-4.4%) ⬇️
...trumentation/github.com/gorilla/mux/otelmux/mux.go 80.7% <0.0%> (-7.7%) ⬇️
...entation/github.com/labstack/echo/otelecho/echo.go 89.8% <0.0%> (-10.2%) ⬇️
instrumentation/net/http/otelhttp/handler.go 85.7% <90.0%> (+2.6%) ⬆️

... and 2 files with indirect coverage changes

Comment on lines 19 to 20
go.opentelemetry.io/otel/sdk v1.16.0 h1:Z1Ok1YsijYL0CSJpHt4cS3wDDh7p572grzNrBMiMWgE=
go.opentelemetry.io/otel/sdk v1.16.0/go.mod h1:tMsIuKXuuIWPBAOrH+eHtvhTL+SntFtXF9QD68aP6p4=
Copy link
Member

Choose a reason for hiding this comment

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

You have to move the test to /test subdirectory as the instrumentation libraries must not depend on the SDK.

@terev
Copy link
Author

terev commented Jun 22, 2023

@pellared I've added one example so far and can add more in the morning. I added it to instrumentation/net/http/otelhttp/example/server/github.com/labstack/echo . It semanticly makes sense but may be tough to find. What do you think?

@terev
Copy link
Author

terev commented Jun 25, 2023

@pellared I've added a bunch of examples to instrumentation/net/http/otelhttp/example/server. Probably not the best place so lmk if there's somewhere else they should be.

@terev terev requested a review from pellared June 25, 2023 20:13
@dmathieu
Copy link
Member

I think simpler, and testable examples would be better than this. What we need is a code sample, not a full-blown runnable app.

Copy link
Member

@pellared pellared left a comment

Choose a reason for hiding this comment

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

I am really on low time until Wednesday, but I did my best to put any feedback that can hopefully help.

Comment on lines +49 to +59
r.GET("/users/:id", func(c echo.Context) error {
id := c.Param("id")
name := getUser(c.Request().Context(), id)
return c.JSON(http.StatusOK, struct {
ID string
Name string
}{
ID: id,
Name: name,
})
}, echo.WrapMiddleware(otelhttp.WithRouteTagMiddleware("/users/:id")))
Copy link
Member

@pellared pellared Jun 26, 2023

Choose a reason for hiding this comment

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

Would it not be possible to get rid of the "/users/:id" duplication?

I do not like requiring to add echo.WrapMiddleware(otelhttp.WithRouteTagMiddleware() for each registering handler.

I would prefer to have something like

	r.Use(echo.WrapMiddleware(otelhttp.NewMiddleware("my-server")))
        r.Use(OTelRouteTaggerMiddleware()) // or: r.Use(otelecho.RouteTaggerMiddleware())

	r.GET("/users/:id", func(c echo.Context) error {
		id := c.Param("id")
		name := getUser(c.Request().Context(), id)
		return c.JSON(http.StatusOK, struct {
			ID   string
			Name string
		}{
			ID:   id,
			Name: name,
		})
	})

I hope something similar could be adopted for other libraries 😉

Copy link
Author

Choose a reason for hiding this comment

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

@pellared I can't come up with a way we can create a generic middleware for this since the route tag is usually router specific and not possible to retrieve in our middleware. If users want a catch all middleware I think each library would need to implement this. For example echo would need a middleware that uses the result of c.Path() as the route tag.

We could provide a utility function that adds a passed route tag as an attribute and changes the span name as discussed previously.

Copy link
Member

Choose a reason for hiding this comment

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

We could provide a utility function that adds a passed route tag as an attribute and changes the span name as discussed previously.

I think this may be more flexible and powerful. Writing a little middleware that would use this function should not be a big deal.

Copy link
Author

Choose a reason for hiding this comment

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

Added this utility function to otelhttp and route tagger middleware in 4 of the http router modules. Added a question about where to put the examples.

Copy link
Member

Choose a reason for hiding this comment

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

Can you update the examples? The existing example structure is good enough. We can refine it later once we have a consensus on the implementation part.

@terev terev requested a review from hanyuancheung as a code owner July 2, 2023 08:19
@terev
Copy link
Author

terev commented Jul 2, 2023

I think simpler, and testable examples would be better than this. What we need is a code sample, not a full-blown runnable app.

Not sure how to do this and actually add examples for the NewMiddlware function. If I add this into the root of the otelhttp module it'll add a bunch of extra dependencies. Should these examples be put in the example directory as testable examples? Even though they'll be examples for the example module?

@dmathieu
Copy link
Member

dmathieu commented Jul 3, 2023

Not sure how to do this and actually add examples for the NewMiddlware function. If I add this into the root of the otelhttp module it'll add a bunch of extra dependencies. Should these examples be put in the example directory as testable examples? Even though they'll be examples for the example module?

They can be put in the same directory, but with a different module name. See this example from gRPC: https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/instrumentation/google.golang.org/grpc/otelgrpc/example_interceptor_test.go

@terev
Copy link
Author

terev commented Jul 4, 2023

Not sure how to do this and actually add examples for the NewMiddlware function. If I add this into the root of the otelhttp module it'll add a bunch of extra dependencies. Should these examples be put in the example directory as testable examples? Even though they'll be examples for the example module?

They can be put in the same directory, but with a different module name. See this example from gRPC: https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/instrumentation/google.golang.org/grpc/otelgrpc/example_interceptor_test.go

Won't that still require dependencies in the go.mod? I created a file called instrumentation/net/http/otelhttp/example_echo_middleware_test.go that is defined within the otelhttp_test package. Then running go mod tidy -v in that directory adds the dependencies required by the example to go.mod.

@terev
Copy link
Author

terev commented Jul 25, 2023

It's still unclear to me where I should be putting the example tests. Maybe there is not really a good answer for this at the moment?

@pellared
Copy link
Member

It's still unclear to me where I should be putting the example tests. Maybe there is not really a good answer for this at the moment?

For me it is good as it is for now. We can improve the examples later. You are correct here: #4017 (comment)

Comment on lines +90 to +96
// RouteTaggerMiddleware annotates the current span with the handler's route path.
func RouteTaggerMiddleware() restful.FilterFunction {
return func(request *restful.Request, response *restful.Response, chain *restful.FilterChain) {
otelhttp.AnnotateSpanWithHTTPRoute(request.Request.Context(), request.SelectedRoutePath())
chain.ProcessFilter(request, response)
}
}
Copy link
Member

@pellared pellared Jul 26, 2023

Choose a reason for hiding this comment

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

We should not depend on otelhttp in other instrumentation libraries. These libraries are not stable and bumping in otelhttp can break otelgin users. The AnnotateSpanWithHTTPRoute implementation is so small that I would rather inline it in existing instrumentation packages.

I would prefer if this PR is only about otelhttp.

I would move the middleware implementations using AnnotateSpanWithHTTPRoute to examples under otelhttp. This would demonstrate how someone could use otelhttp e.g. instead of otelmux. Related comment: #4017 (comment)

@terev
Copy link
Author

terev commented Jul 30, 2024

Does anyone have opinions on whether this should be closed? It seems like the third party instrumentation is due to be removed at some point so maybe this is obsolete?

@dmathieu
Copy link
Member

With the routing enhancements in Go 1.22, and this PR being rather stale, I think we should close it.
Once all supported versions of Go have routing available, we can add that to otelhttp.

Note that while 1.22 added routing support, retrieving the pattern is only available from 1.23. So we'll have to wait for 1.22 to be EOL.
https://pkg.go.dev/net/http@master#Request.Pattern

@dmathieu dmathieu closed this Jul 31, 2024
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.

4 participants