Skip to content

Create a custom processor

The built-in processor library covers the common cases. When none of it fits — a collector processor LinkMesh doesn’t ship a template for, or an in-house convention you apply everywhere — define your own.

What you create is a template, not a single step. It appears in the processor picker afterwards, and any pipeline can add it.

Open Process → Processors and click Create Custom. The wizard runs in one of two modes, and switching between them discards work, so decide up front.

Guided Raw
You define Named fields, types, defaults The configuration body, as YAML
Operators see A form, one input per field A YAML editor
Steps Type → Metadata → Schema → Defaults → Review Metadata → Config → Review
Best when Others will use it and shouldn’t need YAML The config is too structured for a flat field list
  1. Type — the collector processor type this wraps: filter, transform, attributes, and so on. Pick from the list, or type another one if you are wrapping a processor that isn’t offered.

  2. Metadata — name, description, category, icon, and the signal types it supports. Signal types matter: the picker only offers your processor on chains where it applies, so a traces-only processor declared for logs will show up in the wrong place.

  3. Schema — the fields. For each: a name, a type, an optional description (shown as help text on the generated form) and whether it is required.

    The name is the important part. Each field name becomes a key in the generated configuration, spelled exactly as you type it, so it has to match what the underlying collector processor expects. There is no translation step and no placeholder syntax — see how a field becomes collector configuration.

  4. Defaults — the starting value for each field. Someone adding the processor to a pipeline can override any of them; what they don’t touch keeps the default.

  5. Review — check the Generated OTel Config block. This is the real generated shape, and it is the fastest way to catch a misspelled key before it reaches a collector.

For example, defining fields error_mode (default ignore) and blocked_values on a redaction-type processor produces:

processors:
  redaction/my-processor:
    error_mode: ignore
    blocked_values: []

Write the processor’s configuration body directly. This is the body only — everything under the processors: key’s entry, not the key itself, which LinkMesh generates.

The wizard validates that the YAML parses. It does not validate that the keys are ones your collector processor accepts: an unrecognised key is found by the collector, not by the wizard, and surfaces as a rejected config.

  1. Read the Review step’s generated config. A wrong key is far cheaper to find here.

  2. Add it to a pipeline and dry-run it. If the step renders as Unsupported, that only means the preview has no implementation for that processor type — it will still run on the collector, you just cannot see it here.

  3. Attach it to one route on one collector first. Check the collector’s Events tab for config_applied. A config_rejected event carries the collector’s own error message, which will name the offending key. When it is followed by config_rolled_back, the collector failed at start and is back on its previous config.

Editing a template changes it for every pipeline already using it.

Renaming a field deserves particular care. A pipeline stores the values someone entered under the field names they were entered with, and generation merges the template’s defaults with those stored values by key. Rename error_mode to errorMode and a pipeline that had configured the old name now generates both keys — the new one from the template’s default, the old one from its own stored value:

processors:
  filter/my-processor:
    errorMode: ignore      # from the renamed field's default
    error_mode: propagate  # still stored on the pipeline

The collector rejects that, because error_mode is no longer a key it recognises — and the rejection stops all config updates for those collectors, not just this pipeline.

So treat a rename as a migration: add the new field, update every pipeline using the processor, and only then remove the old field. Removing a field has the same shape — the stored value outlives the schema.