Documentation
¶
Overview ¶
Package api implements the read API surface from ARCHITECTURE § 6.
Core endpoints:
GET / — JSON pointer to the viewer project
(binary ships no embedded HTML)
GET /healthz — liveness + in-memory counter snapshot
GET /api/traces — list, SQLite-backed, paginated
GET /api/traces/:id — detail, SQLite + JSONL seek
GET /api/traces/:id/replay — replay recorded SSE events
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func NewMux ¶
NewMux returns an http.Handler ready to mount on the API listener. /api/* requires the admin bearer; /healthz and GET / are unauthenticated so k8s liveness probes, alertmanager, and reverse-proxy health checks (none of which carry bearer tokens) can probe the binary cheaply. The whole mux is wrapped in recoverMW so a handler panic returns 500 instead of taking down the proxy listener that shares this process.
Types ¶
type Deps ¶
type Deps struct {
Store *sqlite.Store
Counters *counters.Counters
AdminToken string
Version string
StartedAt time.Time
// DataDir is the storage root that JSONL paths in SQLite rows are
// relative to. /api/export reads files from here to stream into the
// zip; other handlers seek by absolute JSONLPath and don't need it.
DataDir string
// ExportByteHardCap overrides the default 2 GiB byte cap on
// /api/export (v0.1.2). Set via APILOG_API_EXPORT_BYTE_HARDCAP
// env or `api.export_byte_hardcap` YAML. 0 (zero value) keeps the
// package default; a positive value replaces it; explicit -1 (or
// any negative) disables the cap entirely (equivalent to
// `?bytes_all=1` being the permanent state).
ExportByteHardCap int64
// StorageCoord (v0.1.1) is the storage coordinator. Nil-safe: the
// export handler skips lease arbitration when coord is nil — fine
// for tests / no-retention deployments. When non-nil, exporter
// acquires a lease per (date, keyhash) bucket before reading the
// JSONL so retention can't delete the file mid-stream.
StorageCoord *storage.Coordinator
// Phase K — media extraction toggle. Atomic so PUT /api/config/media
// can flip it from a different goroutine while the writer reads it
// per-trace. Nil = extraction disabled (treat as off).
MediaEnabled *atomic.Bool
// PluginTypes is the catalogue provider for GET /api/plugins/types
// (plugin-b-c-spec §8.5). main.go injects this from the
// builtin-plugin registry; W3 keeps it nil-safe so the handler
// returns an empty list before main.go is wired and during tests
// that do not exercise the catalogue. Returning the slice fresh on
// each call (rather than caching a pointer) lets future hot-swap
// scenarios surface a changing catalogue without touching Deps.
PluginTypes func() []PluginTypeDescriptor
// PluginV2Reg is the live v2 hook-plugin registry. PUT/DELETE
// /api/config/plugins handlers call PluginV2Reg.Reload after a
// successful SaveOverride so the next request sees the new config
// without a process restart (W4.2). Nil-safe: handlers that test
// the persistence layer in isolation can pass Deps without it; the
// handler then skips the Reload step and behaves as a pure
// persist-only endpoint.
PluginV2Reg *pluginv2.Registry
// YAMLPlugins is the pre-override plugin instance list compiled from
// config.yaml at process start. The hot-reload path needs it so
// Reload can merge against YAML defaults the same way startup did
// — passing the merged effective list would double-apply the
// override on each Reload. In v0 the YAML side carries no v2
// instances, so main.go passes nil; the merge semantics in
// pluginv2.Load treat that correctly.
YAMLPlugins []pluginv2.InstanceConfig
// ViewerHost is the optional hosted-viewer surface. When non-nil,
// NewMux registers `<ViewerPublicPath>/` to its handler OUTSIDE
// the auth middleware (the viewer is an unauthenticated browser
// load; the read API the viewer subsequently calls is still
// bearer-gated). Nil-safe: tests and integrations that don't need
// the viewer pass it as zero; the route stays unregistered and
// healthz omits the `viewer` field.
ViewerHost *viewerhost.Host
// ViewerPublicPath is the URL prefix the viewer is mounted under.
// Carried on Deps (instead of read off ViewerHost) so the route
// prefix tracks the operator's APILOG_VIEWER_PUBLIC_PATH override
// without coupling internal/api to viewerhost's accessor surface.
// Empty defaults to "/viewer" at registration time.
ViewerPublicPath string
}
Deps is the bag of process-wide handles the API handlers need.
type PluginConfigField ¶
type PluginConfigField struct {
Name string `json:"name"`
Label string `json:"label"`
Type string `json:"type"`
Default any `json:"default,omitempty"`
Enum []string `json:"enum,omitempty"`
Description string `json:"description,omitempty"`
Required bool `json:"required,omitempty"`
}
PluginConfigField is one form field's descriptor.
Type is one of "string" | "int" | "bool" | "string_array" | "enum". The viewer renders an appropriate input control per Type; unknown types fall back to a string text field on the viewer side.
type PluginConfigSchema ¶
type PluginConfigSchema struct {
Fields []PluginConfigField `json:"fields"`
}
PluginConfigSchema describes the per-instance config a viewer Add / Edit form must render for a given plugin type (spec §8.6).
type PluginTypeDescriptor ¶
type PluginTypeDescriptor struct {
Type string `json:"type"`
Description string `json:"description,omitempty"`
ConfigSchema PluginConfigSchema `json:"config_schema"`
}
PluginTypeDescriptor is one entry in GET /api/plugins/types.
Spec §12.4 explicitly hands W3 the wire shape; this is the shape future builtins (W2) and the viewer Settings UI (W4) will both pin against. Keep fields stable.