github.com/netdata/go.d.plugin@v0.58.1/pkg/logs/regexp.go (about)

     1  // SPDX-License-Identifier: GPL-3.0-or-later
     2  
     3  package logs
     4  
     5  import (
     6  	"bufio"
     7  	"errors"
     8  	"fmt"
     9  	"io"
    10  	"regexp"
    11  )
    12  
    13  type (
    14  	RegExpConfig struct {
    15  		Pattern string `yaml:"pattern"`
    16  	}
    17  
    18  	RegExpParser struct {
    19  		r       *bufio.Reader
    20  		pattern *regexp.Regexp
    21  	}
    22  )
    23  
    24  func NewRegExpParser(config RegExpConfig, in io.Reader) (*RegExpParser, error) {
    25  	if config.Pattern == "" {
    26  		return nil, errors.New("empty pattern")
    27  	}
    28  
    29  	pattern, err := regexp.Compile(config.Pattern)
    30  	if err != nil {
    31  		return nil, fmt.Errorf("compile: %w", err)
    32  	}
    33  
    34  	if pattern.NumSubexp() == 0 {
    35  		return nil, errors.New("pattern has no named subgroups")
    36  	}
    37  
    38  	p := &RegExpParser{
    39  		r:       bufio.NewReader(in),
    40  		pattern: pattern,
    41  	}
    42  	return p, nil
    43  }
    44  
    45  func (p *RegExpParser) ReadLine(line LogLine) error {
    46  	row, err := p.r.ReadSlice('\n')
    47  	if err != nil && len(row) == 0 {
    48  		return err
    49  	}
    50  	if len(row) > 0 && row[len(row)-1] == '\n' {
    51  		row = row[:len(row)-1]
    52  	}
    53  	return p.Parse(row, line)
    54  }
    55  
    56  func (p *RegExpParser) Parse(row []byte, line LogLine) error {
    57  	match := p.pattern.FindSubmatch(row)
    58  	if len(match) == 0 {
    59  		return &ParseError{msg: "regexp parse: unmatched line"}
    60  	}
    61  
    62  	for i, name := range p.pattern.SubexpNames() {
    63  		if name == "" || match[i] == nil {
    64  			continue
    65  		}
    66  		err := line.Assign(name, string(match[i]))
    67  		if err != nil {
    68  			return &ParseError{msg: fmt.Sprintf("regexp parse: %v", err), err: err}
    69  		}
    70  	}
    71  	return nil
    72  }
    73  
    74  func (p RegExpParser) Info() string {
    75  	return fmt.Sprintf("regexp: %s", p.pattern)
    76  }