Documentation
¶
Overview ¶
Package web renders isutools measurements: a live report, a self-contained downloadable snapshot.html, machine-readable JSON, and a reset endpoint.
Index ¶
- Constants
- func NewHandler(p Provider) http.Handler
- func PruneProfileArtifacts(dataDir, protectFile string)
- func SectionHealth(sections map[string]any) []health.Entry
- type AdminAudit
- type AdminErrorResponse
- type BoundaryProfiler
- type BoundaryWindow
- type CPUCaptureCoordinator
- type CPUCaptureStatus
- type CPUIntervalCapture
- type CPULabelDictionary
- type CPUStartRequest
- type CPUStartResult
- type CPUStopRequest
- type CPUStopTicket
- type FixedCPUProfileRecord
- type FixedCPUProfiler
- type FixedCPUStartRequest
- type Meta
- type ProfileAnalysisCapabilities
- type ProfileAnalysisCommit
- type ProfileAnalysisCurrent
- type ProfileAnalysisPublishRequest
- type ProfileAnalysisPublishResponse
- type ProfileCapture
- type ProfileExpectation
- type ProfileExpectedInput
- type ProfileManifest
- type ProfilePair
- type ProfilePoint
- type Provider
- type RendererIdentity
- type RunAbort
- type RunCollectorBoundary
- type RunFinish
- type RunInfo
- type RunSnapshot
- type RunStart
- type RuntimeProfileSemantic
- type SafeLabelTuple
- type SaveResponse
- type Snapshot
- type TraceCaptureCoordinator
- type TraceCaptureStatus
- type TraceIntervalCapture
- type TraceStartRequest
- type TraceStartResult
- type TraceStopRequest
- type TraceStopTicket
Constants ¶
const ( SaveReasonMethodNotAllowed = "method-not-allowed" SaveReasonDataDirUnset = "data-dir-unset" SaveReasonInvalidPass = "invalid-pass" SaveReasonRunNotActive = "run-not-active" SaveReasonRunAlreadySaved = "run-already-saved" SaveReasonMutationBusy = "mutation-busy" SaveReasonSnapshotTooLarge = "snapshot-too-large" SaveReasonPersistFailed = "persist-failed" SaveReasonPersistenceUnsafe = "persistence-unavailable" SaveReasonSaved = "saved" )
const AdminReasonHeader = "X-Isutools-Reason"
AdminReasonHeader mirrors the stable machine-readable reason in an admin endpoint error response. It lets shell wrappers classify a failure without parsing human text.
Variables ¶
This section is empty.
Functions ¶
func NewHandler ¶
NewHandler returns the report handler. Routes are relative: GET / (run index), GET /<run-id> (stored run detail), GET /live, GET /snapshot.html, GET /json, GET /files/<name>, POST /reset, POST /collect, POST /finish, POST /abort, POST /save.
func PruneProfileArtifacts ¶ added in v1.4.0
func PruneProfileArtifacts(dataDir, protectFile string)
PruneProfileArtifacts applies the shared raw-profile retention after a run-aligned CPU completion that may occur without any cumulative profile capture to trigger the handler-local path.
func SectionHealth ¶ added in v1.2.0
SectionHealth derives the health entries a completed run's sections report, one per collector, sorted by collector name.
The baseline collectors carry their notes inside the section value instead of pushing them into a registry, because Collect must be pure. Somebody has to forward them; this is that step, and it is exported so the process-wide registry and this package's renderer forward exactly the same set.
Types ¶
type AdminAudit ¶ added in v1.5.0
type AdminAudit struct {
Time time.Time `json:"time"`
Operation string `json:"operation"`
Status int `json:"status"`
Reason string `json:"reason"`
RunID string `json:"run_id,omitempty"`
Generation int64 `json:"generation"`
}
AdminAudit is a bounded, secret-free audit event for mutating admin calls. Provider.AdminAudit may ship it to an application logger; otherwise web writes the JSON object to the standard logger.
type AdminErrorResponse ¶ added in v1.5.0
AdminErrorResponse is deliberately small and stable. Internal errors, request values, filesystem paths, DSNs and credentials never enter it.
type BoundaryProfiler ¶ added in v1.2.0
type BoundaryProfiler struct {
// contains filtered or unexported fields
}
BoundaryProfiler captures the opening half of a profile pair for a run that was opened outside this package's HTTP surface.
It exists because POST /reset is not the only way a run begins. An application that follows the documented initialize contract opens its runs from its own handler through isutools.ResetNow and may never send a reset at all; without this entry point such a process publishes no opening artifact, and every closing capture finds nothing to pair with and writes nothing.
Both entry points share one process-wide ledger keyed by the data directory, so a run opened here is closed by POST /finish or POST /save exactly as a run opened by POST /reset is, and the two halves are filed under one prefix.
func NewBoundaryProfiler ¶ added in v1.2.0
func NewBoundaryProfiler(p Provider) *BoundaryProfiler
NewBoundaryProfiler returns the capturer for a provider's profile configuration, or nil when the configuration captures nothing — no data directory to publish into, or no profile kinds enabled.
Only DataDir, RuntimeProfiles and Health are read; the capture path touches no collector and serves no request. The kinds are copied, so a caller that later rewrites its own slice cannot change what an opened run captures at its closing boundary.
func (*BoundaryProfiler) CaptureOpen ¶ added in v1.2.0
func (b *BoundaryProfiler) CaptureOpen(run RunStart, generation int64) []string
CaptureOpen writes the opening half of the run's profile pair and returns the artifacts it published.
Call it the moment the coordinator returns the boundary and before the response that releases the benchmarker: the capture is synchronous for the same reason the reset path's is, because a moment chosen by the scheduler is not a boundary.
A nil receiver captures nothing, so a caller never has to branch on whether profiling was configured. Nothing here is fatal.
type BoundaryWindow ¶ added in v1.2.0
type BoundaryWindow struct {
Min time.Time `json:"min,omitzero"`
Max time.Time `json:"max,omitzero"`
Spread time.Duration `json:"spread_ns"`
}
BoundaryWindow is the measured span of one coordinated boundary.
type CPUCaptureCoordinator ¶ added in v1.4.0
type CPUCaptureCoordinator interface {
StartRun(context.Context, CPUStartRequest) CPUStartResult
StartFixed(context.Context, FixedCPUStartRequest) CPUStartResult
RequestStop(CPUStopRequest) CPUStopTicket
Await(CPUStopTicket, context.Context) CPUCaptureStatus
Manifest(runID string, epoch uint64) *CPUIntervalCapture
LabelDictionary(runID string, epoch uint64) *CPULabelDictionary
}
CPUCaptureCoordinator is the transport-facing view of the process-wide CPU profiler owner. Implementations must make RequestStop non-blocking; the runtime profiler's synchronous flush belongs to its worker, never an HTTP or run-controller goroutine.
type CPUCaptureStatus ¶ added in v1.4.0
type CPUCaptureStatus struct {
RunID string
CaptureID string
Epoch uint64
State string
Code string
Err error
BoundaryStart time.Time
BoundaryFinish time.Time
StartRequestedAt time.Time
StartCompletedAt time.Time
StopRequestedAt time.Time
StopCompletedAt time.Time
StopReason string
RunSpan time.Duration
CaptureSpan time.Duration
HeadLoss time.Duration
TailExcess time.Duration
TailLoss time.Duration
Complete bool
}
type CPUIntervalCapture ¶ added in v1.4.0
type CPUIntervalCapture struct {
RunID string `json:"run_id"`
Epoch uint64 `json:"epoch"`
CaptureID string `json:"capture_id"`
ExpectedFile string `json:"expected_file"`
File string `json:"file,omitempty"`
SHA256 string `json:"sha256,omitempty"`
Bytes int64 `json:"bytes,omitempty"`
Sidecar string `json:"sidecar,omitempty"`
SidecarSHA256 string `json:"sidecar_sha256,omitempty"`
CoverageFile string `json:"coverage_file,omitempty"`
CoverageSHA256 string `json:"coverage_sha256,omitempty"`
Status string `json:"status"`
Code string `json:"code,omitempty"`
BoundaryStart time.Time `json:"boundary_start,omitzero"`
BoundaryFinish time.Time `json:"boundary_finish,omitzero"`
StartRequestedAt time.Time `json:"start_requested_at,omitzero"`
StartCompletedAt time.Time `json:"start_completed_at,omitzero"`
StopRequestedAt time.Time `json:"stop_requested_at,omitzero"`
StopCompletedAt time.Time `json:"stop_completed_at,omitzero"`
StopReason string `json:"stop_reason,omitempty"`
RunSpanNs int64 `json:"run_span_ns,omitempty"`
CaptureSpanNs int64 `json:"capture_span_ns,omitempty"`
HeadLossNs int64 `json:"head_loss_ns,omitempty"`
TailExcessNs int64 `json:"tail_excess_ns,omitempty"`
TailLossNs int64 `json:"tail_loss_ns,omitempty"`
Complete bool `json:"complete"`
}
CPUIntervalCapture is the immutable snapshot projection. Fields are added only when the underlying artifact and hash have been fixed.
type CPULabelDictionary ¶ added in v1.4.0
type CPUStartRequest ¶ added in v1.4.0
type CPUStartRequest struct {
RunID string
Epoch uint64
State string
Validity string
BoundaryStart time.Time
GenerationWindow BoundaryWindow
BoundaryWindow BoundaryWindow
}
type CPUStartResult ¶ added in v1.4.0
type CPUStopRequest ¶ added in v1.4.0
type CPUStopTicket ¶ added in v1.4.0
type FixedCPUProfileRecord ¶ added in v1.4.0
type FixedCPUProfileRecord struct {
Schema string `json:"schema"`
Mode string `json:"mode"`
CaptureID string `json:"capture_id"`
Generation int64 `json:"generation"`
RequestedAt time.Time `json:"requested_at"`
StartCompletedAt time.Time `json:"start_completed_at,omitzero"`
StopRequestedAt time.Time `json:"stop_requested_at,omitzero"`
StopCompletedAt time.Time `json:"stop_completed_at,omitzero"`
DurationNs int64 `json:"duration_ns,omitempty"`
File string `json:"file,omitempty"`
SHA256 string `json:"sha256,omitempty"`
Bytes int64 `json:"bytes,omitempty"`
Status string `json:"status"`
Code string `json:"code,omitempty"`
Visibility string `json:"visibility,omitempty"`
Durability string `json:"durability,omitempty"`
}
FixedCPUProfileRecord is the immutable evidence record for the legacy timer-only CPU capture mode. It deliberately contains no RunID because fixed mode is not aligned to a run boundary and must not be mistaken for one.
type FixedCPUProfiler ¶ added in v1.4.0
type FixedCPUProfiler struct {
// contains filtered or unexported fields
}
FixedCPUProfiler is the process-shared entry point for timer-only fixed capture. Handler and ResetNow can hold the same instance; the package-wide runtime guard also preserves compatibility for independently constructed legacy handlers.
func NewFixedCPUProfiler ¶ added in v1.4.0
func NewFixedCPUProfiler(dataDir string, duration time.Duration) *FixedCPUProfiler
func (*FixedCPUProfiler) Capture ¶ added in v1.4.0
func (p *FixedCPUProfiler) Capture(generation int64) bool
type FixedCPUStartRequest ¶ added in v1.4.0
type Meta ¶
type Meta struct {
SchemaVersion int `json:"schema_version"`
Time string `json:"time"`
Generation int64 `json:"generation"`
Revision string `json:"revision"`
Dirty bool `json:"dirty"`
// BuildSource says how Revision was obtained (vcs, ldflags, env, unknown).
// ProvenanceValid is false for an unknown or dirty build, where a snapshot
// cannot be reproduced from Revision alone.
BuildSource string `json:"build_source"`
ProvenanceValid bool `json:"provenance_valid"`
// Score is the benchmark score supplied via POST /save?score=; persisted
// snapshots always carry it so every report is attributable to a result.
Score string `json:"score,omitempty"`
BenchmarkPass *bool `json:"benchmark_pass,omitempty"`
Host sysinfo.Info `json:"host"`
Partial bool `json:"partial"`
Health []health.Entry `json:"health,omitempty"`
Run *RunInfo `json:"run,omitempty"`
// Profiles is the run's runtime-profile record: every capture attempted at
// either boundary and the pairs that can be differenced. It is filled when
// a run is persisted, because that is the first moment both halves exist;
// a live report has no closing half yet and omits the field. Additive and
// omitempty, so a v1.0 reader of this JSON is unaffected.
Profiles *ProfileManifest `json:"profiles,omitempty"`
}
Meta identifies when, on which host, and from which revision a snapshot was taken. Generation increments on every reset so runs are comparable.
type ProfileAnalysisCapabilities ¶ added in v1.4.0
type ProfileAnalysisCapabilities struct {
Schema string `json:"schema"`
StrongAtomicVisibility bool `json:"strong_atomic_visibility"`
CrashDurability string `json:"crash_durability"`
CapabilityError string `json:"capability_error,omitempty"`
RetentionRuns int `json:"retention_runs"`
RetentionBytes uint64 `json:"retention_bytes"`
ProfileCaptureMaxBytes uint64 `json:"profile_capture_max_bytes"`
CaptureSidecarMaxBytes uint64 `json:"capture_sidecar_max_bytes"`
CPUCoverageMaxBytes uint64 `json:"cpu_coverage_max_bytes"`
CPULabelDictionaryMaxBytes uint64 `json:"cpu_label_dictionary_max_bytes"`
ExpectedProfileFilesPerRun uint64 `json:"expected_profile_files_per_run"`
SnapshotArtifactMaxPerRun uint64 `json:"snapshot_artifact_max_bytes_per_run"`
PerRunCeilingBytes uint64 `json:"per_run_ceiling_bytes"`
ProfileUsageKnown bool `json:"profile_usage_known"`
ProfileUsageBytes uint64 `json:"profile_usage_bytes,omitempty"`
DataDirAvailableKnown bool `json:"data_dir_available_known"`
DataDirAvailableBytes uint64 `json:"data_dir_available_bytes,omitempty"`
CurrentGeneration int64 `json:"current_generation"`
EnabledProfileKinds []string `json:"enabled_profile_kinds"`
RuntimeProfileSemantics []RuntimeProfileSemantic `json:"runtime_profile_semantics"`
}
type ProfileAnalysisCommit ¶ added in v1.4.0
type ProfileAnalysisCommit struct {
ProfileAnalysisCurrent
PreviousCommitSequence uint64 `json:"previous_commit_sequence,omitempty"`
PreviousCommitFile string `json:"previous_commit_file,omitempty"`
}
type ProfileAnalysisCurrent ¶ added in v1.4.0
type ProfileAnalysisCurrent struct {
SchemaVersion int `json:"schema_version"`
AnalysisID string `json:"analysis_id"`
ArtifactID string `json:"artifact_id"`
CommitSequence uint64 `json:"commit_sequence"`
SnapshotSHA256 string `json:"snapshot_sha256"`
JSONFile string `json:"json_file"`
JSONSHA256 string `json:"json_sha256"`
HTMLFile string `json:"html_file"`
HTMLSHA256 string `json:"html_sha256"`
CommitFile string `json:"commit_file"`
Renderer RendererIdentity `json:"renderer"`
}
type ProfileAnalysisPublishRequest ¶ added in v1.4.0
type ProfileAnalysisPublishRequest struct {
ExpectedCurrentArtifactID string `json:"expected_current_artifact_id"`
Analysis profilemodel.ProfileAnalysisV1 `json:"analysis"`
}
type ProfileAnalysisPublishResponse ¶ added in v1.4.0
type ProfileAnalysisPublishResponse struct {
AnalysisID string `json:"analysis_id"`
ArtifactID string `json:"artifact_id"`
CommitSequence uint64 `json:"commit_sequence"`
JSONFile string `json:"json_file"`
HTMLFile string `json:"html_file"`
CurrentArtifactID string `json:"current_artifact_id"`
Renderer RendererIdentity `json:"renderer"`
Visibility string `json:"visibility"`
Durability safefs.Durability `json:"durability"`
}
type ProfileCapture ¶ added in v1.2.0
type ProfileCapture struct {
RunID string `json:"run_id"`
Epoch uint64 `json:"epoch"`
Point ProfilePoint `json:"point"`
Kind string `json:"kind"`
// File is the published ".pprof" name, empty when nothing was published.
File string `json:"file,omitempty"`
SHA256 string `json:"sha256,omitempty"`
// Sidecar is this record's own file name, so a manifest entry can be
// followed back to the record on disk.
Sidecar string `json:"sidecar"`
OpenGate string `json:"open_gate,omitempty"`
// Orphan marks an artifact whose run never reached a closing boundary. It
// is written into the record rather than left to inference, because a lone
// opening profile is otherwise indistinguishable from half of a pair whose
// other half has not been taken yet.
Orphan bool `json:"orphan,omitempty"`
// The reference point this capture is measured from, copied from the
// coordinator's boundary record. A boundary is an interval rather than an
// instant, so the measured spreads travel with it and form the uncertainty
// floor under every residual below. Legacy providers leave them zero, which
// means "not reported", not "measured as zero".
RefPhase string `json:"ref_phase"`
RefAt time.Time `json:"ref_at,omitzero"`
RefSpreadNs int64 `json:"ref_spread_ns"`
BoundaryAt time.Time `json:"boundary_at,omitzero"`
BoundarySpreadNs int64 `json:"boundary_spread_ns"`
// The measured capture instants. LagFromRefNs is the distance from the
// boundary to the moment the write actually began, which is the number the
// residual error is built out of.
StartedAt time.Time `json:"started_at,omitzero"`
FinishedAt time.Time `json:"finished_at,omitzero"`
LagFromRefNs int64 `json:"lag_from_ref_ns"`
DurationNs int64 `json:"duration_ns"`
Bytes int64 `json:"bytes"`
Status string `json:"status"`
Code string `json:"code,omitempty"`
Err string `json:"err,omitempty"`
}
ProfileCapture is one profile file's record: what was captured, when, and how far after the boundary it claims to bracket. It is the content of the ".meta.json" sidecar written next to every artifact.
The sidecar is the durable primary record. An opening capture is written at reset, long before any snapshot exists to hold a manifest, so the sidecar is the only place the opening moment can survive a process that never finishes the run.
type ProfileExpectation ¶ added in v1.4.0
type ProfileExpectation struct {
Kind string `json:"kind"`
Mode string `json:"mode"`
Status string `json:"status,omitempty"`
Code string `json:"code,omitempty"`
Inputs []ProfileExpectedInput `json:"inputs"`
}
type ProfileExpectedInput ¶ added in v1.4.0
type ProfileManifest ¶ added in v1.2.0
type ProfileManifest struct {
RunID string `json:"run_id"`
Epoch uint64 `json:"epoch"`
Validity string `json:"validity,omitempty"`
Captures []ProfileCapture `json:"captures,omitempty"`
// Pairs holds only the kinds whose two halves both exist. A kind with one
// half is deliberately absent: a difference cannot be taken from it, and
// listing it would invite the reader to try.
Pairs []ProfilePair `json:"pairs,omitempty"`
Expected []ProfileExpectation `json:"expected,omitempty"`
// CPU is the separately owned interval profile. Unlike Captures/Pairs it
// has one run-aligned input rather than cumulative open/close halves.
CPU *CPUIntervalCapture `json:"cpu,omitempty"`
Trace *TraceIntervalCapture `json:"trace,omitempty"`
CPULabelDictionary *CPULabelDictionary `json:"cpu_label_dictionary,omitempty"`
Executable *buildinfo.ExecutableIdentity `json:"executable,omitempty"`
}
ProfileManifest is a run's whole profile record: every capture attempted at either boundary, and the pairs that can actually be differenced.
type ProfilePair ¶ added in v1.2.0
type ProfilePair struct {
Kind string `json:"kind"`
OpenFile string `json:"open_file"`
CloseFile string `json:"close_file"`
OpenSHA256 string `json:"open_sha256"`
CloseSHA256 string `json:"close_sha256"`
OpenGate string `json:"open_gate,omitempty"`
// RunSpanNs is the distance between the two boundaries themselves.
RunSpanNs int64 `json:"run_span_ns"`
// HeadLossNs is the run's beginning that the difference does not contain.
HeadLossNs int64 `json:"head_loss_ns"`
// TailExcessNs is the post-boundary tail that the difference does contain.
TailExcessNs int64 `json:"tail_excess_ns"`
// ApproxErrorNs is HeadLossNs + TailExcessNs: the total by which the
// difference is not the run.
ApproxErrorNs int64 `json:"approx_error_ns"`
DiffCommand string `json:"diff_command"`
}
ProfilePair is one kind's difference over a run: the two artifacts plus the measured error in treating their difference as the run.
It is an approximation and says so. The difference starts a little after the run does (HeadLossNs, not included) and ends a little after the run ends (TailExcessNs, included), because both halves are taken by the caller after the coordinator has already fixed the boundary.
func (ProfilePair) Lagging ¶ added in v1.2.0
func (p ProfilePair) Lagging() bool
Lagging reports whether either half of the pair was taken too far from the boundary it names. The Runs detail page and the health verdict both call this, so the badge on the page and the entry in health can never disagree.
func (ProfilePair) Notes ¶ added in v1.2.0
func (p ProfilePair) Notes() []string
Notes returns the sentences the Runs detail page prints under a pair.
The approximation notice is unconditional. A small residual is still a residual, and a reader who sees the notice only on bad runs will read its absence as "this one is exact", which no pair ever is.
func (ProfilePair) ResidualText ¶ added in v1.2.0
func (p ProfilePair) ResidualText() string
ResidualText renders the pair's residual error for the Runs detail page.
type ProfilePoint ¶ added in v1.2.0
type ProfilePoint string
ProfilePoint names the run boundary a runtime profile was captured at. A mutex, block or heap profile is process-wide and cumulative, so a single file says nothing about a run: only the difference between the two boundaries does, and the point is what tells them apart.
const ( // ProfilePointOpen is the capture taken as the run opens. ProfilePointOpen ProfilePoint = "open" // ProfilePointClose is the capture taken as the run's boundary is frozen. ProfilePointClose ProfilePoint = "close" )
type Provider ¶
type Provider struct {
SQL sqlSnapshotter
// SQLGeneration and RotateSQL opt into atomic generation boundaries. They
// are separate callbacks so simple aggregation tables remain usable in
// tests and custom integrations.
SQLGeneration func() int64
RotateSQL func() (generation int64, entries []agg.Entry)
// RunGenerationManaged is shorthand for custom providers whose SQL, HTTP,
// and Counters generations are all owned by StartRun. The per-collector
// flags below let production preserve that guarantee when only a subset
// registered successfully.
RunGenerationManaged bool
SQLGenerationManaged bool
HTTPGenerationManaged bool
CountersGenerationManaged bool
RedisGenerationManaged bool
FlowGenerationManaged bool
FlowSource string
Health *health.Registry
HTTP httpCollector
AccessLog accessLogCollector
AccessLogQuiet time.Duration
AccessLogPoll time.Duration
// AccessLogGenerationManaged says the access log's generation adapter is
// registered with the run coordinator, so the coordinator's
// BeginBoundary → Drain → Release cycle owns the aggregate's lifetime.
//
// POST /reset must then keep its hands off the legacy Snapshot()+Reset()
// pair. Reset re-opens the log at the current end of file, drops the
// aggregate and zeroes the health counters the drain's file-replacement
// guard reads; running it between a closing boundary and that boundary's
// drain leaves the drain nothing to seal, and the finished run's
// access-log section silently comes out empty.
AccessLogGenerationManaged bool
CollectTimeout time.Duration
// InspectionTimeout bounds the context passed to DB and Advisor callbacks.
InspectionTimeout time.Duration
Proc processCollector
// ProcRunManaged says Proc is registered with the run coordinator. Its
// reset and final snapshot then happen inside StartRun/FinishRun for both
// the HTTP and embedded ResetNow entry points.
ProcRunManaged bool
// DB captures the database schema (tables/indexes). Called at handler
// startup and on every reset so each generation records the pre-run state.
DB func(context.Context) *dbinspect.Schema
// DBCapabilities returns credential-free, per-target support states.
DBCapabilities func() []dbcap.Target
// PeerResults returns the sealed, host-by-host multi-host evidence. Values
// are displayed separately and are never summed across machines.
PeerResults func() []multihost.PeerResult
// Advisor reports well-known settings that are not configured. Captured
// alongside the DB schema at startup and on every reset.
Advisor func(context.Context) []advisor.Check
// CacheTelemetry is evaluated at snapshot time so application cache
// hit/miss/eviction counters can match the measured interval.
CacheTelemetry func() (*advisor.CacheTelemetry, error)
// QUICTelemetry is evaluated at snapshot time so packet counters can match
// the completed benchmark interval rather than handler startup.
QUICTelemetry func() (*advisor.QUICTelemetry, error)
// ProtocolTrafficClientFacing is false when a CDN/LB terminates the client
// connection before the locally collected access log.
ProtocolTrafficClientFacing *bool
// Counters exposes user-defined counters (isutools.Count). Reset per
// generation.
Counters interface {
Snapshot() []counters.Entry
Reset()
}
// Redis exposes sanitized command-only latency aggregates.
Redis interface {
Snapshot() []redisstats.Entry
Reset()
}
// Flow exposes proxy-independent middleware journeys.
Flow interface {
Snapshot() flowstats.Snapshot
Reset()
}
// DataDir persists snapshots for the dashboard history ("" = disabled).
DataDir string
Executable *buildinfo.ExecutableIdentity
// AdminAudit receives bounded structured audit records for /save failures
// and publication. Request values and underlying error strings are omitted.
AdminAudit func(AdminAudit)
// ProfileAnalysis enables the opt-in derived analysis publication endpoint.
// Original snapshot bytes remain immutable regardless of this setting.
ProfileAnalysis bool
// PprofDuration > 0 captures a CPU profile for that long after every
// reset (i.e. covering the benchmark), stored in DataDir (0 = disabled).
PprofDuration time.Duration
// CPUProfiles is the process-wide managed CPU profiler owner. Nil preserves
// the standalone fixed-duration compatibility path.
CPUProfiles CPUCaptureCoordinator
// CPUProfileMode is "run", "fixed", or empty/off.
CPUProfileMode string
// TraceCapture is the optional, run-aligned execution trace owner. It is
// nil by default and must not be configured with another managed profiler.
TraceCapture TraceCaptureCoordinator
// StartRun opens a measurement run at the reset boundary and names it in
// the reset response. Nil keeps the legacy behaviour, in which a reset
// only rotates the collector generations and no run id exists.
//
// A failure is not fatal to the reset: the generations have already been
// rotated by the time it is called, and refusing to answer would leave the
// bench script unable to proceed with measurements that are, in fact,
// running.
StartRun func(ctx context.Context) (RunStart, error)
// FinishRun fixes the closing boundary of the run in flight and returns as
// soon as that boundary exists. POST /finish calls it and answers 202:
// draining and snapshot building continue in the background, and making
// the caller wait for them would put snapshot-building time inside the
// measured window of whatever runs next.
//
// Nil leaves POST /finish unavailable, which is the legacy behaviour of a
// transport wired without a run coordinator.
FinishRun func(ctx context.Context) (RunFinish, error)
// CompleteRun finishes the run in flight, waits for its immutable
// snapshot, and acknowledges it. POST /save calls it before rendering, so
// the persisted report describes the interval the run measured rather than
// whatever the live collectors happen to hold after their generations were
// frozen.
//
// A process that never opened a run must report the zero RunFinish and no
// error: /save predates the run lifecycle and has to keep working without
// one.
CompleteRun func(ctx context.Context) (RunFinish, error)
// AbortRun abandons the run in flight and fences its background worker.
// POST /abort is idempotent and publishes no snapshot; profile artifacts
// already captured at the opening boundary are marked as orphans.
AbortRun func(ctx context.Context) (RunAbort, error)
// Sections supplies the completed run's collector sections keyed by
// collector name, as produced by the run coordinator. Unknown keys and
// unexpected types are ignored, so a collector can be added on one side of
// the wiring before the other catches up.
Sections func() map[string]any
// RunSnapshot supplies the same sections together with the lifecycle
// evidence that makes a completed run auditable. When set it supersedes
// Sections; the older callback remains for custom-provider compatibility.
RunSnapshot func() *RunSnapshot
// Timeline resolves the bounded, run/epoch-aligned phase analysis. Nil is
// the default-off compatibility path.
Timeline func(runID string, epoch uint64) *timeline.Section
// RuntimeProfiles lists the runtime profiles ("mutex", "block", "heap",
// "allocs", "goroutine", "threadcreate", or "goroutineleak")
// captured at a run boundary, in capture order. Empty — the default —
// captures nothing. The rates themselves are process-wide runtime
// settings owned by the caller; this package only writes what it is told
// is enabled, so a profile whose rate is zero must not appear here.
RuntimeProfiles []string
}
Provider supplies the collectors to render. Nil fields are skipped.
type RendererIdentity ¶ added in v1.4.0
type RunAbort ¶ added in v1.2.0
type RunAbort struct {
RunID string `json:"run_id,omitempty"`
Epoch uint64 `json:"epoch,omitempty"`
Reason string `json:"reason,omitempty"`
Detached bool `json:"detached,omitempty"`
AbortedAt time.Time `json:"aborted_at,omitzero"`
Partial []string `json:"partial,omitempty"`
}
RunAbort is the transport projection of the coordinator's abort result. POST /abort itself answers 204, but the handler needs this record to orphan the right profile pair and report the run id back in its header.
type RunCollectorBoundary ¶ added in v1.2.0
type RunCollectorBoundary struct {
Name string `json:"name"`
Kind string `json:"kind"`
Required bool `json:"required"`
Phase string `json:"phase"`
At time.Time `json:"at,omitzero"`
Committed bool `json:"committed"`
Code string `json:"code,omitempty"`
Err string `json:"err,omitempty"`
Dropped bool `json:"dropped,omitempty"`
}
RunCollectorBoundary records one collector operation at a run boundary.
type RunFinish ¶ added in v1.2.0
type RunFinish struct {
// RunID names the run whose boundary was fixed. Empty means no run was in
// flight, which is not an error: the save/collect loop predates runs.
RunID string `json:"run_id,omitempty"`
// Epoch is the coordinator fencing token for this closing boundary.
Epoch uint64 `json:"epoch,omitempty"`
// Validity is the run's data-quality verdict ("valid", "partial",
// "invalid"), copied verbatim like RunStart.Validity.
Validity string `json:"validity,omitempty"`
// State is normally omitted. Recovery saves set it to the terminal state
// that prevented a normal finish, so an expired run can never look like a
// successfully completed interval.
State string `json:"state,omitempty"`
// StartedAt is copied from the opening boundary for a recovery save. Normal
// completions obtain the same value from RunSnapshot instead.
StartedAt time.Time `json:"started_at,omitzero"`
// AcceptedAt is the measured moment the closing boundary was fixed. It is
// the end of the interval every section of this run describes.
AcceptedAt time.Time `json:"accepted_at,omitzero"`
// Recovered marks the explicit fail-open path used when StartedTTL already
// abandoned the run before /save arrived. RecoveryReason is the stable
// lifecycle reason (currently "started-ttl").
Recovered bool `json:"recovered,omitempty"`
RecoveryReason string `json:"recovery_reason,omitempty"`
// GenerationWindow and BoundaryWindow preserve the coordinator's measured
// uncertainty at the closing boundary for profile residual accounting.
GenerationWindow BoundaryWindow `json:"generation_window,omitzero"`
BoundaryWindow BoundaryWindow `json:"boundary_window,omitzero"`
}
RunFinish is the record of a run's closing boundary, as reported by Provider.FinishRun and Provider.CompleteRun.
type RunInfo ¶ added in v1.2.0
type RunInfo struct {
RunID string `json:"run_id"`
Epoch uint64 `json:"epoch"`
Validity string `json:"validity"`
State string `json:"state,omitempty"`
Recovered bool `json:"recovered,omitempty"`
RecoveryReason string `json:"recovery_reason,omitempty"`
Trigger string `json:"trigger,omitempty"`
Collectors []RunCollectorBoundary `json:"collectors,omitempty"`
GenerationWindow BoundaryWindow `json:"generation_window"`
BoundaryWindow BoundaryWindow `json:"boundary_window"`
StartedAt time.Time `json:"started_at,omitzero"`
FinishedAt time.Time `json:"finished_at,omitzero"`
}
RunInfo is the immutable lifecycle envelope persisted with a report.
type RunSnapshot ¶ added in v1.2.0
RunSnapshot is the provider-side form of a completed run. Sections remain top-level in the report while Info is persisted under Meta.Run.
type RunStart ¶ added in v1.2.0
type RunStart struct {
// RunID is the coordinator's run identifier, echoed in the reset response
// so a bench script can name the run it started.
RunID string
// Epoch is the coordinator fencing token. It prevents a delayed boundary
// artifact from being attached to a newer incarnation of the same run id.
Epoch uint64
// State is the coordinator state at the completed opening boundary. A
// managed reset is allowed to begin profiling only for "started"; notably,
// a required collector failure returns "aborted" with a nil error.
State string
// StartedAt is the opening boundary's moment. Boundary artifacts are named
// after it rather than after the moment they are written, so an opening
// and a closing artifact of one run share a filename prefix.
StartedAt time.Time
// Validity is the run's data-quality verdict ("valid", "partial",
// "invalid"). It is a plain string because the transport copies it
// verbatim and never branches on it.
Validity string
// GenerationWindow and BoundaryWindow preserve the coordinator's measured
// uncertainty at the opening boundary for profile residual accounting.
GenerationWindow BoundaryWindow
BoundaryWindow BoundaryWindow
}
RunStart identifies the measurement run a reset opened.
type RuntimeProfileSemantic ¶ added in v1.7.0
type RuntimeProfileSemantic struct {
Kind string `json:"kind"`
Available bool `json:"available"`
Mode string `json:"mode"`
CapturePoint string `json:"capture_point"`
SampleTypes []string `json:"sample_types"`
Approximate bool `json:"approximate"`
Interference string `json:"interference,omitempty"`
}
RuntimeProfileSemantic is the stable contract for each runtime profile. Interval profiles are close-boundary snapshots; cumulative profiles require both boundaries and include measured head/tail approximation.
func RuntimeProfileSemantics ¶ added in v1.7.0
func RuntimeProfileSemantics() []RuntimeProfileSemantic
RuntimeProfileSemantics reports runtime availability instead of assuming a profile added by a newer Go release exists in the running binary.
type SafeLabelTuple ¶ added in v1.4.0
type SaveResponse ¶ added in v1.4.0
type SaveResponse struct {
File string `json:"file"`
SnapshotBase string `json:"snapshot_base"`
SnapshotFile string `json:"snapshot_file"`
SnapshotSchemaVersion int `json:"snapshot_schema_version"`
RunID string `json:"run_id,omitempty"`
SnapshotSHA256 string `json:"snapshot_sha256"`
Visibility string `json:"visibility"`
Durability string `json:"durability"`
}
SaveResponse pins the exact raw snapshot bytes at the moment /save publishes them. Callers can put this hash into an ABBA ledger without a later fetch racing retention or another generation.
type Snapshot ¶
type Snapshot struct {
Meta Meta `json:"meta"`
DB *dbinspect.Schema `json:"db,omitempty"`
DBCapabilities []dbcap.Target `json:"db_capabilities,omitempty"`
DBCapabilityMatrix []dbcap.MatrixRow `json:"db_capability_matrix,omitempty"`
Advisor []advisor.Check `json:"advisor,omitempty"`
Counters []counters.Entry `json:"counters,omitempty"`
Redis []redisstats.Entry `json:"redis,omitempty"`
Flow *flowstats.Snapshot `json:"flow,omitempty"`
FlowSource string `json:"flow_source,omitempty"`
Connections *httpstats.ConnSnapshot `json:"connections,omitempty"`
SQL []agg.Entry `json:"sql"`
HTTP httpstats.Snapshot `json:"http,omitempty"`
AccessLog *accesslog.Snapshot `json:"accesslog,omitempty"`
Proc *procstats.Snapshot `json:"proc,omitempty"`
Timeline *timeline.Section `json:"timeline,omitempty"`
// The sections below come from the run coordinator's baseline collectors
// rather than from a live collector read, so they describe the interval
// between two run boundaries and are absent until a run has completed.
// Every one of them is additive and omitempty: a v1.0 reader of this JSON
// is unaffected by their presence.
//
// The JSON keys are the collector names the coordinator registers under,
// so a section can be traced from the snapshot back to the collector that
// filled it without a translation table.
Host *hoststats.Section `json:"hoststats,omitempty"`
Network *netstats.NetworkStats `json:"network,omitempty"`
SQLRows *sqlrows.Section `json:"sqlrows,omitempty"`
DBPool []dbpool.Entry `json:"dbpool,omitempty"`
// QueryPlan holds the EXPLAIN output captured in the run's enrich phase.
// It is filled from the same section map as the others rather than from a
// live read, which is what keeps a dashboard refresh from putting EXPLAIN
// statements on the measured database.
QueryPlan *queryplan.Section `json:"queryplan,omitempty"`
Peers []multihost.PeerResult `json:"peers,omitempty"`
}
Snapshot is the complete state of all measurements at one point in time.
func (Snapshot) FlowVisualization ¶ added in v1.7.0
FlowVisualization follows the same single-source contract as UserFlows. It never combines middleware and proxy observations from one request.
func (Snapshot) ScenarioStories ¶ added in v1.6.0
func (s Snapshot) ScenarioStories() []accesslog.StoryEntry
ScenarioStories enforces the configured source. Auto mode prefers the proxy-independent middleware collector and falls back to legacy proxy-log labels only when middleware produced no observations.
type TraceCaptureCoordinator ¶ added in v1.7.0
type TraceCaptureCoordinator interface {
StartRun(TraceStartRequest) TraceStartResult
RequestStop(TraceStopRequest) TraceStopTicket
Await(TraceStopTicket, context.Context) TraceCaptureStatus
Manifest(runID string, epoch uint64) *TraceIntervalCapture
}
TraceCaptureCoordinator is the transport-facing owner of one bounded runtime execution trace. Stop must be non-blocking.
type TraceCaptureStatus ¶ added in v1.7.0
type TraceIntervalCapture ¶ added in v1.7.0
type TraceIntervalCapture struct {
RunID string `json:"run_id"`
Epoch uint64 `json:"epoch"`
CaptureID string `json:"capture_id"`
ExpectedFile string `json:"expected_file"`
File string `json:"file,omitempty"`
SHA256 string `json:"sha256,omitempty"`
Bytes int64 `json:"bytes,omitempty"`
Sidecar string `json:"sidecar,omitempty"`
SidecarSHA256 string `json:"sidecar_sha256,omitempty"`
Status string `json:"status"`
Code string `json:"code,omitempty"`
BoundaryStart time.Time `json:"boundary_start,omitzero"`
BoundaryFinish time.Time `json:"boundary_finish,omitzero"`
StartCompleted time.Time `json:"start_completed_at,omitzero"`
StopCompleted time.Time `json:"stop_completed_at,omitzero"`
StopReason string `json:"stop_reason,omitempty"`
RequestedSpanNs int64 `json:"requested_span_ns"`
CaptureSpanNs int64 `json:"capture_span_ns"`
HeadLossNs int64 `json:"head_loss_ns"`
TailExcessNs int64 `json:"tail_excess_ns"`
Complete bool `json:"complete"`
}