Support item tags as variables
This commit is contained in:
@@ -1,15 +1,16 @@
|
|||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
import { parseLegacyVariableQuery } from '../utils';
|
import { parseLegacyVariableQuery } from '../utils';
|
||||||
import { SelectableValue } from '@grafana/data';
|
import { SelectableValue } from '@grafana/data';
|
||||||
import { VariableQuery, VariableQueryTypes, VariableQueryProps, VariableQueryData } from '../types';
|
import { VariableQuery, VariableQueryData, VariableQueryProps, VariableQueryTypes } from '../types';
|
||||||
import { ZabbixInput } from './ZabbixInput';
|
import { ZabbixInput } from './ZabbixInput';
|
||||||
import { InlineFormLabel, Select, Input } from '@grafana/ui';
|
import { InlineFormLabel, Input, Select } from '@grafana/ui';
|
||||||
|
|
||||||
export class ZabbixVariableQueryEditor extends PureComponent<VariableQueryProps, VariableQueryData> {
|
export class ZabbixVariableQueryEditor extends PureComponent<VariableQueryProps, VariableQueryData> {
|
||||||
queryTypes: Array<SelectableValue<VariableQueryTypes>> = [
|
queryTypes: Array<SelectableValue<VariableQueryTypes>> = [
|
||||||
{ value: VariableQueryTypes.Group, label: 'Group'},
|
{ value: VariableQueryTypes.Group, label: 'Group' },
|
||||||
{ value: VariableQueryTypes.Host, label: 'Host' },
|
{ value: VariableQueryTypes.Host, label: 'Host' },
|
||||||
{ value: VariableQueryTypes.Application, label: 'Application' },
|
{ value: VariableQueryTypes.Application, label: 'Application' },
|
||||||
|
{ value: VariableQueryTypes.ItemTag, label: 'Item tag' },
|
||||||
{ value: VariableQueryTypes.Item, label: 'Item' },
|
{ value: VariableQueryTypes.Item, label: 'Item' },
|
||||||
{ value: VariableQueryTypes.ItemValues, label: 'Item values' },
|
{ value: VariableQueryTypes.ItemValues, label: 'Item values' },
|
||||||
];
|
];
|
||||||
@@ -20,6 +21,7 @@ export class ZabbixVariableQueryEditor extends PureComponent<VariableQueryProps,
|
|||||||
group: '/.*/',
|
group: '/.*/',
|
||||||
host: '',
|
host: '',
|
||||||
application: '',
|
application: '',
|
||||||
|
itemTag: '',
|
||||||
item: '',
|
item: '',
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -64,13 +66,13 @@ export class ZabbixVariableQueryEditor extends PureComponent<VariableQueryProps,
|
|||||||
...newQuery,
|
...newQuery,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
handleQueryChange = () => {
|
handleQueryChange = () => {
|
||||||
const { queryType, group, host, application, item } = this.state;
|
const { queryType, group, host, application, itemTag, item } = this.state;
|
||||||
const queryModel = { queryType, group, host, application, item };
|
const queryModel = { queryType, group, host, application, itemTag, item };
|
||||||
this.props.onChange(queryModel, `Zabbix - ${queryType}`);
|
this.props.onChange(queryModel, `Zabbix - ${queryType}`);
|
||||||
}
|
};
|
||||||
|
|
||||||
handleQueryTypeChange = (selectedItem: SelectableValue<VariableQueryTypes>) => {
|
handleQueryTypeChange = (selectedItem: SelectableValue<VariableQueryTypes>) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
@@ -79,14 +81,16 @@ export class ZabbixVariableQueryEditor extends PureComponent<VariableQueryProps,
|
|||||||
queryType: selectedItem.value,
|
queryType: selectedItem.value,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { group, host, application, item } = this.state;
|
const { group, host, application, itemTag, item } = this.state;
|
||||||
const queryType = selectedItem.value;
|
const queryType = selectedItem.value;
|
||||||
const queryModel = { queryType, group, host, application, item };
|
const queryModel = { queryType, group, host, application, itemTag, item };
|
||||||
this.props.onChange(queryModel, `Zabbix - ${queryType}`);
|
this.props.onChange(queryModel, `Zabbix - ${queryType}`);
|
||||||
}
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { selectedQueryType, legacyQuery, group, host, application, item } = this.state;
|
const { selectedQueryType, legacyQuery, group, host, application, itemTag, item } = this.state;
|
||||||
|
const { datasource } = this.props;
|
||||||
|
const supportsItemTags = datasource.zabbix.isZabbix54OrHigher();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -109,20 +113,32 @@ export class ZabbixVariableQueryEditor extends PureComponent<VariableQueryProps,
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{selectedQueryType.value !== VariableQueryTypes.Group &&
|
{selectedQueryType.value !== VariableQueryTypes.Group &&
|
||||||
<div className="gf-form max-width-30">
|
<div className="gf-form max-width-30">
|
||||||
<InlineFormLabel width={10}>Host</InlineFormLabel>
|
<InlineFormLabel width={10}>Host</InlineFormLabel>
|
||||||
<ZabbixInput
|
<ZabbixInput
|
||||||
value={host}
|
value={host}
|
||||||
onChange={evt => this.handleQueryUpdate(evt, 'host')}
|
onChange={evt => this.handleQueryUpdate(evt, 'host')}
|
||||||
onBlur={this.handleQueryChange}
|
onBlur={this.handleQueryChange}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
{(selectedQueryType.value === VariableQueryTypes.Application ||
|
{(selectedQueryType.value === VariableQueryTypes.Application ||
|
||||||
|
selectedQueryType.value === VariableQueryTypes.ItemTag ||
|
||||||
selectedQueryType.value === VariableQueryTypes.Item ||
|
selectedQueryType.value === VariableQueryTypes.Item ||
|
||||||
selectedQueryType.value === VariableQueryTypes.ItemValues) &&
|
selectedQueryType.value === VariableQueryTypes.ItemValues) &&
|
||||||
<div className="gf-form-inline">
|
<div className="gf-form-inline">
|
||||||
|
{supportsItemTags && (
|
||||||
|
<div className="gf-form max-width-30">
|
||||||
|
<InlineFormLabel width={10}>Item tag</InlineFormLabel>
|
||||||
|
<ZabbixInput
|
||||||
|
value={itemTag}
|
||||||
|
onChange={evt => this.handleQueryUpdate(evt, 'itemTag')}
|
||||||
|
onBlur={this.handleQueryChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{!supportsItemTags && (
|
||||||
<div className="gf-form max-width-30">
|
<div className="gf-form max-width-30">
|
||||||
<InlineFormLabel width={10}>Application</InlineFormLabel>
|
<InlineFormLabel width={10}>Application</InlineFormLabel>
|
||||||
<ZabbixInput
|
<ZabbixInput
|
||||||
@@ -131,29 +147,30 @@ export class ZabbixVariableQueryEditor extends PureComponent<VariableQueryProps,
|
|||||||
onBlur={this.handleQueryChange}
|
onBlur={this.handleQueryChange}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{(selectedQueryType.value === VariableQueryTypes.Item ||
|
)}
|
||||||
selectedQueryType.value === VariableQueryTypes.ItemValues) &&
|
{(selectedQueryType.value === VariableQueryTypes.Item ||
|
||||||
<div className="gf-form max-width-30">
|
selectedQueryType.value === VariableQueryTypes.ItemValues) &&
|
||||||
<InlineFormLabel width={10}>Item</InlineFormLabel>
|
<div className="gf-form max-width-30">
|
||||||
<ZabbixInput
|
<InlineFormLabel width={10}>Item</InlineFormLabel>
|
||||||
value={item}
|
<ZabbixInput
|
||||||
onChange={evt => this.handleQueryUpdate(evt, 'item')}
|
value={item}
|
||||||
onBlur={this.handleQueryChange}
|
onChange={evt => this.handleQueryUpdate(evt, 'item')}
|
||||||
/>
|
onBlur={this.handleQueryChange}
|
||||||
</div>
|
/>
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
{legacyQuery &&
|
{legacyQuery &&
|
||||||
<div className="gf-form">
|
<div className="gf-form">
|
||||||
<InlineFormLabel width={10} tooltip="Original query string, read-only">Legacy Query</InlineFormLabel>
|
<InlineFormLabel width={10} tooltip="Original query string, read-only">Legacy Query</InlineFormLabel>
|
||||||
<Input
|
<Input
|
||||||
css=""
|
css=""
|
||||||
value={legacyQuery}
|
value={legacyQuery}
|
||||||
readOnly={true}
|
readOnly={true}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -663,7 +663,7 @@ export class ZabbixDatasource extends DataSourceApi<ZabbixMetricsQuery, ZabbixDS
|
|||||||
queryModel = utils.parseLegacyVariableQuery(query);
|
queryModel = utils.parseLegacyVariableQuery(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const prop of ['group', 'host', 'application', 'item']) {
|
for (const prop of ['group', 'host', 'application', 'itemTag', 'item']) {
|
||||||
queryModel[prop] = this.replaceTemplateVars(queryModel[prop], {});
|
queryModel[prop] = this.replaceTemplateVars(queryModel[prop], {});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -679,6 +679,9 @@ export class ZabbixDatasource extends DataSourceApi<ZabbixMetricsQuery, ZabbixDS
|
|||||||
case VariableQueryTypes.Application:
|
case VariableQueryTypes.Application:
|
||||||
resultPromise = this.zabbix.getApps(queryModel.group, queryModel.host, queryModel.application);
|
resultPromise = this.zabbix.getApps(queryModel.group, queryModel.host, queryModel.application);
|
||||||
break;
|
break;
|
||||||
|
case VariableQueryTypes.ItemTag:
|
||||||
|
resultPromise = this.zabbix.getItemTags(queryModel.group, queryModel.host, queryModel.itemTag);
|
||||||
|
break;
|
||||||
case VariableQueryTypes.Item:
|
case VariableQueryTypes.Item:
|
||||||
resultPromise = this.zabbix.getItems(queryModel.group, queryModel.host, queryModel.application, null, queryModel.item);
|
resultPromise = this.zabbix.getItems(queryModel.group, queryModel.host, queryModel.application, null, queryModel.item);
|
||||||
break;
|
break;
|
||||||
@@ -781,7 +784,7 @@ export class ZabbixDatasource extends DataSourceApi<ZabbixMetricsQuery, ZabbixDS
|
|||||||
|
|
||||||
// Replace template variables
|
// Replace template variables
|
||||||
replaceTargetVariables(target, options) {
|
replaceTargetVariables(target, options) {
|
||||||
const parts = ['group', 'host', 'application', 'item'];
|
const parts = ['group', 'host', 'application', 'itemTag', 'item'];
|
||||||
_.forEach(parts, p => {
|
_.forEach(parts, p => {
|
||||||
if (target[p] && target[p].filter) {
|
if (target[p] && target[p].filter) {
|
||||||
target[p].filter = this.replaceTemplateVars(target[p].filter, options.scopedVars);
|
target[p].filter = this.replaceTemplateVars(target[p].filter, options.scopedVars);
|
||||||
|
|||||||
@@ -315,7 +315,14 @@ export class ZabbixQueryController extends QueryCtrl {
|
|||||||
if (!this.metric?.tagList) {
|
if (!this.metric?.tagList) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
return this.metric.tagList.map(t => itemTagToString(t));
|
const tags = this.metric.tagList.map(t => itemTagToString(t));
|
||||||
|
|
||||||
|
// Add template variables
|
||||||
|
_.forEach(this.templateSrv.getVariables(), variable => {
|
||||||
|
tags.unshift('$' + variable.name);
|
||||||
|
});
|
||||||
|
|
||||||
|
return tags;
|
||||||
};
|
};
|
||||||
|
|
||||||
getTemplateVariables() {
|
getTemplateVariables() {
|
||||||
|
|||||||
@@ -150,6 +150,7 @@ export interface VariableQuery {
|
|||||||
group?: string;
|
group?: string;
|
||||||
host?: string;
|
host?: string;
|
||||||
application?: string;
|
application?: string;
|
||||||
|
itemTag?: string;
|
||||||
item?: string;
|
item?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,6 +160,7 @@ export enum VariableQueryTypes {
|
|||||||
Group = 'group',
|
Group = 'group',
|
||||||
Host = 'host',
|
Host = 'host',
|
||||||
Application = 'application',
|
Application = 'application',
|
||||||
|
ItemTag = 'itemTag',
|
||||||
Item = 'item',
|
Item = 'item',
|
||||||
ItemValues = 'itemValues',
|
ItemValues = 'itemValues',
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import _ from 'lodash';
|
|||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import semver from 'semver';
|
import semver from 'semver';
|
||||||
import * as utils from '../utils';
|
import * as utils from '../utils';
|
||||||
import { itemTagToString } from '../utils';
|
|
||||||
import responseHandler from '../responseHandler';
|
import responseHandler from '../responseHandler';
|
||||||
import { CachingProxy } from './proxy/cachingProxy';
|
import { CachingProxy } from './proxy/cachingProxy';
|
||||||
import { DBConnector } from './connectors/dbConnector';
|
import { DBConnector } from './connectors/dbConnector';
|
||||||
@@ -11,7 +10,7 @@ import { SQLConnector } from './connectors/sql/sqlConnector';
|
|||||||
import { InfluxDBConnector } from './connectors/influxdb/influxdbConnector';
|
import { InfluxDBConnector } from './connectors/influxdb/influxdbConnector';
|
||||||
import { ZabbixConnector } from './types';
|
import { ZabbixConnector } from './types';
|
||||||
import { joinTriggersWithEvents, joinTriggersWithProblems } from '../problemsHandler';
|
import { joinTriggersWithEvents, joinTriggersWithProblems } from '../problemsHandler';
|
||||||
import { ProblemDTO, ZBXItemTag } from '../types';
|
import { ProblemDTO, ZBXItem, ZBXItemTag } from '../types';
|
||||||
|
|
||||||
interface AppsResponse extends Array<any> {
|
interface AppsResponse extends Array<any> {
|
||||||
appFilterEmpty?: boolean;
|
appFilterEmpty?: boolean;
|
||||||
@@ -20,7 +19,7 @@ interface AppsResponse extends Array<any> {
|
|||||||
|
|
||||||
const REQUESTS_TO_PROXYFY = [
|
const REQUESTS_TO_PROXYFY = [
|
||||||
'getHistory', 'getTrend', 'getGroups', 'getHosts', 'getApps', 'getItems', 'getMacros', 'getItemsByIDs',
|
'getHistory', 'getTrend', 'getGroups', 'getHosts', 'getApps', 'getItems', 'getMacros', 'getItemsByIDs',
|
||||||
'getEvents', 'getAlerts', 'getHostAlerts', 'getAcknowledges', 'getITService', 'getSLA', 'getVersion', 'getProxies',
|
'getEvents', 'getAlerts', 'getHostAlerts', 'getAcknowledges', 'getITService', 'getSLA', 'getProxies',
|
||||||
'getEventAlerts', 'getExtendedEventData', 'getProblems', 'getEventsHistory', 'getTriggersByIds', 'getScripts', 'getValueMappings'
|
'getEventAlerts', 'getExtendedEventData', 'getProblems', 'getEventsHistory', 'getTriggersByIds', 'getScripts', 'getValueMappings'
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -31,7 +30,7 @@ const REQUESTS_TO_CACHE = [
|
|||||||
const REQUESTS_TO_BIND = [
|
const REQUESTS_TO_BIND = [
|
||||||
'getHistory', 'getTrend', 'getMacros', 'getItemsByIDs', 'getEvents', 'getAlerts', 'getHostAlerts',
|
'getHistory', 'getTrend', 'getMacros', 'getItemsByIDs', 'getEvents', 'getAlerts', 'getHostAlerts',
|
||||||
'getAcknowledges', 'getITService', 'acknowledgeEvent', 'getProxies', 'getEventAlerts',
|
'getAcknowledges', 'getITService', 'acknowledgeEvent', 'getProxies', 'getEventAlerts',
|
||||||
'getExtendedEventData', 'getScripts', 'executeScript', 'getValueMappings', 'isZabbix54OrHigher'
|
'getExtendedEventData', 'getScripts', 'executeScript', 'getValueMappings'
|
||||||
];
|
];
|
||||||
|
|
||||||
export class Zabbix implements ZabbixConnector {
|
export class Zabbix implements ZabbixConnector {
|
||||||
@@ -57,7 +56,6 @@ export class Zabbix implements ZabbixConnector {
|
|||||||
getExtendedEventData: (eventids) => Promise<any>;
|
getExtendedEventData: (eventids) => Promise<any>;
|
||||||
getMacros: (hostids: any[]) => Promise<any>;
|
getMacros: (hostids: any[]) => Promise<any>;
|
||||||
getValueMappings: () => Promise<any>;
|
getValueMappings: () => Promise<any>;
|
||||||
isZabbix54OrHigher: () => boolean;
|
|
||||||
|
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
const {
|
const {
|
||||||
@@ -172,13 +170,23 @@ export class Zabbix implements ZabbixConnector {
|
|||||||
|
|
||||||
async getVersion() {
|
async getVersion() {
|
||||||
if (!this.version) {
|
if (!this.version) {
|
||||||
this.version = await this.zabbixAPI.initVersion();
|
if (this.zabbixAPI.version) {
|
||||||
|
this.version = this.zabbixAPI.version;
|
||||||
|
} else {
|
||||||
|
this.version = await this.zabbixAPI.initVersion();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return this.version;
|
return this.version;
|
||||||
}
|
}
|
||||||
|
|
||||||
supportsApplications() {
|
supportsApplications() {
|
||||||
return this.version ? semver.lt(this.version, '5.4.0') : true;
|
const version = this.version || this.zabbixAPI.version;
|
||||||
|
return version ? semver.lt(version, '5.4.0') : true;
|
||||||
|
}
|
||||||
|
|
||||||
|
isZabbix54OrHigher() {
|
||||||
|
const version = this.version || this.zabbixAPI.version;
|
||||||
|
return version ? semver.gte(version, '5.4.0') : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
getItemsFromTarget(target, options) {
|
getItemsFromTarget(target, options) {
|
||||||
@@ -263,6 +271,20 @@ export class Zabbix implements ZabbixConnector {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getItemTags(groupFilter?, hostFilter?, itemTagFilter?) {
|
||||||
|
const items = await this.getAllItems(groupFilter, hostFilter, null, null, {});
|
||||||
|
let tags: ZBXItemTag[] = _.flatten(items.map((item: ZBXItem) => {
|
||||||
|
if (item.tags) {
|
||||||
|
return item.tags;
|
||||||
|
} else {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
tags = _.uniqBy(tags, t => t.tag + t.value || '');
|
||||||
|
const tagsStr = tags.map(t => ({ name: utils.itemTagToString(t) }));
|
||||||
|
return findByFilter(tagsStr, itemTagFilter);
|
||||||
|
}
|
||||||
|
|
||||||
async getAllItems(groupFilter, hostFilter, appFilter, itemTagFilter, options: any = {}) {
|
async getAllItems(groupFilter, hostFilter, appFilter, itemTagFilter, options: any = {}) {
|
||||||
const apps = await this.getApps(groupFilter, hostFilter, appFilter);
|
const apps = await this.getApps(groupFilter, hostFilter, appFilter);
|
||||||
let items: any[];
|
let items: any[];
|
||||||
@@ -272,7 +294,7 @@ export class Zabbix implements ZabbixConnector {
|
|||||||
if (itemTagFilter) {
|
if (itemTagFilter) {
|
||||||
items = items.filter(item => {
|
items = items.filter(item => {
|
||||||
if (item.tags) {
|
if (item.tags) {
|
||||||
const tags: ZBXItemTag[] = item.tags.map(t => itemTagToString(t));
|
const tags: ZBXItemTag[] = item.tags.map(t => utils.itemTagToString(t));
|
||||||
return tags.includes(itemTagFilter);
|
return tags.includes(itemTagFilter);
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
Reference in New Issue
Block a user