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"