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
107
plugins/inputs/zookeeper/README.md
Normal file
107
plugins/inputs/zookeeper/README.md
Normal file
|
@ -0,0 +1,107 @@
|
|||
# Zookeeper Input Plugin
|
||||
|
||||
The zookeeper plugin collects variables outputted from the 'mntr' command
|
||||
[Zookeeper Admin](https://zookeeper.apache.org/doc/current/zookeeperAdmin.html).
|
||||
|
||||
If in Zookeper, the Prometheus Metric provider is enabled, instead use the
|
||||
`prometheus` input plugin. By default, the Prometheus metrics are exposed at
|
||||
`http://<ip>:7000/metrics` URL. Using the `prometheus` input plugin provides a
|
||||
native solution to read and process Prometheus metrics, while this plugin is
|
||||
specific to using `mntr` to collect the Java Properties format.
|
||||
|
||||
## 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
|
||||
# Reads 'mntr' stats from one or many zookeeper servers
|
||||
[[inputs.zookeeper]]
|
||||
## An array of address to gather stats about. Specify an ip or hostname
|
||||
## with port. ie localhost:2181, 10.0.0.1:2181, etc.
|
||||
|
||||
## If no servers are specified, then localhost is used as the host.
|
||||
## If no port is specified, 2181 is used
|
||||
servers = [":2181"]
|
||||
|
||||
## Timeout for metric collections from all servers. Minimum timeout is "1s".
|
||||
# timeout = "5s"
|
||||
|
||||
## Float Parsing - the initial implementation forced any value unable to be
|
||||
## parsed as an int to be a string. Setting this to "float" will attempt to
|
||||
## parse float values as floats and not strings. This would break existing
|
||||
## metrics and may cause issues if a value switches between a float and int.
|
||||
# parse_floats = "string"
|
||||
|
||||
## Optional TLS Config
|
||||
# enable_tls = false
|
||||
# tls_ca = "/etc/telegraf/ca.pem"
|
||||
# tls_cert = "/etc/telegraf/cert.pem"
|
||||
# tls_key = "/etc/telegraf/key.pem"
|
||||
## If false, skip chain & host verification
|
||||
# insecure_skip_verify = true
|
||||
```
|
||||
|
||||
## Metrics
|
||||
|
||||
Exact field names are based on Zookeeper response and may vary between
|
||||
configuration, platform, and version.
|
||||
|
||||
- zookeeper
|
||||
- tags:
|
||||
- server
|
||||
- port
|
||||
- state
|
||||
- fields:
|
||||
- approximate_data_size (integer)
|
||||
- avg_latency (integer)
|
||||
- ephemerals_count (integer)
|
||||
- max_file_descriptor_count (integer)
|
||||
- max_latency (integer)
|
||||
- min_latency (integer)
|
||||
- num_alive_connections (integer)
|
||||
- open_file_descriptor_count (integer)
|
||||
- outstanding_requests (integer)
|
||||
- packets_received (integer)
|
||||
- packets_sent (integer)
|
||||
- version (string)
|
||||
- watch_count (integer)
|
||||
- znode_count (integer)
|
||||
- followers (integer, leader only)
|
||||
- synced_followers (integer, leader only)
|
||||
- pending_syncs (integer, leader only)
|
||||
|
||||
## Debugging
|
||||
|
||||
If you have any issues please check the direct Zookeeper output using netcat:
|
||||
|
||||
```sh
|
||||
$ echo mntr | nc localhost 2181
|
||||
zk_version 3.4.9-3--1, built on Thu, 01 Jun 2017 16:26:44 -0700
|
||||
zk_avg_latency 0
|
||||
zk_max_latency 0
|
||||
zk_min_latency 0
|
||||
zk_packets_received 8
|
||||
zk_packets_sent 7
|
||||
zk_num_alive_connections 1
|
||||
zk_outstanding_requests 0
|
||||
zk_server_state standalone
|
||||
zk_znode_count 129
|
||||
zk_watch_count 0
|
||||
zk_ephemerals_count 0
|
||||
zk_approximate_data_size 10044
|
||||
zk_open_file_descriptor_count 44
|
||||
zk_max_file_descriptor_count 4096
|
||||
```
|
||||
|
||||
## Example Output
|
||||
|
||||
```text
|
||||
zookeeper,server=localhost,port=2181,state=standalone ephemerals_count=0i,approximate_data_size=10044i,open_file_descriptor_count=44i,max_latency=0i,packets_received=7i,outstanding_requests=0i,znode_count=129i,max_file_descriptor_count=4096i,version="3.4.9-3--1",avg_latency=0i,packets_sent=6i,num_alive_connections=1i,watch_count=0i,min_latency=0i 1522351112000000000
|
||||
```
|
17
plugins/inputs/zookeeper/dev/docker-compose.yml
Normal file
17
plugins/inputs/zookeeper/dev/docker-compose.yml
Normal file
|
@ -0,0 +1,17 @@
|
|||
version: '3'
|
||||
services:
|
||||
zoo:
|
||||
image: zookeeper
|
||||
|
||||
telegraf:
|
||||
image: glinton/scratch
|
||||
volumes:
|
||||
- ./telegraf.conf:/telegraf.conf
|
||||
- ../../../../telegraf:/telegraf
|
||||
depends_on:
|
||||
- zoo
|
||||
entrypoint:
|
||||
- /telegraf
|
||||
- --config
|
||||
- /telegraf.conf
|
||||
network_mode: service:zoo
|
9
plugins/inputs/zookeeper/dev/telegraf.conf
Normal file
9
plugins/inputs/zookeeper/dev/telegraf.conf
Normal file
|
@ -0,0 +1,9 @@
|
|||
[agent]
|
||||
interval="1s"
|
||||
flush_interval="1s"
|
||||
|
||||
[[inputs.zookeeper]]
|
||||
servers = [":2181"]
|
||||
|
||||
[[outputs.file]]
|
||||
files = ["stdout"]
|
25
plugins/inputs/zookeeper/sample.conf
Normal file
25
plugins/inputs/zookeeper/sample.conf
Normal file
|
@ -0,0 +1,25 @@
|
|||
# Reads 'mntr' stats from one or many zookeeper servers
|
||||
[[inputs.zookeeper]]
|
||||
## An array of address to gather stats about. Specify an ip or hostname
|
||||
## with port. ie localhost:2181, 10.0.0.1:2181, etc.
|
||||
|
||||
## If no servers are specified, then localhost is used as the host.
|
||||
## If no port is specified, 2181 is used
|
||||
servers = [":2181"]
|
||||
|
||||
## Timeout for metric collections from all servers. Minimum timeout is "1s".
|
||||
# timeout = "5s"
|
||||
|
||||
## Float Parsing - the initial implementation forced any value unable to be
|
||||
## parsed as an int to be a string. Setting this to "float" will attempt to
|
||||
## parse float values as floats and not strings. This would break existing
|
||||
## metrics and may cause issues if a value switches between a float and int.
|
||||
# parse_floats = "string"
|
||||
|
||||
## Optional TLS Config
|
||||
# enable_tls = false
|
||||
# tls_ca = "/etc/telegraf/ca.pem"
|
||||
# tls_cert = "/etc/telegraf/cert.pem"
|
||||
# tls_key = "/etc/telegraf/key.pem"
|
||||
## If false, skip chain & host verification
|
||||
# insecure_skip_verify = true
|
173
plugins/inputs/zookeeper/zookeeper.go
Normal file
173
plugins/inputs/zookeeper/zookeeper.go
Normal file
|
@ -0,0 +1,173 @@
|
|||
//go:generate ../../../tools/readme_config_includer/generator
|
||||
package zookeeper
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"crypto/tls"
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"net"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
"github.com/influxdata/telegraf/config"
|
||||
common_tls "github.com/influxdata/telegraf/plugins/common/tls"
|
||||
"github.com/influxdata/telegraf/plugins/inputs"
|
||||
)
|
||||
|
||||
//go:embed sample.conf
|
||||
var sampleConfig string
|
||||
|
||||
var zookeeperFormatRE = regexp.MustCompile(`^zk_(\w[\w\.\-]*)\s+([\w\.\-]+)`)
|
||||
|
||||
type Zookeeper struct {
|
||||
Servers []string `toml:"servers"`
|
||||
Timeout config.Duration `toml:"timeout"`
|
||||
ParseFloats string `toml:"parse_floats"`
|
||||
|
||||
EnableTLS bool `toml:"enable_tls"`
|
||||
EnableSSL bool `toml:"enable_ssl" deprecated:"1.7.0;1.35.0;use 'enable_tls' instead"`
|
||||
common_tls.ClientConfig
|
||||
|
||||
initialized bool
|
||||
tlsConfig *tls.Config
|
||||
}
|
||||
|
||||
func (*Zookeeper) SampleConfig() string {
|
||||
return sampleConfig
|
||||
}
|
||||
|
||||
func (z *Zookeeper) Gather(acc telegraf.Accumulator) error {
|
||||
ctx := context.Background()
|
||||
|
||||
if !z.initialized {
|
||||
tlsConfig, err := z.ClientConfig.TLSConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
z.tlsConfig = tlsConfig
|
||||
z.initialized = true
|
||||
}
|
||||
|
||||
if z.Timeout < config.Duration(1*time.Second) {
|
||||
z.Timeout = config.Duration(5 * time.Second)
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(ctx, time.Duration(z.Timeout))
|
||||
defer cancel()
|
||||
|
||||
if len(z.Servers) == 0 {
|
||||
z.Servers = []string{":2181"}
|
||||
}
|
||||
|
||||
for _, serverAddress := range z.Servers {
|
||||
acc.AddError(z.gatherServer(ctx, serverAddress, acc))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (z *Zookeeper) gatherServer(ctx context.Context, address string, acc telegraf.Accumulator) error {
|
||||
var zookeeperState string
|
||||
_, _, err := net.SplitHostPort(address)
|
||||
if err != nil {
|
||||
address = address + ":2181"
|
||||
}
|
||||
|
||||
c, err := z.dial(ctx, address)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
// Apply deadline to connection
|
||||
deadline, ok := ctx.Deadline()
|
||||
if ok {
|
||||
if err := c.SetDeadline(deadline); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := fmt.Fprintf(c, "%s\n", "mntr"); err != nil {
|
||||
return err
|
||||
}
|
||||
rdr := bufio.NewReader(c)
|
||||
scanner := bufio.NewScanner(rdr)
|
||||
|
||||
service := strings.Split(address, ":")
|
||||
if len(service) != 2 {
|
||||
return fmt.Errorf("invalid service address: %s", address)
|
||||
}
|
||||
|
||||
fields := make(map[string]interface{})
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
parts := zookeeperFormatRE.FindStringSubmatch(line)
|
||||
|
||||
if len(parts) != 3 {
|
||||
return fmt.Errorf("unexpected line in mntr response: %q", line)
|
||||
}
|
||||
|
||||
measurement := strings.TrimPrefix(parts[1], "zk_")
|
||||
if measurement == "server_state" {
|
||||
zookeeperState = parts[2]
|
||||
continue
|
||||
}
|
||||
|
||||
sValue := parts[2]
|
||||
|
||||
// First attempt to parse as an int
|
||||
iVal, err := strconv.ParseInt(sValue, 10, 64)
|
||||
if err == nil {
|
||||
fields[measurement] = iVal
|
||||
continue
|
||||
}
|
||||
|
||||
// If set, attempt to parse as a float
|
||||
if z.ParseFloats == "float" {
|
||||
fVal, err := strconv.ParseFloat(sValue, 64)
|
||||
if err == nil {
|
||||
fields[measurement] = fVal
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, save as a string
|
||||
fields[measurement] = sValue
|
||||
}
|
||||
|
||||
srv := "localhost"
|
||||
if service[0] != "" {
|
||||
srv = service[0]
|
||||
}
|
||||
|
||||
tags := map[string]string{
|
||||
"server": srv,
|
||||
"port": service[1],
|
||||
"state": zookeeperState,
|
||||
}
|
||||
acc.AddFields("zookeeper", fields, tags)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (z *Zookeeper) dial(ctx context.Context, addr string) (net.Conn, error) {
|
||||
var dialer net.Dialer
|
||||
if z.EnableTLS || z.EnableSSL {
|
||||
deadline, ok := ctx.Deadline()
|
||||
if ok {
|
||||
dialer.Deadline = deadline
|
||||
}
|
||||
return tls.DialWithDialer(&dialer, "tcp", addr, z.tlsConfig)
|
||||
}
|
||||
return dialer.DialContext(ctx, "tcp", addr)
|
||||
}
|
||||
|
||||
func init() {
|
||||
inputs.Add("zookeeper", func() telegraf.Input {
|
||||
return &Zookeeper{}
|
||||
})
|
||||
}
|
87
plugins/inputs/zookeeper/zookeeper_test.go
Normal file
87
plugins/inputs/zookeeper/zookeeper_test.go
Normal file
|
@ -0,0 +1,87 @@
|
|||
package zookeeper
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/go-connections/nat"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/testcontainers/testcontainers-go/wait"
|
||||
|
||||
"github.com/influxdata/telegraf/testutil"
|
||||
)
|
||||
|
||||
func TestZookeeperGeneratesMetricsIntegration(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("Skipping integration test in short mode")
|
||||
}
|
||||
|
||||
servicePort := "2181"
|
||||
container := testutil.Container{
|
||||
Image: "zookeeper",
|
||||
ExposedPorts: []string{servicePort},
|
||||
Env: map[string]string{
|
||||
"ZOO_4LW_COMMANDS_WHITELIST": "mntr",
|
||||
},
|
||||
WaitingFor: wait.ForAll(
|
||||
wait.ForListeningPort(nat.Port(servicePort)),
|
||||
wait.ForLog("ZooKeeper audit is disabled."),
|
||||
),
|
||||
}
|
||||
err := container.Start()
|
||||
require.NoError(t, err, "failed to start container")
|
||||
defer container.Terminate()
|
||||
|
||||
var testset = []struct {
|
||||
name string
|
||||
zookeeper Zookeeper
|
||||
}{
|
||||
{
|
||||
name: "floats as strings",
|
||||
zookeeper: Zookeeper{
|
||||
Servers: []string{
|
||||
fmt.Sprintf("%s:%s", container.Address, container.Ports[servicePort]),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "floats as floats",
|
||||
zookeeper: Zookeeper{
|
||||
Servers: []string{
|
||||
fmt.Sprintf("%s:%s", container.Address, container.Ports[servicePort]),
|
||||
},
|
||||
ParseFloats: "float",
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range testset {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
var acc testutil.Accumulator
|
||||
require.NoError(t, acc.GatherError(tt.zookeeper.Gather))
|
||||
|
||||
intMetrics := []string{
|
||||
"max_latency",
|
||||
"min_latency",
|
||||
"packets_received",
|
||||
"packets_sent",
|
||||
"outstanding_requests",
|
||||
"znode_count",
|
||||
"watch_count",
|
||||
"ephemerals_count",
|
||||
"approximate_data_size",
|
||||
"open_file_descriptor_count",
|
||||
"max_file_descriptor_count",
|
||||
}
|
||||
|
||||
for _, metric := range intMetrics {
|
||||
require.True(t, acc.HasInt64Field("zookeeper", metric), metric)
|
||||
}
|
||||
|
||||
if tt.zookeeper.ParseFloats == "float" {
|
||||
require.True(t, acc.HasFloatField("zookeeper", "avg_latency"), "avg_latency not a float")
|
||||
} else {
|
||||
require.True(t, acc.HasStringField("zookeeper", "avg_latency"), "avg_latency not a string")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue