import _ from 'lodash'; import { getDataSourceSrv } from '@grafana/runtime'; import responseHandler from "../../responseHandler"; export const DEFAULT_QUERY_LIMIT = 10000; export const HISTORY_TO_TABLE_MAP = { '0': 'history', '1': 'history_str', '2': 'history_log', '3': 'history_uint', '4': 'history_text' }; export const TREND_TO_TABLE_MAP = { '0': 'trends', '3': 'trends_uint' }; export const consolidateByFunc = { 'avg': 'AVG', 'min': 'MIN', 'max': 'MAX', 'sum': 'SUM', 'count': 'COUNT' }; export const consolidateByTrendColumns = { 'avg': 'value_avg', 'min': 'value_min', 'max': 'value_max', 'sum': 'num*value_avg' // sum of sums inside the one-hour trend period }; /** * Base class for external history database connectors. Subclasses should implement `getHistory()`, `getTrends()` and * `testDataSource()` methods, which describe how to fetch data from source other than Zabbix API. */ export class DBConnector { constructor(options) { this.datasourceId = options.datasourceId; this.datasourceName = options.datasourceName; this.datasourceTypeId = null; this.datasourceTypeName = null; } static loadDatasource(dsId, dsName) { if (!dsName && dsId !== undefined) { let ds = _.find(getDataSourceSrv().getAll(), {'id': dsId}); if (!ds) { return Promise.reject(`Data Source with ID ${dsId} not found`); } dsName = ds.name; } if (dsName) { return getDataSourceSrv().loadDatasource(dsName); } else { return Promise.reject(`Data Source name should be specified`); } } loadDBDataSource() { return DBConnector.loadDatasource(this.datasourceId, this.datasourceName) .then(ds => { this.datasourceTypeId = ds.meta.id; this.datasourceTypeName = ds.meta.name; if (!this.datasourceName) { this.datasourceName = ds.name; } if (!this.datasourceId) { this.datasourceId = ds.id; } return ds; }); } /** * Send test request to datasource in order to ensure it's working. */ testDataSource() { throw new ZabbixNotImplemented('testDataSource()'); } /** * Get history data from external sources. */ getHistory() { throw new ZabbixNotImplemented('getHistory()'); } /** * Get trends data from external sources. */ getTrends() { throw new ZabbixNotImplemented('getTrends()'); } } // Define Zabbix DB Connector exception type for non-implemented methods export class ZabbixNotImplemented { constructor(methodName) { this.code = null; this.name = 'ZabbixNotImplemented'; this.message = `Zabbix DB Connector Error: method ${methodName || ''} should be implemented in subclass of DBConnector`; } toString() { return this.message; } } export function handleDBDataSourceResponse(response, items) { const series = responseHandler.dataResponseToTimeSeries(response, items); // return convertGrafanaTSResponse(series, items, addHostName); return series; } /** * Converts time series returned by the data source into format that Grafana expects * time_series is Array of series: * ``` * [{ * name: string, * points: Array<[value: number, timestamp: number]> * }] * ``` */ export function convertGrafanaTSResponse(time_series, items, addHostName) { if (time_series.length === 0) { return []; } //uniqBy is needed to deduplicate const hosts = _.uniqBy(_.flatten(_.map(items, 'hosts')), 'hostid'); let grafanaSeries = _.map(_.compact(time_series), series => { const itemid = series.name; const item = _.find(items, {'itemid': itemid}); let alias = item.name; // Add scopedVars for using in alias functions const scopedVars = { '__zbx_item': { value: item.name }, '__zbx_item_name': { value: item.name }, '__zbx_item_key': { value: item.key_ }, '__zbx_item_interval': { value: item.delay }, }; if (_.keys(hosts).length > 0) { const host = _.find(hosts, {'hostid': item.hostid}); scopedVars['__zbx_host'] = { value: host.host }; scopedVars['__zbx_host_name'] = { value: host.name }; // Only add host when multiple hosts selected if (_.keys(hosts).length > 1 && addHostName) { alias = host.name + ": " + alias; } } // CachingProxy deduplicates requests and returns one time series for equal queries. // Clone is needed to prevent changing of series object shared between all targets. const datapoints = _.cloneDeep(series.points); return { target: alias, datapoints, scopedVars, item }; }); return _.sortBy(grafanaSeries, 'target'); } const defaults = { DBConnector, DEFAULT_QUERY_LIMIT, HISTORY_TO_TABLE_MAP, TREND_TO_TABLE_MAP, consolidateByFunc, consolidateByTrendColumns }; export default defaults;