Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add dynamic query variables #9

Merged
merged 2 commits into from
Sep 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
module github.com/grafana/simple-datasource-backend
module github.com/rockset/rockset-grafana-backend

go 1.14

require (
github.com/davecgh/go-spew v1.1.1
github.com/grafana/grafana-plugin-sdk-go v0.65.0
github.com/grafana/grafana-plugin-sdk-go v0.113.0
github.com/rockset/rockset-go-client v0.9.2
)
390 changes: 353 additions & 37 deletions go.sum

Large diffs are not rendered by default.

27 changes: 21 additions & 6 deletions pkg/rockset.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ func makeFrame(timeField, valueField, labelColumn, label string, qr api.QueryRes

var times []time.Time
var values []float64
var strValues []string

var labels map[string]string
// empty label means there is no label column and labels should use the zero value, which is nil
Expand Down Expand Up @@ -253,12 +254,23 @@ func makeFrame(timeField, valueField, labelColumn, label string, qr api.QueryRes

// TODO: this is a bit naïve and could be improved, as the rows can be of different types
f, ok := v.(float64)
if ok {
values = append(values, f)
}
if !ok {
// TODO: is there a way to send warnings back to the Grafana UI?
log.DefaultLogger.Error("could cast to float64", "column", valueField, "value", v)
continue
log.DefaultLogger.Error("could not cast to float64", "column", valueField, "value", v)
g, strOk := v.(string)
if strOk {
strValues = append(strValues, g)
}
if !strOk {
log.DefaultLogger.Error("could not cast to float64 or string", "column", valueField, "value", v)
continue
}

}
values = append(values, f)


// TODO: time conversion could be cached as it is parsed each call to makeFrame
t, err := parseTime(m, timeField)
Expand All @@ -271,8 +283,11 @@ func makeFrame(timeField, valueField, labelColumn, label string, qr api.QueryRes
// add the time dimension
frame.Fields = append(frame.Fields, data.NewField("time", labels, times))
// add values
frame.Fields = append(frame.Fields, data.NewField(valueField, labels, values))

if len(values) > 0 {
frame.Fields = append(frame.Fields, data.NewField(valueField, labels, values))
} else if len(strValues) > 0 {
frame.Fields = append(frame.Fields, data.NewField(valueField, labels, strValues))
}
return frame, nil
}

Expand All @@ -285,7 +300,7 @@ func parseTime(fields map[string]interface{}, key string) (time.Time, error) {

k, ok := ifc.(string)
if !ok {
return time.Time{}, fmt.Errorf("could cast %s to string", key)
return time.Time{}, fmt.Errorf("could not cast %s to string", key)
}

t, err := time.Parse(time.RFC3339Nano, k)
Expand Down
17 changes: 0 additions & 17 deletions src/DataSource.ts

This file was deleted.

50 changes: 50 additions & 0 deletions src/DataSource.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import {
DataSourceInstanceSettings,
DataQueryRequest,
DataQueryResponse,
MetricFindValue,
DataFrame,
} from '@grafana/data';
import { DataSourceWithBackend, getTemplateSrv } from '@grafana/runtime';
import { RocksetDataSourceOptions, RocksetQuery, MyVariableQuery } from './types';

export class DataSource extends DataSourceWithBackend<RocksetQuery, RocksetDataSourceOptions> {
constructor(instanceSettings: DataSourceInstanceSettings<RocksetDataSourceOptions>) {
super(instanceSettings);
}

async metricFindQuery?(query: MyVariableQuery, options?: any): Promise<MetricFindValue[]> {
const request = {
targets: [
{
queryText: query.rawQuery,
queryTimeField: '_event_time',
queryValueField: 'value',
refId: 'metricFindQuery',
},
],
} as DataQueryRequest<MyVariableQuery>;

let res: DataQueryResponse;

try {
res = await this.query(request).toPromise();
} catch (err) {
return Promise.reject(err);
}

if (!res.data.length || !res.data[0].fields.length) {
return [];
}

return (res.data[0] as DataFrame).fields[1].values.toArray().map(_ => ({ text: _.toString() }));
}

applyTemplateVariables(query: RocksetQuery) {
const templateSrv = getTemplateSrv();
return {
...query,
queryText: query.queryText ? templateSrv.replace(query.queryText) : '',
};
}
}
36 changes: 36 additions & 0 deletions src/VariableQueryEditor.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React, { useState } from 'react';
import { MyVariableQuery } from './types';

interface VariableQueryProps {
query: MyVariableQuery;
onChange: (query: MyVariableQuery, definition: string) => void;
}

export const VariableQueryEditor: React.FC<VariableQueryProps> = ({ onChange, query }) => {
const [state, setState] = useState(query);

const saveQuery = () => {
onChange(state, `${state.query}`);
};

const handleChange = (event: React.FormEvent<HTMLInputElement>) =>
setState({
...state,
[event.currentTarget.name]: event.currentTarget.value,
});

return (
<>
<div className="gf-form">
<span className="gf-form-label width-10">Query</span>
<input
name="rawQuery"
className="gf-form-input"
onBlur={saveQuery}
onChange={handleChange}
value={state.rawQuery}
/>
</div>
</>
);
};
4 changes: 3 additions & 1 deletion src/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import { DataSource } from './DataSource';
import { ConfigEditor } from './ConfigEditor';
import { QueryEditor } from './QueryEditor';
import { RocksetQuery, RocksetDataSourceOptions } from './types';
import { VariableQueryEditor } from './VariableQueryEditor';

export const plugin = new DataSourcePlugin<DataSource, RocksetQuery, RocksetDataSourceOptions>(DataSource)
.setConfigEditor(ConfigEditor)
.setQueryEditor(QueryEditor);
.setQueryEditor(QueryEditor)
.setVariableQueryEditor(VariableQueryEditor);
6 changes: 6 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,9 @@ export interface RocksetDataSourceOptions extends DataSourceJsonData {
export interface RocksetSecureJsonData {
apiKey?: string;
}

export interface MyVariableQuery extends RocksetQuery {
namespace: string;
rawQuery: string;
query: string;
}