Plugin SDK

Embed
Preview of the card
<a href="https://forumulate.com/p/watchtower/docs/sdk"><img src="https://forumulate.com/api/public/orgs/watchtower/spaces/docs/pages/55582b1e-974f-449e-8a5d-349e6aa330b2/social-card.svg?v=3e7ae33eec8b" alt="Plugin SDK" width="600" height="315"></a>

A plugin is a separate process built with watchtower/pluginsdk (HashiCorp go-plugin over gRPC, MPL-2.0). Implement any of:

  • Source: Query(ctx, QueryRequest{query, from, to, step, vars}) (Frames, error). Frames are time series, tables or logs. Dashboards use a plugin through a panel query of kind plugin whose text is {"plugin": "<name>", "query": "<text>"}.

  • Action: Run(ctx, RunRequest{inputs, secrets_refs}) (Outputs, error), used in workflows as plugin:<name>.<action>.

  • Filter: Process(ctx, Payload) (Payload, error) for notification and workflow payloads only. Filters never see ingest data.

func main() { pluginsdk.Serve(myPlugin{}) }

pluginsdk/examples/hello_source is the smallest complete plugin. Package the executable as plugin (plugin.exe on Windows) with plugin.yaml (manifest) in a .tar.gz, sign the tarball's SHA-256 with Ed25519, and install it:

POST /v1/orgs/{org}/plugins          body: tarball (up to 100 MiB)
  x-plugin-manifest: base64(JSON of plugin.yaml)
  x-plugin-signature: base64(Ed25519 signature of the 32-byte SHA-256)
PUT  /v1/projects/{project}/plugins/{id}   {"enabled": true}
POST /v1/projects/{project}/datasources/{name}/query   {"query": "...", "from": "...", "to": "..."}

The wire format is JSON inside google.protobuf.BytesValue (pluginsdk/proto/plugin.proto), so plugins need no generated code. Each call has a 30 s timeout; at most 8 calls run at once.

Updated