dumps

package
v1.28.1 Latest Latest
Warning

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

Go to latest
Published: Jul 8, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package dumps receives, buffers, and fans out PHP `dump()`/`dd()` events captured by the lerd debug bridge (auto_prepend_file). The wire format is newline-delimited JSON. Production lerd-ui listens on a per-user Unix socket; tests bind TCP loopback. See docs/features/dumps.md.

Index

Constants

View Source
const (
	KindDump      = "dump"
	KindQuery     = "query"
	KindJob       = "job"
	KindView      = "view"
	KindMail      = "mail"
	KindCache     = "cache"
	KindEvent     = "event"
	KindHTTP      = "http"
	KindLog       = "log"
	KindException = "exception"
)

Event kinds. KindDump (dump()/dd() output) was the first; the rest are emitted by the lerd_devtools Zend extension and the per-framework adapters (Laravel, Symfony). New kinds are added without bumping ProtocolVersion — the buffer and fan-out treat every kind identically, only per-kind consumers (UI lenses, query analysis) interpret Data.

View Source
const DefaultAddr = "127.0.0.1:9913"

DefaultAddr is the loopback bind address the receiver listens on when callers ask for tcp. Picked to avoid clashing with Symfony's `var-dump-server` default (9912) so users who already run it for some other purpose don't see surprise interceptions.

View Source
const DefaultCapacity = 3000

DefaultCapacity is the maximum number of events the ring keeps before it overwrites the oldest entry. A single N+1 request can emit well over a thousand query events, so the old 500-line cap could not even retain one request's worth for analyze_queries to read; sized up so a fresh capture of one pathological request survives long enough to be analyzed.

View Source
const DefaultNetwork = "unix"

DefaultNetwork is the listen network used by lerd-ui. Unix sockets are the default because the FPM containers can already reach the host home directory via the %h:%h bind mount — using a TCP loopback listener would mean opening the receiver to the entire host network ring just so containers could route through host.containers.internal.

View Source
const (
	// MaxLineBytes caps a single dump payload before bufio drops the line.
	// Sized to absorb VarCloner output for moderately large objects without
	// letting a runaway dump pin memory unboundedly.
	MaxLineBytes = 4 << 20 // 4 MiB

)
View Source
const ProtocolVersion = 1

ProtocolVersion is the wire-format version this package understands. Events with a different `v` are dropped.

Variables

This section is empty.

Functions

This section is empty.

Types

type Context

type Context struct {
	Type    string `json:"type"`
	Site    string `json:"site,omitempty"`
	Branch  string `json:"branch,omitempty"`
	Domain  string `json:"domain,omitempty"`
	Request string `json:"request,omitempty"`
	PID     int    `json:"pid,omitempty"`
	// RID is a unique per-request (FPM) / per-invocation (CLI) id stamped by
	// the lerd_devtools extension so consumers can group events by the exact
	// request, not just method+path+pid (which collapses repeat hits to the
	// same URL on a reused pool worker). dump()/dd() events from the pure-PHP
	// bridge carry a rid too, but when the extension isn't loaded the bridge's
	// rid() falls back to a fresh id per call, so it is NOT stable per request:
	// dump grouping must key on the request, not this field (see eventGroup.ts).
	RID string `json:"rid,omitempty"`
	// Worker names the queue/scheduler command this event came from (e.g.
	// "queue:work", "scrape:rtb-data"). Set only for worker-process events,
	// which are captured solely when the user opts in.
	Worker string `json:"worker,omitempty"`
}

Context describes where a dump came from. Type is "fpm" (web request) or "cli" (artisan, tinker, queue worker). Empty fields are omitted on the wire. Branch is non-empty only when the event originated inside a git worktree (set by the bridge from LERD_BRANCH, injected by nginx for worktree vhosts and by lerd's CLI helpers when shelling into a worktree path).

type Event

type Event struct {
	V     int             `json:"v"`
	ID    string          `json:"id"`
	TS    string          `json:"ts"`
	Kind  string          `json:"kind"`
	Ctx   Context         `json:"ctx"`
	Src   Source          `json:"src"`
	Label string          `json:"label,omitempty"`
	Text  string          `json:"text,omitempty"`
	Tree  json.RawMessage `json:"tree,omitempty"`
	Data  json.RawMessage `json:"data,omitempty"`
	Trunc bool            `json:"trunc,omitempty"`
}

Event is one captured payload. For dumps, Text holds the rendered VarDumper output and Tree the pre-walked cloner tree. For every other kind, Data carries the kind-specific structured fields as opaque JSON (a query's sql/bindings/time, a job's class/status, …). The ring and hub never decode Data; only the UI lens and analysis helpers do.

func (Event) Query added in v1.23.0

func (e Event) Query() (QueryData, bool)

Query decodes the Data payload as a QueryData. ok is false when the event is not a query or its payload does not decode.

func (Event) Valid

func (e Event) Valid() bool

Valid reports whether an event passes the minimum schema check applied by the listener before it is appended to the ring.

type FilterOpts

type FilterOpts struct {
	// Site exact-matches Ctx.Site when non-empty.
	Site string
	// Branch exact-matches Ctx.Branch when non-empty, isolating one git
	// worktree's events from the parent site they share a Site name with.
	Branch string
	// Ctx exact-matches Ctx.Type ("fpm" or "cli") when non-empty.
	Ctx string
	// Kind exact-matches Event.Kind when non-empty (e.g. "query", "dump").
	Kind string
	// SinceID drops events whose ID is lexicographically <= SinceID.
	SinceID string
	// Limit caps the returned slice to the most recent N entries.
	// Zero or negative means no limit.
	Limit int
}

FilterOpts narrows a Snapshot. Zero-value fields are ignored.

type Hub

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

Hub fans Events out to subscribers. Publish is non-blocking; subscribers that don't drain fast enough drop events instead of stalling the listener.

func NewHub

func NewHub() *Hub

NewHub returns an empty Hub.

func (*Hub) Count

func (h *Hub) Count() int

Count returns the number of active subscribers (for status/diagnostics).

func (*Hub) Publish

func (h *Hub) Publish(e Event)

Publish delivers e to every active subscriber. Subscribers whose buffer is full miss the event; the publisher never blocks.

func (*Hub) Subscribe

func (h *Hub) Subscribe() (<-chan Event, func())

Subscribe returns a buffered channel that receives every subsequently published event, plus an unsubscribe func that closes the channel and removes it from the hub. The unsubscribe is idempotent.

type QueryData added in v1.23.0

type QueryData struct {
	SQL        string        `json:"sql"`
	Bindings   []interface{} `json:"bindings,omitempty"`
	TimeMS     float64       `json:"time_ms"`
	Connection string        `json:"connection,omitempty"`
	RWType     string        `json:"rw_type,omitempty"`
}

QueryData is the Data payload for KindQuery events. The lerd_devtools extension fills sql/bindings/time_ms from the agnostic PDO/mysqli hook; the Laravel adapter (QueryExecuted) additionally sets Connection and RWType. The originating file:line lives in Event.Src, like dumps.

type Ring

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

Ring is a fixed-size ring buffer of Events safe for concurrent use. Snapshots are taken under a read lock and returned in insertion order.

func NewRing

func NewRing(capacity int) *Ring

NewRing returns a ring with the given capacity. Non-positive capacity is replaced with DefaultCapacity.

func (*Ring) Append

func (r *Ring) Append(e Event)

Append stores e, evicting the oldest entry once the ring is full.

func (*Ring) Cap

func (r *Ring) Cap() int

Cap returns the maximum number of entries the ring can hold.

func (*Ring) Clear

func (r *Ring) Clear()

Clear empties the ring. Subsequent Snapshot() returns an empty slice.

func (*Ring) Filter

func (r *Ring) Filter(opts FilterOpts) []Event

Filter returns a Snapshot filtered by opts, preserving insertion order.

func (*Ring) Len

func (r *Ring) Len() int

Len returns the number of populated entries.

func (*Ring) Snapshot

func (r *Ring) Snapshot() []Event

Snapshot returns a copy of the ring contents in insertion order (oldest first). The returned slice is independent of the ring's backing array.

type Server

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

Server accepts loopback NDJSON connections from the PHP debug bridge, validates each line against ProtocolVersion, appends valid events to the ring, and publishes them to subscribers. Close once via Close().

func Listen

func Listen(ctx context.Context, addr string) (*Server, error)

Listen binds a TCP listener on addr and starts the accept loop. If addr is empty, DefaultAddr is used. The returned Server keeps running until Close is called or ctx is cancelled. Kept for tests and existing callers that already pass a TCP address; production lerd-ui uses ListenOn with "unix" so the receiver isn't reachable from the host network ring.

func ListenOn

func ListenOn(ctx context.Context, network, addr string) (*Server, error)

ListenOn binds on the given network and address. network is either "tcp" or "unix"; for "unix", any pre-existing socket at addr is removed first so a previous lerd-ui crash doesn't pin the path forever.

func (*Server) Addr

func (s *Server) Addr() string

Addr returns the bound address, useful when Listen was called with :0.

func (*Server) Clear

func (s *Server) Clear()

Clear empties the ring. Active subscribers continue to receive events.

func (*Server) Close

func (s *Server) Close() error

Close stops accepting connections, closes in-flight reads, and waits for outstanding goroutines to drain. Safe to call multiple times.

func (*Server) Filter

func (s *Server) Filter(opts FilterOpts) []Event

Filter returns a filtered Snapshot.

func (*Server) Len

func (s *Server) Len() int

Len returns the number of buffered events.

func (*Server) Push

func (s *Server) Push(e Event)

Push injects an event as if it had arrived on the wire. Used by tests to avoid juggling sockets when only ring/hub semantics matter.

func (*Server) Snapshot

func (s *Server) Snapshot() []Event

Snapshot returns a copy of the ring in insertion order.

func (*Server) Subscribe

func (s *Server) Subscribe() (<-chan Event, func())

Subscribe returns a buffered channel of new events plus an unsubscribe func.

func (*Server) Subscribers

func (s *Server) Subscribers() int

Subscribers returns the current subscriber count.

type Source

type Source struct {
	File string `json:"file"`
	Line int    `json:"line"`
}

Source identifies the file:line that produced a dump.

Jump to

Keyboard shortcuts

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