github.com/observiq/carbon@v0.9.11-0.20200820160507-1b872e368a5e/operator/helper/transformer.go (about)

     1  package helper
     2  
     3  import (
     4  	"context"
     5  
     6  	"github.com/observiq/carbon/entry"
     7  	"github.com/observiq/carbon/errors"
     8  	"github.com/observiq/carbon/operator"
     9  	"go.uber.org/zap"
    10  )
    11  
    12  func NewTransformerConfig(operatorID, operatorType string) TransformerConfig {
    13  	return TransformerConfig{
    14  		WriterConfig: NewWriterConfig(operatorID, operatorType),
    15  		OnError:      SendOnError,
    16  	}
    17  }
    18  
    19  // TransformerConfig provides a basic implementation of a transformer config.
    20  type TransformerConfig struct {
    21  	WriterConfig `yaml:",inline"`
    22  	OnError      string `json:"on_error" yaml:"on_error"`
    23  }
    24  
    25  // Build will build a transformer operator.
    26  func (c TransformerConfig) Build(context operator.BuildContext) (TransformerOperator, error) {
    27  	writerOperator, err := c.WriterConfig.Build(context)
    28  	if err != nil {
    29  		return TransformerOperator{}, errors.WithDetails(err, "operator_id", c.ID())
    30  	}
    31  
    32  	switch c.OnError {
    33  	case SendOnError, DropOnError:
    34  	default:
    35  		return TransformerOperator{}, errors.NewError(
    36  			"operator config has an invalid `on_error` field.",
    37  			"ensure that the `on_error` field is set to either `send` or `drop`.",
    38  			"on_error", c.OnError,
    39  		)
    40  	}
    41  
    42  	transformerOperator := TransformerOperator{
    43  		WriterOperator: writerOperator,
    44  		OnError:        c.OnError,
    45  	}
    46  
    47  	return transformerOperator, nil
    48  }
    49  
    50  // TransformerOperator provides a basic implementation of a transformer operator.
    51  type TransformerOperator struct {
    52  	WriterOperator
    53  	OnError string
    54  }
    55  
    56  // CanProcess will always return true for a transformer operator.
    57  func (t *TransformerOperator) CanProcess() bool {
    58  	return true
    59  }
    60  
    61  // ProcessWith will process an entry with a transform function.
    62  func (t *TransformerOperator) ProcessWith(ctx context.Context, entry *entry.Entry, transform TransformFunction) error {
    63  	newEntry, err := transform(entry)
    64  	if err != nil {
    65  		return t.HandleEntryError(ctx, entry, err)
    66  	}
    67  	t.Write(ctx, newEntry)
    68  	return nil
    69  }
    70  
    71  // HandleEntryError will handle an entry error using the on_error strategy.
    72  func (t *TransformerOperator) HandleEntryError(ctx context.Context, entry *entry.Entry, err error) error {
    73  	t.Errorw("Failed to process entry", zap.Any("error", err), zap.Any("action", t.OnError), zap.Any("entry", entry))
    74  	if t.OnError == SendOnError {
    75  		t.Write(ctx, entry)
    76  		return nil
    77  	}
    78  	return err
    79  }
    80  
    81  // TransformFunction is function that transforms an entry.
    82  type TransformFunction = func(*entry.Entry) (*entry.Entry, error)
    83  
    84  // SendOnError specifies an on_error mode for sending entries after an error.
    85  const SendOnError = "send"
    86  
    87  // DropOnError specifies an on_error mode for dropping entries after an error.
    88  const DropOnError = "drop"