Documentation
¶
Overview ¶
Package fdhttp connects net/http to FiveDock. On the server side every request gets its own hub, so its scope and trace never mix with another request's, runs inside an http.server transaction named after its route, and a panicking handler is reported before the response goes out:
handler := fdhttp.New(fdhttp.Options{})
http.ListenAndServe(":8080", handler.Handle(mux))
On the client side Transport records http.client spans and passes the trace on:
client := &http.Client{Transport: fdhttp.NewTransport(nil)}
Inside a handler, fivedock.GetHubFromContext(r.Context()) is the request's hub and fivedock.SpanFromContext(r.Context()) its transaction. Like the fivedock package, fdhttp uses only the standard library.
Index ¶
Examples ¶
Constants ¶
const ( OpServer = "http.server" OpClient = "http.client" Origin = fivedock.SpanOrigin("auto.http.fdhttp") )
Operations and origin of the spans this package records.
const MechanismType = "http.server"
MechanismType is how a panic caught by this package is labeled.
Variables ¶
This section is empty.
Functions ¶
func SetRoute ¶
SetRoute names the route that serves the request of ctx, for routers fdhttp cannot read on its own, such as chi:
fdhttp.SetRoute(r.Context(), chi.RouteContext(r.Context()).RoutePattern())
pattern is a template such as "/orders/{id}"; the request's method is added unless pattern starts with one. It renames the request's transaction at once, with source "route", and names errors captured from then on. Outside a request served by Handle it does nothing.
Example ¶
package main
import (
"net/http"
"fivedock.dev/go/fdhttp"
)
func main() {
// For a router fdhttp cannot read, such as chi: after the router
// matched, hand it the route template.
router := http.HandlerFunc(func(_ http.ResponseWriter, r *http.Request) {
fdhttp.SetRoute(r.Context(), "/projects/{id}") // chi.RouteContext(r.Context()).RoutePattern()
})
_ = fdhttp.New(fdhttp.Options{}).Handle(router)
}
Output:
Types ¶
type Handler ¶
type Handler struct {
// contains filtered or unexported fields
}
Handler wraps http.Handlers with FiveDock's per-request hub, transaction and panic reporting.
func (*Handler) Handle ¶
Handle wraps next. Each request gets a clone of the hub on its context (or of the current hub) carrying the request and the trace continued from its traceparent and baggage headers (or a new one), and runs inside an http.server transaction on that trace, sent when tracing is enabled.
The transaction is named after the route when the handler returns: the pattern an http.ServeMux matched (r.Pattern, which the mux sets on the request fdhttp passes it), or one given to SetRoute, else the method and path with source "url". Errors captured during the request carry the same name. Its status and http.response.status_code come from the response.
Requests whose context is marked with fivedock.SuppressContext pass through untouched.
Example ¶
package main
import (
"log"
"net/http"
fivedock "fivedock.dev/go"
"fivedock.dev/go/fdhttp"
)
func main() {
mux := http.NewServeMux()
mux.HandleFunc("GET /orders/{id}", func(w http.ResponseWriter, r *http.Request) {
// r.Context() carries the request's hub and its http.server
// transaction, named "GET /orders/{id}" once the handler returns.
fivedock.GetHubFromContext(r.Context()).Scope().SetTag("order", r.PathValue("id"))
w.WriteHeader(http.StatusNoContent)
})
handler := fdhttp.New(fdhttp.Options{})
log.Fatal(http.ListenAndServe(":8080", handler.Handle(mux)))
}
Output:
func (*Handler) HandleFunc ¶
func (h *Handler) HandleFunc(next http.HandlerFunc) http.HandlerFunc
HandleFunc is Handle for a handler function.
type Options ¶
type Options struct {
// Repanic panics again after reporting, for an outer recovery layer
// (or net/http itself) to deal with. Without it the handler answers 500
// when nothing was written yet.
Repanic bool
// WaitForDelivery waits, up to Timeout, for a reported panic to be
// delivered before the handler returns: for processes that may exit
// right after.
WaitForDelivery bool
// Timeout bounds WaitForDelivery: 0 means 2 s.
Timeout time.Duration
}
Options configures a Handler.
type Transport ¶
type Transport struct {
// Base sends the requests: nil means http.DefaultTransport.
Base http.RoundTripper
}
Transport is an http.RoundTripper that traces outgoing requests. With a span running on the request's context it records an http.client span around the round trip, and it adds traceparent and baggage headers to requests whose URL matches ClientOptions.TracePropagationTargets (every URL by default), so the service called continues the trace (§6.2). The hub on the request's context, or the current hub, decides.
Requests whose context is marked with fivedock.SuppressContext pass through untouched. The SDK marks its own, so a Transport never traces the SDK's deliveries, even when it is ClientOptions.HTTPTransport.
The span ends when the response headers arrive, as with sentry-go: the time spent reading the body is not part of it.
func NewTransport ¶
func NewTransport(base http.RoundTripper) *Transport
NewTransport returns a Transport that sends through base (nil means http.DefaultTransport).
Example ¶
package main
import (
"context"
"net/http"
fivedock "fivedock.dev/go"
"fivedock.dev/go/fdhttp"
)
func main() {
client := &http.Client{Transport: fdhttp.NewTransport(nil)}
tx := fivedock.StartTransaction(context.Background(), "sync stock")
defer tx.Finish()
req, _ := http.NewRequestWithContext(tx.Context(), http.MethodGet, "https://inventory.internal/stock/42", nil)
if resp, err := client.Do(req); err == nil { // an http.client span, and traceparent and baggage on the request
_ = resp.Body.Close()
}
}
Output:
Source Files
¶
- fdhttp.go
- transport.go