Skip to content

Commit 334dfa3

Browse files
authored
feat: supported query variable, better default settings (#8)
* feat: supported query variable * supported value and label * lint * better error * feat: better default config values * updated carsharing * default user, default dashboard
1 parent d1b07e7 commit 334dfa3

File tree

9 files changed

+246
-40
lines changed

9 files changed

+246
-40
lines changed

pkg/plugin/datasource.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ func (d *Datasource) QueryData(ctx context.Context, req *backend.QueryDataReques
7373
frame.SetMeta(&data.FrameMeta{Channel: channel.String()})
7474
resp.Frames = append(resp.Frames, frame)
7575
} else {
76+
count := 0
7677
columnTypes, ch, err := d.engine.RunQuery(ctx, q.SQL)
7778
if err != nil {
7879
return nil, err
@@ -89,7 +90,7 @@ func (d *Datasource) QueryData(ctx context.Context, req *backend.QueryDataReques
8990
return nil, ctx.Err()
9091
case row, ok := <-ch:
9192
if !ok {
92-
logger.Info("Query finished")
93+
logger.Info("Query finished", "count", count)
9394

9495
resp.Frames = append(resp.Frames, frame)
9596
break LOOP
@@ -99,6 +100,7 @@ func (d *Datasource) QueryData(ctx context.Context, req *backend.QueryDataReques
99100
for i, r := range row {
100101
col := columnTypes[i]
101102
fData[i] = timeplus.ParseValue(col.Name(), col.DatabaseTypeName(), nil, r, false)
103+
count++
102104
}
103105

104106
frame.AppendRow(fData...)
@@ -206,7 +208,6 @@ func (d *Datasource) CheckHealth(ctx context.Context, req *backend.CheckHealthRe
206208
res.Message = "'Host' cannot be empty"
207209
return res, nil
208210
}
209-
210211
engine := timeplus.NewEngine(logger, config.Host, config.TCPPort, config.HTTPPort, config.Username, config.Secrets.Password)
211212

212213
if err := engine.Ping(ctx); err != nil {

pkg/timeplus/engine.go

+20-1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,16 @@ type TimeplusEngine struct {
3737
}
3838

3939
func NewEngine(logger log.Logger, host string, tcpPort, httpPort int, username, password string) *TimeplusEngine {
40+
if tcpPort == 0 {
41+
tcpPort = 8463
42+
}
43+
if httpPort == 0 {
44+
httpPort = 3218
45+
}
46+
if len(username) == 0 {
47+
username = "default"
48+
}
49+
4050
connection := protonDriver.OpenDB(&protonDriver.Options{
4151
Addr: []string{fmt.Sprintf("%s:%d", host, tcpPort)},
4252
Auth: protonDriver.Auth{
@@ -150,7 +160,16 @@ func (e *TimeplusEngine) IsStreamingQuery(ctx context.Context, query string) (bo
150160
}
151161
defer resp.Body.Close()
152162
if resp.StatusCode < 200 || resp.StatusCode > 399 {
153-
return false, fmt.Errorf("failed to analyze %d", resp.StatusCode)
163+
var errStr string
164+
165+
body, err := io.ReadAll(resp.Body)
166+
if err != nil {
167+
errStr = err.Error()
168+
} else {
169+
errStr = string(body)
170+
}
171+
172+
return false, fmt.Errorf("failed to analyze code: %d, error: %s", resp.StatusCode, errStr)
154173
}
155174

156175
body, err := io.ReadAll(resp.Body)

provisioning/dashboards/carsharing.json

+114-19
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,70 @@
2222
"links": [],
2323
"liveNow": false,
2424
"panels": [
25+
{
26+
"datasource": {
27+
"default": true,
28+
"type": "timeplus-proton-datasource",
29+
"uid": "proton-ds"
30+
},
31+
"fieldConfig": {
32+
"defaults": {
33+
"color": {
34+
"mode": "thresholds"
35+
},
36+
"mappings": [],
37+
"thresholds": {
38+
"mode": "absolute",
39+
"steps": [
40+
{
41+
"color": "green",
42+
"value": null
43+
},
44+
{
45+
"color": "red",
46+
"value": 80
47+
}
48+
]
49+
}
50+
},
51+
"overrides": []
52+
},
53+
"gridPos": {
54+
"h": 8,
55+
"w": 24,
56+
"x": 0,
57+
"y": 0
58+
},
59+
"id": 5,
60+
"options": {
61+
"colorMode": "value",
62+
"graphMode": "area",
63+
"justifyMode": "auto",
64+
"orientation": "auto",
65+
"percentChangeColorMode": "standard",
66+
"reduceOptions": {
67+
"calcs": ["lastNotNull"],
68+
"fields": "",
69+
"values": false
70+
},
71+
"showPercentChange": false,
72+
"textMode": "auto",
73+
"wideLayout": true
74+
},
75+
"pluginVersion": "11.2.2",
76+
"targets": [
77+
{
78+
"datasource": {
79+
"type": "timeplus-proton-datasource",
80+
"uid": "proton-ds"
81+
},
82+
"refId": "A",
83+
"sql": "select count(*) from table(bookings) where _tp_time < to_datetime($__to/1000) and _tp_time > to_datetime($__from/1000) and cid='$cid'"
84+
}
85+
],
86+
"title": "Total bookings for car $cid between $__from and $__to",
87+
"type": "stat"
88+
},
2589
{
2690
"datasource": {
2791
"type": "timeplus-proton-datasource",
@@ -57,7 +121,7 @@
57121
"h": 6,
58122
"w": 3,
59123
"x": 0,
60-
"y": 0
124+
"y": 8
61125
},
62126
"id": 1,
63127
"options": {
@@ -70,16 +134,16 @@
70134
},
71135
"showHeader": true
72136
},
73-
"pluginVersion": "10.2.3",
137+
"pluginVersion": "11.2.2",
74138
"targets": [
75139
{
76140
"addNow": false,
77141
"datasource": {
78142
"type": "timeplus-proton-datasource",
79143
"uid": "proton-ds"
80144
},
81-
"sql": "select now()",
82-
"refId": "A"
145+
"refId": "A",
146+
"sql": "select now()"
83147
}
84148
],
85149
"title": "select now()",
@@ -112,32 +176,34 @@
112176
"h": 6,
113177
"w": 7,
114178
"x": 3,
115-
"y": 0
179+
"y": 8
116180
},
117181
"id": 2,
118182
"options": {
119183
"colorMode": "value",
120184
"graphMode": "area",
121185
"justifyMode": "auto",
122186
"orientation": "auto",
187+
"percentChangeColorMode": "standard",
123188
"reduceOptions": {
124189
"calcs": ["lastNotNull"],
125190
"fields": "",
126191
"values": false
127192
},
193+
"showPercentChange": false,
128194
"textMode": "auto",
129195
"wideLayout": true
130196
},
131-
"pluginVersion": "10.2.3",
197+
"pluginVersion": "11.2.2",
132198
"targets": [
133199
{
134200
"addNow": false,
135201
"datasource": {
136202
"type": "timeplus-proton-datasource",
137203
"uid": "proton-ds"
138204
},
139-
"sql": "select count() from car_live_data",
140-
"refId": "A"
205+
"refId": "A",
206+
"sql": "select count() from car_live_data"
141207
}
142208
],
143209
"title": "select count() from car_live_data",
@@ -170,32 +236,34 @@
170236
"h": 6,
171237
"w": 14,
172238
"x": 10,
173-
"y": 0
239+
"y": 8
174240
},
175241
"id": 3,
176242
"options": {
177243
"colorMode": "value",
178244
"graphMode": "area",
179245
"justifyMode": "auto",
180246
"orientation": "auto",
247+
"percentChangeColorMode": "standard",
181248
"reduceOptions": {
182249
"calcs": ["lastNotNull"],
183250
"fields": "",
184251
"values": false
185252
},
253+
"showPercentChange": false,
186254
"textMode": "auto",
187255
"wideLayout": true
188256
},
189-
"pluginVersion": "10.2.3",
257+
"pluginVersion": "11.2.2",
190258
"targets": [
191259
{
192260
"addNow": false,
193261
"datasource": {
194262
"type": "timeplus-proton-datasource",
195263
"uid": "proton-ds"
196264
},
197-
"sql": "select count() from car_live_data where _tp_time>earliest_ts()",
198-
"refId": "A"
265+
"refId": "A",
266+
"sql": "select count() from car_live_data where _tp_time>earliest_ts()"
199267
}
200268
],
201269
"title": "select count() from car_live_data where _tp_time>earliest_ts()",
@@ -239,7 +307,7 @@
239307
"h": 9,
240308
"w": 24,
241309
"x": 0,
242-
"y": 6
310+
"y": 14
243311
},
244312
"id": 4,
245313
"options": {
@@ -307,16 +375,16 @@
307375
"zoom": 12
308376
}
309377
},
310-
"pluginVersion": "10.2.3",
378+
"pluginVersion": "11.2.2",
311379
"targets": [
312380
{
313381
"addNow": false,
314382
"datasource": {
315383
"type": "timeplus-proton-datasource",
316384
"uid": "proton-ds"
317385
},
318-
"sql": "select longitude, latitude,speed_kmh,cid from car_live_data where cid like '%1'",
319-
"refId": "A"
386+
"refId": "A",
387+
"sql": "select longitude, latitude,speed_kmh,cid from car_live_data where cid like '%1'"
320388
}
321389
],
322390
"title": "Panel Title",
@@ -327,16 +395,43 @@
327395
"schemaVersion": 39,
328396
"tags": [],
329397
"templating": {
330-
"list": []
398+
"list": [
399+
{
400+
"current": {
401+
"selected": true,
402+
"text": "c00000",
403+
"value": "c00000"
404+
},
405+
"datasource": {
406+
"type": "timeplus-proton-datasource",
407+
"uid": "proton-ds"
408+
},
409+
"definition": "select cid from table(car_live_data) where _tp_time < to_datetime($__to/1000) and _tp_time > to_datetime($__from/1000)",
410+
"hide": 0,
411+
"includeAll": false,
412+
"label": "Car ID",
413+
"multi": false,
414+
"name": "cid",
415+
"options": [],
416+
"query": {
417+
"query": "select cid from table(car_live_data) where _tp_time < to_datetime($__to/1000) and _tp_time > to_datetime($__from/1000)"
418+
},
419+
"refresh": 2,
420+
"regex": "",
421+
"skipUrlSync": false,
422+
"sort": 0,
423+
"type": "query"
424+
}
425+
]
331426
},
332427
"time": {
333-
"from": "now-6h",
428+
"from": "now-1h",
334429
"to": "now"
335430
},
336431
"timepicker": {},
337432
"timezone": "",
338433
"title": "Carsharing Demo Dashboard",
339434
"uid": "dd9e271d-7225-47d4-9e57-62133db0df62",
340-
"version": 4,
435+
"version": 1,
341436
"weekStart": ""
342437
}

src/components/ConfigEditor.tsx

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
import React, { ChangeEvent } from 'react';
21
import { InlineField, Input, SecretInput } from '@grafana/ui';
3-
import { DataSourcePluginOptionsEditorProps } from '@grafana/data';
2+
import React, { ChangeEvent } from 'react';
43
import { TpDataSourceOptions, TpSecureJsonData } from '../types';
54

5+
import { DataSourcePluginOptionsEditorProps } from '@grafana/data';
6+
67
interface Props extends DataSourcePluginOptionsEditorProps<TpDataSourceOptions, TpSecureJsonData> {}
78

89
export function ConfigEditor(props: Props) {
@@ -75,8 +76,9 @@ export function ConfigEditor(props: Props) {
7576

7677
return (
7778
<>
78-
<InlineField label="Host" labelWidth={14} interactive tooltip={'Hostname'}>
79+
<InlineField required={true} label="Host" labelWidth={14} interactive tooltip={'Hostname'}>
7980
<Input
81+
required={true}
8082
id="config-editor-host"
8183
onChange={onHostChange}
8284
value={jsonData.host}
@@ -109,7 +111,7 @@ export function ConfigEditor(props: Props) {
109111
id="config-editor-username"
110112
onChange={onUsernameChange}
111113
value={jsonData.username}
112-
placeholder="Enter the username, e.g. admin"
114+
placeholder="default"
113115
width={40}
114116
/>
115117
</InlineField>

src/components/QueryEditor.tsx

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
1-
import React from 'react';
2-
import { InlineField, Stack, CodeEditor } from '@grafana/ui';
3-
import { QueryEditorProps } from '@grafana/data';
4-
import { DataSource } from '../datasource';
1+
import { CodeEditor, InlineField, Stack } from '@grafana/ui';
52
import { TpDataSourceOptions, TpQuery } from '../types';
63

4+
import { DataSource } from '../datasource';
5+
import { QueryEditorProps } from '@grafana/data';
6+
import React from 'react';
7+
78
type Props = QueryEditorProps<DataSource, TpQuery, TpDataSourceOptions>;
89

910
export function QueryEditor({ query, onChange }: Props) {
1011
const onSQLChange = (sql: string) => {
1112
onChange({ ...query, sql: sql });
1213
};
1314

14-
1515
const { sql } = query;
1616

1717
return (

0 commit comments

Comments
 (0)