Skip to content

Commit

Permalink
Redis Enterprise introduced new field calls_master in commandstats (#232
Browse files Browse the repository at this point in the history
)

* Redis Enterprise introduced new field calls_master in commandstats

* Update CHANGELOG.md
  • Loading branch information
mikhail-vl authored Nov 7, 2021
1 parent 58ecb1c commit 3ffb8e0
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 250 deletions.
7 changes: 4 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Change Log

## 2.0.0 (IN PROGRESS)
## 2.0.0 (2021-11-06)

### Breaking changes

Expand All @@ -18,8 +18,9 @@
- Use Time-range for XRANGE filtering (#176)
- Disable Command-line interface in the Query Editor (#226)
- Support of ZRANGE command (#182)
- Upgrade Grafana 8.2.3 and backend dependencies
- Support fetching from RedisJSON datasource (JSON.GET, JSON.TYPE, JSON.ARRLEN, JSON.OBJLEN, JSON.OBJKEYS)
- Upgrade Grafana 8.2.3 and backend dependencies (#228)
- Support fetching from RedisJSON datasource (JSON.GET, JSON.TYPE, JSON.ARRLEN, JSON.OBJLEN, JSON.OBJKEYS) (#229)
- Redis Enterprise introduced new field calls_master in commandstats (#232)

### Bug fixes

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
"stop:dev": "docker-compose -f docker-compose/dev.yml down",
"test": "grafana-toolkit plugin:test --coverage",
"test:backend": "mage cover",
"test:backend:single": "go test ./pkg/... -v -run TestQueryJsonGet",
"test:backend:single": "go test ./pkg/... -v -run TestQueryInfo",
"test:integration": "mage integration",
"upgrade": "yarn upgrade --latest",
"watch": "grafana-toolkit plugin:dev --watch"
Expand Down
90 changes: 14 additions & 76 deletions pkg/redis-info.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,14 @@ func queryInfo(qm queryModel, client redisClient) backend.DataResponse {

// Command stats
if qm.Section == "commandstats" {
// Not Streaming
if !qm.Streaming {
frame.Fields = append(frame.Fields, data.NewField("Command", nil, []string{}),
data.NewField("Calls", nil, []int64{}),
data.NewField("Usec", nil, []float64{}).SetConfig(&data.FieldConfig{Unit: "µs"}),
data.NewField("Usec_per_call", nil, []float64{}).SetConfig(&data.FieldConfig{Unit: "µs"}))
}

// Redis 6.2 new fields
alreadyIncludedErrorStats := false
frame.Fields = append(frame.Fields, data.NewField("Command", nil, []string{}),
data.NewField("Calls", nil, []float64{}),
data.NewField("Usec", nil, []float64{}).SetConfig(&data.FieldConfig{Unit: "µs"}),
data.NewField("Usec_per_call", nil, []float64{}).SetConfig(&data.FieldConfig{Unit: "µs"}),
data.NewField("RejectedCalls", nil, []float64{}),
data.NewField("FailedCalls", nil, []float64{}),
data.NewField("CallsMaster", nil, []float64{}),
)

// Parse lines
for _, line := range lines {
Expand All @@ -56,78 +54,18 @@ func queryInfo(qm queryModel, client redisClient) backend.DataResponse {

// Stats
stats := strings.Split(fields[1], ",")
values := map[string]float64{}

if len(stats) < 3 {
continue
}

// Parse Stats
calls := strings.Split(stats[0], "=")
usec := strings.Split(stats[1], "=")
usecPerCall := strings.Split(stats[2], "=")

// Redis 6.2
var failedCalls = make([]string, 0)
var rejectedCalls = make([]string, 0)
if len(stats) > 3 {
rejectedCalls = strings.Split(stats[3], "=")
failedCalls = strings.Split(stats[4], "=")

// Add new Fields
if !alreadyIncludedErrorStats && !qm.Streaming {
frame.Fields = append(frame.Fields,
data.NewField("RejectedCalls", nil, []int64{}),
data.NewField("FailedCalls", nil, []int64{}))
}

alreadyIncludedErrorStats = true
}

var callsValue int64
var rejectedCallsValue int64
var failedCallsValue int64
var usecValue float64
var usecPerCallValue float64

// Parse Calls
if len(calls) == 2 {
callsValue, _ = strconv.ParseInt(calls[1], 10, 64)
}

// Parse rejectedCalls
if len(rejectedCalls) == 2 {
rejectedCallsValue, _ = strconv.ParseInt(rejectedCalls[1], 10, 64)
}

// Parse failedCalls
if len(failedCalls) == 2 {
failedCallsValue, _ = strconv.ParseInt(failedCalls[1], 10, 64)
}

// Parse Usec
if len(usec) == 2 {
usecValue, _ = strconv.ParseFloat(usec[1], 64)
}

// Parse Usec per Call
if len(usecPerCall) == 2 {
usecPerCallValue, _ = strconv.ParseFloat(usecPerCall[1], 64)
for _, stat := range stats {
value := strings.Split(stat, "=")
values[value[0]], _ = strconv.ParseFloat(value[1], 64)
}

// Command name
cmd := strings.Replace(fields[0], "cmdstat_", "", 1)

// Streaming
if qm.Streaming {
frame.Fields = append(frame.Fields, data.NewField(cmd+"", nil, []int64{callsValue}))
} else {
// Add Command
if len(stats) > 3 {
frame.AppendRow(cmd, callsValue, usecValue, usecPerCallValue, rejectedCallsValue, failedCallsValue)
} else {
frame.AppendRow(cmd, callsValue, usecValue, usecPerCallValue)
}
}
// Add Command
frame.AppendRow(cmd, values["calls"], values["usec"], values["usec_per_call"], values["rejected_calls"], values["failed_calls"], values["calls_master"])
}

// Add the frames to the response
Expand Down
33 changes: 6 additions & 27 deletions pkg/redis-info_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ func TestQueryInfo(t *testing.T) {
"should parse bulk string with 'commandstats' section",
queryModel{Command: models.Info, Section: "commandstats"},
"# Commandstats\r\ncmdstat_info:calls=5,usec=203,usec_per_call=40.60\r\ncmdstat_config:calls=1,usec=29,usec_per_call=29.00\r\n",
4,
7,
2,
[]valueToCheckInResponse{
{frameIndex: 0, fieldIndex: 0, rowIndex: 0, value: "info"},
{frameIndex: 0, fieldIndex: 1, rowIndex: 0, value: int64(5)},
{frameIndex: 0, fieldIndex: 1, rowIndex: 0, value: float64(5)},
{frameIndex: 0, fieldIndex: 2, rowIndex: 0, value: float64(203)},
{frameIndex: 0, fieldIndex: 3, rowIndex: 0, value: float64(40.60)},
},
Expand All @@ -51,15 +51,15 @@ func TestQueryInfo(t *testing.T) {
"should parse bulk string with 'redis v6.2 commandstats' section",
queryModel{Command: models.Info, Section: "commandstats"},
"# Commandstats\r\ncmdstat_info:calls=5,usec=203,usec_per_call=40.60,rejected_calls=1,failed_calls=0\r\ncmdstat_config:calls=1,usec=29,usec_per_call=29.00,rejected_calls=0,failed_calls=10\r\n",
6,
7,
2,
[]valueToCheckInResponse{
{frameIndex: 0, fieldIndex: 0, rowIndex: 0, value: "info"},
{frameIndex: 0, fieldIndex: 1, rowIndex: 0, value: int64(5)},
{frameIndex: 0, fieldIndex: 1, rowIndex: 0, value: float64(5)},
{frameIndex: 0, fieldIndex: 2, rowIndex: 0, value: float64(203)},
{frameIndex: 0, fieldIndex: 3, rowIndex: 0, value: float64(40.60)},
{frameIndex: 0, fieldIndex: 4, rowIndex: 0, value: int64(1)},
{frameIndex: 0, fieldIndex: 5, rowIndex: 0, value: int64(0)},
{frameIndex: 0, fieldIndex: 4, rowIndex: 0, value: float64(1)},
{frameIndex: 0, fieldIndex: 5, rowIndex: 0, value: float64(0)},
},
nil,
},
Expand All @@ -77,27 +77,6 @@ func TestQueryInfo(t *testing.T) {
},
nil,
},
{
"should parse bulk string with 'commandstats' and ignore stats if only 2 stats per command",
queryModel{Command: models.Info, Section: "commandstats"},
"# Commandstats\r\ncmdstat_info:calls=5,usec_per_call=40.60\r\ncmdstat_config:calls=1,usec_per_call=29.00\r\n",
4,
0,
nil,
nil,
},
{
"should parse bulk string with 'commandstats' section ans streaming true",
queryModel{Command: models.Info, Section: "commandstats", Streaming: true},
"# Commandstats\r\ncmdstat_info:calls=5,usec=203,usec_per_call=40.60\r\ncmdstat_config:calls=1,usec=29,usec_per_call=29.00\r\n",
2,
1,
[]valueToCheckInResponse{
{frameIndex: 0, fieldIndex: 0, rowIndex: 0, value: int64(5)},
{frameIndex: 0, fieldIndex: 1, rowIndex: 0, value: int64(1)},
},
nil,
},
{
"should handle error",
queryModel{Command: models.Info},
Expand Down
Loading

0 comments on commit 3ffb8e0

Please sign in to comment.