github.com/observiq/carbon@v0.9.11-0.20200820160507-1b872e368a5e/operator/helper/parser.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 ) 10 11 func NewParserConfig(operatorID, operatorType string) ParserConfig { 12 return ParserConfig{ 13 TransformerConfig: NewTransformerConfig(operatorID, operatorType), 14 ParseFrom: entry.NewRecordField(), 15 ParseTo: entry.NewRecordField(), 16 Preserve: false, 17 } 18 } 19 20 // ParserConfig provides the basic implementation of a parser config. 21 type ParserConfig struct { 22 TransformerConfig `yaml:",inline"` 23 24 ParseFrom entry.Field `json:"parse_from" yaml:"parse_from"` 25 ParseTo entry.Field `json:"parse_to" yaml:"parse_to"` 26 Preserve bool `json:"preserve" yaml:"preserve"` 27 TimeParser *TimeParser `json:"timestamp,omitempty" yaml:"timestamp,omitempty"` 28 SeverityParserConfig *SeverityParserConfig `json:"severity,omitempty" yaml:"severity,omitempty"` 29 } 30 31 // Build will build a parser operator. 32 func (c ParserConfig) Build(context operator.BuildContext) (ParserOperator, error) { 33 transformerOperator, err := c.TransformerConfig.Build(context) 34 if err != nil { 35 return ParserOperator{}, err 36 } 37 38 if c.ParseFrom.String() == c.ParseTo.String() && c.Preserve { 39 transformerOperator.Warnw( 40 "preserve is true, but parse_to is set to the same field as parse_from, "+ 41 "which will cause the original value to be overwritten", 42 "operator_id", c.ID(), 43 ) 44 } 45 46 parserOperator := ParserOperator{ 47 TransformerOperator: transformerOperator, 48 ParseFrom: c.ParseFrom, 49 ParseTo: c.ParseTo, 50 Preserve: c.Preserve, 51 } 52 53 if c.TimeParser != nil { 54 if err := c.TimeParser.Validate(context); err != nil { 55 return ParserOperator{}, err 56 } 57 parserOperator.TimeParser = c.TimeParser 58 } 59 60 if c.SeverityParserConfig != nil { 61 severityParser, err := c.SeverityParserConfig.Build(context) 62 if err != nil { 63 return ParserOperator{}, err 64 } 65 parserOperator.SeverityParser = &severityParser 66 } 67 68 return parserOperator, nil 69 } 70 71 // ParserOperator provides a basic implementation of a parser operator. 72 type ParserOperator struct { 73 TransformerOperator 74 ParseFrom entry.Field 75 ParseTo entry.Field 76 Preserve bool 77 TimeParser *TimeParser 78 SeverityParser *SeverityParser 79 } 80 81 // ProcessWith will process an entry with a parser function. 82 func (p *ParserOperator) ProcessWith(ctx context.Context, entry *entry.Entry, parse ParseFunction) error { 83 value, ok := entry.Get(p.ParseFrom) 84 if !ok { 85 err := errors.NewError( 86 "Entry is missing the expected parse_from field.", 87 "Ensure that all incoming entries contain the parse_from field.", 88 "parse_from", p.ParseFrom.String(), 89 ) 90 return p.HandleEntryError(ctx, entry, err) 91 } 92 93 newValue, err := parse(value) 94 if err != nil { 95 return p.HandleEntryError(ctx, entry, err) 96 } 97 98 if !p.Preserve { 99 entry.Delete(p.ParseFrom) 100 } 101 102 entry.Set(p.ParseTo, newValue) 103 104 var timeParseErr error 105 if p.TimeParser != nil { 106 timeParseErr = p.TimeParser.Parse(ctx, entry) 107 } 108 109 var severityParseErr error 110 if p.SeverityParser != nil { 111 severityParseErr = p.SeverityParser.Parse(ctx, entry) 112 } 113 114 // Handle time or severity parsing errors after attempting to parse both 115 if timeParseErr != nil { 116 return p.HandleEntryError(ctx, entry, errors.Wrap(timeParseErr, "time parser")) 117 } 118 if severityParseErr != nil { 119 return p.HandleEntryError(ctx, entry, errors.Wrap(severityParseErr, "severity parser")) 120 } 121 122 p.Write(ctx, entry) 123 return nil 124 } 125 126 // ParseFunction is function that parses a raw value. 127 type ParseFunction = func(interface{}) (interface{}, error)