Merge pull request #1472 from go-redis/feature/slowlog

Feature/slowlog
This commit is contained in:
Vladimir Mihailenco 2020-09-09 13:00:04 +03:00 committed by GitHub
commit 54ec86c34a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 163 additions and 2 deletions

View File

@ -2167,3 +2167,119 @@ func (c *cmdsInfoCache) Get() (map[string]*CommandInfo, error) {
}) })
return c.cmds, err return c.cmds, err
} }
//------------------------------------------------------------------------------
type SlowLog struct {
ID int64
Time time.Time
Duration time.Duration
Args []string
// These are also optional fields emitted only by Redis 4.0 or greater:
// https://redis.io/commands/slowlog#output-format
ClientAddr string
ClientName string
}
type SlowLogCmd struct {
baseCmd
val []SlowLog
}
var _ Cmder = (*SlowLogCmd)(nil)
func NewSlowLogCmd(ctx context.Context, args ...interface{}) *SlowLogCmd {
return &SlowLogCmd{
baseCmd: baseCmd{
ctx: ctx,
args: args,
},
}
}
func (cmd *SlowLogCmd) Val() []SlowLog {
return cmd.val
}
func (cmd *SlowLogCmd) Result() ([]SlowLog, error) {
return cmd.Val(), cmd.Err()
}
func (cmd *SlowLogCmd) String() string {
return cmdString(cmd, cmd.val)
}
func (cmd *SlowLogCmd) readReply(rd *proto.Reader) error {
_, cmd.err = rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
cmd.val = make([]SlowLog, n)
for i := 0; i < len(cmd.val); i++ {
n, err := rd.ReadArrayLen()
if err != nil {
return nil, err
}
if n < 4 {
err := fmt.Errorf("redis: got %d elements in slowlog get, expected at least 4", n)
return nil, err
}
id, err := rd.ReadIntReply()
if err != nil {
return nil, err
}
createdAt, err := rd.ReadIntReply()
if err != nil {
return nil, err
}
createdAtTime := time.Unix(createdAt, 0)
costs, err := rd.ReadIntReply()
if err != nil {
return nil, err
}
costsDuration := time.Duration(costs) * time.Microsecond
cmdLen, err := rd.ReadArrayLen()
if err != nil {
return nil, err
}
if cmdLen < 1 {
err := fmt.Errorf("redis: got %d elements commands reply in slowlog get, expected at least 1", cmdLen)
return nil, err
}
cmdString := make([]string, cmdLen)
for i := 0; i < int(cmdLen); i++ {
cmdString[i], err = rd.ReadString()
if err != nil {
return nil, err
}
}
var address, name string
for i := 4; i < int(n); i++ {
str, err := rd.ReadString()
if err != nil {
return nil, err
}
if i == 4 {
address = str
} else if i == 5 {
name = str
}
}
cmd.val[i] = SlowLog{
ID: id,
Time: createdAtTime,
Duration: costsDuration,
Args: cmdString,
ClientAddr: address,
ClientName: name,
}
}
return nil, nil
})
return cmd.err
}

View File

@ -4,6 +4,7 @@ import (
"context" "context"
"errors" "errors"
"io" "io"
"strconv"
"time" "time"
"github.com/go-redis/redis/v8/internal" "github.com/go-redis/redis/v8/internal"
@ -2306,8 +2307,11 @@ func (c cmdable) SlaveOf(ctx context.Context, host, port string) *StatusCmd {
return cmd return cmd
} }
func (c cmdable) SlowLog(ctx context.Context) { func (c cmdable) SlowLog(ctx context.Context, num int64) *SlowLogCmd {
panic("not implemented") n := strconv.FormatInt(num, 10)
cmd := NewSlowLogCmd(context.Background(), "slowlog", "get", n)
_ = c(ctx, cmd)
return cmd
} }
func (c cmdable) Sync(ctx context.Context) { func (c cmdable) Sync(ctx context.Context) {

View File

@ -4013,6 +4013,25 @@ var _ = Describe("Commands", func() {
Expect(vals).To(Equal([]interface{}{int64(12), proto.RedisError("error"), "abc"})) Expect(vals).To(Equal([]interface{}{int64(12), proto.RedisError("error"), "abc"}))
}) })
}) })
Describe("SlowLog", func() {
It("returns slow query result", func() {
const key = "slowlog-log-slower-than"
old := client.ConfigGet(ctx, key).Val()
client.ConfigSet(ctx, key, "0")
defer client.ConfigSet(ctx, key, old[1].(string))
err := rdb.Do(ctx, "slowlog", "reset").Err()
Expect(err).NotTo(HaveOccurred())
client.Set(ctx, "test", "true", 0)
result, err := client.SlowLog(ctx, -1).Result()
Expect(err).NotTo(HaveOccurred())
Expect(len(result)).To(Equal(2))
})
})
}) })
type numberStruct struct { type numberStruct struct {

View File

@ -510,3 +510,24 @@ func ExampleNewUniversalClient_cluster() {
rdb.Ping(ctx) rdb.Ping(ctx)
} }
func ExampleClient_SlowLog() {
const key = "slowlog-log-slower-than"
old := rdb.ConfigGet(ctx, key).Val()
rdb.ConfigSet(ctx, key, "0")
defer rdb.ConfigSet(ctx, key, old[1].(string))
if err := rdb.Do(ctx, "slowlog", "reset").Err(); err != nil {
panic(err)
}
rdb.Set(ctx, "test", "true", 0)
result, err := rdb.SlowLog(ctx, -1).Result()
if err != nil {
panic(err)
}
fmt.Println(len(result))
// Output: 2
}

1
go.sum
View File

@ -43,6 +43,7 @@ github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9k
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.10.2 h1:aY/nuoWlKJud2J6U0E3NWsjlg+0GtwXxgEqthRdzlcs=
github.com/onsi/gomega v1.10.2/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.10.2/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=