Skip to content

Commit

Permalink
feat: add functionality to get values from redis commands (influxdata…
Browse files Browse the repository at this point in the history
  • Loading branch information
yquansah authored Sep 30, 2020
1 parent 732ccbc commit b68976d
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 3 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ require (
github.com/glinton/ping v0.1.4-0.20200311211934-5ac87da8cd96
github.com/go-logfmt/logfmt v0.4.0
github.com/go-ole/go-ole v1.2.1 // indirect
github.com/go-redis/redis v6.12.0+incompatible
github.com/go-redis/redis v6.15.9+incompatible
github.com/go-sql-driver/mysql v1.5.0
github.com/goburrow/modbus v0.1.0
github.com/goburrow/serial v0.1.0 // indirect
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -214,8 +214,8 @@ github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+
github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=
github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc=
github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
github.com/go-redis/redis v6.12.0+incompatible h1:s+64XI+z/RXqGHz2fQSgRJOEwqqSXeX3dliF7iVkMbE=
github.com/go-redis/redis v6.12.0+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg=
github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
Expand Down
5 changes: 5 additions & 0 deletions plugins/inputs/redis/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@
## If no servers are specified, then localhost is used as the host.
## If no port is specified, 6379 is used
servers = ["tcp://localhost:6379"]
## Optional. Specify redis commands to retrieve values
# [[inputs.redis.commands]]
# command = ["get", "sample-key"]
# field = "sample-key-value"
# type = "string"

## specify server password
# password = "s#cr@t%"
Expand Down
46 changes: 46 additions & 0 deletions plugins/inputs/redis/redis.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,14 @@ import (
"github.com/influxdata/telegraf/plugins/inputs"
)

type RedisCommand struct {
Command []interface{}
Field string
Type string
}

type Redis struct {
Commands []*RedisCommand
Servers []string
Password string
tls.ClientConfig
Expand All @@ -29,6 +36,7 @@ type Redis struct {
}

type Client interface {
Do(returnType string, args ...interface{}) (interface{}, error)
Info() *redis.StringCmd
BaseTags() map[string]string
}
Expand All @@ -38,6 +46,21 @@ type RedisClient struct {
tags map[string]string
}

func (r *RedisClient) Do(returnType string, args ...interface{}) (interface{}, error) {
rawVal := r.client.Do(args...)

switch returnType {
case "integer":
return rawVal.Int64()
case "string":
return rawVal.String()
case "float":
return rawVal.Float64()
default:
return rawVal.String()
}
}

func (r *RedisClient) Info() *redis.StringCmd {
return r.client.Info("ALL")
}
Expand All @@ -64,6 +87,12 @@ var sampleConfig = `
## If no port is specified, 6379 is used
servers = ["tcp://localhost:6379"]
## Optional. Specify redis commands to retrieve values
# [[inputs.redis.commands]]
# command = ["get", "sample-key"]
# field = "sample-key-value"
# type = "string"
## specify server password
# password = "s#cr@t%"
Expand Down Expand Up @@ -179,13 +208,30 @@ func (r *Redis) Gather(acc telegraf.Accumulator) error {
go func(client Client) {
defer wg.Done()
acc.AddError(r.gatherServer(client, acc))
acc.AddError(r.gatherCommandValues(client, acc))
}(client)
}

wg.Wait()
return nil
}

func (r *Redis) gatherCommandValues(client Client, acc telegraf.Accumulator) error {
fields := make(map[string]interface{})
for _, command := range r.Commands {
val, err := client.Do(command.Type, command.Command...)
if err != nil {
return err
}

fields[command.Field] = val
}

acc.AddFields("redis_commands", fields, client.BaseTags())

return nil
}

func (r *Redis) gatherServer(client Client, acc telegraf.Accumulator) error {
info, err := client.Info().Result()
if err != nil {
Expand Down
43 changes: 43 additions & 0 deletions plugins/inputs/redis/redis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,27 @@ import (
"testing"
"time"

"github.com/go-redis/redis"
"github.com/influxdata/telegraf/testutil"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

type testClient struct {
}

func (t *testClient) BaseTags() map[string]string {
return map[string]string{"host": "redis.net"}
}

func (t *testClient) Info() *redis.StringCmd {
return nil
}

func (t *testClient) Do(returnType string, args ...interface{}) (interface{}, error) {
return 2, nil
}

func TestRedisConnect(t *testing.T) {
if testing.Short() {
t.Skip("Skipping integration test in short mode")
Expand All @@ -30,6 +46,33 @@ func TestRedisConnect(t *testing.T) {
require.NoError(t, err)
}

func TestRedis_Commands(t *testing.T) {
const redisListKey = "test-list-length"
var acc testutil.Accumulator

tc := &testClient{}

rc := &RedisCommand{
Command: []interface{}{"llen", "test-list"},
Field: redisListKey,
Type: "integer",
}

r := &Redis{
Commands: []*RedisCommand{rc},
clients: []Client{tc},
}

err := r.gatherCommandValues(tc, &acc)
require.NoError(t, err)

fields := map[string]interface{}{
redisListKey: 2,
}

acc.AssertContainsFields(t, "redis_commands", fields)
}

func TestRedis_ParseMetrics(t *testing.T) {
var acc testutil.Accumulator
tags := map[string]string{"host": "redis.net"}
Expand Down

0 comments on commit b68976d

Please sign in to comment.