Release v1.56.7
⚡ Performance — HTTP Hot Path
Reduced per-request allocations and CPU across the pkg/gofr request lifecycle, closing most of the gap to the net/http router cluster.
Benchmark setup: Apple M4, GOMAXPROCS=4, payloads: plaintext (13 B), json (small object), param (single path param). Numbers are machine-specific and will differ on Linux/x86, in containers with CPU limits, and at higher core counts — treat as relative, not absolute.
End-to-end RPS (vs v1.56.6):
| Endpoint | v1.56.6 | v1.56.7 | Δ |
|---|---|---|---|
| plaintext | 89,835 | 133,304 | +48 % |
| json | 89,177 | 118,513 | +33 % |
| param | 87,224 | 121,159 | +39 % |
Per-request profile (pprof):
| Metric | v1.56.6 | v1.56.7 | Δ |
|---|---|---|---|
| Allocations / req | 132 KB | 60 KB | −54 % |
| CPU / req | 33.5 µs | 21 µs | −37 % |
| p99 latency (plaintext) | 3.7 ms | 1.7 ms | −54 % |
What changed
| Area | Change | Impact |
|---|---|---|
| OTel hot path | When TRACE_EXPORTER is unset, installs a NeverSample() TracerProvider; otel.Tracer(...) handle cached in the middleware closure
| Spans keep unique TraceID/SpanID for log correlation but short-circuit at the sampler — 528 B → 144 B / req |
| Middleware | StatusResponseWriter shared between Logging and Metrics and pooled; attribute slices cached per (route, method); time.Now() deferred past probe/GraphQL filters
| Fewer allocations per request |
| Response & routing | Single Write with a Content-Length header (was 2–3 Writes); path.Clean skipped on already-canonical URLs; handler runs inline (no goroutine) when there's no request timeout and the request isn't a WebSocket upgrade
| Lower CPU and allocations on the response path |
🛠️ Fixes
🔹 Tracing spans
HTTP semconv attributes (http.method, http.route, http.status_code) are now recorded natively on the request span, and the redundant per-route otelhttp.NewHandler wrap has been removed.
- Eliminates the duplicate span emitted per request (2 spans/req → 1).
- Span name corrected from the generic
gofr-routerto the standard<METHOD> <route-template>(e.g.GET /users/{id}), matching OTel HTTP semantic conventions.
Note on tracing defaults: the
NeverSample()provider only applies whenTRACE_EXPORTERis unset — i.e. when tracing isn't configured at all. If you setTRACE_EXPORTER, sampling and export behave as before. No configured setup is affected.
Full Changelog: v1.56.6...v1.56.7