renaming plugins -> inputs
This commit is contained in:
6
plugins/outputs/prometheus_client/README.md
Normal file
6
plugins/outputs/prometheus_client/README.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# Prometheus Client Service Output Plugin
|
||||
|
||||
This plugin starts a Prometheus Client, listening on a port defined in the
|
||||
configuration file.
|
||||
|
||||
It exposes all metrics on `/metrics` to be polled by a Prometheus server.
|
||||
125
plugins/outputs/prometheus_client/prometheus_client.go
Normal file
125
plugins/outputs/prometheus_client/prometheus_client.go
Normal file
@@ -0,0 +1,125 @@
|
||||
package prometheus_client
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/influxdb/influxdb/client/v2"
|
||||
"github.com/influxdb/telegraf/plugins/outputs"
|
||||
"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 == "" {
|
||||
p.Listen = "localhost:9126"
|
||||
}
|
||||
|
||||
http.Handle("/metrics", prometheus.Handler())
|
||||
server := &http.Server{
|
||||
Addr: p.Listen,
|
||||
}
|
||||
|
||||
p.metrics = make(map[string]*prometheus.UntypedVec)
|
||||
go server.ListenAndServe()
|
||||
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
|
||||
key := point.Name()
|
||||
|
||||
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,
|
||||
Help: fmt.Sprintf("Telegraf collected point '%s'", key),
|
||||
},
|
||||
labels,
|
||||
)
|
||||
prometheus.MustRegister(p.metrics[key])
|
||||
}
|
||||
|
||||
l := prometheus.Labels{}
|
||||
for tk, tv := range point.Tags() {
|
||||
l[tk] = tv
|
||||
}
|
||||
|
||||
for _, val := range point.Fields() {
|
||||
switch val := val.(type) {
|
||||
default:
|
||||
log.Printf("Prometheus output, unsupported type. key: %s, type: %T\n",
|
||||
key, val)
|
||||
case int64:
|
||||
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))
|
||||
case float64:
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
outputs.Add("prometheus_client", func() outputs.Output {
|
||||
return &PrometheusClient{}
|
||||
})
|
||||
}
|
||||
100
plugins/outputs/prometheus_client/prometheus_client_test.go
Normal file
100
plugins/outputs/prometheus_client/prometheus_client_test.go
Normal file
@@ -0,0 +1,100 @@
|
||||
package prometheus_client
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/influxdb/influxdb/client/v2"
|
||||
"github.com/influxdb/telegraf/plugins/inputs/prometheus"
|
||||
"github.com/influxdb/telegraf/testutil"
|
||||
)
|
||||
|
||||
var pTesting *PrometheusClient
|
||||
|
||||
func TestPrometheusWritePointEmptyTag(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("Skipping integration test in short mode")
|
||||
}
|
||||
|
||||
p := &prometheus.Prometheus{
|
||||
Urls: []string{"http://localhost:9126/metrics"},
|
||||
}
|
||||
tags := make(map[string]string)
|
||||
pt1, _ := client.NewPoint(
|
||||
"test_point_1",
|
||||
tags,
|
||||
map[string]interface{}{"value": 0.0})
|
||||
pt2, _ := client.NewPoint(
|
||||
"test_point_2",
|
||||
tags,
|
||||
map[string]interface{}{"value": 1.0})
|
||||
var points = []*client.Point{
|
||||
pt1,
|
||||
pt2,
|
||||
}
|
||||
require.NoError(t, pTesting.Write(points))
|
||||
|
||||
expected := []struct {
|
||||
name string
|
||||
value float64
|
||||
tags map[string]string
|
||||
}{
|
||||
{"test_point_1", 0.0, tags},
|
||||
{"test_point_2", 1.0, tags},
|
||||
}
|
||||
|
||||
var acc testutil.Accumulator
|
||||
|
||||
require.NoError(t, p.Gather(&acc))
|
||||
for _, e := range expected {
|
||||
acc.AssertContainsFields(t, "prometheus_"+e.name,
|
||||
map[string]interface{}{"value": e.value})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPrometheusWritePointTag(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("Skipping integration test in short mode")
|
||||
}
|
||||
|
||||
p := &prometheus.Prometheus{
|
||||
Urls: []string{"http://localhost:9126/metrics"},
|
||||
}
|
||||
tags := make(map[string]string)
|
||||
tags["testtag"] = "testvalue"
|
||||
pt1, _ := client.NewPoint(
|
||||
"test_point_3",
|
||||
tags,
|
||||
map[string]interface{}{"value": 0.0})
|
||||
pt2, _ := client.NewPoint(
|
||||
"test_point_4",
|
||||
tags,
|
||||
map[string]interface{}{"value": 1.0})
|
||||
var points = []*client.Point{
|
||||
pt1,
|
||||
pt2,
|
||||
}
|
||||
require.NoError(t, pTesting.Write(points))
|
||||
|
||||
expected := []struct {
|
||||
name string
|
||||
value float64
|
||||
}{
|
||||
{"test_point_3", 0.0},
|
||||
{"test_point_4", 1.0},
|
||||
}
|
||||
|
||||
var acc testutil.Accumulator
|
||||
|
||||
require.NoError(t, p.Gather(&acc))
|
||||
for _, e := range expected {
|
||||
acc.AssertContainsFields(t, "prometheus_"+e.name,
|
||||
map[string]interface{}{"value": e.value})
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
pTesting = &PrometheusClient{Listen: "localhost:9126"}
|
||||
pTesting.Start()
|
||||
}
|
||||
Reference in New Issue
Block a user