10/05/2021 - GO
This example demonstrates how you can attach OpenTelemetry tracing to outgoing HTTP client request and server response. As this is a follow up to the previous example linked below I am cutting it short.
This piece of code is just an addition to http.go
file you can find in the previous post - Implementing OpenTelemetry and Jaeger tracing in Golang HTTP API.
// HTTPClientTransporter is a convenience function which helps attaching tracing
// functionality to conventional HTTP clients.
func HTTPClientTransporter(rt http.RoundTripper) http.RoundTripper {
return otelhttp.NewTransport(rt)
}
This is just an example so you are meant to tidy it up. It is calling the server and expecting a response.
package service
import (
"context"
"fmt"
"net/http"
"time"
"github.com/you/client/internal/pkg/trace"
)
type service struct {
// ...
}
func (s service) httpRequest(ctx context.Context) error {
// Create a child span.
ctx, span := trace.NewSpan(ctx, "service.httpRequest", nil)
defer span.End()
ctx, cancel := context.WithTimeout(ctx, time.Second*10)
defer cancel()
req, err := http.NewRequestWithContext(ctx, http.MethodGet, "http://localhost:8090/server/users", nil)
if err != nil {
trace.AddSpanError(span, err)
trace.FailSpan(span, "request error")
return err
}
res, err := trace.HTTPClientTransporter(http.DefaultTransport).RoundTrip(req)
defer res.Body.Close()
if err != nil {
trace.AddSpanError(span, err)
trace.FailSpan(span, "rounttrip error")
return err
}
if res.StatusCode != http.StatusOK {
err := fmt.Errorf("unexpected response code")
trace.AddSpanError(span, err)
trace.FailSpan(span, "response error")
return err
}
return nil
}
Same as above, you can tidy this up as well.
// ...
func main() {
ctx := context.Background()
// Bootstrap tracer.
prv, err := trace.NewProvider(trace.ProviderConfig{
JaegerEndpoint: "http://localhost:14268/api/traces",
ServiceName: "server",
ServiceVersion: "2.0.0",
Environment: "dev",
Disabled: false,
})
if err != nil {
log.Fatalln(err)
}
defer prv.Close(ctx)
handler := http.NewServeMux()
handler.HandleFunc("/server/users", trace.HTTPHandlerFunc(app.User{}.Create, "users_create"))
log.Fatal(http.ListenAndServe(":8090", handler))
}
// ...
func (u User) Create(w http.ResponseWriter, r *http.Request) {
// Create the parent span.
_, span := trace.NewSpan(r.Context(), "User.Create", nil)
defer span.End()
// ...
}
The first three are a successful request and the last two is failed tracing information.