|
|
|
@ -73,10 +73,11 @@ export class LokiDatasource { |
|
|
|
|
}; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
query(options: DataQueryOptions<LokiQuery>): Promise<{ data: LogsStream[] }> { |
|
|
|
|
async query(options: DataQueryOptions<LokiQuery>) { |
|
|
|
|
const queryTargets = options.targets |
|
|
|
|
.filter(target => target.expr) |
|
|
|
|
.filter(target => target.expr && !target.hide) |
|
|
|
|
.map(target => this.prepareQueryTarget(target, options)); |
|
|
|
|
|
|
|
|
|
if (queryTargets.length === 0) { |
|
|
|
|
return Promise.resolve({ data: [] }); |
|
|
|
|
} |
|
|
|
@ -84,20 +85,29 @@ export class LokiDatasource { |
|
|
|
|
const queries = queryTargets.map(target => this._request('/api/prom/query', target)); |
|
|
|
|
|
|
|
|
|
return Promise.all(queries).then((results: any[]) => { |
|
|
|
|
// Flatten streams from multiple queries
|
|
|
|
|
const allStreams: LogsStream[] = results.reduce((acc, response, i) => { |
|
|
|
|
if (!response) { |
|
|
|
|
return acc; |
|
|
|
|
const allStreams: LogsStream[] = []; |
|
|
|
|
|
|
|
|
|
for (let i = 0; i < results.length; i++) { |
|
|
|
|
const result = results[i]; |
|
|
|
|
const query = queryTargets[i]; |
|
|
|
|
|
|
|
|
|
// add search term to stream & add to array
|
|
|
|
|
if (result.data) { |
|
|
|
|
for (const stream of (result.data.streams || [])) { |
|
|
|
|
stream.search = query.regexp; |
|
|
|
|
allStreams.push(stream); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
const streams: LogsStream[] = response.data.streams || []; |
|
|
|
|
// Inject search for match highlighting
|
|
|
|
|
const search: string = queryTargets[i].regexp; |
|
|
|
|
streams.forEach(s => { |
|
|
|
|
s.search = search; |
|
|
|
|
}); |
|
|
|
|
return [...acc, ...streams]; |
|
|
|
|
}, []); |
|
|
|
|
return { data: allStreams }; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// check resultType
|
|
|
|
|
if (options.targets[0].resultFormat === 'time_series') { |
|
|
|
|
const logs = mergeStreamsToLogs(allStreams, this.maxLines); |
|
|
|
|
logs.series = makeSeriesForLogs(logs.rows, options.intervalMs); |
|
|
|
|
return { data: logs.series }; |
|
|
|
|
} else { |
|
|
|
|
return { data: allStreams }; |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -142,35 +152,35 @@ export class LokiDatasource { |
|
|
|
|
|
|
|
|
|
testDatasource() { |
|
|
|
|
return this._request('/api/prom/label') |
|
|
|
|
.then(res => { |
|
|
|
|
if (res && res.data && res.data.values && res.data.values.length > 0) { |
|
|
|
|
return { status: 'success', message: 'Data source connected and labels found.' }; |
|
|
|
|
} |
|
|
|
|
return { |
|
|
|
|
status: 'error', |
|
|
|
|
message: |
|
|
|
|
'Data source connected, but no labels received. Verify that Loki and Promtail is configured properly.', |
|
|
|
|
}; |
|
|
|
|
}) |
|
|
|
|
.catch(err => { |
|
|
|
|
let message = 'Loki: '; |
|
|
|
|
if (err.statusText) { |
|
|
|
|
message += err.statusText; |
|
|
|
|
} else { |
|
|
|
|
message += 'Cannot connect to Loki'; |
|
|
|
|
} |
|
|
|
|
.then(res => { |
|
|
|
|
if (res && res.data && res.data.values && res.data.values.length > 0) { |
|
|
|
|
return { status: 'success', message: 'Data source connected and labels found.' }; |
|
|
|
|
} |
|
|
|
|
return { |
|
|
|
|
status: 'error', |
|
|
|
|
message: |
|
|
|
|
'Data source connected, but no labels received. Verify that Loki and Promtail is configured properly.', |
|
|
|
|
}; |
|
|
|
|
}) |
|
|
|
|
.catch(err => { |
|
|
|
|
let message = 'Loki: '; |
|
|
|
|
if (err.statusText) { |
|
|
|
|
message += err.statusText; |
|
|
|
|
} else { |
|
|
|
|
message += 'Cannot connect to Loki'; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (err.status) { |
|
|
|
|
message += `. ${err.status}`; |
|
|
|
|
} |
|
|
|
|
if (err.status) { |
|
|
|
|
message += `. ${err.status}`; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (err.data && err.data.message) { |
|
|
|
|
message += `. ${err.data.message}`; |
|
|
|
|
} else if (err.data) { |
|
|
|
|
message += `. ${err.data}`; |
|
|
|
|
} |
|
|
|
|
return { status: 'error', message: message }; |
|
|
|
|
}); |
|
|
|
|
if (err.data && err.data.message) { |
|
|
|
|
message += `. ${err.data.message}`; |
|
|
|
|
} else if (err.data) { |
|
|
|
|
message += `. ${err.data}`; |
|
|
|
|
} |
|
|
|
|
return { status: 'error', message: message }; |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|