Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm

- Improve performance by reducing allocations in the gRPC stats handler in `go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc`. (#8035)

### Deprecated

- `WithRouteTag` in `go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp` is deprecated.
The route is already added automatically for spans.
For metrics, the alternative is to use the `WithMetricAttributesFn` option. (#8117)

### Removed

- Drop support for [Go 1.23]. (#7831)
Expand Down
12 changes: 2 additions & 10 deletions examples/dice/instrumented/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,17 +71,9 @@ func run() error {
func newHTTPHandler() http.Handler {
mux := http.NewServeMux()

// handleFunc is a replacement for mux.HandleFunc
// which enriches the handler's HTTP instrumentation with the pattern as the http.route.
handleFunc := func(pattern string, handlerFunc func(http.ResponseWriter, *http.Request)) {
// Configure the "http.route" for the HTTP instrumentation.
handler := otelhttp.WithRouteTag(pattern, http.HandlerFunc(handlerFunc))
mux.Handle(pattern, handler)
}

// Register handlers.
handleFunc("/rolldice/", rolldice)
handleFunc("/rolldice/{player}", rolldice)
mux.Handle("/rolldice", http.HandlerFunc(rolldice))
mux.Handle("/rolldice/{player}", http.HandlerFunc(rolldice))

// Add HTTP instrumentation for the whole server.
handler := otelhttp.NewHandler(mux, "/")
Expand Down
3 changes: 1 addition & 2 deletions instrumentation/net/http/otelhttp/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,5 @@
// SPDX-License-Identifier: Apache-2.0

// Package otelhttp provides an http.Handler and functions that are intended
// to be used to add tracing by wrapping existing handlers (with Handler) and
// routes WithRouteTag.
// to be used to add tracing by wrapping existing handlers.
package otelhttp // import "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
3 changes: 3 additions & 0 deletions instrumentation/net/http/otelhttp/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,9 @@ func (h *middleware) metricAttributesFromRequest(r *http.Request) []attribute.Ke

// WithRouteTag annotates spans and metrics with the provided route name
// with HTTP route attribute.
//
// Deprecated: spans are automatically annotated with the route attribute.
// To annotate metrics, use the `WithMetricAttributesFn` option.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This should be

Suggested change
// To annotate metrics, use the `WithMetricAttributesFn` option.
// To annotate metrics, use the [WithMetricAttributesFn] option.

func WithRouteTag(route string, h http.Handler) http.Handler {
attr := semconv.NewHTTPServer(nil).Route(route)
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
Expand Down
64 changes: 31 additions & 33 deletions instrumentation/net/http/otelhttp/handler_example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,43 +44,41 @@ func ExampleNewHandler() {
}

var mux http.ServeMux
mux.Handle("/hello/",
otelhttp.WithRouteTag("/hello/:name", http.HandlerFunc(
func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
labeler, _ := otelhttp.LabelerFromContext(ctx)
mux.Handle("/hello/", http.HandlerFunc(
func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
labeler, _ := otelhttp.LabelerFromContext(ctx)

var name string
// Wrap another function in its own span
if err := func(ctx context.Context) error {
ctx, span := trace.SpanFromContext(ctx).TracerProvider().Tracer("exampleTracer").Start(ctx, "figureOutName")
defer span.End()
var name string
// Wrap another function in its own span
if err := func(ctx context.Context) error {
ctx, span := trace.SpanFromContext(ctx).TracerProvider().Tracer("exampleTracer").Start(ctx, "figureOutName")
defer span.End()

var err error
name, err = figureOutName(ctx, r.URL.Path[1:])
return err
}(ctx); err != nil {
log.Println("error figuring out name: ", err)
http.Error(w, err.Error(), http.StatusInternalServerError)
labeler.Add(attribute.Bool("error", true))
return
}
var err error
name, err = figureOutName(ctx, r.URL.Path[1:])
return err
}(ctx); err != nil {
log.Println("error figuring out name: ", err)
http.Error(w, err.Error(), http.StatusInternalServerError)
labeler.Add(attribute.Bool("error", true))
return
}

d, err := io.ReadAll(r.Body)
if err != nil {
log.Println("error reading body: ", err)
w.WriteHeader(http.StatusBadRequest)
labeler.Add(attribute.Bool("error", true))
return
}
d, err := io.ReadAll(r.Body)
if err != nil {
log.Println("error reading body: ", err)
w.WriteHeader(http.StatusBadRequest)
labeler.Add(attribute.Bool("error", true))
return
}

n, err := io.WriteString(w, "Hello, "+name+"!\nYou sent me this:\n"+string(d))
if err != nil {
log.Printf("error writing reply after %d bytes: %s", n, err)
labeler.Add(attribute.Bool("error", true))
}
}),
),
n, err := io.WriteString(w, "Hello, "+name+"!\nYou sent me this:\n"+string(d))
if err != nil {
log.Printf("error writing reply after %d bytes: %s", n, err)
labeler.Add(attribute.Bool("error", true))
}
}),
)

if err := http.ListenAndServe(":7777",
Expand Down
Loading