feat(tracewaygin): tag CPU profiles with endpoint route label#7
Open
FrameAutomata wants to merge 5 commits into
Open
feat(tracewaygin): tag CPU profiles with endpoint route label#7FrameAutomata wants to merge 5 commits into
FrameAutomata wants to merge 5 commits into
Conversation
Add an opt-in background profiler that, on an interval (default 60s, CPU window ~30s capped to interval/2), captures CPU and heap pprof profiles and POSTs each as a separate request to <server>/api/profiles/ingest, reusing the connection-string token and host. The ingest URL is derived from the existing report URL (scheme+host + /api/profiles/ingest); Bearer auth, serverName and appVersion reuse the existing report plumbing. Profiling never affects the host app: capture and upload failures are isolated and silent unless WithDebug is set, and a bad URL disables profiling without failing Init. Verified against the backend contract (tracewayapp/traceway /api/profiles/ingest): path, Bearer auth, service/serverName/appVersion query params, and raw already-gzipped pprof body with no extra Content-Encoding. Core package only; HTTP middleware pass-through options are a follow-up. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Init split the connection string on "@" and unconditionally indexed connParts[1], panicking with "index out of range" when the string had no "@". Use SplitN with a length guard so a malformed connection string returns an error, and so a "@" inside the URL (e.g. userinfo) no longer silently truncates the endpoint. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Wrap each request handler's execution in pprof.Do with an "endpoint" label set to the matched route (c.FullPath(), falling back to the raw path for recorded unmatched routes). CPU profile samples taken during a request now carry the route, so profiles can be sliced per-endpoint in the dashboard. The label key is exactly "endpoint" to match the backend allowlist. The labeling lives inside wrapAndExecute alongside the existing c.Next() and panic-recovery handling, and the labeled context is set back on the request so handler-spawned goroutines inherit the tag. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The gin middleware tags each request's CPU samples with an `endpoint`
pprof label, but tracewaygin had no way to turn continuous profiling on,
so those labels were never captured by a running CPU profile. Enabling
profiling required a separate, undocumented traceway.Init(WithProfiling)
call before adding the middleware (relying on the second Init no-opping).
Add WithProfiling(serviceName) and WithProfilingInterval(d) option
passthroughs, matching the existing wrappers, so:
r.Use(tracewaygin.New(conn, tracewaygin.WithProfiling("shop")))
enables endpoint-labeled continuous profiling in one call.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Wraps each gin request handler's execution in
pprof.Dowith an"endpoint"label set to the request's route, so CPU profile samples taken during a request carry the route and can be sliced per-endpoint in the dashboard."endpoint"to match the backend allowlist.c.FullPath(), e.g./users/:id), falling back to the raw path only for recorded unmatched routes (WithRecordUnmatched(true)) — the same value already used for the trace endpoint.wrapAndExecute, alongside the existingc.Next()call and panic recovery, so the request-execution concern stays in one place.pprof.Doruns the handler synchronously, so panics still propagate to the deferred recover.c.Request, so goroutines spawned by the handler inherit theendpointtag in their own profile samples.Why
Continuous CPU profiles are far more actionable when each sample is attributed to the route that produced it — letting the dashboard answer "which endpoint is burning CPU?" rather than just showing aggregate hot functions.
Testing
TestMiddleware_EndpointPprofLabel— matched route/users/:idseespprof.Label(ctx, "endpoint") == "/users/:id"during handler execution (route pattern, not raw URL).TestMiddleware_EndpointPprofLabel_Unmatched— withWithRecordUnmatched(true), aNoRoutehandler sees the raw path label.go vetpass; manually verified withgo tool pprof -tagsthat 100% of samples carryendpoint: /users/:id.🤖 Generated with Claude Code