Adding upstream version 1.34.4.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
e393c3af3f
commit
4978089aab
4963 changed files with 677545 additions and 0 deletions
109
plugins/inputs/consul/README.md
Normal file
109
plugins/inputs/consul/README.md
Normal file
|
@ -0,0 +1,109 @@
|
|||
# Hashicorp Consul Input Plugin
|
||||
|
||||
This plugin will collect statistics about all health checks registered in
|
||||
[Consul][consul] using the [Consul API][api]. The plugin will not report any
|
||||
[telemetry metrics][telemetry] but Consul can report those statistics using
|
||||
the StatsD protocol if needed.
|
||||
|
||||
⭐ Telegraf v1.0.0
|
||||
🏷️ server
|
||||
💻 all
|
||||
|
||||
[api]: https://www.consul.io/docs/agent/http/health.html#health_state
|
||||
[telemetry]: https://www.consul.io/docs/agent/telemetry.html
|
||||
[consul]: https://www.consul.io
|
||||
|
||||
## Global configuration options <!-- @/docs/includes/plugin_config.md -->
|
||||
|
||||
In addition to the plugin-specific configuration settings, plugins support
|
||||
additional global and plugin configuration settings. These settings are used to
|
||||
modify metrics, tags, and field or create aliases and configure ordering, etc.
|
||||
See the [CONFIGURATION.md][CONFIGURATION.md] for more details.
|
||||
|
||||
[CONFIGURATION.md]: ../../../docs/CONFIGURATION.md#plugins
|
||||
|
||||
## Configuration
|
||||
|
||||
```toml @sample.conf
|
||||
# Gather health check statuses from services registered in Consul
|
||||
[[inputs.consul]]
|
||||
## Consul server address
|
||||
# address = "localhost:8500"
|
||||
|
||||
## URI scheme for the Consul server, one of "http", "https"
|
||||
# scheme = "http"
|
||||
|
||||
## Metric version controls the mapping from Consul metrics into
|
||||
## Telegraf metrics. Version 2 moved all fields with string values
|
||||
## to tags.
|
||||
##
|
||||
## example: metric_version = 1; deprecated in 1.16
|
||||
## metric_version = 2; recommended version
|
||||
# metric_version = 1
|
||||
|
||||
## ACL token used in every request
|
||||
# token = ""
|
||||
|
||||
## HTTP Basic Authentication username and password.
|
||||
# username = ""
|
||||
# password = ""
|
||||
|
||||
## Data center to query the health checks from
|
||||
# datacenter = ""
|
||||
|
||||
## 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
|
||||
# insecure_skip_verify = true
|
||||
|
||||
## Consul checks' tag splitting
|
||||
# When tags are formatted like "key:value" with ":" as a delimiter then
|
||||
# they will be split and reported as proper key:value in Telegraf
|
||||
# tag_delimiter = ":"
|
||||
```
|
||||
|
||||
## Metrics
|
||||
|
||||
### metric_version = 1
|
||||
|
||||
- consul_health_checks
|
||||
- tags:
|
||||
- node (node that check/service is registered on)
|
||||
- service_name
|
||||
- check_id
|
||||
- fields:
|
||||
- check_name
|
||||
- service_id
|
||||
- status
|
||||
- passing (integer)
|
||||
- critical (integer)
|
||||
- warning (integer)
|
||||
|
||||
### metric_version = 2
|
||||
|
||||
- consul_health_checks
|
||||
- tags:
|
||||
- node (node that check/service is registered on)
|
||||
- service_name
|
||||
- check_id
|
||||
- check_name
|
||||
- service_id
|
||||
- status
|
||||
- fields:
|
||||
- passing (integer)
|
||||
- critical (integer)
|
||||
- warning (integer)
|
||||
|
||||
`passing`, `critical`, and `warning` are integer representations of the health
|
||||
check state. A value of `1` represents that the status was the state of the
|
||||
health check at this sample. `status` is string representation of the same
|
||||
state.
|
||||
|
||||
## Example Output
|
||||
|
||||
```text
|
||||
consul_health_checks,host=wolfpit,node=consul-server-node,check_id="serfHealth" check_name="Serf Health Status",service_id="",status="passing",passing=1i,critical=0i,warning=0i 1464698464486439902
|
||||
consul_health_checks,host=wolfpit,node=consul-server-node,service_name=www.example.com,check_id="service:www-example-com.test01" check_name="Service 'www.example.com' check",service_id="www-example-com.test01",status="critical",passing=0i,critical=1i,warning=0i 1464698464486519036
|
||||
```
|
151
plugins/inputs/consul/consul.go
Normal file
151
plugins/inputs/consul/consul.go
Normal file
|
@ -0,0 +1,151 @@
|
|||
//go:generate ../../../tools/readme_config_includer/generator
|
||||
package consul
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/consul/api"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
telegraf_config "github.com/influxdata/telegraf/config"
|
||||
"github.com/influxdata/telegraf/plugins/common/tls"
|
||||
"github.com/influxdata/telegraf/plugins/inputs"
|
||||
)
|
||||
|
||||
//go:embed sample.conf
|
||||
var sampleConfig string
|
||||
|
||||
type Consul struct {
|
||||
Address string `toml:"address"`
|
||||
Scheme string `toml:"scheme"`
|
||||
Token string `toml:"token"`
|
||||
Username string `toml:"username"`
|
||||
Password string `toml:"password"`
|
||||
Datacentre string `toml:"datacentre" deprecated:"1.10.0;1.35.0;use 'datacenter' instead"`
|
||||
Datacenter string `toml:"datacenter"`
|
||||
TagDelimiter string `toml:"tag_delimiter"`
|
||||
MetricVersion int `toml:"metric_version"`
|
||||
Log telegraf.Logger
|
||||
tls.ClientConfig
|
||||
|
||||
// client used to connect to Consul agent
|
||||
client *api.Client
|
||||
}
|
||||
|
||||
func (*Consul) SampleConfig() string {
|
||||
return sampleConfig
|
||||
}
|
||||
|
||||
func (c *Consul) Init() error {
|
||||
if c.MetricVersion != 2 {
|
||||
telegraf_config.PrintOptionValueDeprecationNotice("inputs.consul", "metric_version", 1,
|
||||
telegraf.DeprecationInfo{
|
||||
Since: "1.16.0",
|
||||
RemovalIn: "1.40.0",
|
||||
Notice: `please update to 'metric_version = 2'`,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
config := api.DefaultConfig()
|
||||
|
||||
if c.Address != "" {
|
||||
config.Address = c.Address
|
||||
}
|
||||
|
||||
if c.Scheme != "" {
|
||||
config.Scheme = c.Scheme
|
||||
}
|
||||
|
||||
if c.Datacentre != "" {
|
||||
config.Datacenter = c.Datacentre
|
||||
}
|
||||
|
||||
if c.Datacenter != "" {
|
||||
config.Datacenter = c.Datacenter
|
||||
}
|
||||
|
||||
if c.Token != "" {
|
||||
config.Token = c.Token
|
||||
}
|
||||
|
||||
if c.Username != "" {
|
||||
config.HttpAuth = &api.HttpBasicAuth{
|
||||
Username: c.Username,
|
||||
Password: c.Password,
|
||||
}
|
||||
}
|
||||
|
||||
tlsCfg, err := c.ClientConfig.TLSConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
config.Transport = &http.Transport{
|
||||
TLSClientConfig: tlsCfg,
|
||||
}
|
||||
|
||||
c.client, err = api.NewClient(config)
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Consul) Gather(acc telegraf.Accumulator) error {
|
||||
checks, _, err := c.client.Health().State("any", nil)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.gatherHealthCheck(acc, checks)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
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["passing"] = 0
|
||||
record["critical"] = 0
|
||||
record["warning"] = 0
|
||||
record[check.Status] = 1
|
||||
|
||||
if c.MetricVersion == 2 {
|
||||
tags["check_name"] = check.Name
|
||||
tags["service_id"] = check.ServiceID
|
||||
tags["status"] = check.Status
|
||||
} else {
|
||||
record["check_name"] = check.Name
|
||||
record["service_id"] = check.ServiceID
|
||||
record["status"] = check.Status
|
||||
}
|
||||
|
||||
tags["node"] = check.Node
|
||||
tags["service_name"] = check.ServiceName
|
||||
tags["check_id"] = check.CheckID
|
||||
|
||||
for _, checkTag := range check.ServiceTags {
|
||||
if c.TagDelimiter != "" {
|
||||
splittedTag := strings.SplitN(checkTag, c.TagDelimiter, 2)
|
||||
if len(splittedTag) == 1 && checkTag != "" {
|
||||
tags[checkTag] = checkTag
|
||||
} else if len(splittedTag) == 2 && splittedTag[1] != "" {
|
||||
tags[splittedTag[0]] = splittedTag[1]
|
||||
}
|
||||
} else if checkTag != "" {
|
||||
tags[checkTag] = checkTag
|
||||
}
|
||||
}
|
||||
|
||||
acc.AddFields("consul_health_checks", record, tags)
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
inputs.Add("consul", func() telegraf.Input {
|
||||
return &Consul{}
|
||||
})
|
||||
}
|
138
plugins/inputs/consul/consul_test.go
Normal file
138
plugins/inputs/consul/consul_test.go
Normal file
|
@ -0,0 +1,138 @@
|
|||
package consul
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/consul/api"
|
||||
|
||||
"github.com/influxdata/telegraf/testutil"
|
||||
)
|
||||
|
||||
var sampleChecks = []*api.HealthCheck{
|
||||
{
|
||||
Node: "localhost",
|
||||
CheckID: "foo.health123",
|
||||
Name: "foo.health",
|
||||
Status: "passing",
|
||||
Notes: "lorem ipsum",
|
||||
Output: "OK",
|
||||
ServiceID: "foo.123",
|
||||
ServiceName: "foo",
|
||||
ServiceTags: []string{"bar", "env:sandbox", "tagkey:value:stillvalue"},
|
||||
},
|
||||
}
|
||||
|
||||
func TestGatherHealthCheck(t *testing.T) {
|
||||
expectedFields := map[string]interface{}{
|
||||
"check_name": "foo.health",
|
||||
"status": "passing",
|
||||
"passing": 1,
|
||||
"critical": 0,
|
||||
"warning": 0,
|
||||
"service_id": "foo.123",
|
||||
}
|
||||
|
||||
expectedTags := map[string]string{
|
||||
"node": "localhost",
|
||||
"service_name": "foo",
|
||||
"check_id": "foo.health123",
|
||||
"bar": "bar",
|
||||
"env:sandbox": "env:sandbox",
|
||||
"tagkey:value:stillvalue": "tagkey:value:stillvalue",
|
||||
}
|
||||
|
||||
var acc testutil.Accumulator
|
||||
|
||||
consul := &Consul{}
|
||||
consul.gatherHealthCheck(&acc, sampleChecks)
|
||||
|
||||
acc.AssertContainsTaggedFields(t, "consul_health_checks", expectedFields, expectedTags)
|
||||
}
|
||||
|
||||
func TestGatherHealthCheckWithDelimitedTags(t *testing.T) {
|
||||
expectedFields := map[string]interface{}{
|
||||
"check_name": "foo.health",
|
||||
"status": "passing",
|
||||
"passing": 1,
|
||||
"critical": 0,
|
||||
"warning": 0,
|
||||
"service_id": "foo.123",
|
||||
}
|
||||
|
||||
expectedTags := map[string]string{
|
||||
"node": "localhost",
|
||||
"service_name": "foo",
|
||||
"check_id": "foo.health123",
|
||||
"bar": "bar",
|
||||
"env": "sandbox",
|
||||
"tagkey": "value:stillvalue",
|
||||
}
|
||||
|
||||
var acc testutil.Accumulator
|
||||
|
||||
consul := &Consul{
|
||||
TagDelimiter: ":",
|
||||
}
|
||||
consul.gatherHealthCheck(&acc, sampleChecks)
|
||||
|
||||
acc.AssertContainsTaggedFields(t, "consul_health_checks", expectedFields, expectedTags)
|
||||
}
|
||||
|
||||
func TestGatherHealthCheckV2(t *testing.T) {
|
||||
expectedFields := map[string]interface{}{
|
||||
"passing": 1,
|
||||
"critical": 0,
|
||||
"warning": 0,
|
||||
}
|
||||
|
||||
expectedTags := map[string]string{
|
||||
"node": "localhost",
|
||||
"check_id": "foo.health123",
|
||||
"check_name": "foo.health",
|
||||
"status": "passing",
|
||||
"service_id": "foo.123",
|
||||
"service_name": "foo",
|
||||
"bar": "bar",
|
||||
"env:sandbox": "env:sandbox",
|
||||
"tagkey:value:stillvalue": "tagkey:value:stillvalue",
|
||||
}
|
||||
|
||||
var acc testutil.Accumulator
|
||||
|
||||
consul := &Consul{
|
||||
MetricVersion: 2,
|
||||
}
|
||||
consul.gatherHealthCheck(&acc, sampleChecks)
|
||||
|
||||
acc.AssertContainsTaggedFields(t, "consul_health_checks", expectedFields, expectedTags)
|
||||
}
|
||||
|
||||
func TestGatherHealthCheckWithDelimitedTagsV2(t *testing.T) {
|
||||
expectedFields := map[string]interface{}{
|
||||
"passing": 1,
|
||||
"critical": 0,
|
||||
"warning": 0,
|
||||
}
|
||||
|
||||
expectedTags := map[string]string{
|
||||
"node": "localhost",
|
||||
"check_id": "foo.health123",
|
||||
"check_name": "foo.health",
|
||||
"status": "passing",
|
||||
"service_id": "foo.123",
|
||||
"service_name": "foo",
|
||||
"bar": "bar",
|
||||
"env": "sandbox",
|
||||
"tagkey": "value:stillvalue",
|
||||
}
|
||||
|
||||
var acc testutil.Accumulator
|
||||
|
||||
consul := &Consul{
|
||||
MetricVersion: 2,
|
||||
TagDelimiter: ":",
|
||||
}
|
||||
consul.gatherHealthCheck(&acc, sampleChecks)
|
||||
|
||||
acc.AssertContainsTaggedFields(t, "consul_health_checks", expectedFields, expectedTags)
|
||||
}
|
37
plugins/inputs/consul/sample.conf
Normal file
37
plugins/inputs/consul/sample.conf
Normal file
|
@ -0,0 +1,37 @@
|
|||
# Gather health check statuses from services registered in Consul
|
||||
[[inputs.consul]]
|
||||
## Consul server address
|
||||
# address = "localhost:8500"
|
||||
|
||||
## URI scheme for the Consul server, one of "http", "https"
|
||||
# scheme = "http"
|
||||
|
||||
## Metric version controls the mapping from Consul metrics into
|
||||
## Telegraf metrics. Version 2 moved all fields with string values
|
||||
## to tags.
|
||||
##
|
||||
## example: metric_version = 1; deprecated in 1.16
|
||||
## metric_version = 2; recommended version
|
||||
# metric_version = 1
|
||||
|
||||
## ACL token used in every request
|
||||
# token = ""
|
||||
|
||||
## HTTP Basic Authentication username and password.
|
||||
# username = ""
|
||||
# password = ""
|
||||
|
||||
## Data center to query the health checks from
|
||||
# datacenter = ""
|
||||
|
||||
## 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
|
||||
# insecure_skip_verify = true
|
||||
|
||||
## Consul checks' tag splitting
|
||||
# When tags are formatted like "key:value" with ":" as a delimiter then
|
||||
# they will be split and reported as proper key:value in Telegraf
|
||||
# tag_delimiter = ":"
|
Loading…
Add table
Add a link
Reference in a new issue