2015-10-22 16:17:57 +00:00
|
|
|
package prometheus_client
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2015-12-01 17:08:38 +00:00
|
|
|
"log"
|
2015-10-28 22:19:13 +00:00
|
|
|
"net/http"
|
|
|
|
|
2016-01-20 20:19:03 +00:00
|
|
|
"github.com/influxdata/influxdb/client/v2"
|
|
|
|
"github.com/influxdata/telegraf/plugins/outputs"
|
2015-10-22 16:17:57 +00:00
|
|
|
"github.com/prometheus/client_golang/prometheus"
|
|
|
|
)
|
|
|
|
|
|
|
|
type PrometheusClient struct {
|
|
|
|
Listen string
|
|
|
|
metrics map[string]*prometheus.UntypedVec
|
|
|
|
}
|
|
|
|
|
|
|
|
var sampleConfig = `
|
|
|
|
# Address to listen on
|
|
|
|
# listen = ":9126"
|
|
|
|
`
|
|
|
|
|
|
|
|
func (p *PrometheusClient) Start() error {
|
|
|
|
if p.Listen == "" {
|
2015-10-28 22:19:13 +00:00
|
|
|
p.Listen = "localhost:9126"
|
2015-10-22 16:17:57 +00:00
|
|
|
}
|
2015-10-28 22:19:13 +00:00
|
|
|
|
2015-10-22 16:17:57 +00:00
|
|
|
http.Handle("/metrics", prometheus.Handler())
|
|
|
|
server := &http.Server{
|
2015-10-28 22:19:13 +00:00
|
|
|
Addr: p.Listen,
|
2015-10-22 16:17:57 +00:00
|
|
|
}
|
2015-10-28 22:19:13 +00:00
|
|
|
|
2015-10-22 16:17:57 +00:00
|
|
|
p.metrics = make(map[string]*prometheus.UntypedVec)
|
2015-10-28 22:19:13 +00:00
|
|
|
go server.ListenAndServe()
|
2015-10-22 16:17:57 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *PrometheusClient) Stop() {
|
|
|
|
// TODO: Use a listener for http.Server that counts active connections
|
|
|
|
// that can be stopped and closed gracefully
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *PrometheusClient) Connect() error {
|
|
|
|
// This service output does not need to make any further connections
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *PrometheusClient) Close() error {
|
|
|
|
// This service output does not need to close any of its connections
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *PrometheusClient) SampleConfig() string {
|
|
|
|
return sampleConfig
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *PrometheusClient) Description() string {
|
|
|
|
return "Configuration for the Prometheus client to spawn"
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *PrometheusClient) Write(points []*client.Point) error {
|
|
|
|
if len(points) == 0 {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, point := range points {
|
|
|
|
var labels []string
|
2015-12-01 17:08:38 +00:00
|
|
|
key := point.Name()
|
2015-10-22 16:17:57 +00:00
|
|
|
|
|
|
|
for k, _ := range point.Tags() {
|
|
|
|
if len(k) > 0 {
|
|
|
|
labels = append(labels, k)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if _, ok := p.metrics[key]; !ok {
|
|
|
|
p.metrics[key] = prometheus.NewUntypedVec(
|
|
|
|
prometheus.UntypedOpts{
|
|
|
|
Name: key,
|
2015-12-01 17:08:38 +00:00
|
|
|
Help: fmt.Sprintf("Telegraf collected point '%s'", key),
|
2015-10-22 16:17:57 +00:00
|
|
|
},
|
|
|
|
labels,
|
|
|
|
)
|
|
|
|
prometheus.MustRegister(p.metrics[key])
|
|
|
|
}
|
|
|
|
|
|
|
|
l := prometheus.Labels{}
|
|
|
|
for tk, tv := range point.Tags() {
|
|
|
|
l[tk] = tv
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, val := range point.Fields() {
|
2015-12-01 17:08:38 +00:00
|
|
|
switch val := val.(type) {
|
|
|
|
default:
|
|
|
|
log.Printf("Prometheus output, unsupported type. key: %s, type: %T\n",
|
|
|
|
key, val)
|
2015-10-22 16:17:57 +00:00
|
|
|
case int64:
|
2015-12-01 17:08:38 +00:00
|
|
|
m, err := p.metrics[key].GetMetricWith(l)
|
|
|
|
if err != nil {
|
|
|
|
log.Printf("ERROR Getting metric in Prometheus output, "+
|
|
|
|
"key: %s, labels: %v,\nerr: %s\n",
|
|
|
|
key, l, err.Error())
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
m.Set(float64(val))
|
2015-10-22 16:17:57 +00:00
|
|
|
case float64:
|
2015-12-01 17:08:38 +00:00
|
|
|
m, err := p.metrics[key].GetMetricWith(l)
|
|
|
|
if err != nil {
|
|
|
|
log.Printf("ERROR Getting metric in Prometheus output, "+
|
|
|
|
"key: %s, labels: %v,\nerr: %s\n",
|
|
|
|
key, l, err.Error())
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
m.Set(val)
|
2015-10-22 16:17:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
outputs.Add("prometheus_client", func() outputs.Output {
|
|
|
|
return &PrometheusClient{}
|
|
|
|
})
|
|
|
|
}
|