Skip to content

Commit 1cf813d

Browse files
nitishtbalaji-jr
andauthored
address feedback from grafana (#41)
Co-authored-by: balaji-jr <[email protected]>
1 parent 89c9db3 commit 1cf813d

File tree

3 files changed

+75
-76
lines changed

3 files changed

+75
-76
lines changed

pkg/main.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99
)
1010

1111
func main() {
12-
if err := datasource.Manage("grafana-datasourcehttpbackend-datasource", plugin.NewDatasource, plugin.DatasourceOpts); err != nil {
12+
if err := datasource.Manage("parseable-parseable-datasource", plugin.NewDatasource, plugin.DatasourceOpts); err != nil {
1313
log.DefaultLogger.Error(err.Error())
1414
os.Exit(1)
1515
}

pkg/plugin/datasource.go

+10-25
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ import (
66
"encoding/json"
77
"errors"
88
"fmt"
9+
"io"
10+
"net/http"
11+
url2 "net/url"
12+
"reflect"
13+
914
"github.com/grafana/grafana-plugin-sdk-go/backend"
1015
"github.com/grafana/grafana-plugin-sdk-go/backend/datasource"
1116
"github.com/grafana/grafana-plugin-sdk-go/backend/httpclient"
@@ -15,10 +20,6 @@ import (
1520
"github.com/grafana/grafana-plugin-sdk-go/data"
1621
"go.opentelemetry.io/otel/attribute"
1722
"go.opentelemetry.io/otel/trace"
18-
"io"
19-
"net/http"
20-
url2 "net/url"
21-
"reflect"
2223
)
2324

2425
var (
@@ -65,32 +66,17 @@ func (d *Datasource) Dispose() {
6566
}
6667

6768
func (d *Datasource) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
68-
ctxLogger := log.DefaultLogger.FromContext(ctx)
69-
ctxLogger.Debug("QueryData", "queries", len(req.Queries))
70-
7169
response := backend.NewQueryDataResponse()
72-
73-
for i, q := range req.Queries {
74-
ctxLogger.Debug("Processing query", "number", i, "ref", q.RefID)
75-
76-
if i%2 != 0 {
77-
response.Responses[q.RefID] = backend.ErrDataResponse(
78-
backend.StatusBadRequest,
79-
fmt.Sprintf("user friendly error for query number %v, excluding any sensitive information", i+1),
80-
)
81-
continue
82-
}
83-
70+
for _, q := range req.Queries {
8471
res, err := d.query(ctx, req.PluginContext, q)
8572
switch {
8673
case err == nil:
87-
break
8874
case errors.Is(err, context.DeadlineExceeded):
8975
res = backend.ErrDataResponse(backend.StatusTimeout, "gateway timeout")
9076
case errors.Is(err, errRemoteRequest):
9177
res = backend.ErrDataResponse(backend.StatusBadGateway, "bad gateway request")
9278
case errors.Is(err, errRemoteResponse):
93-
res = backend.ErrDataResponse(backend.StatusValidationFailed, err.Error())
79+
res = backend.ErrDataResponse(backend.StatusInternal, err.Error())
9480
default:
9581
res = backend.ErrDataResponse(backend.StatusInternal, err.Error())
9682
}
@@ -145,12 +131,11 @@ func (d *Datasource) query(ctx context.Context, pCtx backend.PluginContext, quer
145131
}
146132

147133
req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewBuffer(requestBodyAsString))
148-
req.Header.Set("Content-Type", "application/json")
149-
150134
if err != nil {
151135
ctxLogger.Error("query: failed to create request", "err", err)
152136
return backend.DataResponse{}, fmt.Errorf("new request with context: %w", err)
153137
}
138+
req.Header.Set("Content-Type", "application/json")
154139

155140
httpResp, err := d.httpClient.Do(req)
156141

@@ -172,12 +157,12 @@ func (d *Datasource) query(ctx context.Context, pCtx backend.PluginContext, quer
172157
span.AddEvent("HTTP request done")
173158

174159
if httpResp.StatusCode != http.StatusOK {
175-
body, err := io.ReadAll(httpResp.Body)
160+
_, err := io.ReadAll(httpResp.Body)
176161
if err != nil {
177162
ctxLogger.Error("query: failed to read response body", "err", err)
178163
return backend.DataResponse{}, fmt.Errorf("%w: read body: %s", errRemoteResponse, err)
179164
}
180-
return backend.DataResponse{}, fmt.Errorf("%w: expected 200 response, got %d. Response: %s", errRemoteResponse, httpResp.StatusCode, body)
165+
return backend.DataResponse{}, fmt.Errorf("%w: expected 200 response, got %d", errRemoteResponse, httpResp.StatusCode)
181166
}
182167

183168
var body apiMetrics

src/datasource.ts

+64-50
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
1-
import { getBackendSrv, getTemplateSrv, BackendSrvRequest, FetchResponse } from "@grafana/runtime";
1+
import { getBackendSrv, getTemplateSrv, BackendSrvRequest, FetchResponse, DataSourceWithBackend } from "@grafana/runtime";
22
import {
33
DataQueryRequest,
44
DataQueryResponse,
5-
DataSourceApi,
65
DataSourceInstanceSettings,
76
MutableDataFrame,
87
DataFrame,
98
FieldType,
109
guessFieldTypeFromValue,
1110
MetricFindValue
1211
} from '@grafana/data';
13-
import { lastValueFrom, of } from 'rxjs';
12+
import { lastValueFrom, of, Observable } from 'rxjs';
1413
import { catchError, map } from 'rxjs/operators';
1514
import { isArray, isNull } from "lodash";
1615

@@ -23,7 +22,7 @@ import {
2322
StreamSchemaResponse,
2423
StreamStatsResponse
2524
} from './types';
26-
export class DataSource extends DataSourceApi<MyQuery, MyDataSourceOptions> {
25+
export class DataSource extends DataSourceWithBackend<MyQuery, MyDataSourceOptions> {
2726
url: string;
2827
withCredentials: boolean;
2928
headers: any;
@@ -45,49 +44,57 @@ export class DataSource extends DataSourceApi<MyQuery, MyDataSourceOptions> {
4544
return result;
4645
}
4746

48-
async query(options: DataQueryRequest<MyQuery>): Promise<DataQueryResponse> {
49-
options.targets = options.targets.filter((t) => !t.hide);
50-
if (options.targets.length === 0) {
51-
return Promise.resolve({ data: [] });
52-
}
47+
query(options: DataQueryRequest<MyQuery>): Observable<DataQueryResponse>{
48+
return new Observable<DataQueryResponse>(observer => {
49+
options.targets = options.targets.filter((t) => !t.hide);
50+
if (options.targets.length === 0) {
51+
observer.next({ data: [] });
52+
observer.complete();
53+
return;
54+
}
5355

54-
const { range } = options;
55-
if (!range) {
56-
return Promise.resolve({ data: [] });
57-
}
58-
const start = range!.from;
59-
const end = range!.to;
56+
const { range } = options;
57+
if (!range) {
58+
observer.next({ data: [] });
59+
observer.complete();
60+
return;
61+
}
62+
const start = range!.from;
63+
const end = range!.to;
6064

61-
const calls = options.targets.map(target => {
62-
const query = getTemplateSrv().replace(target.queryText, options.scopedVars, this.formatter);
65+
const calls = options.targets.map(target => {
66+
const query = getTemplateSrv().replace(target.queryText, options.scopedVars, this.formatter);
6367

64-
const request = {
65-
"query": query,
66-
"startTime": start.toISOString(),
67-
"endTime": end.toISOString(),
68-
"send_null": true
69-
};
68+
const request = {
69+
"query": query,
70+
"startTime": start.toISOString(),
71+
"endTime": end.toISOString(),
72+
"send_null": true
73+
};
7074

71-
return lastValueFrom(
72-
this.doFetch<any[]>({
73-
url: this.url + '/api/v1/query',
74-
data: request,
75-
method: 'POST',
76-
}).pipe(
77-
map((response) => {
78-
return this.arrayToDataFrame(response.data);
79-
}),
80-
catchError((err) => {
81-
throw new Error(err.data.message);
82-
})
83-
)
84-
);
85-
});
75+
return lastValueFrom(
76+
this.doFetch<any[]>({
77+
url: this.url + '/api/v1/query',
78+
data: request,
79+
method: 'POST',
80+
}).pipe(
81+
map((response) => {
82+
return this.arrayToDataFrame(response.data);
83+
}),
84+
catchError((err) => {
85+
throw new Error(err.data.message);
86+
})
87+
)
88+
);
89+
});
8690

87-
const data = await Promise.all(calls);
88-
return {
89-
data,
90-
};
91+
Promise.all(calls).then(data => {
92+
observer.next({ data });
93+
observer.complete();
94+
}).catch(error => {
95+
observer.error(error);
96+
});
97+
});
9198
}
9299

93100
private formatter(value: string | string[], options: any): string {
@@ -113,14 +120,21 @@ export class DataSource extends DataSourceApi<MyQuery, MyDataSourceOptions> {
113120
options.targets = [];
114121
options.targets.push({ queryText: query, scopedVars: {} });
115122

116-
const response = await this.query(options);
117-
118-
return response.data.map((dataFrame) => {
119-
return dataFrame.fields[0].values.toArray();
120-
}
121-
).flat().map((value) => {
122-
return { text: value };
123-
});
123+
return new Promise<MetricFindValue[]>((resolve, reject) => {
124+
this.query(options).subscribe({
125+
next: (response: DataQueryResponse) => {
126+
const values: MetricFindValue[] = response.data
127+
.map((dataFrame: DataFrame) => dataFrame.fields[0].values.toArray())
128+
.flat()
129+
.map((value: any) => ({ text: value }));
130+
131+
resolve(values);
132+
},
133+
error: (error: any) => {
134+
reject(error);
135+
},
136+
});
137+
})
124138
}
125139

126140
arrayToDataFrame(array: any[]): DataFrame {

0 commit comments

Comments
 (0)