Implement telegraf's own full metric type

main reasons behind this:
- make adding/removing tags cheap
- make adding/removing fields cheap
- make parsing cheaper
- make parse -> decorate -> write out bytes metric flow much faster

Refactor serializer to use byte buffer
This commit is contained in:
Cameron Sparr
2016-11-22 12:51:57 +00:00
parent 332f678afb
commit db7a4b24b6
40 changed files with 1376 additions and 398 deletions

View File

@@ -6,8 +6,7 @@ import (
"time"
"github.com/influxdata/telegraf"
"github.com/influxdata/influxdb/models"
"github.com/influxdata/telegraf/metric"
)
// InfluxParser is an object for Parsing incoming metrics.
@@ -19,18 +18,16 @@ type InfluxParser struct {
func (p *InfluxParser) ParseWithDefaultTime(buf []byte, t time.Time) ([]telegraf.Metric, error) {
// parse even if the buffer begins with a newline
buf = bytes.TrimPrefix(buf, []byte("\n"))
points, err := models.ParsePointsWithPrecision(buf, t, "n")
metrics := make([]telegraf.Metric, len(points))
for i, point := range points {
for k, v := range p.DefaultTags {
// only set the default tag if it doesn't already exist:
if tmp := point.Tags().GetString(k); tmp == "" {
point.AddTag(k, v)
metrics, err := metric.ParseWithDefaultTime(buf, t)
if len(p.DefaultTags) > 0 {
for _, m := range metrics {
for k, v := range p.DefaultTags {
// only set the default tag if it doesn't already exist:
if !m.HasTag(k) {
m.AddTag(k, v)
}
}
}
// Ignore error here because it's impossible that a model.Point
// wouldn't parse into client.Point properly
metrics[i] = telegraf.NewMetricFromPoint(point)
}
return metrics, err
}

View File

@@ -14,15 +14,14 @@ var (
ms []telegraf.Metric
writer = ioutil.Discard
metrics500 []byte
exptime = time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC).UnixNano()
)
var exptime = time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
const (
validInflux = "cpu_load_short,cpu=cpu0 value=10 1257894000000000000"
validInflux = "cpu_load_short,cpu=cpu0 value=10 1257894000000000000\n"
validInfluxNewline = "\ncpu_load_short,cpu=cpu0 value=10 1257894000000000000\n"
invalidInflux = "I don't think this is line protocol"
invalidInflux2 = "{\"a\": 5, \"b\": {\"c\": 6}}"
invalidInflux = "I don't think this is line protocol\n"
invalidInflux2 = "{\"a\": 5, \"b\": {\"c\": 6}}\n"
)
const influxMulti = `
@@ -57,7 +56,7 @@ func TestParseValidInflux(t *testing.T) {
assert.Equal(t, map[string]string{
"cpu": "cpu0",
}, metrics[0].Tags())
assert.Equal(t, exptime, metrics[0].Time())
assert.Equal(t, exptime, metrics[0].Time().UnixNano())
metrics, err = parser.Parse([]byte(validInfluxNewline))
assert.NoError(t, err)
@@ -69,7 +68,7 @@ func TestParseValidInflux(t *testing.T) {
assert.Equal(t, map[string]string{
"cpu": "cpu0",
}, metrics[0].Tags())
assert.Equal(t, exptime, metrics[0].Time())
assert.Equal(t, exptime, metrics[0].Time().UnixNano())
}
func TestParseLineValidInflux(t *testing.T) {
@@ -84,7 +83,7 @@ func TestParseLineValidInflux(t *testing.T) {
assert.Equal(t, map[string]string{
"cpu": "cpu0",
}, metric.Tags())
assert.Equal(t, exptime, metric.Time())
assert.Equal(t, exptime, metric.Time().UnixNano())
metric, err = parser.ParseLine(validInfluxNewline)
assert.NoError(t, err)
@@ -95,7 +94,7 @@ func TestParseLineValidInflux(t *testing.T) {
assert.Equal(t, map[string]string{
"cpu": "cpu0",
}, metric.Tags())
assert.Equal(t, exptime, metric.Time())
assert.Equal(t, exptime, metric.Time().UnixNano())
}
func TestParseMultipleValid(t *testing.T) {
@@ -229,11 +228,8 @@ func BenchmarkParseAddTagWrite(b *testing.B) {
panic("500 metrics not parsed!!")
}
for _, tmp := range ms {
tags := tmp.Tags()
tags["host"] = "localhost"
tmp, _ = telegraf.NewMetric(tmp.Name(), tags, tmp.Fields(), tmp.Time())
writer.Write([]byte(tmp.String()))
writer.Write([]byte{'\n'})
tmp.AddTag("host", "localhost")
writer.Write(tmp.Serialize())
}
}
}