agent

package
v0.5.0 Latest Latest
Warning

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

Go to latest
Published: Nov 10, 2026 License: Apache-2.0 Imports: 37 Imported by: 0

Documentation

Overview

Derived from reqfleet/shibuya; modified for engine-sdk.

Derived from reqfleet/shibuya; modified for engine-sdk. Package agent runs coordinator-dependent engine adapters.

Platform support

Deployed agents require Linux containers and cgroup resource metrics. Windows clients may import SDK types and use Handler without starting an agent. On non-Unix systems, AgentServer.Run returns an error matching errors.ErrUnsupported before starting workers, subscriptions, or HTTP services. Workload execution requires Unix process-group supervision.

Coordinator authority

An agent is not a standalone runner. The coordinator authorizes preparation, start and stop, and supplies an explicit RunSpec for the addressed agent. Settings are already resolved: adapters must not interpret VU scope, redistribute load, infer settings from topology or manufacture a missing assignment. Native settings may already be rendered into coordinator-provided configuration files. Artifact assignments are per file, not derived from the agent's identity. Materialized input has already been partitioned; native input requires the engine to apply the exact supplied shard. Replicated input is consumed whole.

Callback order and ownership

PrepareDependencies receives the staged dependency declaration, if any. An absent declaration still invokes reconciliation to remove prior dependencies. A coordinator preparation barrier may separate this stage from start. Execution artifacts are staged before BeforeStart, then BuildCommand returns the primary command. No callback launches or reaps the primary workload; the runtime owns it. Context paths are absolute. Inputs, results and temporary files are reset per run. State and dependency reconciliation files survive. The current runtime serializes runs and reuses the existing image paths only after cleanup ends.

Observe and Progress run after launch, on separate polling loops, outside the runtime lock. Live Progress uses the monitor's cancellation context, allowing summaries to outlast individual observation probes without delaying readiness or status requests. Their read-only RunContext remains valid until each callback returns. Callbacks must honor context cancellation, including child processes. They may cache engine-private summaries by RunID, but must not mutate the supplied settings or artifact maps. BuildCommand is required; other hooks are optional. Without Observe, a successful launch acknowledges readiness.

Outcomes and shutdown

Startup acknowledgement and terminal outcome are independent. WorkComplete acknowledges that startup succeeded but cannot override a failed process. A successful short run completes even if readiness was never polled. A nonzero exit after readiness is an execution failure. Optional progress cannot change lifecycle state or make the status endpoint unavailable. Progress payloads must be valid JSON and identify their engine schema; aggregation belongs to the coordinator. After canceling and joining the live monitors, the runtime captures a final progress snapshot with a fresh two-second context. Adapters should reuse cached summaries/checkpoints rather than restart canceled long-running work.

Stop targets a run and carries the coordinator's reason: scheduled completion or cancellation. Preparation cancellation prevents launch. The runtime retains ownership while callbacks roll back or terminate child processes. For a running workload, Stop receives a fresh context bounded by StopTimeout (ten seconds by default). Without Stop the runtime sends SIGTERM to the process group; after the grace period it sends SIGKILL. Stop must honor its context and must not wait on the primary process. The runtime reaps it, terminates remaining descendants and joins all callbacks/readers before releasing the workspace for another run.

Duplicate requests do not execute a run twice. Retired run IDs are remembered for the agent process lifetime. A stale stop or callback cannot affect a newer run. A new run cannot start while preparation, execution or cleanup is active. Run-scoped progress acknowledges a stopped run only after its worker has finished cleanup. A stop received before preparation tombstones that run ID.

Metrics integration

Adapters either map result-file events with MetricParser, explicitly declare MetricsSchemaShibuyaV1 for an adapter-normalized MetricsHandler or MetricsURL, or expose the registry without request ingestion. These sources are mutually exclusive; a Prometheus handler or URL alone is not a schema mapping. See the metrics contract for names, units, labels, bucket profiles, accumulation semantics, and built-in adapter limitations.

Runtime label admission uses AgentServerOptions.LabelsUsageLimit, not coordinator run messages. LoadAgentServerOptions resolves the lowercase label_limit environment variable (default 10 when unset or empty); MakeAgentServer uses the same loader. NewAgentServer uses the resolved option directly, including zero. Adapters can initialize native exporters from those options before construction. The SDK has no tier policy. Workloads inherit label_limit if present; Command.Env may override it. The SDK does not rewrite it from LabelsUsageLimit. Native engines enforce their own configured limits. Native proxying streams by default without parsing, format negotiation, validation, or SDK label admission. MetricsHandler serves directly behind the SDK's GET /metrics authentication, preserving the incoming request context and the handler's status, headers, and body, including errors. It does not proxy, parse, fold, cache, or merge output. The adapter owns parsing, normalization, label limits, concurrent access, run-local exporter state, final-scrape retention, and exporter shutdown; the SDK owns the listener. ResultFile may still name workload output without a parser.

FoldNativeMetrics explicitly enables last-resort SDK folding for URL-backed native engines that cannot enforce the budget. It and NativeMetricsOverflowLabel require MetricsURL and cannot be used with MetricsHandler or registry ingestion. Folding buffers and parses each Prometheus text snapshot (at most 16 MiB), validates safe aggregation, and re-encodes the result. Invalid snapshots fail rather than bypassing admission. Admission is stable across scrapes; colliding cumulative counters and histograms are aggregated within each snapshot, not added again across snapshots. The producer must retain cumulative source series for the run. NativeMetricsOverflowLabel defaults to "others"; Replay's engine-owned overflow convention is "_other_". Replay handles its limits through config.yaml with SDK folding disabled. Its native max_labels=0 setting remains unlimited.

With folding enabled, admission survives completion for final scrapes and resets on the next successful workload launch; the producer must still be reachable. This bounds exported request labels, not producer memory, other dimensions, or plan-wide labels across agents. Result-file ingestion and opt-in folding permit N named labels plus one overflow label; zero permits only overflow in these SDK-managed modes. Upload validators return optional preflight counts to the calling control plane without tier or label-limit inputs; those counts do not guarantee runtime cardinality.

Derived from reqfleet/shibuya; modified for engine-sdk.

Derived from reqfleet/shibuya; modified for engine-sdk.

Derived from reqfleet/shibuya; modified for engine-sdk.

Derived from reqfleet/shibuya; modified for engine-sdk.

Derived from reqfleet/shibuya; modified for engine-sdk.

Derived from reqfleet/shibuya; modified for engine-sdk.

Derived from reqfleet/shibuya; modified for engine-sdk.

Index

Constants

View Source
const (
	FILEMODE = 0700
)

Variables

View Source
var STDERR = "/dev/stderr"

Functions

This section is empty.

Types

type AgentDir

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

func NewAgentDirHandler

func NewAgentDirHandler(dir string) AgentDir

func (AgentDir) ConfFilesDir

func (af AgentDir) ConfFilesDir() ConfFilesDirectory

func (AgentDir) Dir

func (af AgentDir) Dir() AgentDirectory

func (AgentDir) ResultFilesDir

func (af AgentDir) ResultFilesDir() ResultFilesDirectory

func (AgentDir) TestFilesDir

func (af AgentDir) TestFilesDir() TestFilesDirectory

type AgentDirectory

type AgentDirectory string

func (AgentDirectory) Filepath

func (af AgentDirectory) Filepath(sub ...string) string

type AgentServer

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

func MakeAgentServer

func MakeAgentServer(options AgentServerOptions) *AgentServer

MakeAgentServer loads environment-backed options using LoadAgentServerOptions, then constructs a server with NewAgentServer. It logs fatally on configuration errors. Call LoadAgentServerOptions directly to handle errors without exiting or to configure adapter components before constructing the server.

func NewAgentServer

func NewAgentServer(opts AgentServerOptions) *AgentServer

NewAgentServer constructs a server from explicit options without reloading the environment-backed settings handled by LoadAgentServerOptions. It does not start listeners or workloads; call Run to start the agent. A zero LabelsUsageLimit is used as-is, not replaced with a default.

func (*AgentServer) Handler

func (as *AgentServer) Handler() http.Handler

Handler returns the authenticated agent HTTP endpoints. Health checks bypass authentication.

func (*AgentServer) Run

func (as *AgentServer) Run() error

func (*AgentServer) SubscribeToCoordinator

func (as *AgentServer) SubscribeToCoordinator() (chan protocol.Message, error)

type AgentServerOptions

type AgentServerOptions struct {
	EngineMeta          EngineMeta
	CoordinatorRootCAs  *x509.CertPool
	TestFileName        string
	DependencyFileName  string
	PrepareDependencies func(context.Context, RunContext) error
	BeforeStart         func(context.Context, RunContext) error
	BuildCommand        func(context.Context, RunContext) (Command, error)
	Observe             func(context.Context, RunContext) (protocol.Observation, error)
	Progress            func(context.Context, RunContext) (protocol.Progress, error)
	Stop                func(context.Context, RunContext, Process) error
	StopTimeout         time.Duration
	// MetricsURL proxies an external normalized endpoint; it cannot be combined
	// with MetricsHandler or MetricParser.
	MetricsURL string
	// MetricsHandler serves normalized metrics directly at the authenticated
	// GET /metrics route, using the incoming request and response writer.
	// It requires NativeMetricsSchema and cannot be combined with MetricsURL,
	// MetricParser, FoldNativeMetrics, or NativeMetricsOverflowLabel.
	// ResultFile may still name workload output; the SDK does not tail it.
	// The adapter owns normalization, label limits, concurrent access, run-local
	// state, and exporter shutdown. The SDK owns the HTTP listener and does not
	// parse, merge, cache, or close the handler's output or state.
	MetricsHandler http.Handler
	// NativeMetricsSchema declares the profile supplied by MetricsURL or MetricsHandler.
	NativeMetricsSchema MetricsSchema
	// FoldNativeMetrics opts into SDK parsing and label folding for MetricsURL
	// as a last resort. It requires MetricsURL. By default the native endpoint
	// streams unchanged and the engine must enforce its own configured label limit.
	FoldNativeMetrics bool
	// NativeMetricsOverflowLabel selects the folding fallback's overflow name.
	// It requires MetricsURL and defaults to "others"; use "_other_" for Replay's convention.
	NativeMetricsOverflowLabel string
	MetricParser               func(string) (ShibuyaMetric, error)
	ResultFile                 string
	Logger                     *log.Entry
	ConfFileName               string
	LabelsUsageLimit           int
}

AgentServerOptions configures an adapter, not an independent execution mode. Callbacks must honor cancellation and must not retain mutable run data beyond their return. The runtime waits for callbacks and cleanup before another run.

func LoadAgentServerOptions added in v0.4.0

func LoadAgentServerOptions(options AgentServerOptions) (AgentServerOptions, error)

LoadAgentServerOptions resolves SDK-owned environment settings before server construction. It does not log, terminate the process, start services, or validate adapter callbacks and metrics integration. On error it returns zero options; the caller's options are not modified.

Precedence and validation match MakeAgentServer:

  • LabelsUsageLimit is always replaced by label_limit, or 10 when that variable is unset or empty, even if the input option is nonzero. Nonempty values use strconv.Atoi: decimal digits with an optional sign, no surrounding whitespace, within the platform int range. Negative results are rejected; 0, +0, -0, and +1 are valid. Zero permits only the overflow label in SDK-managed modes.
  • A non-nil CoordinatorRootCAs is preserved and coordinator_ca_cert is ignored. Otherwise coordinator_ca_cert must contain at least one parseable PEM certificate. Unset, empty, whitespace-only, and malformed values are errors.
  • A nonzero EngineMeta is preserved as a whole, without filling missing fields or validating it. Otherwise engine_name must have five hyphen-separated components with an integer fifth component, and offset must be an integer. Both integers use strconv.Atoi; unset, empty, malformed, and overflowing integers are errors. EngineID is their sum, formatted in decimal. coordinator_ip, collection_id, zone, plan_id, and api_key are copied as-is; unset and empty values both become empty strings, without validation.

All other options are preserved. To override a resolved value (including a zero label limit), assign it after loading. Configure adapter-owned components from the resolved options, then pass them to NewAgentServer, not MakeAgentServer, to avoid another environment read.

type Command

type Command struct {
	Command string
	Args    []string
	Dir     string
	Env     []string
}

func (Command) ToExec

func (c Command) ToExec() *exec.Cmd

type ConfFilesDirectory

type ConfFilesDirectory string

func (ConfFilesDirectory) Filepath

func (cf ConfFilesDirectory) Filepath(sub ...string) string

type EngineMeta

type EngineMeta struct {
	CoordinatorIP string
	CollectionID  string
	Zone          string
	PlanID        string
	EngineID      string
	APIKey        string
}

type MetricsSchema

type MetricsSchema string

MetricsSchema identifies the reporting profile promised by a native adapter.

const MetricsSchemaShibuyaV1 MetricsSchema = "shibuya-v1"

type Process

type Process struct {
	PID int
}

Process identifies the runtime-owned primary workload. Stop callbacks may request shutdown but must not reap it; the runtime owns waiting and escalation.

type ResultFilesDirectory

type ResultFilesDirectory string

func (ResultFilesDirectory) ResultFile

func (rf ResultFilesDirectory) ResultFile(sub ...string) string

type RunContext

type RunContext struct {
	RunID          string
	CollectionID   string
	PlanID         string
	AgentID        string
	Zone           string
	Workspace      Workspace
	TestFile       string
	ConfigFile     string
	DependencyFile string
	ResultFile     string
	Settings       json.RawMessage
	Artifacts      map[string]protocol.ArtifactAssignment
}

RunContext is a read-only snapshot supplied to each adapter callback. Settings and artifact assignments come from the coordinator, without allocation or fallback inference in the agent. Paths are resolved locally by the runtime. DependencyFile is empty when the coordinator supplies no declaration; dependency preparation must still reconcile any installation left by a previous run.

type ShibuyaMetric

type ShibuyaMetric struct {
	Label        string
	Status       string
	Raw          string
	CollectionID string
	PlanID       string
	EngineID     string
	RunID        string
	Zone         string
	Threads      float64
	Latency      float64
	EgressBytes  float64
}

func (ShibuyaMetric) LabelIsValid

func (sm ShibuyaMetric) LabelIsValid() (bool, error)

Cortex has the limit for metric label values for 2048 We set the limit to half of it. 1024 is already pretty long for any valid label(test) names

func (ShibuyaMetric) LabelLength

func (sm ShibuyaMetric) LabelLength() int

func (ShibuyaMetric) ToPrometheus

func (sm ShibuyaMetric) ToPrometheus()

type TestFilesDirectory

type TestFilesDirectory string

func (TestFilesDirectory) Filepath

func (tf TestFilesDirectory) Filepath(sub ...string) string

type Workspace

type Workspace struct {
	Root    string
	Inputs  string
	Config  string
	Results string
	Temp    string
	State   string
}

Workspace separates run files from reusable engine/dependency state. A runtime executes one run at a time; it may reuse physical paths only after all callbacks, processes and cleanup from the preceding run have finished.

Jump to

Keyboard shortcuts

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