Help us shape the future of Go! Take the 2026 Go Developer Survey

devtools

package
v0.30.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 19, 2026 License: MIT Imports: 28 Imported by: 0

Documentation

Overview

Package devtools is Vukem's development dashboard, served at /_vukem: recent requests with timings, SQL queries (with N+1 detection), jobs, events, sent mail previews, log records, per-request traces and the route table. Everything lives in bounded in-memory ring buffers.

Apps enable it with vukem.WithDevtools() or DEVTOOLS=true; the app refuses to boot when it is enabled with APP_ENV=production, and the dashboard answers only loopback requests for a loopback Host unless DEVTOOLS_INSECURE_ALLOW_REMOTE=true. Collection hooks are observers set on the database, queue and event bus, a mail transport wrapper and a slog handler, so an app without devtools pays nothing.

New returns the Devtools collector; Devtools.Middleware records requests, Devtools.Register mounts the dashboard at Path, and the Observe methods, Devtools.MailTransport and Devtools.LogHandler are the hooks the app wires for you.

See https://github.com/AlexGalhardo/vukem/blob/main/docs/devtools.md.

Index

Examples

Constants

View Source
const (
	DefaultCapacity          = 200
	DefaultNPlusOneThreshold = 3
)

Defaults for Config.

View Source
const Path = "/_vukem"

Path is the dashboard prefix.

Variables

This section is empty.

Functions

func NormalizeSQL

func NormalizeSQL(query string) string

NormalizeSQL returns the statement shape used for display and N+1 detection: literals become "?", $n placeholders become "?", lists of placeholders collapse to "(?...)" and whitespace is collapsed. Literal values never reach the dashboard.

Example
package main

import (
	"fmt"

	"github.com/AlexGalhardo/vukem/devtools"
)

func main() {
	// Literals never reach the dashboard; the shape also groups N+1 queries.
	fmt.Println(devtools.NormalizeSQL("SELECT * FROM posts WHERE user_id = 42 AND title = 'secret'"))
	fmt.Println(devtools.NormalizeSQL("SELECT * FROM users WHERE id IN ($1, $2, $3)"))
}
Output:
SELECT * FROM posts WHERE user_id = ? AND title = ?
SELECT * FROM users WHERE id IN (?...)

func RedactArgs

func RedactArgs(args []any) []string

RedactArgs describes bound values by type (and length for strings and bytes), never by value: arguments hold user data, tokens and passwords.

Example
package main

import (
	"fmt"

	"github.com/AlexGalhardo/vukem/devtools"
)

func main() {
	fmt.Println(devtools.RedactArgs([]any{42, "hunter2", []byte("raw")}))
}
Output:
[int string(len=7) bytes(len=3)]

Types

type Config

type Config struct {
	// Capacity is the number of records kept per kind (default 200).
	Capacity int
	// NPlusOneThreshold flags a SELECT whose normalized statement runs at
	// least this many times within one request (default 3).
	NPlusOneThreshold int
	// InsecureAllowRemote serves the dashboard to any client. By default
	// only loopback clients with a loopback Host (no proxy headers) get it.
	InsecureAllowRemote bool
	// Level is the minimum level of collected log records (default Info).
	Level slog.Leveler
	// Routes lists the app routes for the routes page (Router.Routes).
	Routes func() []router.RouteInfo
	// Now is the clock (default time.Now).
	Now func() time.Time
}

Config tunes the collector.

type Devtools

type Devtools struct {
	// contains filtered or unexported fields
}

Devtools collects records and serves the dashboard. It implements database.QueryObserver, queue.Observer and events.Observer.

func New

func New(cfg Config) *Devtools

New returns an empty collector.

func (*Devtools) Allowed

func (d *Devtools) Allowed(r *http.Request) bool

Allowed reports whether r may see the dashboard: with InsecureAllowRemote always; otherwise only when the direct peer is a loopback address, no proxy header is present, and Host is a loopback name (which defeats DNS rebinding from a page the developer visits).

func (*Devtools) Events

func (d *Devtools) Events() []Event

Events returns the recorded dispatches, newest first.

func (*Devtools) Jobs

func (d *Devtools) Jobs() []Job

Jobs returns the recorded job steps, newest first.

func (*Devtools) LogHandler

func (d *Devtools) LogHandler() slog.Handler

LogHandler returns a slog.Handler that keeps records at Config.Level or above; tee it next to the app handler with slog.NewMultiHandler.

func (*Devtools) Logs

func (d *Devtools) Logs() []Log

Logs returns the recorded log records, newest first.

func (*Devtools) MailTransport

func (d *Devtools) MailTransport(next mail.Transport) mail.Transport

MailTransport wraps next so every message it sends is kept for preview.

func (*Devtools) Mails

func (d *Devtools) Mails() []Mail

Mails returns the recorded messages, newest first.

func (*Devtools) Middleware

func (d *Devtools) Middleware() router.Middleware

Middleware records every request except the dashboard's own. Install it first with Router.UseServer so its timing covers the whole stack.

func (*Devtools) ObserveEvent

func (d *Devtools) ObserveEvent(ctx context.Context, e events.Event)

ObserveEvent implements events.Observer.

func (*Devtools) ObserveJob

func (d *Devtools) ObserveJob(ctx context.Context, e queue.JobEvent)

ObserveJob implements queue.Observer.

func (*Devtools) ObserveQuery

func (d *Devtools) ObserveQuery(ctx context.Context, q database.Query)

ObserveQuery implements database.QueryObserver.

func (*Devtools) Queries

func (d *Devtools) Queries() []Query

Queries returns the recorded queries, newest first.

func (*Devtools) Register

func (d *Devtools) Register(r *router.Router)

Register adds the dashboard routes under Path, guarded by Allowed.

func (*Devtools) Requests

func (d *Devtools) Requests() []Request

Requests returns the recorded requests, newest first.

func (*Devtools) RouteMiddleware

func (d *Devtools) RouteMiddleware() router.Middleware

RouteMiddleware captures the matched route pattern; install it with Router.Use.

func (*Devtools) Trace

func (d *Devtools) Trace(id string) (Trace, bool)

Trace returns the request with trace id id and its timeline.

type Event

type Event struct {
	TraceID   string
	Time      time.Time
	Type      string
	Listeners int
	Duration  time.Duration
	Err       string
}

Event is a recorded event dispatch.

type Job

type Job struct {
	TraceID  string
	Time     time.Time
	ID       string
	Kind     string
	Queue    string
	Status   string
	Attempt  int
	Duration time.Duration
	Err      string
}

Job is a recorded queue step.

type Log

type Log struct {
	TraceID string
	Time    time.Time
	Level   string
	Message string
	Attrs   string
}

Log is a recorded log record.

type Mail

type Mail struct {
	ID          string
	TraceID     string
	Time        time.Time
	From        string
	To          []string
	Cc          []string
	Subject     string
	HTML        string
	Text        string
	Attachments []string
	Err         string
}

Mail is a recorded outgoing message.

type Query

type Query struct {
	TraceID  string
	Time     time.Time
	SQL      string
	Args     []string
	Duration time.Duration
	Caller   string
	Err      string
	NPlusOne bool
}

Query is a recorded SQL statement; Args are redacted to types.

type Repeat

type Repeat struct {
	SQL   string
	Count int
}

Repeat is a statement shape and how often it ran in one request.

type Request

type Request struct {
	// ID is the devtools trace id ("r12").
	ID string
	// RequestID is the X-Request-ID response header, when set.
	RequestID string
	Method    string
	Path      string
	// Pattern is the matched ServeMux pattern ("GET /users/{id}").
	Pattern string
	// Route is the route name, when the route has one.
	Route     string
	Status    int
	Start     time.Time
	Duration  time.Duration
	Queries   int
	QueryTime time.Duration
	// NPlusOne lists the SELECT shapes repeated at least the threshold.
	NPlusOne []Repeat
}

Request is a recorded HTTP request.

type TimelineItem

type TimelineItem struct {
	Offset time.Duration
	Kind   string
	Text   string
	Detail string
	Link   string
	Flag   bool
}

TimelineItem is one entry of a request trace.

type Trace

type Trace struct {
	Request Request
	Items   []TimelineItem
}

Trace is a request with everything recorded during it, in time order.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL