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

observe

package
v0.17.0 Latest Latest
Warning

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

Go to latest
Published: Oct 23, 2026 License: AGPL-3.0 Imports: 13 Imported by: 0

Documentation

Overview

Package observe keeps durable, revision-fenced observations of expensive or external checks so pages and APIs serve the last saved result at once while refreshes run as bounded background jobs.

Each registered Spec describes one capability kind: how to enumerate its keys, the configuration revision a key currently has, whether the capability is enabled, and the check to run. A refresh is admitted at most once per in-flight generation (one hundred concurrent requests make one job), runs with a timeout and a bounded number of attempts, and only writes its result when the configuration revision it was queued for is still current. The last successful result stays visible with its age when a newer attempt fails; it is never relabelled as the newer attempt.

Index

Constants

View Source
const JobKindPrefix = "observe."

JobKindPrefix prefixes the job kind of every capability ("observe.<kind>"), so a disabled capability's queued refreshes wait unclaimed (and can be parked) instead of failing as unregistered work.

View Source
const ServiceName = "observe"

ServiceName is the kernel service name the admin module publishes.

Variables

View Source
var (
	ErrUnknownKind = errors.New("observe: unknown capability kind")
	ErrDisabled    = errors.New("observe: capability disabled")
	ErrNotFound    = errors.New("observe: key not found")
	ErrManual      = errors.New("observe: results of this kind are recorded by explicit actions only")
)

Errors returned by Refresh.

Functions

func Age

func Age(seconds int64) string

Age formats a saved result's age for templates.

func Migrations

func Migrations() fs.FS

Migrations returns the observations table migrations.

Types

type Attempt

type Attempt struct {
	Status      string  `json:"status" enum:"waiting,running,succeeded,failed,superseded"`
	StartedAt   *string `json:"started_at"`
	FinishedAt  *string `json:"finished_at"`
	Number      int     `json:"number" doc:"1-based attempt number within the job; 0 while waiting"`
	DurationMS  *int64  `json:"duration_ms" doc:"Null until the attempt finished"`
	Error       string  `json:"error" doc:"Sanitized failure reason; empty on success"`
	Remediation string  `json:"remediation"`
	JobID       string  `json:"job_id"`
	Generation  int64   `json:"generation"`
}

Attempt is the latest refresh attempt, independent from the saved result.

type Observation

type Observation struct {
	Kind    string   `json:"kind"`
	Key     string   `json:"key"`
	Status  string   `` /* 222-byte string literal not displayed */
	Attempt *Attempt `json:"attempt" doc:"Null before the first refresh"`
	Saved   *Saved   `json:"saved" doc:"Null until a refresh succeeded"`
	Enabled bool     `json:"enabled"`
}

Observation is the readable state of one key.

type Ref

type Ref struct {
	Kind       string `json:"kind"`
	Key        string `json:"key"`
	JobID      string `json:"job_id"`
	Generation int64  `json:"generation"`
	Deduped    bool   `json:"deduplicated" doc:"True when a refresh for this key was already queued or running"`
}

Ref identifies an admitted or deduplicated refresh.

type Result

type Result struct {
	Scope string
	Data  any
}

Result is what a check returns. Scope names the evidence level, e.g. "connectivity" or "discovery"; it is saved beside the data so readers never mistake reachability for a verified operation.

type Saved

type Saved struct {
	At            string          `json:"at"`
	AgeSeconds    int64           `json:"age_seconds"`
	Revision      string          `json:"revision"`
	RevisionMatch *bool           `json:"revision_match" doc:"Null when the key's current revision cannot be read"`
	DurationMS    *int64          `json:"duration_ms"`
	Scope         string          `json:"scope"`
	Data          json.RawMessage `json:"data"`
}

Saved is the last successful read, kept even when newer attempts fail.

type Service

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

Service owns the observations table and the refresh jobs.

func New

func New(d *sql.DB, q *jobs.Queue, log *slog.Logger) *Service

New returns a service on d; q must be the queue whose workers will run the refreshes. Register specs before the queue starts.

func (*Service) All

func (s *Service) All(ctx context.Context) ([]Observation, error)

All returns every saved observation of every registered kind.

func (*Service) Forget

func (s *Service) Forget(ctx context.Context, kind, key string) error

Forget deletes the saved observation of key (for a removed profile). Queued refreshes for it are superseded when they run.

func (*Service) Get

func (s *Service) Get(ctx context.Context, kind, key string) (Observation, error)

Get returns the observation for key. A key that was never refreshed is returned with status "never" when it exists (Revision != ""), else ErrNotFound.

func (*Service) Kinds

func (s *Service) Kinds() []string

Kinds lists the registered kinds, sorted.

func (*Service) List

func (s *Service) List(ctx context.Context, kind string) ([]Observation, error)

List returns the saved observations of kind, keys sorted.

func (*Service) ListWithRevision added in v0.16.0

func (s *Service) ListWithRevision(ctx context.Context, kind string, revision func(context.Context, string) (string, error)) ([]Observation, error)

ListWithRevision resolves saved observations against a caller's consistent configuration snapshot. The resolver must use already-read configuration; enabled state is evaluated once per list rather than once per saved key. Freshness, attempts and revision mismatch use the same rules as List.

func (*Service) Record

func (s *Service) Record(ctx context.Context, kind, key, revision string, res Result, runErr error, duration time.Duration) error

Record saves the outcome of a check that ran synchronously (an explicit operator action) as the key's newest attempt, outside the job path. The generation is unchanged; a refresh queued for the same key keeps its own fence. A nil err saves the result as the last success; otherwise the previous success is kept and only the attempt is recorded.

func (*Service) Refresh

func (s *Service) Refresh(ctx context.Context, kind, key string) (Ref, error)

Refresh admits one background refresh for key and returns at once with its job reference. A refresh already queued or running for the key is returned instead of a second one (Deduped). It never runs the check in the caller's request.

func (*Service) Register

func (s *Service) Register(spec Spec)

Register adds a capability kind and its job handler. Panics on an empty kind or a duplicate (a programmer error, like duplicate routes).

func (*Service) Tick

func (s *Service) Tick(ctx context.Context) error

Tick is the scheduler: run it from a queue cron. It parks queued refreshes of kinds no longer registered (a disabled capability), releases parked refreshes of registered kinds once, then admits a refresh for every key whose saved result is missing, stale or for another revision, up to MaxInFlight per kind. Disabled kinds are skipped entirely.

type Spec

type Spec struct {
	Kind string
	// Timeout bounds one attempt (default 20s). MaxAttempts bounds retries
	// through the job queue (default 3). Freshness is how long a success is
	// served as fresh and how often the scheduler refreshes keys (default
	// 15m; <= 0 means refresh only on demand). MaxInFlight caps queued or
	// running refreshes of this kind admitted by the scheduler (default 2).
	Timeout     time.Duration
	MaxAttempts int
	Freshness   time.Duration
	MaxInFlight int
	// Keys enumerates the keys the scheduler refreshes (nil: on demand only).
	Keys func(ctx context.Context) ([]string, error)
	// Revision returns the key's current configuration revision, or "" when
	// the key no longer exists. A result is only saved while the revision it
	// was queued for is still current.
	Revision func(ctx context.Context, key string) (string, error)
	// Enabled reports whether the capability may run (nil: always). A
	// disabled capability is neither scheduled nor refreshed on demand;
	// its saved rows are kept.
	Enabled func(ctx context.Context) bool
	// Run performs the check for key at revision. Its error message is
	// stored (truncated) and shown to operators: never include credentials.
	Run func(ctx context.Context, key, revision string) (Result, error)
	// Remediation is the operator hint stored with a failed attempt.
	Remediation string
	// Manual marks a kind whose results come only from Record (an explicit
	// operator action with input the job queue cannot carry, such as a
	// pasted key). Refresh returns ErrManual, the scheduler never admits
	// it, and Run is never called.
	Manual bool
}

Spec registers one capability kind.

Jump to

Keyboard shortcuts

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