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
28
plugins/inputs/twemproxy/README.md
Normal file
28
plugins/inputs/twemproxy/README.md
Normal file
|
@ -0,0 +1,28 @@
|
|||
# Twemproxy Input Plugin
|
||||
|
||||
The `twemproxy` plugin gathers statistics from
|
||||
[Twemproxy](https://github.com/twitter/twemproxy) servers.
|
||||
|
||||
## 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
|
||||
# Read Twemproxy stats data
|
||||
[[inputs.twemproxy]]
|
||||
## Twemproxy stats address and port (no scheme)
|
||||
addr = "localhost:22222"
|
||||
## Monitor pool name
|
||||
pools = ["redis_pool", "mc_pool"]
|
||||
```
|
||||
|
||||
## Metrics
|
||||
|
||||
## Example Output
|
6
plugins/inputs/twemproxy/sample.conf
Normal file
6
plugins/inputs/twemproxy/sample.conf
Normal file
|
@ -0,0 +1,6 @@
|
|||
# Read Twemproxy stats data
|
||||
[[inputs.twemproxy]]
|
||||
## Twemproxy stats address and port (no scheme)
|
||||
addr = "localhost:22222"
|
||||
## Monitor pool name
|
||||
pools = ["redis_pool", "mc_pool"]
|
128
plugins/inputs/twemproxy/twemproxy.go
Normal file
128
plugins/inputs/twemproxy/twemproxy.go
Normal file
|
@ -0,0 +1,128 @@
|
|||
//go:generate ../../../tools/readme_config_includer/generator
|
||||
package twemproxy
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
"github.com/influxdata/telegraf/plugins/inputs"
|
||||
)
|
||||
|
||||
//go:embed sample.conf
|
||||
var sampleConfig string
|
||||
|
||||
type Twemproxy struct {
|
||||
Addr string `toml:"addr"`
|
||||
Pools []string `toml:"pools"`
|
||||
}
|
||||
|
||||
func (*Twemproxy) SampleConfig() string {
|
||||
return sampleConfig
|
||||
}
|
||||
|
||||
func (t *Twemproxy) Gather(acc telegraf.Accumulator) error {
|
||||
conn, err := net.DialTimeout("tcp", t.Addr, 1*time.Second)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
body, err := io.ReadAll(conn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var stats map[string]interface{}
|
||||
if err = json.Unmarshal(body, &stats); err != nil {
|
||||
return errors.New("error decoding JSON response")
|
||||
}
|
||||
|
||||
tags := make(map[string]string)
|
||||
tags["twemproxy"] = t.Addr
|
||||
t.processStat(acc, tags, stats)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Process Twemproxy server stats
|
||||
func (t *Twemproxy) processStat(acc telegraf.Accumulator, tags map[string]string, data map[string]interface{}) {
|
||||
if source, ok := data["source"]; ok {
|
||||
if val, ok := source.(string); ok {
|
||||
tags["source"] = val
|
||||
}
|
||||
}
|
||||
|
||||
fields := make(map[string]interface{})
|
||||
metrics := []string{"total_connections", "curr_connections", "timestamp"}
|
||||
for _, m := range metrics {
|
||||
if value, ok := data[m]; ok {
|
||||
if val, ok := value.(float64); ok {
|
||||
fields[m] = val
|
||||
}
|
||||
}
|
||||
}
|
||||
acc.AddFields("twemproxy", fields, tags)
|
||||
|
||||
for _, pool := range t.Pools {
|
||||
if poolStat, ok := data[pool]; ok {
|
||||
if data, ok := poolStat.(map[string]interface{}); ok {
|
||||
poolTags := copyTags(tags)
|
||||
poolTags["pool"] = pool
|
||||
processPool(acc, poolTags, data)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Process pool data in Twemproxy stats
|
||||
func processPool(acc telegraf.Accumulator, tags map[string]string, data map[string]interface{}) {
|
||||
serverTags := make(map[string]map[string]string)
|
||||
|
||||
fields := make(map[string]interface{})
|
||||
for key, value := range data {
|
||||
switch key {
|
||||
case "client_connections", "forward_error", "client_err", "server_ejects", "fragments", "client_eof":
|
||||
if val, ok := value.(float64); ok {
|
||||
fields[key] = val
|
||||
}
|
||||
default:
|
||||
if data, ok := value.(map[string]interface{}); ok {
|
||||
if _, ok := serverTags[key]; !ok {
|
||||
serverTags[key] = copyTags(tags)
|
||||
serverTags[key]["server"] = key
|
||||
}
|
||||
processServer(acc, serverTags[key], data)
|
||||
}
|
||||
}
|
||||
}
|
||||
acc.AddFields("twemproxy_pool", fields, tags)
|
||||
}
|
||||
|
||||
// Process backend server(redis/memcached) stats
|
||||
func processServer(acc telegraf.Accumulator, tags map[string]string, data map[string]interface{}) {
|
||||
fields := make(map[string]interface{})
|
||||
for key, value := range data {
|
||||
if val, ok := value.(float64); ok {
|
||||
fields[key] = val
|
||||
}
|
||||
}
|
||||
acc.AddFields("twemproxy_pool_server", fields, tags)
|
||||
}
|
||||
|
||||
// Tags is not expected to be mutated after passing to Add.
|
||||
func copyTags(tags map[string]string) map[string]string {
|
||||
newTags := make(map[string]string)
|
||||
for k, v := range tags {
|
||||
newTags[k] = v
|
||||
}
|
||||
return newTags
|
||||
}
|
||||
|
||||
func init() {
|
||||
inputs.Add("twemproxy", func() telegraf.Input {
|
||||
return &Twemproxy{}
|
||||
})
|
||||
}
|
176
plugins/inputs/twemproxy/twemproxy_test.go
Normal file
176
plugins/inputs/twemproxy/twemproxy_test.go
Normal file
|
@ -0,0 +1,176 @@
|
|||
package twemproxy
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/influxdata/telegraf/testutil"
|
||||
)
|
||||
|
||||
const sampleAddr = "127.0.0.1:22222"
|
||||
|
||||
const sampleStats = `{
|
||||
"total_connections": 276448,
|
||||
"uptime": 160657,
|
||||
"version": "0.4.1",
|
||||
"service": "nutcracker",
|
||||
"curr_connections": 1322,
|
||||
"source": "server1.website.com",
|
||||
"demo": {
|
||||
"client_connections": 1305,
|
||||
"forward_error": 11684,
|
||||
"client_err": 147942,
|
||||
"server_ejects": 0,
|
||||
"fragments": 0,
|
||||
"client_eof": 126813,
|
||||
"10.16.29.1:6379": {
|
||||
"requests": 43604566,
|
||||
"server_eof": 0,
|
||||
"out_queue": 0,
|
||||
"server_err": 0,
|
||||
"out_queue_bytes": 0,
|
||||
"in_queue": 0,
|
||||
"server_timedout": 24,
|
||||
"request_bytes": 2775840400,
|
||||
"server_connections": 1,
|
||||
"response_bytes": 7663182096,
|
||||
"in_queue_bytes": 0,
|
||||
"server_ejected_at": 0,
|
||||
"responses": 43603900
|
||||
},
|
||||
"10.16.29.2:6379": {
|
||||
"requests": 37870211,
|
||||
"server_eof": 0,
|
||||
"out_queue": 0,
|
||||
"server_err": 0,
|
||||
"out_queue_bytes": 0,
|
||||
"in_queue": 0,
|
||||
"server_timedout": 25,
|
||||
"request_bytes": 2412114759,
|
||||
"server_connections": 1,
|
||||
"response_bytes": 5228980582,
|
||||
"in_queue_bytes": 0,
|
||||
"server_ejected_at": 0,
|
||||
"responses": 37869551
|
||||
}
|
||||
},
|
||||
"timestamp": 1447312436
|
||||
}`
|
||||
|
||||
func mockTwemproxyServer() (net.Listener, error) {
|
||||
listener, err := net.Listen("tcp", sampleAddr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
go func(l net.Listener) {
|
||||
conn, err := l.Accept()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if _, err := conn.Write([]byte(sampleStats)); err != nil {
|
||||
return
|
||||
}
|
||||
if err := conn.Close(); err != nil {
|
||||
return
|
||||
}
|
||||
}(listener)
|
||||
|
||||
return listener, nil
|
||||
}
|
||||
|
||||
func TestGather(t *testing.T) {
|
||||
mockServer, err := mockTwemproxyServer()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer mockServer.Close()
|
||||
|
||||
twemproxy := &Twemproxy{
|
||||
Addr: sampleAddr,
|
||||
Pools: []string{"demo"},
|
||||
}
|
||||
|
||||
var acc testutil.Accumulator
|
||||
acc.SetDebug(true)
|
||||
err = twemproxy.Gather(&acc)
|
||||
require.NoError(t, err)
|
||||
|
||||
var sourceData map[string]interface{}
|
||||
if err := json.Unmarshal([]byte(sampleStats), &sourceData); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fields := map[string]interface{}{
|
||||
"total_connections": float64(276448),
|
||||
"curr_connections": float64(1322),
|
||||
"timestamp": float64(1.447312436e+09),
|
||||
}
|
||||
tags := map[string]string{
|
||||
"twemproxy": sampleAddr,
|
||||
"source": sourceData["source"].(string),
|
||||
}
|
||||
acc.AssertContainsTaggedFields(t, "twemproxy", fields, tags)
|
||||
|
||||
poolName := "demo"
|
||||
poolFields := map[string]interface{}{
|
||||
"client_connections": float64(1305),
|
||||
"client_eof": float64(126813),
|
||||
"client_err": float64(147942),
|
||||
"forward_error": float64(11684),
|
||||
"fragments": float64(0),
|
||||
"server_ejects": float64(0),
|
||||
}
|
||||
tags["pool"] = poolName
|
||||
acc.AssertContainsTaggedFields(t, "twemproxy_pool", poolFields, tags)
|
||||
|
||||
poolServerTags1 := map[string]string{
|
||||
"pool": "demo",
|
||||
"server": "10.16.29.2:6379",
|
||||
"source": "server1.website.com",
|
||||
"twemproxy": "127.0.0.1:22222",
|
||||
}
|
||||
poolServerFields1 := map[string]interface{}{
|
||||
"in_queue": float64(0),
|
||||
"in_queue_bytes": float64(0),
|
||||
"out_queue": float64(0),
|
||||
"out_queue_bytes": float64(0),
|
||||
"request_bytes": float64(2.412114759e+09),
|
||||
"requests": float64(3.7870211e+07),
|
||||
"response_bytes": float64(5.228980582e+09),
|
||||
"responses": float64(3.7869551e+07),
|
||||
"server_connections": float64(1),
|
||||
"server_ejected_at": float64(0),
|
||||
"server_eof": float64(0),
|
||||
"server_err": float64(0),
|
||||
"server_timedout": float64(25),
|
||||
}
|
||||
acc.AssertContainsTaggedFields(t, "twemproxy_pool_server",
|
||||
poolServerFields1, poolServerTags1)
|
||||
|
||||
poolServerTags2 := map[string]string{
|
||||
"pool": "demo",
|
||||
"server": "10.16.29.1:6379",
|
||||
"source": "server1.website.com",
|
||||
"twemproxy": "127.0.0.1:22222",
|
||||
}
|
||||
poolServerFields2 := map[string]interface{}{
|
||||
"in_queue": float64(0),
|
||||
"in_queue_bytes": float64(0),
|
||||
"out_queue": float64(0),
|
||||
"out_queue_bytes": float64(0),
|
||||
"request_bytes": float64(2.7758404e+09),
|
||||
"requests": float64(4.3604566e+07),
|
||||
"response_bytes": float64(7.663182096e+09),
|
||||
"responses": float64(4.36039e+07),
|
||||
"server_connections": float64(1),
|
||||
"server_ejected_at": float64(0),
|
||||
"server_eof": float64(0),
|
||||
"server_err": float64(0),
|
||||
"server_timedout": float64(24),
|
||||
}
|
||||
acc.AssertContainsTaggedFields(t, "twemproxy_pool_server",
|
||||
poolServerFields2, poolServerTags2)
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue