-
Notifications
You must be signed in to change notification settings - Fork 38
/
redis-custom.go
162 lines (134 loc) · 3.76 KB
/
redis-custom.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
package main
import (
"fmt"
"strconv"
"strings"
"bitbucket.org/creachadair/shell"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/backend/log"
"github.com/grafana/grafana-plugin-sdk-go/data"
"github.com/mediocregopher/radix/v3"
)
/**
* Execute Query
* Can PANIC if command is wrong
*/
func (ds *redisDatasource) executeCustomQuery(qm queryModel, client ClientInterface) (interface{}, error) {
var result interface{}
var err error
// Split query
query, ok := shell.Split(qm.Query)
// Check if query is valid
if !ok {
err = fmt.Errorf("Query is not valid")
return result, err
}
// Separate command from params
command, params := query[0], query[1:]
// Handle Panic from custom command to catch "should never get here"
defer func() {
if err := recover(); err != nil {
log.DefaultLogger.Error("PANIC", "command", err, "query", qm.Query)
}
}()
// Run command without params
if len(params) == 0 {
err = client.Do(radix.Cmd(&result, command))
return result, err
}
// Extract key or 1st parameter as required for FlatCmd
key, params := params[0], params[1:]
err = client.Do(radix.FlatCmd(&result, command, key, params))
return result, err
}
/**
* Parse Value
*/
func (ds *redisDatasource) parseInterfaceValue(value []interface{}, response backend.DataResponse) ([]string, backend.DataResponse) {
var values []string
for _, element := range value {
switch element := element.(type) {
case []byte:
values = append(values, string(element))
case int64:
values = append(values, strconv.FormatInt(element, 10))
case string:
values = append(values, element)
case []interface{}:
var parsedValues []string
parsedValues, response = ds.parseInterfaceValue(element, response)
// If no values
if len(parsedValues) == 0 {
parsedValues = append(parsedValues, "(empty array)")
}
values = append(values, parsedValues...)
default:
response.Error = fmt.Errorf("Unsupported array return type")
return values, response
}
}
return values, response
}
/**
* Custom Command, used for CLI and Variables
*/
func (ds *redisDatasource) queryCustomCommand(qm queryModel, client ClientInterface) backend.DataResponse {
response := backend.DataResponse{}
// Query is empty
if qm.Query == "" {
response.Error = fmt.Errorf("Command is empty")
return response
}
var result interface{}
var err error
// Parse and execute query
result, err = ds.executeCustomQuery(qm, client)
// Check error
if err != nil {
return ds.errorHandler(response, err)
}
/**
* Check results and add frames
*/
switch result := result.(type) {
case int64:
// Add Frame
response.Frames = append(response.Frames,
data.NewFrame(qm.Key,
data.NewField("Value", nil, []int64{result})))
case []byte:
value := string(result)
// Split lines
values := strings.Split(strings.Replace(value, "\r\n", "\n", -1), "\n")
// Parse float if only one value
if len(values) == 1 {
response.Frames = append(response.Frames, ds.createFrameValue(qm.Key, values[0]))
break
}
// Add Frame
response.Frames = append(response.Frames,
data.NewFrame(qm.Key,
data.NewField("Value", nil, values)))
case string:
// Add Frame
response.Frames = append(response.Frames, ds.createFrameValue(qm.Key, result))
case []interface{}:
var values []string
// Parse values
values, response = ds.parseInterfaceValue(result, response)
// Error when parsing intarface
if response.Error != nil {
return response
}
// Add Frame
response.Frames = append(response.Frames,
data.NewFrame(qm.Key,
data.NewField("Value", nil, values)))
case nil:
response.Error = fmt.Errorf("Wrong command")
default:
response.Error = fmt.Errorf("Unsupported return type")
}
// Return Response
return response
}