|
1 | | -import { getBackendSrv } from '@grafana/runtime'; |
| 1 | +import { DataSourceWithBackend } from '@grafana/runtime'; |
2 | 2 |
|
3 | | -import { |
4 | | - DataQueryRequest, |
5 | | - DataQueryResponse, |
6 | | - DataSourceApi, |
7 | | - DataSourceInstanceSettings, |
8 | | - MutableDataFrame, |
9 | | -} from '@grafana/data'; |
| 3 | +import { DataSourceInstanceSettings } from '@grafana/data'; |
10 | 4 |
|
11 | 5 | import { SplunkQuery, SplunkDataSourceOptions } from './types'; |
12 | 6 |
|
13 | | -export class DataSource extends DataSourceApi<SplunkQuery, SplunkDataSourceOptions> { |
| 7 | +export class DataSource extends DataSourceWithBackend<SplunkQuery, SplunkDataSourceOptions> { |
14 | 8 | url?: string; |
15 | 9 |
|
16 | 10 | constructor(instanceSettings: DataSourceInstanceSettings<SplunkDataSourceOptions>) { |
17 | 11 | super(instanceSettings); |
18 | 12 |
|
19 | 13 | this.url = instanceSettings.url; |
20 | 14 | } |
21 | | - |
22 | | - async query(options: DataQueryRequest<SplunkQuery>): Promise<DataQueryResponse> { |
23 | | - const moment = require('moment'); |
24 | | - const promises = options.targets.map((query) => |
25 | | - this.doRequest(query, options).then((response) => { |
26 | | - const frame = new MutableDataFrame({ |
27 | | - refId: query.refId, |
28 | | - fields: [], |
29 | | - }); |
30 | | - |
31 | | - // console.log(`DEBUG: nFields=${response.fields.length}`); |
32 | | - // console.log(`DEBUG: nResults=${response.results.length}`); |
33 | | - |
34 | | - //let fields = response.data.fields.map((field: any) => field['name']); |
35 | | - response.fields.forEach((field: any) => { |
36 | | - // console.log(`DEBUG: field=${field}`); |
37 | | - frame.addField({ name: field }); |
38 | | - }); |
39 | | - |
40 | | - response.results.forEach((result: any) => { |
41 | | - // console.log(`DEBUG: result=${JSON.stringify(result)}`); |
42 | | - let row: any[] = []; |
43 | | - |
44 | | - response.fields.forEach((field: any) => { |
45 | | - if (field === 'Time') { |
46 | | - let time = moment(result['_time']).format('YYYY-MM-DDTHH:mm:ssZ'); |
47 | | - row.push(time); |
48 | | - } else { |
49 | | - row.push(result[field]); |
50 | | - } |
51 | | - }); |
52 | | - frame.appendRow(row); |
53 | | - }); |
54 | | - |
55 | | - return frame; |
56 | | - }) |
57 | | - ); |
58 | | - |
59 | | - return Promise.all(promises).then((data) => ({ data })); |
60 | | - } |
61 | | - |
62 | | - async testDatasource() { |
63 | | - const data = new URLSearchParams({ |
64 | | - search: `search index=_internal * | stats count`, |
65 | | - output_mode: 'json', |
66 | | - exec_mode: 'oneshot', |
67 | | - }).toString(); |
68 | | - |
69 | | - return getBackendSrv() |
70 | | - .datasourceRequest({ |
71 | | - method: 'POST', |
72 | | - url: this.url + '/services/search/jobs', |
73 | | - headers: { |
74 | | - 'Content-Type': 'application/x-www-form-urlencoded', |
75 | | - }, |
76 | | - data: data, |
77 | | - }) |
78 | | - .then( |
79 | | - (response: any) => { |
80 | | - return { |
81 | | - status: 'success', |
82 | | - message: 'Data source is working', |
83 | | - title: 'Success', |
84 | | - }; |
85 | | - }, |
86 | | - (err: any) => { |
87 | | - return { |
88 | | - status: 'error', |
89 | | - message: err.statusText, |
90 | | - title: 'Error', |
91 | | - }; |
92 | | - } |
93 | | - ); |
94 | | - } |
95 | | - |
96 | | - async doSearchStatusRequest(sid: string) { |
97 | | - const result: boolean = await getBackendSrv() |
98 | | - .datasourceRequest({ |
99 | | - method: 'GET', |
100 | | - url: this.url + '/services/search/jobs/' + sid, |
101 | | - params: { |
102 | | - output_mode: 'json', |
103 | | - }, |
104 | | - }) |
105 | | - .then((response) => { |
106 | | - let status = response.data.entry[0].content.dispatchState; |
107 | | - // console.log(`DEBUG: dispatchState=${status}`); |
108 | | - return status === 'DONE' || status === 'PAUSED' || status === 'FAILED'; |
109 | | - }); |
110 | | - |
111 | | - return result; |
112 | | - } |
113 | | - |
114 | | - async doSearchRequest(query: SplunkQuery, options: DataQueryRequest<SplunkQuery>) { |
115 | | - const { range } = options; |
116 | | - const from = Math.floor(range!.from.valueOf() / 1000); |
117 | | - const to = Math.floor(range!.to.valueOf() / 1000); |
118 | | - |
119 | | - const data = new URLSearchParams({ |
120 | | - search: `search ${query.queryText}`, |
121 | | - output_mode: 'json', |
122 | | - earliest_time: from.toString(), |
123 | | - latest_time: to.toString(), |
124 | | - }).toString(); |
125 | | - |
126 | | - const sid: string = await getBackendSrv() |
127 | | - .datasourceRequest({ |
128 | | - method: 'POST', |
129 | | - url: this.url + '/services/search/jobs', |
130 | | - headers: { |
131 | | - 'Content-Type': 'application/x-www-form-urlencoded', |
132 | | - }, |
133 | | - data: data, |
134 | | - }) |
135 | | - .then((response) => { |
136 | | - return response.data.sid; |
137 | | - }); |
138 | | - |
139 | | - return sid; |
140 | | - } |
141 | | - |
142 | | - async doGetAllResultsRequest(sid: string) { |
143 | | - const count = 50000; |
144 | | - let offset = 0; |
145 | | - let isFirst = true; |
146 | | - let isFinished = false; |
147 | | - let fields: any[] = []; |
148 | | - let results: any[] = []; |
149 | | - |
150 | | - while (!isFinished) { |
151 | | - await getBackendSrv() |
152 | | - .datasourceRequest({ |
153 | | - method: 'GET', |
154 | | - url: this.url + '/services/search/jobs/' + sid + '/results', |
155 | | - params: { |
156 | | - output_mode: 'json', |
157 | | - offset: offset, |
158 | | - count: count, |
159 | | - }, |
160 | | - }) |
161 | | - .then((response) => { |
162 | | - // console.log(`DEBUG: count=${count} offset=${offset} ${JSON.stringify(response.data)}`); |
163 | | - if (response.data.post_process_count === 0 && response.data.results.length === 0) { |
164 | | - isFinished = true; |
165 | | - } else { |
166 | | - if (isFirst) { |
167 | | - isFirst = false; |
168 | | - fields = response.data.fields.map((field: any) => field['name']); |
169 | | - } |
170 | | - offset = offset + count; |
171 | | - results = results.concat(response.data.results); |
172 | | - } |
173 | | - }); |
174 | | - |
175 | | - offset = offset + count; |
176 | | - } |
177 | | - |
178 | | - if (fields.includes('_time')) { |
179 | | - fields.push('Time'); |
180 | | - } |
181 | | - |
182 | | - const index = fields.indexOf('_raw', 0); |
183 | | - if (index > -1) { |
184 | | - fields.splice(index, 1); |
185 | | - fields = fields.reverse(); |
186 | | - fields.push('_raw'); |
187 | | - fields = fields.reverse(); |
188 | | - } |
189 | | - |
190 | | - return { fields: fields, results: results }; |
191 | | - } |
192 | | - |
193 | | - async doRequest(query: SplunkQuery, options: DataQueryRequest<SplunkQuery>) { |
194 | | - const sid: string = await this.doSearchRequest(query, options); |
195 | | - // console.log(`DEBUG: sid=${sid}`); |
196 | | - |
197 | | - while (!(await this.doSearchStatusRequest(sid))) {} |
198 | | - |
199 | | - const result = await this.doGetAllResultsRequest(sid); |
200 | | - return result; |
201 | | - } |
202 | 15 | } |
0 commit comments