Instrumenting net/http with OpenTelemetry


  • Go 1.13+



git clone
cd example/net-http
  • Step 2. Install uptrace-go and net/http instrumentation:
go get
go get
  • Step 3. Edit main.go to configure OpenTelemetry to export data to Uptrace:
import ""

	// copy your project DSN here or use UPTRACE_DSN env var
	// uptrace.WithDSN("https://<key><project_id>"),

  • Step 4. Edit main.go to instrument the net/http server:
func main() {
    http.Handle("/hello", otelhttp.NewHandler(

func helloHandler(w http.ResponseWriter, req *http.Request) { ... }
UPTRACE_DSN="https://<token><project_id>" go run main.go

Filtering requests

You can exclude some requests for being traced using otelhttp.WithFilteropen in new window:

handler = otelhttp.NewHandler(handler, "", otelhttp.WithFilter(otelReqFilter))

func otelReqFilter(req *http.Request) bool {
	return req.URL.Path != "/ping"

Route attribute

If you are instrumenting individual handlers (not a whole server), you can annotate handler spans with http.route attribute:

handler = otelhttp.WithRouteTag("/hello/:username", handler)

Span name

You can customize span name formatting using otelhttp.WithSpanNameFormatteropen in new window:

handler = otelhttp.NewHandler(handler, "", otelhttp.WithSpanNameFormatter(httpSpanName))

func spanName(operation string, r *http.Request) string {
	return operation


otelhttp provides a HTTP transport to instrument http.Client:

client := http.Client{
	Transport: otelhttp.NewTransport(http.DefaultTransport),

You can also use shortcuts to make HTTP requets:

resp, err := otelhttp.Get(ctx, "")

What is next?

Next, instrumentopen in new window more operations (for example, database queries or error logs) or learn about OpenTelemetry API to create your own instrumentations.