Skip to content
Documentation Prelude Collector

You are viewing documentation for 1.0.0. This version is no longer maintained.

See the latest version →

Transforms API

Manage user-defined Starlark transforms that reshape collected telemetry before it reaches the output pipeline in Prelude Collector.

Transforms are user-defined Starlark functions that the Prelude Collector runs against parsed telemetry before it reaches the output pipeline. After this first mention, the rest of this page refers to Prelude Collector as "the collector". A transform is the right place to derive a rate from a counter, normalize a vendor quirk, or drop entries you do not want shipped. This page covers when to use the API, common mistakes, and a worked example. For the full endpoint schema, see the API reference.

When to use this API

  • Reshaping a single value. Convert units, format an enum, truncate a string, derive a ratio from a paired field — anything the built-in transforms do not already cover.
  • Normalising vendor differences. Squash per-NetOS quirks (capitalisation, encoding, string framing) so downstream dashboards see one shape.
  • Iterating safely. Update an existing transform with PUT to fix a bug; the registry hot-reloads and the next collection cycle picks up the new expression without a restart.

To remove a transform from a field's pipeline, delete the entry from the field's transforms list in the relevant mapping. The transform itself can stay registered; it only runs when a mapping references it by name.

How transforms are invoked

A transform is a function that takes one scalar value and returns one scalar value. The collector wraps your code in def transform(value): and runs it once per field per parsed entry. Transforms cannot mutate other fields, see neighbouring entries, or drop a row — those are mapping-level concerns (field-transforms, value-transforms, ignore-values) covered in the Transforms overview.

Common pitfalls

  • Wrong signature. The expression is a function body that receives value and must return a value. It is not a row mutator. Returning None is treated as failure: a warning is logged and the original value is kept.
  • Slow transforms. Starlark is sandboxed but not free. Execution is capped at 1,000,000 Starlark steps; there is no separate wall-clock timeout, so a CPU-bound loop runs to the step limit.
  • Hyphens in names. The validator regex is ^[a-z][a-z0-9_]*$bps_to_human is valid, bps-to-human is not.
  • Name conflicts return 400 Bad Request with the failing field reported in the form-error envelope, not 409 Conflict. This applies both to duplicates of existing custom transforms and to collisions with a built-in transform name.

Worked example: derive Mbps from a bytes-per-second counter

export BASE="https://collector.example.com"
export TOKEN="<your-api-token>"

# 1. Create a transform that converts bytes/sec to Mbps and rounds to 2 decimals.
curl -sk -X POST "$BASE/api/v1/transforms" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "bytes_per_sec_to_mbps",
    "description": "Convert byte/sec counter to Mbps with 2-decimal precision.",
    "expression": "mbps = to_mbps(value * 8)\nreturn round(mbps, 2)"
  }'
# → 201 Created with the saved transform object (id, name, description, expression).

# 2. Inspect the saved transform.
curl -sk "$BASE/api/v1/transforms/1" \
  -H "Authorization: Bearer $TOKEN"

# 3. Iterate: update the expression. Hot-reload picks up the new logic on the next cycle.
curl -sk -X PUT "$BASE/api/v1/transforms/1" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "expression": "return round(to_mbps(value * 8), 1)"
  }'

# 4. Attach the transform by adding its name to the field's transforms list inside
#    the mapping (see Models API → mappings). Transforms apply in left-to-right order.

# 5. Verify the new field appears on the parsed entries.
curl -sk "$BASE/api/v1/snapshots/$DEVICE_ID" \
  -H "Authorization: Bearer $TOKEN"

Bruno: 07 Transforms / Create transform, 07 Transforms / Get transform, 07 Transforms / Update transform, 06 Snapshots / Get device snapshot

UI equivalent: https://collector.example.com/transforms/ — the same form with a "Test against a sample value" button that compile-checks the expression and runs it without saving.

Reference

Full request/response shapes for every endpoint live in the Bruno collection. Required body fields are name and expression; description is optional. There is no enabled or version field — disable a transform by removing its name from the mapping that uses it, or delete it outright with DELETE.

See also

Filtering by: