Add custom metrics name builder in graphite output

This commit is contained in:
alexander akulov 2016-02-04 18:28:20 +05:00
parent 331b700d1b
commit 85f40ad742
2 changed files with 69 additions and 60 deletions

View File

@ -1,6 +1,7 @@
package graphite
import (
"bytes"
"errors"
"fmt"
"github.com/influxdata/telegraf"
@ -15,10 +16,11 @@ import (
type Graphite struct {
// URL is only for backwards compatability
Servers []string
Prefix string
Timeout int
conns []net.Conn
Servers []string
Prefix string
Timeout int
MetricsNameBuilder map[string][]string
conns []net.Conn
}
var sampleConfig = `
@ -28,6 +30,11 @@ var sampleConfig = `
prefix = ""
# timeout in seconds for the write connection to graphite
timeout = 2
# # Build custom metric name from tags for each plugins
# [graphite.metricsnamebuilder]
# # Igore unlisted tags and put metric name after disk name
# diskio = ["host","{{metric}}","name","{{field}}"]
# disk = ["host","{{metric}}","name","{{field}}"]
`
func (g *Graphite) Connect() error {
@ -72,34 +79,16 @@ func (g *Graphite) Write(metrics []telegraf.Metric) error {
// Prepare data
var bp []string
for _, metric := range metrics {
// Get name
name := metric.Name()
// Convert UnixNano to Unix timestamps
timestamp := metric.UnixNano() / 1000000000
tag_str := buildTags(metric)
for field_name, value := range metric.Fields() {
// Convert value
value_str := fmt.Sprintf("%#v", value)
// Write graphite metric
var graphitePoint string
if name == field_name {
graphitePoint = fmt.Sprintf("%s.%s %s %d\n",
tag_str,
strings.Replace(name, ".", "_", -1),
value_str,
timestamp)
} else {
graphitePoint = fmt.Sprintf("%s.%s.%s %s %d\n",
tag_str,
strings.Replace(name, ".", "_", -1),
strings.Replace(field_name, ".", "_", -1),
value_str,
timestamp)
}
if g.Prefix != "" {
graphitePoint = fmt.Sprintf("%s.%s", g.Prefix, graphitePoint)
}
graphitePoint := fmt.Sprintf("%s %s %d\n",
g.buildMetricName(metric, field_name),
value_str,
timestamp)
bp = append(bp, graphitePoint)
}
}
@ -107,7 +96,6 @@ func (g *Graphite) Write(metrics []telegraf.Metric) error {
// This will get set to nil if a successful write occurs
err := errors.New("Could not write to any Graphite server in cluster\n")
// Send data to a random server
p := rand.Perm(len(g.conns))
for _, n := range p {
@ -127,36 +115,35 @@ func (g *Graphite) Write(metrics []telegraf.Metric) error {
}
return err
}
func buildTags(metric telegraf.Metric) string {
var keys []string
func (g *Graphite) buildMetricName(metric telegraf.Metric, fieldName string) string {
metricName := bytes.NewBufferString(g.Prefix)
metricName.WriteString(".")
tags := metric.Tags()
for k := range tags {
if k == "host" {
metricsTemplate, ok := g.MetricsNameBuilder[metric.Name()]
if !ok {
metricsTemplate = []string{"host"}
for k := range tags {
if k != "host" {
metricsTemplate = append(metricsTemplate, k)
}
}
sort.Strings(metricsTemplate[1:])
if metric.Name() != fieldName {
metricsTemplate = append(metricsTemplate, "{{metric}}")
}
metricsTemplate = append(metricsTemplate, "{{field}}")
}
tags["{{metric}}"] = metric.Name()
tags["{{field}}"] = fieldName
for _, tagName := range metricsTemplate {
tagValue, ok := tags[tagName]
if !ok || tagValue == "" {
continue
}
keys = append(keys, k)
metricName.WriteString(strings.Replace(tagValue, ".", "_", -1))
metricName.WriteString(".")
}
sort.Strings(keys)
var tag_str string
if host, ok := tags["host"]; ok {
if len(keys) > 0 {
tag_str = strings.Replace(host, ".", "_", -1) + "."
} else {
tag_str = strings.Replace(host, ".", "_", -1)
}
}
for i, k := range keys {
tag_value := strings.Replace(tags[k], ".", "_", -1)
if i == 0 {
tag_str += tag_value
} else {
tag_str += "." + tag_value
}
}
return tag_str
return strings.Trim(metricName.String(), ".")
}
func init() {

View File

@ -103,7 +103,7 @@ func TCPServer(t *testing.T, wg *sync.WaitGroup) {
wg.Done()
}
func TestGraphiteTags(t *testing.T) {
func TestGraphiteMetricName(t *testing.T) {
m1, _ := telegraf.NewMetric(
"mymeasurement",
map[string]string{"host": "192.168.0.1"},
@ -122,12 +122,34 @@ func TestGraphiteTags(t *testing.T) {
map[string]interface{}{"value": float64(3.14)},
time.Date(2010, time.November, 10, 23, 0, 0, 0, time.UTC),
)
m4, _ := telegraf.NewMetric(
"custom1",
map[string]string{"host": "192.168.0.1", "afoo": "first", "bfoo": "second"},
map[string]interface{}{"value": float64(3.14)},
time.Date(2010, time.November, 10, 23, 0, 0, 0, time.UTC),
)
m5, _ := telegraf.NewMetric(
"custom.2",
map[string]string{"host": "192.168.0.1", "afoo": "first", "bfoo": "second"},
map[string]interface{}{"value": float64(3.14)},
time.Date(2010, time.November, 10, 23, 0, 0, 0, time.UTC),
)
g := Graphite{
Prefix: "my.prefix",
MetricsNameBuilder: map[string][]string{
"custom1": []string{"host", "afoo", "bfoo"},
"custom.2": []string{"{{field}}", "bfoo", "{{metric}}"}},
}
metricName1 := g.buildMetricName(m1, "value")
metricName2 := g.buildMetricName(m2, "value")
metricName3 := g.buildMetricName(m3, "value")
metricName4 := g.buildMetricName(m4, "value")
metricName5 := g.buildMetricName(m5, "value")
tags1 := buildTags(m1)
tags2 := buildTags(m2)
tags3 := buildTags(m3)
assert.Equal(t, "my.prefix.192_168_0_1.mymeasurement.value", metricName1)
assert.Equal(t, "my.prefix.192_168_0_1.first.second.mymeasurement.value", metricName2)
assert.Equal(t, "my.prefix.first.second.mymeasurement.value", metricName3)
assert.Equal(t, "my.prefix.192_168_0_1.first.second", metricName4)
assert.Equal(t, "my.prefix.value.second.custom_2", metricName5)
assert.Equal(t, "192_168_0_1", tags1)
assert.Equal(t, "192_168_0_1.first.second", tags2)
assert.Equal(t, "first.second", tags3)
}