Skip to content

Latest commit

 

History

26 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

webpprof — a Telescope-like request profiler and debug toolbar for Go

Go Reference CI

webpprof is a Telescope-like request profiler and debug toolbar for Go (Golang) web applications. It shows everything one HTTP request did — SQL queries, cache operations, background jobs, logs, mail, outgoing HTTP calls, middleware, and panics — in one searchable local UI.

Early-stage: webpprof is pre-v1. Public APIs and persisted capture formats may change between minor releases, so pin a version and review the changelog before upgrading.

Use it to find why an endpoint is slow, inspect the SQL it executed, follow related operations through context.Context, and replay a captured HTTP request as cURL. webpprof runs inside the application and needs no external collector, Docker stack, or database.

webpprof is a development and diagnostic tool, not a long-term production APM. Captures are bounded and kept in memory by default, with optional local persistence for short investigations.

webpprof query details with a correlated request and highlighted SQL

Why webpprof?

Go already has excellent runtime profiling and observability tools. webpprof adds a request-centric view for application debugging:

  • Why is this HTTP endpoint slow?
  • Which SQL queries, cache operations, and outgoing calls did it execute?
  • Which logs, jobs, mail, and exceptions belong to it?
  • What happened before a panic or failed response?
  • Can an AI coding agent inspect the same captured timeline?

It complements pprof, tracing, and production APMs with a quick local Go request profiler, SQL query profiler, debug toolbar, and observability dashboard.

Features

  • Inspect method, route, status, duration, headers, bounded bodies, raw HTTP, and ready-to-run cURL for captured requests.
  • Correlate middleware, SQL, cache, jobs, logs, mail, outgoing HTTP, exceptions, and custom events through context.Context; inspect Schedule, Callable, and measured Task work as standalone execution roots.
  • Find possible N+1 queries, SQL-heavy requests, sequential HTTP calls, cache miss/query bursts, slow middleware, and direct operation failures.
  • Explore a request-wide waterfall with nesting, critical path, bottleneck, and operation-time breakdown.
  • Search and filter live events by entity, duration, status, time, and tags.
  • Profile net/http, Gin, Chi, Echo, Fiber, gRPC, pgx, GORM, Bun, database/sql, Redis, queues, messaging, logging, mail, and OpenTelemetry.
  • Let Codex, Claude, Cursor, and other MCP clients inspect the profiler through the separate read-only webpprof-mcp binary.

Measured capture overhead

The repository includes an end-to-end benchmark that marshals and redacts a custom event, records it into a full 10,000-entry store, and performs one FIFO eviction per operation. Results on Go 1.25.13, darwin/arm64, Apple M3 Pro:

Configuration Time/op Bytes/op Allocs/op
Event kind disabled 52 ns 224 B 1
In-memory, steady-state eviction 3.89 µs 4,162 B 51
JSONL journal, steady-state eviction 8.82 µs 5,204 B 60
SQLite, steady-state eviction 73.4 µs 5,790 B 88

Run both benchmark suites on deployment-like hardware:

go test . -run '^$' -bench BenchmarkProfilerOverhead -benchmem -count=6
go test ./storage/sqlite -run '^$' -bench BenchmarkProfilerSQLiteSteadyStateEviction -benchmem -count=6

The SQLite row includes synchronous eviction and write I/O. Run the relevant suite before enabling additional capture kinds in a hot path. These numbers are a reproducible reference, not a latency guarantee.

Getting started

Install the core module:

go get github.com/levskiy0/webpprof@latest

Start a private profiler server and wrap the application handler:

profiler, err := webpprof.Start(
    "127.0.0.1:6061",
    webpprof.WithToken(os.Getenv("WEBPPROF_TOKEN")),
    webpprof.WithExcludedRequests("GET /health", "GET *.js", "GET *.webp"),
)
if err != nil {
    return err
}
defer profiler.Shutdown(context.Background())

handler := webpprofhttp.MiddlewareWith(profiler, applicationHandler)

Pass the handler's context to database, cache, logger, queue, mail, and HTTP client operations. Their profilers use that context to attach events to the request:

if err := repository.Find(r.Context(), playerID); err != nil {
    return err
}
logger.InfoContext(r.Context(), "player loaded", "player_id", playerID)

Open http://127.0.0.1:6061/debug/webpprof/ and enter the token. Use webpprof.New(router, options...) instead when the application owns the HTTP server that serves the profiler UI.

Third-party integrations are independent nested Go modules, so installing Gin, pgx, or GORM support does not add unrelated SDKs to the application's module graph:

go get github.com/levskiy0/webpprof/profiler/gin@latest
go get github.com/levskiy0/webpprof/profiler/pgx@latest
go get github.com/levskiy0/webpprof/profiler/gorm@latest

See all integrations and setup examples.

Debug with AI agents over MCP

webpprof-mcp is a separate process. It reads a running profiler through its private HTTP API and exposes bounded, read-only MCP tools over stdio:

Codex / Claude / Cursor <-- MCP over stdio --> webpprof-mcp <-- HTTP --> Go application

Installing the Go library does not install the MCP executable. Install its independent module from any directory:

go install github.com/levskiy0/webpprof/cmd/webpprof-mcp@latest
webpprof-mcp --version

For a reproducible install, replace @latest with @v0.5.0. The executable is written to GOBIN, or GOPATH/bin when GOBIN is unset.

The MCP command is versioned independently. Its versions are published as cmd/webpprof-mcp/vX.Y.Z Go module tags through proxy.golang.org, without a separate GitHub Release. Use @latest or pin an exact command version.

Register it in Codex:

codex mcp add webpprof \
  --env WEBPPROF_TOKEN="$WEBPPROF_TOKEN" \
  -- webpprof-mcp --url http://127.0.0.1:6061/debug/webpprof/

The server provides tools to check status, list and wait for requests, inspect automatic findings, and search related events. Payloads, values, arguments, and stacks are omitted unless explicitly requested; tools never replay requests, clear events, or mutate the application.

See MCP installation, client configuration, tools, and security.

Try it locally

Run the bundled application from the repository root:

go run ./example

Open http://127.0.0.1:3030/, generate a successful, failed, or panic request, then inspect it at http://127.0.0.1:3030/debug/webpprof/. The example is a real net/http application using database/sql, pure-Go SQLite, structured log/slog, SQL EXPLAIN, and SQLite-backed profiler storage. Its composition root shows the complete integration in one place: wrap the HTTP handler, SQL driver, and slog handler once. Its ordinary handlers also use the optional Measure helper to create service-level spans while SQL and logs remain automatic. The clearly marked /api/manual/* routes contain the custom integration and synthetic diagnostics. See example/README.md for the annotated wiring, automatic behavior, routes, and configuration.

What is recorded

Entity Automatic profilers Examples of recorded data
HTTP request http, Gin, Chi, Echo, Fiber, gRPC Route, status, headers, bounded bodies, duration, error
Middleware http, Gin Name, state, total span, measured middleware work, error
SQL query Bun, GORM, pgx, database/sql, OTel SQL, connection, rows, duration, callsite, optional EXPLAIN
Cache go-cache, go-redis Store, operation, key, hit, TTL, duration, error
Job go-queue, Asynq Queue, state, attempts, bounded arguments, duration, error
Log slog, Zap, zerolog Level, message, structured fields, stack
Mail email, go-mail Transport, recipients, subject, state, duration, error
Outgoing call HTTP, gRPC Method, target, status, bounded payloads, duration, error
Messaging NATS, kafka-go Subject/topic, producer/consumer state, size, duration, error
Schedule schedule Name, planned time, state, duration, error or panic
Callable callable Custom command name, state, duration, payload/result, error or panic
Task core StartTask / MeasureTask Application operation name, state, fields, duration, error or panic
Exception/event HTTP recovery or manual API Type, message, stack, custom fields and tags

All entity types also have context-aware manual logging APIs. See the complete event and entity reference.

Use Task for a long-running application operation that is neither an incoming request, a scheduled callback, nor a callable command. It becomes an independent execution root; pass the callback context to dependencies so its queries, logs, cache operations, and outgoing calls appear in the same scope:

measurement := profiler.MeasureTask(ctx, webpprof.Task{
    Name:   "reports.players.generate",
    Fields: map[string]any{"format": "pdf"},
}, func(taskCtx context.Context) error {
    return reports.Generate(taskCtx)
})

return measurement.Err

Use StartTask and FinishResult when the lifecycle crosses function boundaries or result fields are only known at completion.

For application services and unsupported dependencies, measure a block without writing stopwatch/error boilerplate:

measurement := profiler.Measure(ctx, webpprof.Event{
    Kind: "service",
    Name: "players.refresh",
}, func(ctx context.Context) error {
    return players.Refresh(ctx) // nested profilers inherit this Event as parent
})

metrics.Record(measurement.Failed(), measurement.Duration)
return measurement.Err

MeasureValueWith covers (T, error) functions. StartEvent plus FinishResult provides a manual lifecycle for async wrappers or result-derived status and fields. All helpers use only the standard library, honor WithoutRecording, preserve panics after recording them, and are documented in writing a custom profiler.

Supported integrations

Core and standard-library profilers ship in the root module:

Package Integration point
profiler/http Incoming http.Handler, named middleware, and http.RoundTripper
profiler/sql driver.Connector or driver.Driver before sql.OpenDB
profiler/slog Standard slog.Handler
profiler/email Dependency-neutral mail Sender
profiler/schedule Scheduled func(context.Context) callbacks
profiler/callable Custom func(context.Context) error commands

Optional integrations are isolated modules:

Area Modules
HTTP and RPC Gin, Chi, Echo, Fiber, gRPC
SQL and ORM pgx, GORM, Bun
Cache go-cache, go-redis
Jobs go-queue, Asynq
Messaging NATS, kafka-go
Logging Zap, zerolog
Mail and tracing go-mail, OpenTelemetry

The application retains ownership of wrapped dependencies and closes them as usual. Use one profiler per operation path: stacking Bun, GORM, pgx, database/sql, or OTel instrumentation around the same query records duplicates.

See installation and recipes for every profiler and SQL callsites, EXPLAIN, and replay.

Execution correlation and findings

The request middleware stores a capture in context.Context. Context-aware profilers and Log*Context functions inherit the request ID, tags, and current parent operation:

flowchart LR
    A["Incoming request"] --> B["webpprof middleware"]
    B --> C["context.Context"]
    C --> D["SQL / cache / logs"]
    C --> E["jobs / mail / HTTP calls"]
    D --> F["Request timeline and findings"]
    E --> F
Loading

Automatic findings currently cover repeated query fingerprints, SQL wall-clock coverage, sequential safe HTTP calls, cache miss/query bursts, slow middleware, slow operations, and failed execution roots, jobs, mail, or HTTP calls. Schedule and Callable wrappers plus the Task lifecycle create independent roots and parent their nested work. Bottleneck analysis follows those parent links and prefers a nested operation when it explains most of an inclusive wrapper span. It also requires operation-specific absolute latency thresholds, so an otherwise fast operation is not labeled merely for being the longest.

See request correlation, tags, middleware timing, and finding rules.

Configuration and security

Captures default to at most 10,000 events or 64 MiB for 30 minutes, with a 64 KiB limit per HTTP body. Configure retention, byte limits, sampling, selective capture, redaction, disabled event kinds, and optional local storage at startup:

sqliteStorage, err := webpprofsqlite.Open(context.Background(), "./var/webpprof/events.db")
if err != nil {
    return err
}

profiler := webpprof.New(
    mux,
    webpprof.WithToken(os.Getenv("WEBPPROF_TOKEN")),
    webpprof.WithRetention(2*time.Hour),
    webpprof.WithMaxEvents(25_000),
    webpprof.WithMaxBytes(128<<20),
    webpprof.WithRequestSampleRate(0.25),
    webpprof.WithStorage(sqliteStorage),
)

SQLite is an independent optional module: go get github.com/levskiy0/webpprof/storage/sqlite@latest. Without a token, captured data and live updates stay unavailable. Local-only unauthenticated access requires the explicit webpprof.WithUnsafeUnauthenticatedAccess() option. Existing SQLite users should follow the migration example.

Keep the profiler on loopback or a private administrative network and always set a strong token outside source control. Captures can contain personal data, SQL, request bodies, mail, and stack traces even after automatic redaction.

Documentation

Guide Use it for
MCP server Installing webpprof-mcp and connecting AI coding agents
Integrations Framework, SQL, cache, queue, messaging, logging, and mail setup
Configuration Capture limits, filters, sampling, storage, import, and export
Dashboard Built-in and custom metrics, counters, and charts
Correlation and findings Context propagation, tags, middleware, and automatic analysis
Event reference Manual APIs, Meta, entity fields, and background work
SQL profiling Callsites, source links, EXPLAIN, and Go replay
Custom profilers Implementing an adapter for another dependency

Development

The repository uses go.work for local development; consumers do not need it. Each optional integration and the MCP command has its own go.mod.

make check

The check runs dependency isolation, module verification, go vet, all Go tests, JavaScript syntax validation, and whitespace checks.

License

webpprof is available under the MIT License.

About

Telescope-like application profiler for Go with a live Web UI for HTTP, SQL, cache, jobs, logs, mail, schedules, and runtime metrics.

Topics

Resources

Security policy

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages