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
- Variables
- func CompileSchema(step string, schema []byte) (*jsonschema.Schema, error)
- func Fail(class string, err error) error
- func Failf(class, format string, args ...any) error
- func NewServer(p *Plugin) (pluginv1.PluginServiceServer, error)
- func Serve(p *Plugin)
- func TargetFields(schema []byte) ([]string, error)
- func ValidateConfig(s *jsonschema.Schema, config []byte) error
- func ValidateDescription(d *pluginv1.DescribeResponse) error
- type Call
- type Error
- type GRPCPlugin
- type Phases
- type Plugin
- type Result
- type SessionInfo
- type Step
Constants ¶
const MaxValuesBytes = 1 << 20
MaxValuesBytes caps the JSON a step may return.
const PluginKey = "stampede"
PluginKey names the plugin in go-plugin's plugin set.
const TargetKeyword = "x-stampede-target"
TargetKeyword marks the top-level config property that holds the address a step connects to.
Variables ¶
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}$`) )
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 ¶
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 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 ¶
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.
type Error ¶
Error is a step failure with a class: a short label that groups failures in reports, such as "mqtt timeout" or "sql 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 ¶
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. |