Skip to content

Digging deeper

Dev dashboard

A development-only dashboard at /_vukem with requests, SQL queries and N+1 detection, jobs, events, mail previews, logs and per-request traces.

Last updated:

The devtools package (core, stdlib only) serves a dashboard at /_vukem: recent requests with timings, SQL queries with N+1 detection, jobs, events, sent mail previews, log records, a per-request trace and the route table. Everything lives in bounded in-memory ring buffers (200 records per kind).

Enabling#

Terminal
DEVTOOLS=true vukem serve   # or set DEVTOOLS=true in .env
Go
app, err := vukem.New(vukem.WithDevtools(), /* … */) // app.Devtools; nil when off
  • The dashboard answers only requests whose direct peer is a loopback address, whose Host is localhost, *.localhost or a loopback IP, and that carry no Forwarded, X-Forwarded-* or X-Real-Ip header. Anything else gets a plain 404. The Host check stops DNS-rebinding pages from reading the dashboard through your browser.
  • DEVTOOLS_INSECURE_ALLOW_REMOTE=true drops those checks (an app in a container or a remote VM). Anyone who reaches the app then sees its requests, queries, logs and mail.

Pages#

PathShows
/_vukem/counts per kind, N+1 alerts, recent requests
/_vukem/requests, /_vukem/requests/{id}requests (method, path, route, status, duration, query count); the trace of one request with a timeline of its queries, logs, jobs, events and mail
/_vukem/queriesnormalized SQL, redacted arguments, duration, caller frame, N+1 badge
/_vukem/jobsdispatched and attempted jobs (kind, queue, status, attempt, error)
/_vukem/eventsdispatched event types, listener count, duration, error
/_vukem/mails, /_vukem/mails/{id}sent messages and their HTML and text preview
/_vukem/logslog records at LOG_LEVEL or above
/_vukem/routesthe route table with middleware

Pages are server-rendered with no script, so they work under the default CSP. ?refresh=5 reloads the page every 5 seconds (2–60). The dashboard's own requests are never recorded.

How it collects#

KindHook
Requestsoutermost server middleware, so timings cover the whole stack
SQLa database.QueryObserver set by app.DB(); observers added with vukem.WithQueryObservers (tracing) run next to it; statements run on DB.SQL() directly bypass it
Jobs, eventsqueue.Observer and events.Observer
Mailwraps the transport chosen by MAIL_MAILER
Logsa handler teed next to the app's

The observed packages never import devtools; with it off, each hook costs one nil check.

Redaction and N+1#

  • SQL is shown as a normalized shape (literals and placeholders become ?). Bound arguments are shown as types and lengths (string(len=16), int, NULL), never values. Jobs and events show kinds and Go types, not payloads.
  • A SELECT shape that runs at least 3 times in one request (devtools.Config.NPlusOneThreshold) is flagged as N+1.
  • Mail HTML renders in a sandboxed iframe under a CSP with no script source that blocks remote images (and tracking pixels).