-
Notifications
You must be signed in to change notification settings - Fork 458
/
sqlConnector.ts
140 lines (120 loc) · 4.02 KB
/
sqlConnector.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
import _ from 'lodash';
import { getBackendSrv } from '@grafana/runtime';
import { compactQuery } from '../../../utils';
import mysql from './mysql';
import postgres from './postgres';
import dbConnector, {
DBConnector,
DEFAULT_QUERY_LIMIT,
HISTORY_TO_TABLE_MAP,
TREND_TO_TABLE_MAP,
} from '../dbConnector';
const supportedDatabases = {
mysql: 'mysql',
postgres: 'postgres',
};
export class SQLConnector extends DBConnector {
private limit: number;
private sqlDialect: any;
constructor(options) {
super(options);
this.limit = options.limit || DEFAULT_QUERY_LIMIT;
this.sqlDialect = null;
super.loadDBDataSource().then(() => {
this.loadSQLDialect();
});
}
loadSQLDialect() {
if (this.datasourceTypeId === supportedDatabases.postgres) {
this.sqlDialect = postgres;
} else {
this.sqlDialect = mysql;
}
}
/**
* Try to invoke test query for one of Zabbix database tables.
*/
testDataSource() {
const testQuery = this.sqlDialect.testQuery();
return this.invokeSQLQuery(testQuery);
}
getHistory(items, timeFrom, timeTill, options) {
const { aggFunction, intervalSec } = getAggFunc(timeFrom, timeTill, options);
// Group items by value type and perform request for each value type
const grouped_items = _.groupBy(items, 'value_type');
const promises = _.map(grouped_items, (items, value_type) => {
const itemids = _.map(items, 'itemid').join(', ');
const table = HISTORY_TO_TABLE_MAP[value_type];
let query = this.sqlDialect.historyQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction);
query = compactQuery(query);
return this.invokeSQLQuery(query);
});
return Promise.all(promises).then((results) => {
return _.flatten(results);
});
}
getTrends(items, timeFrom, timeTill, options) {
const { consolidateBy } = options;
const { aggFunction, intervalSec } = getAggFunc(timeFrom, timeTill, options);
// Group items by value type and perform request for each value type
const grouped_items = _.groupBy(items, 'value_type');
const promises = _.map(grouped_items, (items, value_type) => {
const itemids = _.map(items, 'itemid').join(', ');
const table = TREND_TO_TABLE_MAP[value_type];
let valueColumn = _.includes(['avg', 'min', 'max', 'sum'], consolidateBy) ? consolidateBy : 'avg';
valueColumn = dbConnector.consolidateByTrendColumns[valueColumn];
let query = this.sqlDialect.trendsQuery(
itemids,
table,
timeFrom,
timeTill,
intervalSec,
aggFunction,
valueColumn
);
query = compactQuery(query);
return this.invokeSQLQuery(query);
});
return Promise.all(promises).then((results) => {
return _.flatten(results);
});
}
invokeSQLQuery(query) {
const queryDef = {
refId: 'A',
format: 'time_series',
datasourceId: this.datasourceId,
rawSql: query,
maxDataPoints: this.limit,
};
return getBackendSrv()
.datasourceRequest({
url: '/api/ds/query',
method: 'POST',
data: {
queries: [queryDef],
},
})
.then((response) => {
const results = response.data.results;
if (results['A']) {
return results['A'].frames;
} else {
return null;
}
});
}
}
function getAggFunc(timeFrom, timeTill, options) {
const { intervalMs } = options;
let { consolidateBy } = options;
let intervalSec = Math.ceil(intervalMs / 1000);
// The interval must match the time range exactly n times, otherwise
// the resulting first and last data points will yield invalid values in the
// calculated average value in downsampleSeries - when using consolidateBy(avg)
const numOfIntervals = Math.ceil((timeTill - timeFrom) / intervalSec);
intervalSec = Math.ceil((timeTill - timeFrom) / numOfIntervals);
consolidateBy = consolidateBy || 'avg';
const aggFunction = dbConnector.consolidateByFunc[consolidateBy];
return { aggFunction, intervalSec };
}