The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
grafana/public/app/plugins/datasource/mssql/response_parser.ts

160 lines
4.2 KiB

import _ from 'lodash';
import { MetricFindValue } from '@grafana/data';
interface TableResponse extends Record<string, any> {
type: string;
refId: string;
meta: any;
}
interface SeriesResponse extends Record<string, any> {
target: string;
refId: string;
meta: any;
datapoints: [any[]];
}
export interface MssqlResponse {
data: Array<TableResponse | SeriesResponse>;
}
export default class ResponseParser {
processQueryResult(res: any): MssqlResponse {
const data: any[] = [];
if (!res.data.results) {
return { data };
}
for (const key in res.data.results) {
const queryRes = res.data.results[key];
if (queryRes.series) {
for (const series of queryRes.series) {
data.push({
target: series.name,
datapoints: series.points,
refId: queryRes.refId,
meta: queryRes.meta,
});
}
}
if (queryRes.tables) {
for (const table of queryRes.tables) {
table.type = 'table';
table.refId = queryRes.refId;
table.meta = queryRes.meta;
data.push(table);
}
}
}
return { data: data };
}
parseMetricFindQueryResult(refId: string, results: any): MetricFindValue[] {
if (!results || results.data.length === 0 || results.data.results[refId].meta.rowCount === 0) {
return [];
}
const columns = results.data.results[refId].tables[0].columns;
const rows = results.data.results[refId].tables[0].rows;
const textColIndex = this.findColIndex(columns, '__text');
const valueColIndex = this.findColIndex(columns, '__value');
if (columns.length === 2 && textColIndex !== -1 && valueColIndex !== -1) {
return this.transformToKeyValueList(rows, textColIndex, valueColIndex);
}
return this.transformToSimpleList(rows);
}
transformToKeyValueList(rows: any, textColIndex: number, valueColIndex: number): MetricFindValue[] {
const res = [];
for (let i = 0; i < rows.length; i++) {
if (!this.containsKey(res, rows[i][textColIndex])) {
res.push({ text: rows[i][textColIndex], value: rows[i][valueColIndex] });
}
}
return res;
}
transformToSimpleList(rows: any): MetricFindValue[] {
const res = [];
for (let i = 0; i < rows.length; i++) {
for (let j = 0; j < rows[i].length; j++) {
res.push(rows[i][j]);
}
}
const unique = Array.from(new Set(res));
return _.map(unique, value => {
return { text: value };
});
}
findColIndex(columns: any[], colName: string) {
for (let i = 0; i < columns.length; i++) {
if (columns[i].text === colName) {
return i;
}
}
return -1;
}
containsKey(res: any[], key: any) {
for (let i = 0; i < res.length; i++) {
if (res[i].text === key) {
return true;
}
}
return false;
}
transformAnnotationResponse(options: any, data: any) {
const table = data.data.results[options.annotation.name].tables[0];
let timeColumnIndex = -1;
let timeEndColumnIndex = -1;
let textColumnIndex = -1;
let tagsColumnIndex = -1;
for (let i = 0; i < table.columns.length; i++) {
if (table.columns[i].text === 'time') {
timeColumnIndex = i;
} else if (table.columns[i].text === 'timeend') {
timeEndColumnIndex = i;
} else if (table.columns[i].text === 'text') {
textColumnIndex = i;
} else if (table.columns[i].text === 'tags') {
tagsColumnIndex = i;
}
}
if (timeColumnIndex === -1) {
return Promise.reject({ message: 'Missing mandatory time column (with time column alias) in annotation query.' });
}
const list = [];
for (let i = 0; i < table.rows.length; i++) {
const row = table.rows[i];
const timeEnd =
timeEndColumnIndex !== -1 && row[timeEndColumnIndex] ? Math.floor(row[timeEndColumnIndex]) : undefined;
list.push({
annotation: options.annotation,
time: Math.floor(row[timeColumnIndex]),
timeEnd,
text: row[textColumnIndex],
tags: row[tagsColumnIndex] ? row[tagsColumnIndex].trim().split(/\s*,\s*/) : [],
});
}
return list;
}
}