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
- type Context
- type Event
- type FilterOpts
- type Group
- type GroupOpts
- type GroupPage
- type Hub
- type QueryData
- type Ring
- func (r *Ring) Append(e Event)
- func (r *Ring) Cap() int
- func (r *Ring) Clear()
- func (r *Ring) Close() error
- func (r *Ring) Counts(opts FilterOpts) map[string]int
- func (r *Ring) Event(id string) (json.RawMessage, bool)
- func (r *Ring) FacetValues(opts FilterOpts) []string
- func (r *Ring) Filter(opts FilterOpts) []Event
- func (r *Ring) FilterJSON(opts FilterOpts) []byte
- func (r *Ring) GroupRows(opts GroupOpts, key string, before int64) []Row
- func (r *Ring) Groups(opts GroupOpts) GroupPage
- func (r *Ring) Import(path string) error
- func (r *Ring) Len() int
- func (r *Ring) Remove(drop func(Event) bool)
- func (r *Ring) RequestIDs() map[string]bool
- func (r *Ring) Resize(capacity int)
- func (r *Ring) SetKeep(keep map[string]bool)
- func (r *Ring) Sites() []string
- func (r *Ring) Snapshot() []Event
- func (r *Ring) TestCount(opts FilterOpts) int
- func (r *Ring) Workers(opts FilterOpts) []string
- type Row
- type Server
- func (s *Server) Addr() string
- func (s *Server) Cap() int
- func (s *Server) Clear()
- func (s *Server) ClearKind(kind string)
- func (s *Server) Close() error
- func (s *Server) Counts(opts FilterOpts) map[string]int
- func (s *Server) Event(id string) (json.RawMessage, bool)
- func (s *Server) FacetValues(opts FilterOpts) []string
- func (s *Server) Filter(opts FilterOpts) []Event
- func (s *Server) FilterJSON(opts FilterOpts) []byte
- func (s *Server) ForgetRequests(rids []string)
- func (s *Server) GroupRows(opts GroupOpts, key string, before int64) []Row
- func (s *Server) Groups(opts GroupOpts) GroupPage
- func (s *Server) Import(path string) error
- func (s *Server) Len() int
- func (s *Server) Push(e Event)
- func (s *Server) RequestIDs() map[string]bool
- func (s *Server) Resize(capacity int)
- func (s *Server) SetKeep(keep map[string]bool)
- func (s *Server) SetKeepTests(keep bool)
- func (s *Server) SetSiteResolver(fn func(string) string)
- func (s *Server) Sites() []string
- func (s *Server) Snapshot() []Event
- func (s *Server) Subscribe() (<-chan Event, func())
- func (s *Server) Subscribers() int
- func (s *Server) TestCount(opts FilterOpts) int
- func (s *Server) Workers(opts FilterOpts) []string
- type Source
Constants ¶
const ( KindDump = "dump" KindQuery = "query" KindJob = "job" KindView = "view" KindMail = "mail" KindCache = "cache" KindEvent = "event" KindHTTP = "http" KindLog = "log" KindException = "exception" KindMessage = "message" // KindBrowser is a JavaScript error, console message or failed request // posted by the browser logs script rather than sent by PHP. KindBrowser = "browser" )
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.
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.
const DefaultCapacity = 5000
DefaultCapacity is how many events the ring keeps when dumps.buffer is unset, matching config.DefaultDumpsBuffer. An event-heavy request emits thousands, so 3000 let one push the requests before it out within seconds.
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.
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 )
const ProtocolVersion = 1
ProtocolVersion is the wire-format version this package understands. Events with a different `v` are dropped.
const SlowMS = 100
SlowMS tags a query at or above it as slow, Telescope's default threshold.
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"`
// Command is the CLI counterpart of Request: the invocation an event came
// from ("artisan queue:work --queue=high"), stamped by the bridge for every
// cli-SAPI process so console events can name where they happened.
Command string `json:"command,omitempty"`
// Test marks an event captured inside a PHPUnit/Pest run. The Debug lenses
// hide these by default; they are tagged rather than dropped so a dump
// added to diagnose a failing test stays one toggle away.
Test bool `json:"test,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) OfRequest ¶ added in v1.37.0
OfRequest reports whether an event belongs to the request rid names: it ran in that request, or it is a browser event naming it as the request a fetch or XHR reached.
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
// RID keeps one request's events: those it ran, and a browser event that
// names it as the request a fetch reached. A kept request is found even
// after it left the buffer.
RID string
// SinceID drops events whose ID is lexicographically <= SinceID.
SinceID string
// Before keeps only events whose ID sorts before it, so a list pages back
// from the oldest row it already shows.
Before string
// HideTests leaves out events captured inside a test run.
HideTests bool
// Route keeps one route as the timing view names it ("GET /users/:id").
Route 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 Group ¶ added in v1.37.0
type Group struct {
Key string `json:"key"`
Count int `json:"count"`
TotalMS float64 `json:"total_ms"`
SlowCount int `json:"slow_count"`
NPlusOne bool `json:"n_plus_one"`
Rows []Row `json:"rows"`
// contains filtered or unexported fields
}
Group is one request in a lens, its newest Rows rows first.
type GroupOpts ¶ added in v1.37.0
type GroupOpts struct {
FilterOpts
// Search matches the lens's text: a query's SQL, a dump's output, any
// other kind's payload, and every event's request, route and id.
Search string
// Worker keeps one queue or scheduler command's events.
Worker string
// HideWorkers leaves out what worker processes emitted, except jobs, which
// are the only sign a queue is being drained.
HideWorkers bool
// Facet keeps one job status, log level or browser event type.
Facet string
// Before is a page's Next, to read the groups older than that page.
Before int64
// Limit is how many groups a page holds, Rows how many rows each carries.
Limit int
Rows int
}
GroupOpts narrows a lens. FilterOpts carries the scope (site, branch, kind, request, test runs); the rest are the lens's own controls.
type GroupPage ¶ added in v1.37.0
type GroupPage struct {
Groups []Group `json:"groups"`
Next int64 `json:"next"`
Total int `json:"total"`
}
GroupPage is one page of a lens. Next reads the page after it, 0 at the end; Total is every event the lens matches, across all its pages.
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.
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 the debug buffer: the newest cap events, plus every event of the kept requests however old. It lives in SQLite rather than memory, since a single slow page can carry thousands of events and lerd-ui has to stay small; a reader decodes only what it asked for. Safe for concurrent use.
func NewRing ¶
NewRing returns a ring held in an in-memory database, for a process that does not need the buffer to outlive it.
func OpenRing ¶ added in v1.37.0
OpenRing opens (creating if needed) the ring stored at path, so the buffer survives a lerd-ui restart. Non-positive capacity means DefaultCapacity.
func (*Ring) Append ¶
Append stores e, dropping the oldest event once the ring is full unless it belongs to a kept request.
func (*Ring) Counts ¶ added in v1.37.0
func (r *Ring) Counts(opts FilterOpts) map[string]int
Counts is how many events of each kind opts selects, page views aside: the lens bar's badges, counted where the events are rather than in a tab.
func (*Ring) Event ¶ added in v1.37.0
func (r *Ring) Event(id string) (json.RawMessage, bool)
Event is one whole event by id, for a row a lens opens.
func (*Ring) FacetValues ¶ added in v1.37.0
func (r *Ring) FacetValues(opts FilterOpts) []string
FacetValues lists the facet values opts's kind has in its scope: a job's statuses, a log's levels, a message's channels, a browser event's types.
func (*Ring) Filter ¶
func (r *Ring) Filter(opts FilterOpts) []Event
Filter returns the events opts selects, oldest first.
func (*Ring) FilterJSON ¶ added in v1.37.0
func (r *Ring) FilterJSON(opts FilterOpts) []byte
FilterJSON is Filter encoded as a JSON array, built from the stored rows as they are, so serving thousands of events costs one copy rather than a decode and an encode of each.
func (*Ring) GroupRows ¶ added in v1.37.0
GroupRows reads more of one group's rows, the ones older than the row at before, newest first. Paging from a row rather than an offset keeps events that land in the group meanwhile from handing back a row already shown.
func (*Ring) Groups ¶ added in v1.37.0
Groups returns one page of opts's lens: the requests with the latest activity first, each with its count, query time and N+1 flag.
func (*Ring) Import ¶ added in v1.37.0
Import appends the events an older lerd-ui saved to a JSON file at path, oldest first, and deletes the file once every one is on disk. Until then it is their only copy, so a write that fails, or a ring held in memory, leaves it for the next start. A missing file is nothing to import.
func (*Ring) Remove ¶ added in v1.36.0
Remove drops every event drop matches, kept requests included.
func (*Ring) RequestIDs ¶ added in v1.37.0
RequestIDs is the set of requests with at least one event in the ring: the ones a recent request's Inspect can open on something.
func (*Ring) Resize ¶ added in v1.37.0
Resize changes how many events the ring keeps, dropping the oldest that no longer fit unless a kept request ran them.
func (*Ring) SetKeep ¶ added in v1.37.0
SetKeep replaces the set of requests whose events outlive the buffer, and lets go of the ones no longer in it.
func (*Ring) Sites ¶ added in v1.37.0
Sites lists every site with an event in the buffer, for the site filter.
func (*Ring) TestCount ¶ added in v1.37.0
func (r *Ring) TestCount(opts FilterOpts) int
TestCount is how many test-run events opts would select with them shown, for the hint that some are hidden.
func (*Ring) Workers ¶ added in v1.37.0
func (r *Ring) Workers(opts FilterOpts) []string
Workers lists the worker commands with events in opts's scope, for the lens command filter.
type Row ¶ added in v1.37.0
type Row struct {
Event json.RawMessage `json:"event"`
Dup int `json:"dup"`
Seq int64 `json:"seq"`
}
Row is one event and, for a query, how often its fingerprint ran in the request (1 when unique). Seq is its place in the buffer, which reading more of the group pages back from.
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 ¶
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 ¶
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 ListenWithRing ¶ added in v1.37.0
ListenWithRing is ListenOn buffering into ring, such as one OpenRing keeps on disk so the buffer survives a restart.
func (*Server) Cap ¶ added in v1.37.0
Cap returns how many events the server keeps, and Resize changes it.
func (*Server) Clear ¶
func (s *Server) Clear()
Clear empties the ring. Active subscribers continue to receive events.
func (*Server) ClearKind ¶ added in v1.37.0
ClearKind drops the buffered events of one kind and keeps the rest.
func (*Server) Close ¶
Close stops accepting connections, closes in-flight reads, and waits for outstanding goroutines to drain. Safe to call multiple times.
func (*Server) Counts ¶ added in v1.37.0
func (s *Server) Counts(opts FilterOpts) map[string]int
Counts, TestCount, Groups, GroupRows, Sites and Workers are the Debug lenses' queries; see the Ring methods of the same names.
func (*Server) FacetValues ¶ added in v1.37.0
func (s *Server) FacetValues(opts FilterOpts) []string
func (*Server) Filter ¶
func (s *Server) Filter(opts FilterOpts) []Event
Filter returns a filtered Snapshot.
func (*Server) FilterJSON ¶ added in v1.37.0
func (s *Server) FilterJSON(opts FilterOpts) []byte
FilterJSON is Filter as the JSON array the API serves.
func (*Server) ForgetRequests ¶ added in v1.37.0
ForgetRequests drops every buffered event of the given requests, as their history is removed from request timing.
func (*Server) Import ¶ added in v1.37.0
Import takes in the buffer an older lerd-ui saved as JSON at path.
func (*Server) Push ¶
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) RequestIDs ¶ added in v1.37.0
RequestIDs is the set of requests with captured events still buffered.
func (*Server) SetKeep ¶ added in v1.37.0
SetKeep names the requests whose events outlive the buffer.
func (*Server) SetKeepTests ¶ added in v1.36.0
SetKeepTests switches recording of test-run events. Switching it off also drops the ones already buffered, since the space they hold is the reason.
func (*Server) SetSiteResolver ¶ added in v1.37.0
SetSiteResolver sets how an incoming event's site name is mapped to the registered site before the event is stored.
func (*Server) Subscribe ¶
Subscribe returns a buffered channel of new events plus an unsubscribe func.
func (*Server) Subscribers ¶
Subscribers returns the current subscriber count.
func (*Server) TestCount ¶ added in v1.37.0
func (s *Server) TestCount(opts FilterOpts) int
func (*Server) Workers ¶ added in v1.37.0
func (s *Server) Workers(opts FilterOpts) []string