112 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			112 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			Go
		
	
	
	
package logfmt
 | 
						|
 | 
						|
import (
 | 
						|
	"bytes"
 | 
						|
	"fmt"
 | 
						|
	"strconv"
 | 
						|
	"time"
 | 
						|
 | 
						|
	"github.com/go-logfmt/logfmt"
 | 
						|
	"github.com/influxdata/telegraf"
 | 
						|
	"github.com/influxdata/telegraf/metric"
 | 
						|
)
 | 
						|
 | 
						|
var (
 | 
						|
	ErrNoMetric = fmt.Errorf("no metric in line")
 | 
						|
)
 | 
						|
 | 
						|
// Parser decodes logfmt formatted messages into metrics.
 | 
						|
type Parser struct {
 | 
						|
	MetricName  string
 | 
						|
	DefaultTags map[string]string
 | 
						|
	Now         func() time.Time
 | 
						|
}
 | 
						|
 | 
						|
// NewParser creates a parser.
 | 
						|
func NewParser(metricName string, defaultTags map[string]string) *Parser {
 | 
						|
	return &Parser{
 | 
						|
		MetricName:  metricName,
 | 
						|
		DefaultTags: defaultTags,
 | 
						|
		Now:         time.Now,
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// Parse converts a slice of bytes in logfmt format to metrics.
 | 
						|
func (p *Parser) Parse(b []byte) ([]telegraf.Metric, error) {
 | 
						|
	reader := bytes.NewReader(b)
 | 
						|
	decoder := logfmt.NewDecoder(reader)
 | 
						|
	metrics := make([]telegraf.Metric, 0)
 | 
						|
	for {
 | 
						|
		ok := decoder.ScanRecord()
 | 
						|
		if !ok {
 | 
						|
			err := decoder.Err()
 | 
						|
			if err != nil {
 | 
						|
				return nil, err
 | 
						|
			}
 | 
						|
			break
 | 
						|
		}
 | 
						|
		fields := make(map[string]interface{})
 | 
						|
		for decoder.ScanKeyval() {
 | 
						|
			if string(decoder.Value()) == "" {
 | 
						|
				continue
 | 
						|
			}
 | 
						|
 | 
						|
			//type conversions
 | 
						|
			value := string(decoder.Value())
 | 
						|
			if iValue, err := strconv.ParseInt(value, 10, 64); err == nil {
 | 
						|
				fields[string(decoder.Key())] = iValue
 | 
						|
			} else if fValue, err := strconv.ParseFloat(value, 64); err == nil {
 | 
						|
				fields[string(decoder.Key())] = fValue
 | 
						|
			} else if bValue, err := strconv.ParseBool(value); err == nil {
 | 
						|
				fields[string(decoder.Key())] = bValue
 | 
						|
			} else {
 | 
						|
				fields[string(decoder.Key())] = value
 | 
						|
			}
 | 
						|
		}
 | 
						|
		if len(fields) == 0 {
 | 
						|
			continue
 | 
						|
		}
 | 
						|
 | 
						|
		m, err := metric.New(p.MetricName, map[string]string{}, fields, p.Now())
 | 
						|
		if err != nil {
 | 
						|
			return nil, err
 | 
						|
		}
 | 
						|
 | 
						|
		metrics = append(metrics, m)
 | 
						|
	}
 | 
						|
	p.applyDefaultTags(metrics)
 | 
						|
	return metrics, nil
 | 
						|
}
 | 
						|
 | 
						|
// ParseLine converts a single line of text in logfmt format to metrics.
 | 
						|
func (p *Parser) ParseLine(s string) (telegraf.Metric, error) {
 | 
						|
	metrics, err := p.Parse([]byte(s))
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
 | 
						|
	if len(metrics) < 1 {
 | 
						|
		return nil, ErrNoMetric
 | 
						|
	}
 | 
						|
	return metrics[0], nil
 | 
						|
}
 | 
						|
 | 
						|
// SetDefaultTags adds tags to the metrics outputs of Parse and ParseLine.
 | 
						|
func (p *Parser) SetDefaultTags(tags map[string]string) {
 | 
						|
	p.DefaultTags = tags
 | 
						|
}
 | 
						|
 | 
						|
func (p *Parser) applyDefaultTags(metrics []telegraf.Metric) {
 | 
						|
	if len(p.DefaultTags) == 0 {
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	for _, m := range metrics {
 | 
						|
		for k, v := range p.DefaultTags {
 | 
						|
			if !m.HasTag(k) {
 | 
						|
				m.AddTag(k, v)
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 |