diff --git a/src/datasource-zabbix/specs/influxdbConnector.test.js b/src/datasource-zabbix/specs/influxdbConnector.test.js new file mode 100644 index 0000000..96084ab --- /dev/null +++ b/src/datasource-zabbix/specs/influxdbConnector.test.js @@ -0,0 +1,95 @@ +import { InfluxDBConnector } from '../zabbix/connectors/influxdb/influxdbConnector'; +import { compactQuery } from '../utils'; + +describe('InfluxDBConnector', () => { + let ctx = {}; + + beforeEach(() => { + ctx.options = { datasourceName: 'InfluxDB DS' }; + ctx.datasourceSrvMock = { + loadDatasource: jest.fn().mockResolvedValue( + { id: 42, name: 'InfluxDB DS', meta: {} } + ), + }; + ctx.influxDBConnector = new InfluxDBConnector(ctx.options, ctx.datasourceSrvMock); + ctx.influxDBConnector.invokeInfluxDBQuery = jest.fn().mockResolvedValue([]); + ctx.defaultQueryParams = { + itemids: ['123', '234'], + timeFrom: 15000, timeTill: 15100, intervalSec: 5, + table: 'history', aggFunction: 'MAX' + }; + }); + + describe('When building InfluxDB query', () => { + it('should build proper query', () => { + const { itemids, timeFrom, timeTill, intervalSec, table, aggFunction } = ctx.defaultQueryParams; + const query = ctx.influxDBConnector.buildHistoryQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction); + const expected = compactQuery(`SELECT MAX("value") + FROM "history" WHERE ("itemid" = '123' OR "itemid" = '234') AND "time" >= 15000s AND "time" <= 15100s + GROUP BY time(5s), "itemid" fill(none) + `); + expect(query).toBe(expected); + }); + + it('should use MEAN instead of AVG', () => { + const { itemids, timeFrom, timeTill, intervalSec, table } = ctx.defaultQueryParams; + const aggFunction = 'AVG'; + const query = ctx.influxDBConnector.buildHistoryQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction); + const expected = compactQuery(`SELECT MEAN("value") + FROM "history" WHERE ("itemid" = '123' OR "itemid" = '234') AND "time" >= 15000s AND "time" <= 15100s + GROUP BY time(5s), "itemid" fill(none) + `); + expect(query).toBe(expected); + }); + }); + + describe('When invoking InfluxDB query', () => { + it('should query proper table depending on item type', () => { + const { timeFrom, timeTill} = ctx.defaultQueryParams; + const options = { intervalMs: 5000 }; + const items = [ + { itemid: '123', value_type: 3 } + ]; + const expectedQuery = compactQuery(`SELECT MEAN("value") + FROM "history_uint" WHERE ("itemid" = '123') AND "time" >= 15000s AND "time" <= 15100s + GROUP BY time(5s), "itemid" fill(none) + `); + ctx.influxDBConnector.getHistory(items, timeFrom, timeTill, options); + expect(ctx.influxDBConnector.invokeInfluxDBQuery).toHaveBeenCalledWith(expectedQuery); + }); + + it('should split query if different item types are used', () => { + const { timeFrom, timeTill} = ctx.defaultQueryParams; + const options = { intervalMs: 5000 }; + const items = [ + { itemid: '123', value_type: 0 }, + { itemid: '234', value_type: 3 }, + ]; + const sharedQueryPart = `AND "time" >= 15000s AND "time" <= 15100s GROUP BY time(5s), "itemid" fill(none)`; + const expectedQueryFirst = compactQuery(`SELECT MEAN("value") + FROM "history" WHERE ("itemid" = '123') ${sharedQueryPart} + `); + const expectedQuerySecond = compactQuery(`SELECT MEAN("value") + FROM "history_uint" WHERE ("itemid" = '234') ${sharedQueryPart} + `); + ctx.influxDBConnector.getHistory(items, timeFrom, timeTill, options); + expect(ctx.influxDBConnector.invokeInfluxDBQuery).toHaveBeenCalledTimes(2); + expect(ctx.influxDBConnector.invokeInfluxDBQuery).toHaveBeenNthCalledWith(1, expectedQueryFirst); + expect(ctx.influxDBConnector.invokeInfluxDBQuery).toHaveBeenNthCalledWith(2, expectedQuerySecond); + }); + + it('should use the same table for trends query', () => { + const { timeFrom, timeTill} = ctx.defaultQueryParams; + const options = { intervalMs: 5000 }; + const items = [ + { itemid: '123', value_type: 3 } + ]; + const expectedQuery = compactQuery(`SELECT MEAN("value") + FROM "history_uint" WHERE ("itemid" = '123') AND "time" >= 15000s AND "time" <= 15100s + GROUP BY time(5s), "itemid" fill(none) + `); + ctx.influxDBConnector.getTrends(items, timeFrom, timeTill, options); + expect(ctx.influxDBConnector.invokeInfluxDBQuery).toHaveBeenCalledWith(expectedQuery); + }); + }); +}); diff --git a/src/datasource-zabbix/utils.js b/src/datasource-zabbix/utils.js index 53f0bea..ab6639e 100644 --- a/src/datasource-zabbix/utils.js +++ b/src/datasource-zabbix/utils.js @@ -258,6 +258,13 @@ export function parseVersion(version) { return { major, minor, patch, meta }; } +/** + * Replaces any space-like symbols (tabs, new lines, spaces) by single whitespace. + */ +export function compactQuery(query) { + return query.replace(/\s+/g, ' ').trim(); +} + // Fix for backward compatibility with lodash 2.4 if (!_.includes) { _.includes = _.contains; diff --git a/src/datasource-zabbix/zabbix/connectors/influxdb/influxdbConnector.js b/src/datasource-zabbix/zabbix/connectors/influxdb/influxdbConnector.js index 682268d..2e957db 100644 --- a/src/datasource-zabbix/zabbix/connectors/influxdb/influxdbConnector.js +++ b/src/datasource-zabbix/zabbix/connectors/influxdb/influxdbConnector.js @@ -1,4 +1,5 @@ import _ from 'lodash'; +import { compactQuery } from '../../../utils'; import { DBConnector, HISTORY_TO_TABLE_MAP, consolidateByFunc } from '../dbConnector'; export class InfluxDBConnector extends DBConnector { @@ -104,7 +105,3 @@ function handleInfluxHistoryResponse(results) { return seriesList; } - -function compactQuery(query) { - return query.replace(/\s+/g, ' '); -} diff --git a/src/datasource-zabbix/zabbix/connectors/sql/sqlConnector.js b/src/datasource-zabbix/zabbix/connectors/sql/sqlConnector.js index 7c03e4e..0ec5dc6 100644 --- a/src/datasource-zabbix/zabbix/connectors/sql/sqlConnector.js +++ b/src/datasource-zabbix/zabbix/connectors/sql/sqlConnector.js @@ -1,4 +1,5 @@ import _ from 'lodash'; +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'; @@ -52,7 +53,7 @@ export class SQLConnector extends DBConnector { let table = HISTORY_TO_TABLE_MAP[value_type]; let query = this.sqlDialect.historyQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction); - query = compactSQLQuery(query); + query = compactQuery(query); return this.invokeSQLQuery(query); }); @@ -77,7 +78,7 @@ export class SQLConnector extends DBConnector { valueColumn = dbConnector.consolidateByTrendColumns[valueColumn]; let query = this.sqlDialect.trendsQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction, valueColumn); - query = compactSQLQuery(query); + query = compactQuery(query); return this.invokeSQLQuery(query); }); @@ -112,7 +113,3 @@ export class SQLConnector extends DBConnector { }); } } - -function compactSQLQuery(query) { - return query.replace(/\s+/g, ' '); -}