2016-06-01 10:02:28 +00:00
|
|
|
package consul
|
|
|
|
|
|
|
|
import (
|
|
|
|
"net/http"
|
2018-05-17 21:24:51 +00:00
|
|
|
"strings"
|
2016-06-01 10:02:28 +00:00
|
|
|
|
|
|
|
"github.com/hashicorp/consul/api"
|
2019-03-19 20:39:42 +00:00
|
|
|
|
2016-06-01 10:02:28 +00:00
|
|
|
"github.com/influxdata/telegraf"
|
2018-05-04 23:33:23 +00:00
|
|
|
"github.com/influxdata/telegraf/internal/tls"
|
2016-06-01 10:02:28 +00:00
|
|
|
"github.com/influxdata/telegraf/plugins/inputs"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Consul struct {
|
|
|
|
Address string
|
|
|
|
Scheme string
|
|
|
|
Token string
|
|
|
|
Username string
|
|
|
|
Password string
|
2019-01-23 22:12:19 +00:00
|
|
|
Datacentre string // deprecated in 1.10; use Datacenter
|
2019-01-23 22:10:38 +00:00
|
|
|
Datacenter string
|
2018-05-04 23:33:23 +00:00
|
|
|
tls.ClientConfig
|
2018-05-17 21:24:51 +00:00
|
|
|
TagDelimiter string
|
2016-06-01 10:02:28 +00:00
|
|
|
|
|
|
|
// client used to connect to Consul agnet
|
|
|
|
client *api.Client
|
|
|
|
}
|
|
|
|
|
|
|
|
var sampleConfig = `
|
2018-03-27 02:22:17 +00:00
|
|
|
## Consul server address
|
2016-06-01 10:02:28 +00:00
|
|
|
# address = "localhost"
|
2018-03-27 02:22:17 +00:00
|
|
|
|
|
|
|
## URI scheme for the Consul server, one of "http", "https"
|
2016-06-01 10:02:28 +00:00
|
|
|
# scheme = "http"
|
2018-03-27 02:22:17 +00:00
|
|
|
|
|
|
|
## ACL token used in every request
|
2016-06-01 10:02:28 +00:00
|
|
|
# token = ""
|
2018-03-27 02:22:17 +00:00
|
|
|
|
|
|
|
## HTTP Basic Authentication username and password.
|
2016-06-01 10:02:28 +00:00
|
|
|
# username = ""
|
|
|
|
# password = ""
|
2018-03-27 02:22:17 +00:00
|
|
|
|
2019-01-23 22:10:38 +00:00
|
|
|
## Data center to query the health checks from
|
|
|
|
# datacenter = ""
|
2018-03-27 02:22:17 +00:00
|
|
|
|
2018-05-04 23:33:23 +00:00
|
|
|
## Optional TLS Config
|
|
|
|
# tls_ca = "/etc/telegraf/ca.pem"
|
|
|
|
# tls_cert = "/etc/telegraf/cert.pem"
|
|
|
|
# tls_key = "/etc/telegraf/key.pem"
|
|
|
|
## Use TLS but skip chain & host verification
|
2018-03-27 02:22:17 +00:00
|
|
|
# insecure_skip_verify = true
|
2018-05-17 21:24:51 +00:00
|
|
|
|
|
|
|
## Consul checks' tag splitting
|
|
|
|
# When tags are formatted like "key:value" with ":" as a delimiter then
|
|
|
|
# they will be splitted and reported as proper key:value in Telegraf
|
|
|
|
# tag_delimiter = ":"
|
2016-06-01 10:02:28 +00:00
|
|
|
`
|
|
|
|
|
|
|
|
func (c *Consul) Description() string {
|
|
|
|
return "Gather health check statuses from services registered in Consul"
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Consul) SampleConfig() string {
|
|
|
|
return sampleConfig
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Consul) createAPIClient() (*api.Client, error) {
|
|
|
|
config := api.DefaultConfig()
|
|
|
|
|
|
|
|
if c.Address != "" {
|
|
|
|
config.Address = c.Address
|
|
|
|
}
|
|
|
|
|
|
|
|
if c.Scheme != "" {
|
|
|
|
config.Scheme = c.Scheme
|
|
|
|
}
|
|
|
|
|
|
|
|
if c.Datacentre != "" {
|
|
|
|
config.Datacenter = c.Datacentre
|
|
|
|
}
|
|
|
|
|
2019-01-23 22:10:38 +00:00
|
|
|
if c.Datacenter != "" {
|
|
|
|
config.Datacenter = c.Datacenter
|
|
|
|
}
|
|
|
|
|
2017-10-23 19:31:27 +00:00
|
|
|
if c.Token != "" {
|
|
|
|
config.Token = c.Token
|
|
|
|
}
|
|
|
|
|
2016-06-01 10:02:28 +00:00
|
|
|
if c.Username != "" {
|
|
|
|
config.HttpAuth = &api.HttpBasicAuth{
|
|
|
|
Username: c.Username,
|
|
|
|
Password: c.Password,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-04 23:33:23 +00:00
|
|
|
tlsCfg, err := c.ClientConfig.TLSConfig()
|
2016-06-01 10:02:28 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2018-05-17 21:24:51 +00:00
|
|
|
config.Transport = &http.Transport{
|
2016-06-01 10:02:28 +00:00
|
|
|
TLSClientConfig: tlsCfg,
|
|
|
|
}
|
|
|
|
|
|
|
|
return api.NewClient(config)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Consul) GatherHealthCheck(acc telegraf.Accumulator, checks []*api.HealthCheck) {
|
|
|
|
for _, check := range checks {
|
|
|
|
record := make(map[string]interface{})
|
|
|
|
tags := make(map[string]string)
|
|
|
|
|
|
|
|
record["check_name"] = check.Name
|
|
|
|
record["service_id"] = check.ServiceID
|
2017-01-29 00:47:25 +00:00
|
|
|
|
2016-06-01 10:02:28 +00:00
|
|
|
record["status"] = check.Status
|
2017-01-29 00:47:25 +00:00
|
|
|
record["passing"] = 0
|
|
|
|
record["critical"] = 0
|
|
|
|
record["warning"] = 0
|
|
|
|
record[check.Status] = 1
|
2016-06-01 10:02:28 +00:00
|
|
|
|
|
|
|
tags["node"] = check.Node
|
|
|
|
tags["service_name"] = check.ServiceName
|
2016-12-20 13:03:31 +00:00
|
|
|
tags["check_id"] = check.CheckID
|
2016-06-01 10:02:28 +00:00
|
|
|
|
2018-05-17 21:24:51 +00:00
|
|
|
for _, checkTag := range check.ServiceTags {
|
|
|
|
if c.TagDelimiter != "" {
|
|
|
|
splittedTag := strings.SplitN(checkTag, c.TagDelimiter, 2)
|
2019-03-19 20:39:42 +00:00
|
|
|
if len(splittedTag) == 1 && checkTag != "" {
|
2018-05-17 21:24:51 +00:00
|
|
|
tags[checkTag] = checkTag
|
2019-03-19 20:39:42 +00:00
|
|
|
} else if len(splittedTag) == 2 && splittedTag[1] != "" {
|
2018-05-17 21:24:51 +00:00
|
|
|
tags[splittedTag[0]] = splittedTag[1]
|
|
|
|
}
|
2019-03-19 20:39:42 +00:00
|
|
|
} else if checkTag != "" {
|
2018-05-17 21:24:51 +00:00
|
|
|
tags[checkTag] = checkTag
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-01 10:02:28 +00:00
|
|
|
acc.AddFields("consul_health_checks", record, tags)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Consul) Gather(acc telegraf.Accumulator) error {
|
|
|
|
if c.client == nil {
|
|
|
|
newClient, err := c.createAPIClient()
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
c.client = newClient
|
|
|
|
}
|
|
|
|
|
|
|
|
checks, _, err := c.client.Health().State("any", nil)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
c.GatherHealthCheck(acc, checks)
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
inputs.Add("consul", func() telegraf.Input {
|
|
|
|
return &Consul{}
|
|
|
|
})
|
|
|
|
}
|