@@ -10,11 +10,13 @@ import {
10
10
toDataFrame ,
11
11
MetricFindValue ,
12
12
FieldType ,
13
+ ScopedVars ,
14
+ TimeRange ,
13
15
} from '@grafana/data' ;
14
16
import { getTemplateSrv } from '@grafana/runtime' ;
15
17
16
18
import API from './api' ;
17
- import { JsonApiQuery , JsonApiVariableQuery , JsonApiDataSourceOptions , Pair } from './types' ;
19
+ import { JsonApiQuery , JsonApiDataSourceOptions , Pair } from './types' ;
18
20
19
21
export class DataSource extends DataSourceApi < JsonApiQuery , JsonApiDataSourceOptions > {
20
22
api : API ;
@@ -25,76 +27,7 @@ export class DataSource extends DataSourceApi<JsonApiQuery, JsonApiDataSourceOpt
25
27
}
26
28
27
29
async query ( request : DataQueryRequest < JsonApiQuery > ) : Promise < DataQueryResponse > {
28
- const templateSrv = getTemplateSrv ( ) ;
29
-
30
- const replaceMacros = ( str : string ) => {
31
- return str
32
- . replace ( / \$ _ _ u n i x E p o c h F r o m \( \) / g, request . range . from . unix ( ) . toString ( ) )
33
- . replace ( / \$ _ _ u n i x E p o c h T o \( \) / g, request . range . to . unix ( ) . toString ( ) ) ;
34
- } ;
35
-
36
- const promises = request . targets . map ( async query => {
37
- const urlPathTreated = templateSrv . replace ( query . urlPath , request . scopedVars ) ;
38
- const bodyTreated = templateSrv . replace ( query . body , request . scopedVars ) ;
39
-
40
- const paramsTreated : Array < Pair < string , string > > = ( query . params ?? [ ] ) . map ( ( [ key , value ] ) => {
41
- const keyTreated = replaceMacros ( templateSrv . replace ( key , request . scopedVars ) ) ;
42
- const valueTreated = replaceMacros ( templateSrv . replace ( value , request . scopedVars ) ) ;
43
- return [ keyTreated , valueTreated ] ;
44
- } ) ;
45
-
46
- const headersTreated : Array < Pair < string , string > > = ( query . headers ?? [ ] ) . map ( ( [ key , value ] ) => {
47
- const keyTreated = templateSrv . replace ( key , request . scopedVars ) ;
48
- const valueTreated = templateSrv . replace ( value , request . scopedVars ) ;
49
- return [ keyTreated , valueTreated ] ;
50
- } ) ;
51
-
52
- const response = await this . api . cachedGet (
53
- query . cacheDurationSeconds ,
54
- query . method ,
55
- urlPathTreated ,
56
- paramsTreated ,
57
- headersTreated ,
58
- bodyTreated
59
- ) ;
60
-
61
- const fields = query . fields
62
- . filter ( field => field . jsonPath )
63
- . map ( field => {
64
- const jsonPathTreated = replaceMacros ( templateSrv . replace ( field . jsonPath , request . scopedVars ) ) ;
65
- const nameTreated = templateSrv . replace ( field . name , request . scopedVars ) ;
66
-
67
- const values = JSONPath ( { path : jsonPathTreated , json : response } ) ;
68
-
69
- // Get the path for automatic setting of the field name.
70
- //
71
- // Casted to any due to typing issues with JSONPath-Plus
72
- const paths = ( JSONPath as any ) . toPathArray ( jsonPathTreated ) ;
73
-
74
- const propertyType = field . type ? field . type : detectFieldType ( values ) ;
75
- const typedValues = parseValues ( values , propertyType ) ;
76
-
77
- return {
78
- name : nameTreated || paths [ paths . length - 1 ] ,
79
- type : propertyType ,
80
- values : typedValues ,
81
- } ;
82
- } ) ;
83
-
84
- const fieldLengths = fields . map ( field => field . values . length ) ;
85
- const uniqueFieldLengths = Array . from ( new Set ( fieldLengths ) ) . length ;
86
-
87
- // All fields need to have the same length for the data frame to be valid.
88
- if ( uniqueFieldLengths > 1 ) {
89
- throw new Error ( 'Fields have different lengths' ) ;
90
- }
91
-
92
- return toDataFrame ( {
93
- name : query . refId ,
94
- refId : query . refId ,
95
- fields : fields ,
96
- } ) ;
97
- } ) ;
30
+ const promises = request . targets . map ( query => this . doRequest ( query , request . range , request . scopedVars ) ) ;
98
31
99
32
// Wait for all queries to finish before returning the result.
100
33
return Promise . all ( promises ) . then ( data => ( { data } ) ) ;
@@ -105,28 +38,9 @@ export class DataSource extends DataSourceApi<JsonApiQuery, JsonApiDataSourceOpt
105
38
*
106
39
* @param query
107
40
*/
108
- async metricFindQuery ?( query : JsonApiVariableQuery ) : Promise < MetricFindValue [ ] > {
109
- if ( ! query . jsonPath ) {
110
- return [ ] ;
111
- }
112
-
113
- const templateSrv = getTemplateSrv ( ) ;
114
-
115
- const queryParamsTreated = templateSrv . replace ( query . queryParams ) ;
116
- const urlPathTreated = templateSrv . replace ( query . urlPath ) ;
117
- const jsonPathTreated = templateSrv . replace ( query . jsonPath ) ;
118
-
119
- const params : Array < Pair < string , string > > = [ ] ;
120
- new URLSearchParams ( '?' + queryParamsTreated ) . forEach ( ( value : string , key : string ) => {
121
- params . push ( [ key , value ] ) ;
122
- } ) ;
123
-
124
- const response = await this . api . get ( 'GET' , urlPathTreated , params ) ;
125
-
126
- return JSONPath ( {
127
- path : jsonPathTreated ,
128
- json : response ,
129
- } ) . map ( ( _ : any ) => ( { text : _ } ) ) ;
41
+ async metricFindQuery ?( query : JsonApiQuery ) : Promise < MetricFindValue [ ] > {
42
+ const frame = await this . doRequest ( query ) ;
43
+ return frame . fields [ 0 ] . values . toArray ( ) . map ( _ => ( { text : _ } ) ) ;
130
44
}
131
45
132
46
/**
@@ -169,6 +83,83 @@ export class DataSource extends DataSourceApi<JsonApiQuery, JsonApiDataSourceOpt
169
83
}
170
84
}
171
85
}
86
+
87
+ async doRequest ( query : JsonApiQuery , range ?: TimeRange , scopedVars ?: ScopedVars ) {
88
+ const templateSrv = getTemplateSrv ( ) ;
89
+
90
+ const replaceMacros = ( str : string ) => {
91
+ return range
92
+ ? str
93
+ . replace ( / \$ _ _ u n i x E p o c h F r o m \( \) / g, range . from . unix ( ) . toString ( ) )
94
+ . replace ( / \$ _ _ u n i x E p o c h T o \( \) / g, range . to . unix ( ) . toString ( ) )
95
+ : str ;
96
+ } ;
97
+
98
+ const urlPathTreated = templateSrv . replace ( query . urlPath , scopedVars ) ;
99
+ const bodyTreated = templateSrv . replace ( query . body , scopedVars ) ;
100
+
101
+ const paramsTreated : Array < Pair < string , string > > = ( query . params ?? [ ] ) . map ( ( [ key , value ] ) => {
102
+ const keyTreated = replaceMacros ( templateSrv . replace ( key , scopedVars ) ) ;
103
+ const valueTreated = replaceMacros ( templateSrv . replace ( value , scopedVars ) ) ;
104
+ return [ keyTreated , valueTreated ] ;
105
+ } ) ;
106
+
107
+ const headersTreated : Array < Pair < string , string > > = ( query . headers ?? [ ] ) . map ( ( [ key , value ] ) => {
108
+ const keyTreated = templateSrv . replace ( key , scopedVars ) ;
109
+ const valueTreated = templateSrv . replace ( value , scopedVars ) ;
110
+ return [ keyTreated , valueTreated ] ;
111
+ } ) ;
112
+
113
+ const response = await this . api . cachedGet (
114
+ query . cacheDurationSeconds ,
115
+ query . method ,
116
+ urlPathTreated ,
117
+ paramsTreated ,
118
+ headersTreated ,
119
+ bodyTreated
120
+ ) ;
121
+
122
+ if ( ! response ) {
123
+ throw new Error ( 'Query returned empty data' ) ;
124
+ }
125
+
126
+ const fields = query . fields
127
+ . filter ( field => field . jsonPath )
128
+ . map ( field => {
129
+ const jsonPathTreated = replaceMacros ( templateSrv . replace ( field . jsonPath , scopedVars ) ) ;
130
+ const nameTreated = templateSrv . replace ( field . name , scopedVars ) ;
131
+
132
+ const values = JSONPath ( { path : jsonPathTreated , json : response } ) ;
133
+
134
+ // Get the path for automatic setting of the field name.
135
+ //
136
+ // Casted to any due to typing issues with JSONPath-Plus
137
+ const paths = ( JSONPath as any ) . toPathArray ( jsonPathTreated ) ;
138
+
139
+ const propertyType = field . type ? field . type : detectFieldType ( values ) ;
140
+ const typedValues = parseValues ( values , propertyType ) ;
141
+
142
+ return {
143
+ name : nameTreated || paths [ paths . length - 1 ] ,
144
+ type : propertyType ,
145
+ values : typedValues ,
146
+ } ;
147
+ } ) ;
148
+
149
+ const fieldLengths = fields . map ( field => field . values . length ) ;
150
+ const uniqueFieldLengths = Array . from ( new Set ( fieldLengths ) ) . length ;
151
+
152
+ // All fields need to have the same length for the data frame to be valid.
153
+ if ( uniqueFieldLengths > 1 ) {
154
+ throw new Error ( 'Fields have different lengths' ) ;
155
+ }
156
+
157
+ return toDataFrame ( {
158
+ name : query . refId ,
159
+ refId : query . refId ,
160
+ fields : fields ,
161
+ } ) ;
162
+ }
172
163
}
173
164
174
165
/**
0 commit comments