pluginsdk

package
v1.2.0 Latest Latest
Warning

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

Go to latest
Published: Oct 7, 2026 License: Apache-2.0 Imports: 19 Imported by: 0

Documentation

Overview

Package pluginsdk is the public API for writing Stampede protocol plugins: steps such as mqtt.publish or kafka.produce that Stampede runs next to its built-in HTTP, GraphQL, WebSocket, SSE and gRPC steps.

A plugin is an ordinary Go program. It describes its step types, each with a JSON Schema for its configuration, and calls Serve:

func main() {
	pluginsdk.Serve(&pluginsdk.Plugin{
		Name:    "echo",
		Version: "0.1.0",
		Steps: []pluginsdk.Step{{
			Name:   "say",
			Schema: `{"type":"object","properties":{"text":{"type":"string"}},"required":["text"]}`,
			Run: func(ctx context.Context, c *pluginsdk.Call) (*pluginsdk.Result, error) {
				var cfg struct{ Text string `json:"text"` }
				if err := c.Decode(&cfg); err != nil {
					return nil, err
				}
				return &pluginsdk.Result{Values: map[string]any{"text": cfg.Text}}, nil
			},
		}},
	})
}

Built as stampede-plugin-echo and installed with `stampede plugin install`, its step is used in a scenario as

steps:
  - plugin: echo.say
    with: { text: "hello ${vu}" }
    extract: { said: "$.text" }

Stampede starts the plugin as a child process and talks to it over gRPC (hashicorp/go-plugin), so a crash in a plugin fails its steps but never the worker. Package conformance checks a built plugin against the contract.

Index

Constants

View Source
const MaxValuesBytes = 1 << 20

MaxValuesBytes caps the JSON a step may return.

View Source
const PluginKey = "stampede"

PluginKey names the plugin in go-plugin's plugin set.

View Source
const TargetKeyword = "x-stampede-target"

TargetKeyword marks the top-level config property that holds the address a step connects to.

Variables

View Source
var (
	// NameRe is what a plugin name must look like.
	NameRe = regexp.MustCompile(`^[a-z][a-z0-9-]{0,62}$`)
	// StepNameRe is what a step name must look like.
	StepNameRe = regexp.MustCompile(`^[A-Za-z][A-Za-z0-9_-]{0,62}$`)
)
View Source
var Handshake = plugin.HandshakeConfig{
	ProtocolVersion:  1,
	MagicCookieKey:   "STAMPEDE_PLUGIN",
	MagicCookieValue: "d3b5a8c4-stampede-protocol-plugin",
}

Handshake is shared by Stampede and every plugin. ProtocolVersion is the plugin protocol's major version (proto/stampede/plugin/v1); a host refuses a plugin built for another. The cookie only stops the binary from being mistaken for a normal program; it is not a secret.

Functions

func CompileSchema

func CompileSchema(step string, schema []byte) (*jsonschema.Schema, error)

CompileSchema compiles a step's config schema. Configs are JSON objects, so the schema must accept only objects.

func Fail

func Fail(class string, err error) error

Fail returns an error that fails the step with the given class. The class must be bounded: no ids, addresses or other values that vary from call to call (put those in err).

func Failf

func Failf(class, format string, args ...any) error

Failf is Fail with a formatted detail.

func NewServer

func NewServer(p *Plugin) (pluginv1.PluginServiceServer, error)

NewServer returns the plugin service for p without starting a process, for serving it in-process (tests) or over a transport of your own.

func Serve

func Serve(p *Plugin)

Serve runs the plugin until Stampede stops it. It exits the process with an error when the plugin's description is invalid.

func TargetFields

func TargetFields(schema []byte) ([]string, error)

TargetFields lists the top-level properties a schema marks with "x-stampede-target": true. A marked property must be a string or an array of strings; the keyword is not allowed below the top level.

func ValidateConfig

func ValidateConfig(s *jsonschema.Schema, config []byte) error

ValidateConfig checks a config, given as JSON, against a compiled schema.

func ValidateDescription

func ValidateDescription(d *pluginv1.DescribeResponse) error

ValidateDescription checks what a plugin describes about itself: its name and version, and that every step has a unique valid name and a config schema that compiles.

Types

type Call

type Call struct {
	Step string
	// Session is the value NewSession returned for this virtual user.
	Session   any
	VU        int64
	Iteration int64
	// Config is the step's rendered config, a JSON object that has passed
	// the step's schema.
	Config json.RawMessage
	// Timeout is the step's timeout; ctx carries the same deadline.
	Timeout time.Duration
	// Traceparent and Baggage are W3C trace context for this step, for
	// protocols that can carry it (message headers, metadata).
	Traceparent string
	Baggage     string
}

Call is one execution of a step.

func (*Call) Decode

func (c *Call) Decode(v any) error

Decode unmarshals the config into v, rejecting fields v does not define.

type Error

type Error struct {
	Class string
	Err   error
}

Error is a step failure with a class: a short label that groups failures in reports, such as "mqtt timeout" or "sql error".

func (*Error) Error

func (e *Error) Error() string

func (*Error) Unwrap

func (e *Error) Unwrap() error

type GRPCPlugin

type GRPCPlugin struct {
	plugin.NetRPCUnsupportedPlugin
	// Impl is the plugin's implementation; nil on the host side.
	Impl pluginv1.PluginServiceServer
}

GRPCPlugin connects go-plugin to the plugin service. Plugins serve it through Serve; the host uses it to dispense a client.

func (*GRPCPlugin) GRPCClient

func (p *GRPCPlugin) GRPCClient(_ context.Context, _ *plugin.GRPCBroker, c *grpc.ClientConn) (any, error)

GRPCClient returns a pluginv1.PluginServiceClient.

func (*GRPCPlugin) GRPCServer

func (p *GRPCPlugin) GRPCServer(_ *plugin.GRPCBroker, s *grpc.Server) error

GRPCServer registers the plugin service.

type Phases

type Phases struct {
	DNS, Connect, TLS time.Duration
	// Wait is the time from sending to the first byte of the reply.
	Wait time.Duration
	// Download is the time spent reading the reply.
	Download time.Duration
	// FirstEvent is the time from the start of a streaming step to its
	// first message.
	FirstEvent time.Duration
}

Phases are the parts of a step's latency, named as in Stampede's reports. Leave the ones that do not apply at zero.

type Plugin

type Plugin struct {
	// Name is used in scenarios (mqtt in mqtt.publish) and in the
	// executable's name (stampede-plugin-mqtt): lowercase letters, digits
	// and hyphens, starting with a letter.
	Name string
	// Version is the plugin's own version, such as 0.1.0.
	Version     string
	Description string
	Steps       []Step
	// NewSession creates the state of one virtual user: its connection or
	// client. Every step the user runs receives it as Call.Session. If the
	// value implements io.Closer it is closed when the user retires. Nil
	// gives every user a nil session.
	NewSession func(ctx context.Context, info SessionInfo) (any, error)
}

Plugin describes a plugin and implements its steps.

type Result

type Result struct {
	// Latency is the step's duration. Zero means the SDK uses how long Run
	// took.
	Latency time.Duration
	// Phases break the latency down where meaningful.
	Phases Phases
	// BytesIn and BytesOut count payload bytes received and sent.
	BytesIn, BytesOut int64
	// Values is what the step returned, marshalled to a JSON object
	// (a map or a struct). Scenario checks and extractors read it:
	// extract: { id: "$.messageId" }.
	Values any
	// Events counts messages a streaming step received. With
	// Phases.FirstEvent set the step is reported like a stream: time to
	// first message and messages per second.
	Events int64
	// Skipped means there was nothing to do (connect on a session that is
	// already connected): Stampede records no sample for the step.
	Skipped bool
}

Result is what a step measured and returned.

type SessionInfo

type SessionInfo struct {
	// VU is unique within a run.
	VU    int64
	RunID string
}

SessionInfo identifies the virtual user a session belongs to.

type Step

type Step struct {
	// Name is the step's name within the plugin (publish in mqtt.publish):
	// letters, digits, underscores and hyphens, starting with a letter.
	Name        string
	Description string
	// Schema is a JSON Schema (draft 2020-12) for the step's config, the
	// `with:` block of a scenario step. Stampede checks scenarios against
	// it when they are loaded, and the SDK checks every rendered config
	// before Run sees it. Mark the top-level property holding the address
	// the step connects to with "x-stampede-target": true so Stampede can
	// apply its target policy to it.
	Schema string
	// Run executes the step. A returned error fails the step; use Fail to
	// give it an error class. Run is called concurrently for different
	// sessions, never for the same one.
	Run func(ctx context.Context, c *Call) (*Result, error)
}

Step is one kind of step.

Directories

Path Synopsis
Package conformance checks a built plugin against Stampede's plugin contract.
Package conformance checks a built plugin against Stampede's plugin contract.

Jump to

Keyboard shortcuts

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