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)