mirror of
https://github.com/redis/go-redis.git
synced 2025-11-08 13:02:18 +03:00
feat: support for latency command (#3584)
* support for latency command * add NonRedisEnterprise label for latency test
This commit is contained in:
77
command.go
77
command.go
@@ -3794,6 +3794,83 @@ func (cmd *SlowLogCmd) readReply(rd *proto.Reader) error {
|
|||||||
|
|
||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
type Latency struct {
|
||||||
|
Name string
|
||||||
|
Time time.Time
|
||||||
|
Latest time.Duration
|
||||||
|
Max time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
type LatencyCmd struct {
|
||||||
|
baseCmd
|
||||||
|
val []Latency
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ Cmder = (*LatencyCmd)(nil)
|
||||||
|
|
||||||
|
func NewLatencyCmd(ctx context.Context, args ...interface{}) *LatencyCmd {
|
||||||
|
return &LatencyCmd{
|
||||||
|
baseCmd: baseCmd{
|
||||||
|
ctx: ctx,
|
||||||
|
args: args,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *LatencyCmd) SetVal(val []Latency) {
|
||||||
|
cmd.val = val
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *LatencyCmd) Val() []Latency {
|
||||||
|
return cmd.val
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *LatencyCmd) Result() ([]Latency, error) {
|
||||||
|
return cmd.val, cmd.err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *LatencyCmd) String() string {
|
||||||
|
return cmdString(cmd, cmd.val)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *LatencyCmd) readReply(rd *proto.Reader) error {
|
||||||
|
n, err := rd.ReadArrayLen()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
cmd.val = make([]Latency, n)
|
||||||
|
for i := 0; i < len(cmd.val); i++ {
|
||||||
|
nn, err := rd.ReadArrayLen()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if nn < 3 {
|
||||||
|
return fmt.Errorf("redis: got %d elements in latency get, expected at least 3", nn)
|
||||||
|
}
|
||||||
|
if cmd.val[i].Name, err = rd.ReadString(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
createdAt, err := rd.ReadInt()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
cmd.val[i].Time = time.Unix(createdAt, 0)
|
||||||
|
latest, err := rd.ReadInt()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
cmd.val[i].Latest = time.Duration(latest) * time.Millisecond
|
||||||
|
maximum, err := rd.ReadInt()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
cmd.val[i].Max = time.Duration(maximum) * time.Millisecond
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
|
||||||
type MapStringInterfaceCmd struct {
|
type MapStringInterfaceCmd struct {
|
||||||
baseCmd
|
baseCmd
|
||||||
|
|
||||||
|
|||||||
18
commands.go
18
commands.go
@@ -214,6 +214,8 @@ type Cmdable interface {
|
|||||||
Time(ctx context.Context) *TimeCmd
|
Time(ctx context.Context) *TimeCmd
|
||||||
DebugObject(ctx context.Context, key string) *StringCmd
|
DebugObject(ctx context.Context, key string) *StringCmd
|
||||||
MemoryUsage(ctx context.Context, key string, samples ...int) *IntCmd
|
MemoryUsage(ctx context.Context, key string, samples ...int) *IntCmd
|
||||||
|
Latency(ctx context.Context) *LatencyCmd
|
||||||
|
LatencyReset(ctx context.Context, events ...interface{}) *StatusCmd
|
||||||
|
|
||||||
ModuleLoadex(ctx context.Context, conf *ModuleLoadexConfig) *StringCmd
|
ModuleLoadex(ctx context.Context, conf *ModuleLoadexConfig) *StringCmd
|
||||||
|
|
||||||
@@ -673,6 +675,22 @@ func (c cmdable) SlowLogGet(ctx context.Context, num int64) *SlowLogCmd {
|
|||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c cmdable) Latency(ctx context.Context) *LatencyCmd {
|
||||||
|
cmd := NewLatencyCmd(ctx, "latency", "latest")
|
||||||
|
_ = c(ctx, cmd)
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c cmdable) LatencyReset(ctx context.Context, events ...interface{}) *StatusCmd {
|
||||||
|
args := make([]interface{}, 2+len(events))
|
||||||
|
args[0] = "latency"
|
||||||
|
args[1] = "reset"
|
||||||
|
copy(args[2:], events)
|
||||||
|
cmd := NewStatusCmd(ctx, args...)
|
||||||
|
_ = c(ctx, cmd)
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
func (c cmdable) Sync(_ context.Context) {
|
func (c cmdable) Sync(_ context.Context) {
|
||||||
panic("not implemented")
|
panic("not implemented")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8312,6 +8312,86 @@ var _ = Describe("Commands", func() {
|
|||||||
Expect(len(result)).NotTo(BeZero())
|
Expect(len(result)).NotTo(BeZero())
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Describe("Latency", Label("NonRedisEnterprise"), func() {
|
||||||
|
It("returns latencies", func() {
|
||||||
|
const key = "latency-monitor-threshold"
|
||||||
|
|
||||||
|
old := client.ConfigGet(ctx, key).Val()
|
||||||
|
client.ConfigSet(ctx, key, "1")
|
||||||
|
defer client.ConfigSet(ctx, key, old[key])
|
||||||
|
|
||||||
|
err := client.Do(ctx, "DEBUG", "SLEEP", 0.01).Err()
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
result, err := client.Latency(ctx).Result()
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(len(result)).NotTo(BeZero())
|
||||||
|
})
|
||||||
|
|
||||||
|
It("reset all latencies", func() {
|
||||||
|
const key = "latency-monitor-threshold"
|
||||||
|
|
||||||
|
result, err := client.Latency(ctx).Result()
|
||||||
|
// reset all latencies
|
||||||
|
err = client.LatencyReset(ctx).Err()
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
old := client.ConfigGet(ctx, key).Val()
|
||||||
|
client.ConfigSet(ctx, key, "1")
|
||||||
|
defer client.ConfigSet(ctx, key, old[key])
|
||||||
|
|
||||||
|
// get latency after reset
|
||||||
|
result, err = client.Latency(ctx).Result()
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(len(result)).Should(Equal(0))
|
||||||
|
|
||||||
|
// create a new latency
|
||||||
|
err = client.Do(ctx, "DEBUG", "SLEEP", 0.01).Err()
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
// get latency after create a new latency
|
||||||
|
result, err = client.Latency(ctx).Result()
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(len(result)).Should(Equal(1))
|
||||||
|
|
||||||
|
// reset all latencies again
|
||||||
|
err = client.LatencyReset(ctx).Err()
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
// get latency after reset again
|
||||||
|
result, err = client.Latency(ctx).Result()
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(len(result)).Should(Equal(0))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("reset latencies by add event name args", func() {
|
||||||
|
const key = "latency-monitor-threshold"
|
||||||
|
|
||||||
|
old := client.ConfigGet(ctx, key).Val()
|
||||||
|
client.ConfigSet(ctx, key, "1")
|
||||||
|
defer client.ConfigSet(ctx, key, old[key])
|
||||||
|
|
||||||
|
result, err := client.Latency(ctx).Result()
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(len(result)).Should(Equal(0))
|
||||||
|
|
||||||
|
err = client.Do(ctx, "DEBUG", "SLEEP", 0.01).Err()
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
result, err = client.Latency(ctx).Result()
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(len(result)).Should(Equal(1))
|
||||||
|
|
||||||
|
// reset latency by event name
|
||||||
|
err = client.LatencyReset(ctx, result[0].Name).Err()
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
result, err = client.Latency(ctx).Result()
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(len(result)).Should(Equal(0))
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
type numberStruct struct {
|
type numberStruct struct {
|
||||||
|
|||||||
Reference in New Issue
Block a user