Fix prometheus label names, and dont panic if invalid

fixes #907
This commit is contained in:
Cameron Sparr 2016-03-22 10:34:33 -06:00
parent 7f65ffcb15
commit 69606a45e0
3 changed files with 37 additions and 12 deletions

View File

@ -18,6 +18,7 @@
- [#884](https://github.com/influxdata/telegraf/issues/884): Do not call write method if there are 0 metrics to write. - [#884](https://github.com/influxdata/telegraf/issues/884): Do not call write method if there are 0 metrics to write.
- [#898](https://github.com/influxdata/telegraf/issues/898): Put database name in quotes, fixes special characters in the database name. - [#898](https://github.com/influxdata/telegraf/issues/898): Put database name in quotes, fixes special characters in the database name.
- [#656](https://github.com/influxdata/telegraf/issues/656): No longer run `lsof` on linux to get netstat data, fixes permissions issue. - [#656](https://github.com/influxdata/telegraf/issues/656): No longer run `lsof` on linux to get netstat data, fixes permissions issue.
- [#907](https://github.com/influxdata/telegraf/issues/907): Fix prometheus invalid label/measurement name key.
## v0.11.1 [2016-03-17] ## v0.11.1 [2016-03-17]

View File

@ -90,8 +90,6 @@ func (u *UdpListener) Start(acc telegraf.Accumulator) error {
} }
func (u *UdpListener) Stop() { func (u *UdpListener) Stop() {
u.Lock()
defer u.Unlock()
close(u.done) close(u.done)
u.listener.Close() u.listener.Close()
u.wg.Wait() u.wg.Wait()

View File

@ -4,12 +4,26 @@ import (
"fmt" "fmt"
"log" "log"
"net/http" "net/http"
"regexp"
"strings"
"github.com/influxdata/telegraf" "github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/plugins/outputs" "github.com/influxdata/telegraf/plugins/outputs"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
) )
var (
sanitizedChars = strings.NewReplacer("/", "_", "@", "_", " ", "_", "-", "_", ".", "_")
// Prometheus metric names must match this regex
// see https://prometheus.io/docs/concepts/data_model/#metric-names-and-labels
metricName = regexp.MustCompile("^[a-zA-Z_:][a-zA-Z0-9_:]*$")
// Prometheus labels must match this regex
// see https://prometheus.io/docs/concepts/data_model/#metric-names-and-labels
labelName = regexp.MustCompile("^[a-zA-Z_][a-zA-Z0-9_]*$")
)
type PrometheusClient struct { type PrometheusClient struct {
Listen string Listen string
metrics map[string]*prometheus.UntypedVec metrics map[string]*prometheus.UntypedVec
@ -64,27 +78,36 @@ func (p *PrometheusClient) Write(metrics []telegraf.Metric) error {
} }
for _, point := range metrics { for _, point := range metrics {
var labels []string
key := point.Name() key := point.Name()
key = sanitizedChars.Replace(key)
for k, _ := range point.Tags() { var labels []string
if len(k) > 0 {
labels = append(labels, k)
}
}
l := prometheus.Labels{} l := prometheus.Labels{}
for tk, tv := range point.Tags() { for k, v := range point.Tags() {
l[tk] = tv k = sanitizedChars.Replace(k)
if len(k) == 0 {
continue
}
if !labelName.MatchString(k) {
continue
}
labels = append(labels, k)
l[k] = v
} }
for n, val := range point.Fields() { for n, val := range point.Fields() {
n = sanitizedChars.Replace(n)
var mname string var mname string
if n == "value" { if n == "value" {
mname = key mname = key
} else { } else {
mname = fmt.Sprintf("%s_%s", key, n) mname = fmt.Sprintf("%s_%s", key, n)
} }
if !metricName.MatchString(mname) {
continue
}
if _, ok := p.metrics[mname]; !ok { if _, ok := p.metrics[mname]; !ok {
p.metrics[mname] = prometheus.NewUntypedVec( p.metrics[mname] = prometheus.NewUntypedVec(
prometheus.UntypedOpts{ prometheus.UntypedOpts{
@ -93,7 +116,10 @@ func (p *PrometheusClient) Write(metrics []telegraf.Metric) error {
}, },
labels, labels,
) )
prometheus.MustRegister(p.metrics[mname]) if err := prometheus.Register(p.metrics[mname]); err != nil {
log.Printf("prometheus_client: Metric failed to register with prometheus, %s", err)
continue
}
} }
switch val := val.(type) { switch val := val.(type) {