github gofr-dev/gofr v1.56.7

9 hours ago

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-router to the standard <METHOD> <route-template> (e.g. GET /users/{id}), matching OTel HTTP semantic conventions.

Note on tracing defaults: the NeverSample() provider only applies when TRACE_EXPORTER is unset — i.e. when tracing isn't configured at all. If you set TRACE_EXPORTER, sampling and export behave as before. No configured setup is affected.

Full Changelog: v1.56.6...v1.56.7

Don't miss a new gofr release

NewReleases is sending notifications on new releases.