Adding upstream version 1.34.4.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
e393c3af3f
commit
4978089aab
4963 changed files with 677545 additions and 0 deletions
225
plugins/parsers/wavefront/element.go
Normal file
225
plugins/parsers/wavefront/element.go
Normal file
|
@ -0,0 +1,225 @@
|
|||
package wavefront
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
errInvalidTimestamp = errors.New("invalid timestamp")
|
||||
)
|
||||
|
||||
type elementParser interface {
|
||||
parse(p *PointParser, pt *Point) error
|
||||
}
|
||||
|
||||
type nameParser struct{}
|
||||
type valueParser struct{}
|
||||
type timestampParser struct {
|
||||
optional bool
|
||||
}
|
||||
type whiteSpaceParser struct {
|
||||
nextOptional bool
|
||||
}
|
||||
type tagParser struct{}
|
||||
type loopedParser struct {
|
||||
wrappedParser elementParser
|
||||
wsParser *whiteSpaceParser
|
||||
}
|
||||
|
||||
func (*nameParser) parse(p *PointParser, pt *Point) error {
|
||||
// Valid characters are: a-z, A-Z, 0-9, hyphen ("-"), underscore ("_"), dot (".").
|
||||
// Forward slash ("/") and comma (",") are allowed if metricName is enclosed in double quotes.
|
||||
// Delta (U+2206) is allowed as the first character of the
|
||||
// metricName
|
||||
name, err := parseLiteral(p)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pt.Name = name
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*valueParser) parse(p *PointParser, pt *Point) error {
|
||||
tok, lit := p.scan()
|
||||
if tok == EOF {
|
||||
return fmt.Errorf("found %q, expected number", lit)
|
||||
}
|
||||
|
||||
p.writeBuf.Reset()
|
||||
if tok == MinusSign {
|
||||
p.writeBuf.WriteString(lit)
|
||||
tok, lit = p.scan()
|
||||
}
|
||||
|
||||
for tok != EOF && (tok == Letter || tok == Number || tok == Dot || tok == MinusSign) {
|
||||
p.writeBuf.WriteString(lit)
|
||||
tok, lit = p.scan()
|
||||
}
|
||||
p.unscan()
|
||||
|
||||
pt.Value = p.writeBuf.String()
|
||||
if _, err := strconv.ParseFloat(pt.Value, 64); err != nil {
|
||||
return fmt.Errorf("invalid metric value %s", pt.Value)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ep *timestampParser) parse(p *PointParser, pt *Point) error {
|
||||
tok, lit := p.scan()
|
||||
if tok == EOF {
|
||||
if ep.optional {
|
||||
p.unscanTokens(2)
|
||||
return setTimestamp(pt, 0, 1)
|
||||
}
|
||||
return fmt.Errorf("found %q, expected number", lit)
|
||||
}
|
||||
|
||||
if tok != Number {
|
||||
if ep.optional {
|
||||
p.unscanTokens(2)
|
||||
return setTimestamp(pt, 0, 1)
|
||||
}
|
||||
return errInvalidTimestamp
|
||||
}
|
||||
|
||||
p.writeBuf.Reset()
|
||||
for tok == Number {
|
||||
p.writeBuf.WriteString(lit)
|
||||
tok, lit = p.scan()
|
||||
}
|
||||
p.unscan()
|
||||
|
||||
tsStr := p.writeBuf.String()
|
||||
ts, err := strconv.ParseInt(tsStr, 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return setTimestamp(pt, ts, len(tsStr))
|
||||
}
|
||||
|
||||
func setTimestamp(pt *Point, ts int64, numDigits int) error {
|
||||
if numDigits == 19 {
|
||||
// nanoseconds
|
||||
ts = ts / 1e9
|
||||
} else if numDigits == 16 {
|
||||
// microseconds
|
||||
ts = ts / 1e6
|
||||
} else if numDigits == 13 {
|
||||
// milliseconds
|
||||
ts = ts / 1e3
|
||||
} else if numDigits != 10 {
|
||||
// must be in seconds, return error if not 0
|
||||
if ts != 0 {
|
||||
return errInvalidTimestamp
|
||||
}
|
||||
ts = getCurrentTime()
|
||||
}
|
||||
pt.Timestamp = ts
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ep *loopedParser) parse(p *PointParser, pt *Point) error {
|
||||
for {
|
||||
err := ep.wrappedParser.parse(p, pt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = ep.wsParser.parse(p, pt)
|
||||
if errors.Is(err, io.EOF) {
|
||||
break
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*tagParser) parse(p *PointParser, pt *Point) error {
|
||||
k, err := parseLiteral(p)
|
||||
if err != nil {
|
||||
if k == "" {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
next, lit := p.scan()
|
||||
if next != Equals {
|
||||
return fmt.Errorf("found %q, expected equals", lit)
|
||||
}
|
||||
|
||||
v, err := parseLiteral(p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(pt.Tags) == 0 {
|
||||
pt.Tags = make(map[string]string)
|
||||
}
|
||||
pt.Tags[k] = v
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ep *whiteSpaceParser) parse(p *PointParser, _ *Point) error {
|
||||
tok := Ws
|
||||
for tok == Ws {
|
||||
tok, _ = p.scan()
|
||||
}
|
||||
|
||||
if tok == EOF {
|
||||
if !ep.nextOptional {
|
||||
return io.EOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
p.unscan()
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseQuotedLiteral(p *PointParser) (string, error) {
|
||||
p.writeBuf.Reset()
|
||||
|
||||
escaped := false
|
||||
tok, lit := p.scan()
|
||||
for tok != EOF && (tok != Quotes || (tok == Quotes && escaped)) {
|
||||
// let everything through
|
||||
escaped = tok == Backslash
|
||||
p.writeBuf.WriteString(lit)
|
||||
tok, lit = p.scan()
|
||||
}
|
||||
if tok == EOF {
|
||||
return "", fmt.Errorf("found %q, expected quotes", lit)
|
||||
}
|
||||
return p.writeBuf.String(), nil
|
||||
}
|
||||
|
||||
func parseLiteral(p *PointParser) (string, error) {
|
||||
tok, lit := p.scan()
|
||||
if tok == EOF {
|
||||
return "", fmt.Errorf("found %q, expected literal", lit)
|
||||
}
|
||||
|
||||
if tok == Quotes {
|
||||
return parseQuotedLiteral(p)
|
||||
}
|
||||
|
||||
p.writeBuf.Reset()
|
||||
for tok != EOF && tok > literalBeg && tok < literalEnd {
|
||||
p.writeBuf.WriteString(lit)
|
||||
tok, lit = p.scan()
|
||||
if tok == Delta {
|
||||
return "", errors.New("found delta inside metric name")
|
||||
}
|
||||
}
|
||||
if tok == Quotes {
|
||||
return "", errors.New("found quote inside unquoted literal")
|
||||
}
|
||||
p.unscan()
|
||||
return p.writeBuf.String(), nil
|
||||
}
|
||||
|
||||
func getCurrentTime() int64 {
|
||||
return time.Now().UnixNano() / 1e9
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue