Refactor InfluxDB listener (#6974)
Use streaming parser in InfluxDB listener
This commit is contained in:
@@ -3,8 +3,10 @@ package influx
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
)
|
||||
@@ -17,6 +19,9 @@ var (
|
||||
ErrNoMetric = errors.New("no metric in line")
|
||||
)
|
||||
|
||||
type TimeFunc func() time.Time
|
||||
|
||||
// ParseError indicates a error in the parsing of the text.
|
||||
type ParseError struct {
|
||||
Offset int
|
||||
LineOffset int
|
||||
@@ -38,6 +43,8 @@ func (e *ParseError) Error() string {
|
||||
return fmt.Sprintf("metric parse error: %s at %d:%d: %q", e.msg, e.LineNumber, e.Column, buffer)
|
||||
}
|
||||
|
||||
// Parser is an InfluxDB Line Protocol parser that implements the
|
||||
// parsers.Parser interface.
|
||||
type Parser struct {
|
||||
DefaultTags map[string]string
|
||||
|
||||
@@ -62,6 +69,10 @@ func NewSeriesParser(handler *MetricHandler) *Parser {
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Parser) SetTimeFunc(f TimeFunc) {
|
||||
h.handler.SetTimeFunc(f)
|
||||
}
|
||||
|
||||
func (p *Parser) Parse(input []byte) ([]telegraf.Metric, error) {
|
||||
p.Lock()
|
||||
defer p.Unlock()
|
||||
@@ -75,7 +86,6 @@ func (p *Parser) Parse(input []byte) ([]telegraf.Metric, error) {
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
p.handler.Reset()
|
||||
return nil, &ParseError{
|
||||
Offset: p.machine.Position(),
|
||||
LineOffset: p.machine.LineOffset(),
|
||||
@@ -88,7 +98,6 @@ func (p *Parser) Parse(input []byte) ([]telegraf.Metric, error) {
|
||||
|
||||
metric, err := p.handler.Metric()
|
||||
if err != nil {
|
||||
p.handler.Reset()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -126,10 +135,93 @@ func (p *Parser) applyDefaultTags(metrics []telegraf.Metric) {
|
||||
}
|
||||
|
||||
for _, m := range metrics {
|
||||
for k, v := range p.DefaultTags {
|
||||
if !m.HasTag(k) {
|
||||
m.AddTag(k, v)
|
||||
}
|
||||
p.applyDefaultTagsSingle(m)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Parser) applyDefaultTagsSingle(metric telegraf.Metric) {
|
||||
for k, v := range p.DefaultTags {
|
||||
if !metric.HasTag(k) {
|
||||
metric.AddTag(k, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// StreamParser is an InfluxDB Line Protocol parser. It is not safe for
|
||||
// concurrent use in multiple goroutines.
|
||||
type StreamParser struct {
|
||||
machine *streamMachine
|
||||
handler *MetricHandler
|
||||
}
|
||||
|
||||
func NewStreamParser(r io.Reader) *StreamParser {
|
||||
handler := NewMetricHandler()
|
||||
return &StreamParser{
|
||||
machine: NewStreamMachine(r, handler),
|
||||
handler: handler,
|
||||
}
|
||||
}
|
||||
|
||||
// SetTimeFunc changes the function used to determine the time of metrics
|
||||
// without a timestamp. The default TimeFunc is time.Now. Useful mostly for
|
||||
// testing, or perhaps if you want all metrics to have the same timestamp.
|
||||
func (h *StreamParser) SetTimeFunc(f TimeFunc) {
|
||||
h.handler.SetTimeFunc(f)
|
||||
}
|
||||
|
||||
func (h *StreamParser) SetTimePrecision(u time.Duration) {
|
||||
h.handler.SetTimePrecision(u)
|
||||
}
|
||||
|
||||
// Next parses the next item from the stream. You can repeat calls to this
|
||||
// function until it returns EOF.
|
||||
func (p *StreamParser) Next() (telegraf.Metric, error) {
|
||||
err := p.machine.Next()
|
||||
if err == EOF {
|
||||
return nil, EOF
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, &ParseError{
|
||||
Offset: p.machine.Position(),
|
||||
LineOffset: p.machine.LineOffset(),
|
||||
LineNumber: p.machine.LineNumber(),
|
||||
Column: p.machine.Column(),
|
||||
msg: err.Error(),
|
||||
buf: p.machine.LineText(),
|
||||
}
|
||||
}
|
||||
|
||||
metric, err := p.handler.Metric()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return metric, nil
|
||||
}
|
||||
|
||||
// Position returns the current byte offset into the data.
|
||||
func (p *StreamParser) Position() int {
|
||||
return p.machine.Position()
|
||||
}
|
||||
|
||||
// LineOffset returns the byte offset of the current line.
|
||||
func (p *StreamParser) LineOffset() int {
|
||||
return p.machine.LineOffset()
|
||||
}
|
||||
|
||||
// LineNumber returns the current line number. Lines are counted based on the
|
||||
// regular expression `\r?\n`.
|
||||
func (p *StreamParser) LineNumber() int {
|
||||
return p.machine.LineNumber()
|
||||
}
|
||||
|
||||
// Column returns the current column.
|
||||
func (p *StreamParser) Column() int {
|
||||
return p.machine.Column()
|
||||
}
|
||||
|
||||
// LineText returns the text of the current line that has been parsed so far.
|
||||
func (p *StreamParser) LineText() string {
|
||||
return p.machine.LineText()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user