Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Port remove operator #273

Merged
merged 5 commits into from
May 7, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added
- Added float64 to Severity parser's supported types [PR 267](https://github.com/observIQ/stanza/issues/267)

- Added remove operator
## [0.13.18] - 2021-04-02

### Changed
Expand Down
181 changes: 181 additions & 0 deletions docs/operators/remove.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
## `remove` operator

The `remove` operator removes a field from a record.

### Configuration Fields

| Field | Default | Description |
| --- | --- | --- |
| `id` | `remove` | A unique identifier for the operator |
| `output` | Next in pipeline | The connected operator(s) that will receive all outbound entries |
| `field` | required | The [field](/docs/types/field.md) to remove.
| `on_error` | `send` | The behavior of the operator if it encounters an error. See [on_error](/docs/types/on_error.md) |
| `if` | | An [expression](/docs/types/expression.md) that, when set, will be evaluated to determine whether this operator should be used for the given entry. This allows you to do easy conditional parsing without branching logic with routers. |

Example usage:

<hr>

Remove a value from the record
```yaml
- type: remove
field: key1
```

<table>
<tr><td> Input Entry </td> <td> Output Entry </td></tr>
<tr>
<td>

```json
{
"resource": { },
"labels": { },
"record": {
"key1": "val1",
}
}
```

</td>
<td>

```json
{
"resource": { },
"labels": { },
"record": { }
}
```

</td>
</tr>
</table>

<hr>

Remove an object from the record
```yaml
- type: remove
field: object
```

<table>
<tr><td> Input Entry </td> <td> Output Entry </td></tr>
<tr>
<td>

```json
{
"resource": { },
"labels": { },
"record": {
"object": {
"nestedkey": "nestedval"
},
"key": "val"
},
}
```

</td>
<td>

```json
{
"resource": { },
"labels": { },
"record": {
"key": "val"
}
}
```

</td>
</tr>
</table>

<hr>

Remove a value from labels
```yaml
- type: remove
field: $labels.otherkey
```

<table>
<tr><td> Input Entry </td> <td> Output Entry </td></tr>
<tr>
<td>

```json
{
"resource": { },
"labels": {
"otherkey": "val"
},
"record": {
"key": "val"
},
}
```

</td>
<td>

```json
{
"resource": { },
"labels": { },
"record": {
"key": "val"
}
}
```

</td>
</tr>
</table>

<hr>

Remove a value from resource

```yaml
- type: remove
field: $resource.otherkey
```

<table>
<tr><td> Input Entry </td> <td> Output Entry </td></tr>
<tr>
<td>

```json
{
"resource": {
"otherkey": "val"
},
"labels": { },
"record": {
"key": "val"
},
}
```

</td>
<td>

```json
{
"resource": { },
"labels": { },
"record": {
"key": "val"
}
}
```

</td>
</tr>
</table>
66 changes: 66 additions & 0 deletions operator/builtin/transformer/remove/remove.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package remove

import (
"context"
"fmt"

"github.com/observiq/stanza/entry"
"github.com/observiq/stanza/operator"
"github.com/observiq/stanza/operator/helper"
)

func init() {
operator.Register("remove", func() operator.Builder { return NewRemoveOperatorConfig("") })
}

// NewRemoveOperatorConfig creates a new restructure operator config with default values
func NewRemoveOperatorConfig(operatorID string) *RemoveOperatorConfig {
return &RemoveOperatorConfig{
TransformerConfig: helper.NewTransformerConfig(operatorID, "remove"),
}
}

// RemoveOperatorConfig is the configuration of a restructure operator
type RemoveOperatorConfig struct {
helper.TransformerConfig `mapstructure:",squash" yaml:",inline"`

Field entry.Field `mapstructure:"field" json:"field" yaml:"field"`
}

// Build will build a Remove operator from the supplied configuration
func (c RemoveOperatorConfig) Build(context operator.BuildContext) ([]operator.Operator, error) {
transformerOperator, err := c.TransformerConfig.Build(context)
if err != nil {
return nil, err
}
if c.Field == entry.NewNilField() {
return nil, fmt.Errorf("remove: field is empty")
}

removeOperator := &RemoveOperator{
TransformerOperator: transformerOperator,
Field: c.Field,
}

return []operator.Operator{removeOperator}, nil
}

// RemoveOperator is an operator that deletes a field
type RemoveOperator struct {
helper.TransformerOperator
Field entry.Field
}

// Process will process an entry with a restructure transformation.
func (p *RemoveOperator) Process(ctx context.Context, entry *entry.Entry) error {
return p.ProcessWith(ctx, entry, p.Transform)
}

// Transform will apply the restructure operations to an entry
func (p *RemoveOperator) Transform(entry *entry.Entry) error {
_, exist := entry.Delete(p.Field)
if !exist {
return fmt.Errorf("remove: field does not exist")
}
return nil
}
Loading