> For the complete documentation index, see [llms.txt](https://docs.bindplane.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.bindplane.com/integrations/processors/transform.md).

# Transform

Transforms telemetry by running [OpenTelemetry Transformation Language (OTTL)](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/pkg/ottl#opentelemetry-transformation-language) statements against each record. Statements run in order from top to bottom and can set, keep, delete, or rewrite fields on a record's attributes, body, and resource. Optional conditions gate whether the statements run at all on a given record.

### Supported Telemetry Types

| Logs | Metrics | Traces |
| ---- | ------- | ------ |
| ✓    | ✓       | ✓      |

Choose Telemetry Type picks one signal per processor instance. Add another instance to handle a second signal.

### Configuration

#### Basic Configuration

<figure><img src="/files/QwsV4sUOT0MK7chFd7aL" alt="Bindplane docs - Transform - image 1"><figcaption></figcaption></figure>

**Statements**

| Parameter             | Type               | Required | Default   | Description                                                                                                                                                                                                            |
| --------------------- | ------------------ | -------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Choose Telemetry Type | Telemetry Selector | Yes      | Logs      | The signal this instance runs on: Logs, Metrics, or Traces (one at a time).                                                                                                                                            |
| OTTL Statements       | Code Blocks        | Yes      | *(empty)* | The OTTL statements to execute, one per block. They run in order from top to bottom.                                                                                                                                   |
| Conditions            | Code Blocks        | No       | *(empty)* | OTTL conditions that gate the statements. If any condition is true for a record, the statements run on that record. Leave empty to run on every record. Individual statements may still add their own `where` clauses. |

**Advanced**

| Parameter         | Type                              | Required | Default   | Description                                                                                                                                                                    |
| ----------------- | --------------------------------- | -------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Error Mode        | Enum: ignore, silent, propagate   | No       | ignore    | How to handle statement errors. `ignore` logs the error and continues, `silent` continues without logging, `propagate` halts processing and returns the error up the pipeline. |
| Context (Logs)    | Enum: log, resource               | No       | log       | The OTTL context the statements execute in for logs. Applies when Choose Telemetry Type is Logs.                                                                               |
| Context (Metrics) | Enum: datapoint, metric, resource | No       | datapoint | The OTTL context the statements execute in for metrics. Applies when Choose Telemetry Type is Metrics.                                                                         |
| Context (Traces)  | Enum: span, spanevent, resource   | No       | span      | The OTTL context the statements execute in for traces. Applies when Choose Telemetry Type is Traces.                                                                           |

The UI shows a single **Context** field whose options depend on the selected telemetry type. The default context (`log`, `datapoint`, or `span`) is the most specific level for that signal. Choose `resource` to operate on resource-level attributes shared across all records from a source.

### Examples

#### Set, rename, and clean up log attributes

Run several OTTL statements in order on logs, gated by a condition so they only touch records from one service. This example keeps the default `log` context.

OTTL Statements:

```
set(attributes["environment"], "production")
set(attributes["http.target"], attributes["http.url"]) where attributes["http.url"] != nil
delete_key(attributes, "http.url")
replace_pattern(body, "password=[^ ]+", "password=****")
keep_keys(attributes, ["environment", "http.target", "service.name"])
```

Conditions:

```
attributes["service.name"] == "checkout"
```

The statements add an `environment` attribute, copy `http.url` into `http.target` only when it exists, drop the original `http.url`, redact a password pattern in the body, then keep only the named attributes. Because a condition is set, the statements run only on records whose `service.name` is `checkout`.

<figure><img src="/files/nRv4MDb44IklAGdUEhgy" alt="Bindplane docs - Transform - image 2"><figcaption></figcaption></figure>

#### Normalize resource attributes using the resource context

Set the Context advanced parameter to `resource` to operate on resource-level fields rather than per-record fields. This is the right level for attributes that describe the source rather than an individual log.

OTTL Statements:

```
set(resource.attributes["deployment.environment"], "prod")
replace_pattern(resource.attributes["host.name"], "\\.internal\\.example\\.com$", "")
delete_key(resource.attributes, "k8s.pod.uid")
```

With Context set to `resource`, these statements run once per resource: they stamp a deployment environment, strip an internal DNS suffix from the host name, and drop a noisy pod UID attribute.

<figure><img src="/files/mADLsOcMvYIwpjE4sJYL" alt="Bindplane docs - Transform - image 3"><figcaption></figcaption></figure>

### Configuration Tips

* Statements run top to bottom. Order matters when a later statement reads a field an earlier one sets or deletes.
* Use `where` on an individual statement for fine-grained control, and the Conditions field to gate the whole set. Both can be combined.
* The default context (`log`, `datapoint`, `span`) addresses per-record fields. Switch Context to `resource` only when you mean to change resource-level attributes shared across records.

### Troubleshooting

#### Statements don't seem to run

Symptoms: telemetry passes through unchanged after the processor.

Solutions:

1. Check the Conditions field. If a condition is set and never evaluates true, the statements never run. Clear it to run on every record.
2. Confirm Choose Telemetry Type matches the signal you are sending. A Logs instance does nothing to metrics or traces.

#### A statement errors and processing stops

Symptoms: records are dropped or the pipeline reports errors after adding the processor.

Solutions:

1. With Error Mode set to `propagate`, any statement error halts processing. Set it to `ignore` while you debug so the error is logged but processing continues.
2. Guard field access that may be missing, for example `set(attributes["x"], attributes["y"]) where attributes["y"] != nil`, so a nil field does not error.

#### Resource statements affect more records than expected

Symptoms: a change applied at the `resource` context shows up on records you didn't intend to modify.

Solutions:

1. Resource attributes are shared by every record from the same source. If you need per-record changes, use the default context (`log`, `datapoint`, or `span`) instead of `resource`.

### Standalone Processor

```yaml
apiVersion: bindplane.observiq.com/v1
kind: Processor
metadata:
  name: transform
spec:
  type: transform
  parameters:
    - name: telemetry_type
      value: Logs
    - name: statements
      value:
        - set(attributes["environment"], "production")
        - delete_key(attributes, "http.url")
        - replace_pattern(body, "password=[^ ]+", "password=****")
    - name: conditions
      value:
        - attributes["service.name"] == "checkout"
    - name: error_mode
      value: ignore
    - name: logs_context
      value: log
```

### Related Resources

* [OpenTelemetry Transformation Language (OTTL)](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/pkg/ottl#opentelemetry-transformation-language)
* [OTTL functions reference](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/pkg/ottl/ottlfuncs/README.md)

### Bindplane Resources

These field and OTTL processors pair well with Transform for parsing and reshaping telemetry:

* [Add Fields](/integrations/processors/add-fields.md)
* [Delete Fields](/integrations/processors/delete-fields.md)
* [Rename Fields](/integrations/processors/rename-fields.md)
* [Filter by Condition](/integrations/processors/filter-by-condition.md)
* [Parse JSON](/integrations/processors/parse-json.md)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.bindplane.com/integrations/processors/transform.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
