Add optional Prometheus exporter to telegraf.
This will allow Telegraf plugins to be useful with Prometheus. This is disabled by default.
This commit is contained in:
parent
05924b9d09
commit
45d9aec62e
62
agent.go
62
agent.go
|
@ -5,18 +5,21 @@ import (
|
||||||
"log"
|
"log"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
|
"regexp"
|
||||||
"sort"
|
"sort"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/influxdb/influxdb/client"
|
"github.com/influxdb/influxdb/client"
|
||||||
"github.com/influxdb/telegraf/plugins"
|
"github.com/influxdb/telegraf/plugins"
|
||||||
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
)
|
)
|
||||||
|
|
||||||
type runningPlugin struct {
|
type runningPlugin struct {
|
||||||
name string
|
name string
|
||||||
plugin plugins.Plugin
|
plugin plugins.Plugin
|
||||||
config *ConfiguredPlugin
|
config *ConfiguredPlugin
|
||||||
|
mu sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
type Agent struct {
|
type Agent struct {
|
||||||
|
@ -53,6 +56,7 @@ func NewAgent(config *Config) (*Agent, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
config.Tags["host"] = agent.Hostname
|
config.Tags["host"] = agent.Hostname
|
||||||
|
prometheus.MustRegister(agent)
|
||||||
|
|
||||||
return agent, nil
|
return agent, nil
|
||||||
}
|
}
|
||||||
|
@ -97,7 +101,7 @@ func (a *Agent) LoadPlugins() ([]string, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
a.plugins = append(a.plugins, &runningPlugin{name, plugin, config})
|
a.plugins = append(a.plugins, &runningPlugin{name, plugin, config, sync.Mutex{}})
|
||||||
names = append(names, name)
|
names = append(names, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,7 +129,9 @@ func (a *Agent) crankParallel() error {
|
||||||
acc.Prefix = plugin.name + "_"
|
acc.Prefix = plugin.name + "_"
|
||||||
acc.Config = plugin.config
|
acc.Config = plugin.config
|
||||||
|
|
||||||
|
plugin.mu.Lock()
|
||||||
plugin.plugin.Gather(&acc)
|
plugin.plugin.Gather(&acc)
|
||||||
|
plugin.mu.Unlock()
|
||||||
|
|
||||||
points <- &acc
|
points <- &acc
|
||||||
}(plugin)
|
}(plugin)
|
||||||
|
@ -156,7 +162,9 @@ func (a *Agent) crank() error {
|
||||||
for _, plugin := range a.plugins {
|
for _, plugin := range a.plugins {
|
||||||
acc.Prefix = plugin.name + "_"
|
acc.Prefix = plugin.name + "_"
|
||||||
acc.Config = plugin.config
|
acc.Config = plugin.config
|
||||||
|
plugin.mu.Lock()
|
||||||
err := plugin.plugin.Gather(&acc)
|
err := plugin.plugin.Gather(&acc)
|
||||||
|
plugin.mu.Unlock()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -180,7 +188,9 @@ func (a *Agent) crankSeparate(shutdown chan struct{}, plugin *runningPlugin) err
|
||||||
|
|
||||||
acc.Prefix = plugin.name + "_"
|
acc.Prefix = plugin.name + "_"
|
||||||
acc.Config = plugin.config
|
acc.Config = plugin.config
|
||||||
|
plugin.mu.Lock()
|
||||||
err := plugin.plugin.Gather(&acc)
|
err := plugin.plugin.Gather(&acc)
|
||||||
|
plugin.mu.Unlock()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -200,6 +210,56 @@ func (a *Agent) crankSeparate(shutdown chan struct{}, plugin *runningPlugin) err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Implements prometheus.Collector
|
||||||
|
func (a *Agent) Describe(ch chan<- *prometheus.Desc) {
|
||||||
|
prometheus.NewGauge(prometheus.GaugeOpts{Name: "Dummy", Help: "Dummy"}).Describe(ch)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implements prometheus.Collector
|
||||||
|
func (a *Agent) Collect(ch chan<- prometheus.Metric) {
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
|
||||||
|
invalidNameCharRE := regexp.MustCompile(`[^a-zA-Z0-9_]`)
|
||||||
|
|
||||||
|
for _, plugin := range a.plugins {
|
||||||
|
wg.Add(1)
|
||||||
|
go func(plugin *runningPlugin) {
|
||||||
|
defer wg.Done()
|
||||||
|
var acc BatchPoints
|
||||||
|
acc.Prefix = plugin.name + "_"
|
||||||
|
|
||||||
|
plugin.mu.Lock()
|
||||||
|
err := plugin.plugin.Gather(&acc)
|
||||||
|
plugin.mu.Unlock()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, point := range acc.Points {
|
||||||
|
var value float64
|
||||||
|
switch point.Fields["value"].(type) {
|
||||||
|
case float64, int64:
|
||||||
|
value = point.Fields["value"].(float64)
|
||||||
|
default:
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
tags := map[string]string{}
|
||||||
|
for k, v := range point.Tags {
|
||||||
|
tags[invalidNameCharRE.ReplaceAllString(k, "_")] = v
|
||||||
|
}
|
||||||
|
desc := prometheus.NewDesc(invalidNameCharRE.ReplaceAllString(point.Measurement, "_"), point.Measurement, nil, tags)
|
||||||
|
metric, err := prometheus.NewConstMetric(desc, prometheus.UntypedValue, value)
|
||||||
|
if err == nil {
|
||||||
|
ch <- metric
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}(plugin)
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
func (a *Agent) TestAllPlugins() error {
|
func (a *Agent) TestAllPlugins() error {
|
||||||
var names []string
|
var names []string
|
||||||
|
|
||||||
|
|
|
@ -4,12 +4,14 @@ import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/influxdb/telegraf"
|
"github.com/influxdb/telegraf"
|
||||||
_ "github.com/influxdb/telegraf/plugins/all"
|
_ "github.com/influxdb/telegraf/plugins/all"
|
||||||
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
)
|
)
|
||||||
|
|
||||||
var fDebug = flag.Bool("debug", false, "show metrics as they're generated to stdout")
|
var fDebug = flag.Bool("debug", false, "show metrics as they're generated to stdout")
|
||||||
|
@ -117,5 +119,21 @@ func main() {
|
||||||
f.Close()
|
f.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pc := &telegraf.PrometheusCollector{ListenAddress: ""}
|
||||||
|
err = config.ApplyPrometheusCollector(pc)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
if pc.ListenAddress != "" {
|
||||||
|
http.Handle("/metrics", prometheus.Handler())
|
||||||
|
log.Printf("Listening on %s for Prometheus", pc.ListenAddress)
|
||||||
|
go func() {
|
||||||
|
err := http.ListenAndServe(pc.ListenAddress, nil)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
ag.Run(shutdown)
|
ag.Run(shutdown)
|
||||||
}
|
}
|
||||||
|
|
23
config.go
23
config.go
|
@ -36,8 +36,13 @@ type Config struct {
|
||||||
UserAgent string
|
UserAgent string
|
||||||
Tags map[string]string
|
Tags map[string]string
|
||||||
|
|
||||||
agent *ast.Table
|
agent *ast.Table
|
||||||
plugins map[string]*ast.Table
|
plugins map[string]*ast.Table
|
||||||
|
prometheusCollector *ast.Table
|
||||||
|
}
|
||||||
|
|
||||||
|
type PrometheusCollector struct {
|
||||||
|
ListenAddress string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) Plugins() map[string]*ast.Table {
|
func (c *Config) Plugins() map[string]*ast.Table {
|
||||||
|
@ -85,6 +90,14 @@ func (c *Config) ApplyAgent(v interface{}) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Config) ApplyPrometheusCollector(v interface{}) error {
|
||||||
|
if c.prometheusCollector != nil {
|
||||||
|
return toml.UnmarshalTable(c.prometheusCollector, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Config) ApplyPlugin(name string, v interface{}) (*ConfiguredPlugin, error) {
|
func (c *Config) ApplyPlugin(name string, v interface{}) (*ConfiguredPlugin, error) {
|
||||||
cp := &ConfiguredPlugin{Name: name}
|
cp := &ConfiguredPlugin{Name: name}
|
||||||
|
|
||||||
|
@ -183,6 +196,8 @@ func LoadConfig(path string) (*Config, error) {
|
||||||
}
|
}
|
||||||
case "agent":
|
case "agent":
|
||||||
c.agent = subtbl
|
c.agent = subtbl
|
||||||
|
case "prometheus_collector":
|
||||||
|
c.prometheusCollector = subtbl
|
||||||
default:
|
default:
|
||||||
c.plugins[name] = subtbl
|
c.plugins[name] = subtbl
|
||||||
}
|
}
|
||||||
|
@ -261,6 +276,10 @@ database = "telegraf" # required.
|
||||||
# debug = false
|
# debug = false
|
||||||
# hostname = "prod3241"
|
# hostname = "prod3241"
|
||||||
|
|
||||||
|
[prometheus_collector]
|
||||||
|
# If set, expose all metrics on this address for Prometheus
|
||||||
|
# listen_address = ":9115"
|
||||||
|
|
||||||
# PLUGINS
|
# PLUGINS
|
||||||
|
|
||||||
`
|
`
|
||||||
|
|
Loading…
Reference in New Issue