Update datasource config editor

This commit is contained in:
Alexander Zobnin
2020-06-01 18:05:50 +03:00
parent 875e611400
commit 48767fe479
15 changed files with 730 additions and 487 deletions

View File

@@ -50,7 +50,7 @@ const getStyles = stylesFactory((theme: GrafanaTheme) => {
height: 2rem;
background-image: none;
background-color: ${actionBlue};
border: 1px solid ${theme.colors.gray1 || (theme as any).palette.gray1};
border: 1px solid ${theme.palette.gray1};
border-radius: 1px;
color: ${theme.colors.text};

View File

@@ -0,0 +1,268 @@
import React, { useEffect, useState } from 'react';
import { getDataSourceSrv } from '@grafana/runtime';
import { DataSourcePluginOptionsEditorProps, DataSourceSettings, SelectableValue } from '@grafana/data';
import { DataSourceHttpSettings, LegacyForms, Field, Input, Button, InlineFormLabel } from '@grafana/ui';
const { Select, FormField, Switch } = LegacyForms;
import { ZabbixDSOptions, ZabbixSecureJSONData } from '../types';
const SUPPORTED_SQL_DS = ['mysql', 'postgres', 'influxdb'];
export type Props = DataSourcePluginOptionsEditorProps<ZabbixDSOptions, ZabbixSecureJSONData>;
export const ConfigEditor = (props: Props) => {
const { options, onOptionsChange } = props;
const [selectedDBDatasource, setSelectedDBDatasource] = useState(null);
const [currentDSType, setCurrentDSType] = useState('');
// Apply some defaults on initial render
useEffect(() => {
onOptionsChange({
...options,
jsonData: {
trends: true,
...options.jsonData,
},
});
if (options.jsonData.dbConnectionEnable) {
if (!options.jsonData.dbConnectionDatasourceId) {
const dsName = options.jsonData.dbConnectionDatasourceName;
getDataSourceSrv().get(dsName)
.then(ds => {
if (ds) {
const selectedDs = getDirectDBDatasources().find(dsOption => dsOption.id === ds.id);
setSelectedDBDatasource({ label: selectedDs.name, value: selectedDs.id });
setCurrentDSType(selectedDs.type);
onOptionsChange({
...options,
jsonData: {
...options.jsonData,
dbConnectionDatasourceId: ds.id,
},
});
}
});
} else {
const selectedDs = getDirectDBDatasources().find(dsOption => dsOption.id === options.jsonData.dbConnectionDatasourceId);
setSelectedDBDatasource({ label: selectedDs.name, value: selectedDs.id });
setCurrentDSType(selectedDs.type);
}
}
}, []);
return (
<>
<DataSourceHttpSettings
defaultUrl={'http://localhost:9200'}
dataSourceConfig={options}
showAccessOptions={true}
onChange={onOptionsChange}
/>
<div className="gf-form-group">
<h3 className="page-heading">Zabbix API details</h3>
<div className="gf-form max-width-25">
<FormField
labelWidth={7}
inputWidth={15}
label="Username"
value={options.jsonData.username || ''}
onChange={jsonDataChangeHandler('username', options, onOptionsChange)}
required
/>
</div>
<div className="gf-form max-width-25">
{options.secureJsonFields?.password ?
<>
<FormField
labelWidth={7}
inputWidth={15}
label="Password"
disabled={true}
value=""
placeholder="Configured"
/>
<Button onClick={resetSecureJsonField('password', options, onOptionsChange)}>Reset</Button>
</>:
<FormField
labelWidth={7}
inputWidth={15}
label="Password"
type="password"
value={options.secureJsonData?.password || options.jsonData.password || ''}
onChange={secureJsonDataChangeHandler('password', options, onOptionsChange)}
required
/>
}
</div>
<Switch
label="Trends"
labelClass="width-7"
checked={options.jsonData.trends}
onChange={jsonDataSwitchHandler('trends', options, onOptionsChange)}
/>
{options.jsonData.trends &&
<>
<div className="gf-form">
<FormField
labelWidth={7}
inputWidth={4}
label="After"
value={options.jsonData.trendsFrom || ''}
placeholder="7d"
onChange={jsonDataChangeHandler('trendsFrom', options, onOptionsChange)}
tooltip="Time after which trends will be used.
Best practice is to set this value to your history storage period (7d, 30d, etc)."
/>
</div>
<div className="gf-form">
<FormField
labelWidth={7}
inputWidth={4}
label="Range"
value={options.jsonData.trendsRange || ''}
placeholder="4d"
onChange={jsonDataChangeHandler('trendsRange', options, onOptionsChange)}
tooltip="Time range width after which trends will be used instead of history.
It's better to set this value in range of 4 to 7 days to prevent loading large amount of history data."
/>
</div>
</>
}
<div className="gf-form">
<FormField
labelWidth={7}
inputWidth={4}
label="Cache TTL"
value={options.jsonData.cacheTTL || ''}
placeholder="1h"
onChange={jsonDataChangeHandler('cacheTTL', options, onOptionsChange)}
tooltip="Zabbix data source caches metric names in memory. Specify how often data will be updated."
/>
</div>
</div>
<div className="gf-form-group">
<h3 className="page-heading">Direct DB Connection</h3>
<Switch
label="Enable"
labelClass="width-9"
checked={options.jsonData.dbConnectionEnable}
onChange={jsonDataSwitchHandler('dbConnectionEnable', options, onOptionsChange)}
/>
{options.jsonData.dbConnectionEnable &&
<>
<div className="gf-form">
<InlineFormLabel width={9}>Data Source</InlineFormLabel>
<Select width={16} options={getDirectDBDSOptions()} value={selectedDBDatasource} />
</div>
{currentDSType === 'influxdb' &&
<div className="gf-form">
<FormField
labelWidth={9}
inputWidth={16}
label="Retention Policy"
value={options.jsonData.dbConnectionRetentionPolicy || ''}
placeholder="Retention policy name"
onChange={jsonDataChangeHandler('dbConnectionRetentionPolicy', options, onOptionsChange)}
tooltip="Specify retention policy name for fetching long-term stored data (optional).
Leave it blank if only default retention policy used."
/>
</div>
}
</>
}
</div>
<div className="gf-form-group">
<h3 className="page-heading">Other</h3>
<Switch
label="Disable acknowledges for read-only users"
labelClass="width-20"
checked={options.jsonData.disableReadOnlyUsersAck}
onChange={jsonDataSwitchHandler('disableReadOnlyUsersAck', options, onOptionsChange)}
/>
</div>
</>
);
};
const jsonDataChangeHandler = (
key: keyof ZabbixDSOptions,
value: DataSourceSettings<ZabbixDSOptions, ZabbixSecureJSONData>,
onChange: Props['onOptionsChange']
) => (
event: React.SyntheticEvent<HTMLInputElement | HTMLSelectElement>
) => {
onChange({
...value,
jsonData: {
...value.jsonData,
[key]: event.currentTarget.value || (event.target as HTMLInputElement).checked,
},
});
};
const jsonDataSwitchHandler = (
key: keyof ZabbixDSOptions,
value: DataSourceSettings<ZabbixDSOptions, ZabbixSecureJSONData>,
onChange: Props['onOptionsChange']
) => (
event: React.SyntheticEvent<HTMLInputElement>
) => {
onChange({
...value,
jsonData: {
...value.jsonData,
[key]: (event.target as HTMLInputElement).checked,
},
});
};
const secureJsonDataChangeHandler = (
key: keyof ZabbixDSOptions,
value: DataSourceSettings<ZabbixDSOptions, ZabbixSecureJSONData>,
onChange: Props['onOptionsChange']
) => (
event: React.SyntheticEvent<HTMLInputElement | HTMLSelectElement>
) => {
onChange({
...value,
jsonData: {
...value.jsonData,
password: '',
},
secureJsonData: {
...value.secureJsonData,
[key]: event.currentTarget.value,
},
});
};
const resetSecureJsonField = (
key: keyof ZabbixDSOptions,
value: DataSourceSettings<ZabbixDSOptions, ZabbixSecureJSONData>,
onChange: Props['onOptionsChange']
) => (
event: React.SyntheticEvent<HTMLButtonElement>
) => {
onChange({
...value,
secureJsonFields: {
...value.secureJsonFields,
[key]: false,
},
});
};
const getDirectDBDatasources = () => {
let dsList = (getDataSourceSrv() as any).getAll();
dsList = dsList.filter(ds => SUPPORTED_SQL_DS.includes(ds.type));
return dsList;
};
const getDirectDBDSOptions = () => {
const dsList = getDirectDBDatasources();
const dsOpts: Array<SelectableValue<number>> = dsList.map(ds => ({ label: ds.name, value: ds.id }));
return dsOpts;
};

View File

@@ -3,12 +3,7 @@ import { parseLegacyVariableQuery } from '../utils';
import { SelectableValue } from '@grafana/data';
import { VariableQuery, VariableQueryTypes, VariableQueryProps, VariableQueryData } from '../types';
import { ZabbixInput } from './ZabbixInput';
// FormLabel was renamed to InlineFormLabel in Grafana 7.0
import * as grafanaUi from '@grafana/ui';
const FormLabel = grafanaUi.FormLabel || (grafanaUi as any).InlineFormLabel;
const Select = (grafanaUi as any).LegacyForms?.Select || (grafanaUi as any).Select;
const Input = (grafanaUi as any).LegacyForms?.Input || (grafanaUi as any).Input;
import { InlineFormLabel, Select, Input } from '@grafana/ui';
export class ZabbixVariableQueryEditor extends PureComponent<VariableQueryProps, VariableQueryData> {
queryTypes: Array<SelectableValue<VariableQueryTypes>> = [
@@ -96,7 +91,7 @@ export class ZabbixVariableQueryEditor extends PureComponent<VariableQueryProps,
return (
<>
<div className="gf-form max-width-21">
<FormLabel width={10}>Query Type</FormLabel>
<InlineFormLabel width={10}>Query Type</InlineFormLabel>
<Select
width={11}
value={selectedQueryType}
@@ -106,7 +101,7 @@ export class ZabbixVariableQueryEditor extends PureComponent<VariableQueryProps,
</div>
<div className="gf-form-inline">
<div className="gf-form max-width-30">
<FormLabel width={10}>Group</FormLabel>
<InlineFormLabel width={10}>Group</InlineFormLabel>
<ZabbixInput
value={group}
onChange={evt => this.handleQueryUpdate(evt, 'group')}
@@ -115,7 +110,7 @@ export class ZabbixVariableQueryEditor extends PureComponent<VariableQueryProps,
</div>
{selectedQueryType.value !== VariableQueryTypes.Group &&
<div className="gf-form max-width-30">
<FormLabel width={10}>Host</FormLabel>
<InlineFormLabel width={10}>Host</InlineFormLabel>
<ZabbixInput
value={host}
onChange={evt => this.handleQueryUpdate(evt, 'host')}
@@ -129,7 +124,7 @@ export class ZabbixVariableQueryEditor extends PureComponent<VariableQueryProps,
selectedQueryType.value === VariableQueryTypes.ItemValues) &&
<div className="gf-form-inline">
<div className="gf-form max-width-30">
<FormLabel width={10}>Application</FormLabel>
<InlineFormLabel width={10}>Application</InlineFormLabel>
<ZabbixInput
value={application}
onChange={evt => this.handleQueryUpdate(evt, 'application')}
@@ -139,7 +134,7 @@ export class ZabbixVariableQueryEditor extends PureComponent<VariableQueryProps,
{(selectedQueryType.value === VariableQueryTypes.Item ||
selectedQueryType.value === VariableQueryTypes.ItemValues) &&
<div className="gf-form max-width-30">
<FormLabel width={10}>Item</FormLabel>
<InlineFormLabel width={10}>Item</InlineFormLabel>
<ZabbixInput
value={item}
onChange={evt => this.handleQueryUpdate(evt, 'item')}
@@ -152,7 +147,7 @@ export class ZabbixVariableQueryEditor extends PureComponent<VariableQueryProps,
{legacyQuery &&
<div className="gf-form">
<FormLabel width={10} tooltip="Original query string, read-only">Legacy Query</FormLabel>
<InlineFormLabel width={10} tooltip="Original query string, read-only">Legacy Query</InlineFormLabel>
<Input
value={legacyQuery}
readOnly={true}

View File

@@ -11,10 +11,10 @@ const variablePattern = RegExp(`^${variableRegex.source}`);
const getStyles = (theme: GrafanaTheme) => ({
inputRegex: css`
color: ${theme.colors.orange || (theme as any).palette.orange}
color: ${theme.palette.orange}
`,
inputVariable: css`
color: ${theme.colors.variable || (theme as any).palette.variable}
color: ${theme.colors.textBlue}
`,
});

View File

@@ -1,57 +0,0 @@
import _ from 'lodash';
import { getDataSourceSrv } from '@grafana/runtime';
import { migrateDSConfig } from './migrations';
const SUPPORTED_SQL_DS = ['mysql', 'postgres', 'influxdb'];
const defaultConfig = {
trends: false,
dbConnectionEnable: false,
dbConnectionDatasourceId: null,
alerting: false,
addThresholds: false,
alertingMinSeverity: 3,
disableReadOnlyUsersAck: false,
};
export class ZabbixDSConfigController {
/** @ngInject */
constructor() {
this.current.jsonData = migrateDSConfig(this.current.jsonData);
_.defaults(this.current.jsonData, defaultConfig);
this.dbConnectionDatasourceId = this.current.jsonData.dbConnectionDatasourceId;
this.dbDataSources = this.getSupportedDBDataSources();
if (!this.dbConnectionDatasourceId) {
this.loadCurrentDBDatasource();
}
}
getSupportedDBDataSources() {
let datasources = getDataSourceSrv().getAll();
return _.filter(datasources, ds => {
return _.includes(SUPPORTED_SQL_DS, ds.type);
});
}
getCurrentDatasourceType() {
const dsId = this.dbConnectionDatasourceId;
const currentDs = _.find(this.dbDataSources, { 'id': dsId });
return currentDs ? currentDs.type : null;
}
loadCurrentDBDatasource() {
const dsName= this.current.jsonData.dbConnectionDatasourceName;
getDataSourceSrv().loadDatasource(dsName)
.then(ds => {
if (ds) {
this.dbConnectionDatasourceId = ds.id;
}
});
}
onDBConnectionDatasourceChange() {
this.current.jsonData.dbConnectionDatasourceId = this.dbConnectionDatasourceId;
}
}

View File

@@ -11,11 +11,11 @@ import responseHandler from './responseHandler';
import problemsHandler from './problemsHandler';
import { Zabbix } from './zabbix/zabbix';
import { ZabbixAPIError } from './zabbix/connectors/zabbix_api/zabbixAPIConnector';
import { VariableQueryTypes, ShowProblemTypes } from './types';
import { ZabbixMetricsQuery, ZabbixDSOptions, VariableQueryTypes, ShowProblemTypes } from './types';
import { getBackendSrv } from '@grafana/runtime';
import { DataSourceApi, DataSourceInstanceSettings } from '@grafana/data';
export class ZabbixDatasource extends DataSourceApi {
export class ZabbixDatasource extends DataSourceApi<ZabbixMetricsQuery, ZabbixDSOptions> {
name: string;
basicAuth: any;
withCredentials: any;
@@ -39,7 +39,7 @@ export class ZabbixDatasource extends DataSourceApi {
replaceTemplateVars: (target: any, scopedVars?: any) => any;
/** @ngInject */
constructor(instanceSettings: DataSourceInstanceSettings, private templateSrv, private zabbixAlertingSrv) {
constructor(instanceSettings: DataSourceInstanceSettings<ZabbixDSOptions>, private templateSrv, private zabbixAlertingSrv) {
super(instanceSettings);
this.templateSrv = templateSrv;
@@ -503,11 +503,7 @@ export class ZabbixDatasource extends DataSourceApi {
*/
async testDatasource() {
try {
const result = await this.doTSDBConnectionTest();
/**
* @type {ZabbixConnectionInfo}
*/
const { zabbixVersion, dbConnectorStatus } = result.results["zabbixAPI"].meta;
const { zabbixVersion, dbConnectorStatus } = await this.zabbix.testDataSource();
let message = `Zabbix API version: ${zabbixVersion}`;
if (dbConnectorStatus) {
message += `, DB connector type: ${dbConnectorStatus.dsType}`;

View File

@@ -1,33 +1,26 @@
import { DataSourcePlugin } from '@grafana/data';
import { loadPluginCss } from '@grafana/runtime';
import { ZabbixDatasource } from './datasource';
import { ZabbixQueryController } from './query.controller';
import { ZabbixDSConfigController } from './config.controller';
import { ZabbixVariableQueryEditor } from './components/VariableQueryEditor';
import { ConfigEditor } from './components/ConfigEditor';
import './zabbixAlerting.service.js';
import './add-metric-function.directive';
import './metric-function-editor.directive';
class ZabbixQueryOptionsController {
static templateUrl = 'datasource-zabbix/partials/query.options.html';
}
class ZabbixAnnotationsQueryController {
static templateUrl = 'datasource-zabbix/partials/annotations.editor.html';
}
ZabbixQueryController.templateUrl = 'datasource-zabbix/partials/query.editor.html';
ZabbixDSConfigController.templateUrl = 'datasource-zabbix/partials/config.html';
loadPluginCss({
dark: 'plugins/alexanderzobnin-zabbix-app/css/grafana-zabbix.dark.css',
light: 'plugins/alexanderzobnin-zabbix-app/css/grafana-zabbix.light.css'
});
export {
ZabbixDatasource as Datasource,
ZabbixDSConfigController as ConfigCtrl,
ZabbixQueryController as QueryCtrl,
ZabbixQueryOptionsController as QueryOptionsCtrl,
ZabbixAnnotationsQueryController as AnnotationsQueryCtrl,
ZabbixVariableQueryEditor as VariableQueryEditor,
};
export const plugin = new DataSourcePlugin(ZabbixDatasource)
.setConfigEditor(ConfigEditor)
.setQueryCtrl(ZabbixQueryController)
.setAnnotationQueryCtrl(ZabbixAnnotationsQueryController)
.setVariableQueryEditor(ZabbixVariableQueryEditor);

View File

@@ -1,154 +0,0 @@
<datasource-http-settings current="ctrl.current" suggest-url="http://localhost/zabbix/api_jsonrpc.php">
</datasource-http-settings>
<div class="gf-form-group">
<h3 class="page-heading">Zabbix API details</h3>
<div class="gf-form">
<span class="gf-form-label width-7">
Username
</span>
<input class="gf-form-input max-width-21"
type="text"
ng-model='ctrl.current.jsonData.username'
placeholder="user"
required>
</input>
</div>
<div class="gf-form">
<span class="gf-form-label width-7">
Password
</span>
<input class="gf-form-input max-width-21"
type="password"
ng-model='ctrl.current.jsonData.password'
placeholder="password">
</input>
</div>
<gf-form-switch class="gf-form" label-class="width-7"
label="Trends"
checked="ctrl.current.jsonData.trends"
switch-class="max-width-5">
</gf-form-switch>
<div class="gf-form-inline">
<div class="gf-form" ng-if="ctrl.current.jsonData.trends">
<span class="gf-form-label width-7">
After
<info-popover mode="right-normal">
Time after which trends will be used.
Best practice is to set this value to your history storage period (7d, 30d, etc).
</info-popover>
</span>
<input class="gf-form-input max-width-5"
type="text"
ng-model='ctrl.current.jsonData.trendsFrom'
placeholder="7d">
</input>
</div>
<div class="gf-form" ng-if="ctrl.current.jsonData.trends">
<span class="gf-form-label width-7">
Range
<info-popover mode="right-normal">
Time range width after which trends will be used instead of history.
It's better to set this value in range of 4 to 7 days to prevent loading large amount of history data.
</info-popover>
</span>
<input class="gf-form-input max-width-5" type="text" ng-model='ctrl.current.jsonData.trendsRange' placeholder="4d">
</input>
</div>
</div>
<div class="gf-form">
<span class="gf-form-label width-12">
Cache TTL
<info-popover mode="right-normal">
Zabbix data source caches metric names in memory. Specify how often data will be updated.
</info-popover>
</span>
<input class="gf-form-input max-width-7"
type="text"
ng-model='ctrl.current.jsonData.cacheTTL'
placeholder="1h">
</input>
</div>
</div>
<div class="gf-form-group">
<h3 class="page-heading">Direct DB Connection</h3>
<gf-form-switch class="gf-form" label-class="width-12"
label="Enable"
checked="ctrl.current.jsonData.dbConnectionEnable">
</gf-form-switch>
<div ng-if="ctrl.current.jsonData.dbConnectionEnable">
<div class="gf-form max-width-30">
<span class="gf-form-label width-12">
Data Source
<info-popover mode="right-normal">
Select Data Source for Zabbix history database.
In order to use this feature it should be <a href="/datasources/new" target="_blank">created</a> and
configured first. Zabbix plugin uses this data source for querying history data directly from the database.
This way usually faster than pulling data from Zabbix API, especially on the wide time ranges, and reduces
amount of data transferred.
</info-popover>
</span>
<div class="gf-form-select-wrapper max-width-16">
<select class="gf-form-input"
ng-model="ctrl.dbConnectionDatasourceId"
ng-options="ds.id as ds.name for ds in ctrl.dbDataSources"
ng-change="ctrl.onDBConnectionDatasourceChange()">
</select>
</div>
</div>
</div>
<div ng-if="ctrl.getCurrentDatasourceType() === 'influxdb'">
<div class="gf-form max-width-30">
<span class="gf-form-label width-12">
Retention Policy
<info-popover mode="right-normal">
Specify retention policy name for fetching long-term stored data (optional).
Leave it blank if only default retention policy used.
</info-popover>
</span>
<input class="gf-form-input max-width-16"
type="text"
ng-model='ctrl.current.jsonData.dbConnectionRetentionPolicy'
placeholder="Retention policy name">
</input>
</div>
</div>
</div>
<div class="gf-form-group">
<h3 class="page-heading">Alerting</h3>
<gf-form-switch class="gf-form" label-class="width-12"
label="Enable alerting"
checked="ctrl.current.jsonData.alerting">
</gf-form-switch>
<div ng-if="ctrl.current.jsonData.alerting">
<gf-form-switch class="gf-form" label-class="width-12"
label="Add thresholds"
checked="ctrl.current.jsonData.addThresholds">
</gf-form-switch>
<div class="gf-form max-width-20">
<span class="gf-form-label width-12">Min severity</span>
<div class="gf-form-select-wrapper max-width-16">
<select class="gf-form-input" ng-model="ctrl.current.jsonData.alertingMinSeverity"
ng-options="s.val as s.text for s in [
{val: 0, text: 'Not classified'}, {val: 1, text:'Information'},
{val: 2, text: 'Warning'}, {val: 3, text: 'Average'},
{val: 4, text: 'High'}, {val: 5, text: 'Disaster'}]">
</select>
</div>
</div>
</div>
</div>
<div class="gf-form-group">
<h3 class="page-heading">Other</h3>
<gf-form-switch class="gf-form" label-class="width-20"
label="Disable acknowledges for read-only users"
checked="ctrl.current.jsonData.disableReadOnlyUsersAck">
</gf-form-switch>
</div>

View File

@@ -1,88 +0,0 @@
<section class="grafana-metric-options gf-form-group">
<div class="gf-form-inline">
<div class="gf-form max-width-15">
<span class="gf-form-label">Max data points</span>
<input type="text"
class="gf-form-input"
ng-model="ctrl.panelCtrl.panel.maxDataPoints"
bs-tooltip="'Override max data points, automatically set to graph width in pixels.'"
data-placement="right"
ng-model-onblur ng-change="ctrl.panelCtrl.refresh()"
spellcheck='false'
placeholder="auto">
</input>
</div>
</div>
<div class="gf-form-inline">
<div class="gf-form">
<span class="gf-form-label width-10">
<i class="fa fa-info-circle"></i>
<a ng-click="ctrl.panelCtrl.toggleEditorHelp(1);" bs-tooltip="'click to show helpful info'" data-placement="bottom">
Max data points
</a>
</span>
<span class="gf-form-label width-10">
<i class="fa fa-info-circle"></i>
<a ng-click="ctrl.panelCtrl.toggleEditorHelp(2);" bs-tooltip="'click to show helpful info'" data-placement="bottom">
IT services
</a>
</span>
<span class="gf-form-label width-12">
<i class="fa fa-info-circle"></i>
<a ng-click="ctrl.panelCtrl.toggleEditorHelp(3)" bs-tooltip="'click to show helpful info'" data-placement="bottom">
IT service property
</a>
</span>
<span class="gf-form-label width-8">
<i class="fa fa-info-circle"></i>
<a ng-click="ctrl.panelCtrl.toggleEditorHelp(4)" bs-tooltip="'click to show helpful info'" data-placement="bottom">
Text filter
</a>
</span>
</div>
</div>
</section>
<div class="editor-row">
<div class="pull-left">
<div class="grafana-info-box span8" ng-if="ctrl.panelCtrl.editorHelpIndex === 1">
<h5>Max data points</h5>
<ul>
<li>Grafana-Zabbix plugin uses maxDataPoints parameter to consolidate the real number of values down to this
number
</li>
<li>If there are more real values, then by default they will be consolidated using averages</li>
<li>This could hide real peaks and max values in your series</li>
<li>Point consolidation will effect series legend values (min,max,total,current)</li>
<li>If you override maxDataPoint and set a high value performance can be severely effected</li>
</ul>
</div>
<div class="grafana-info-box span8" ng-if="ctrl.panelCtrl.editorHelpIndex === 2">
<h5>IT services</h5>
<ul>
<li>Select "IT services" in targets menu to activate IT services mode.</li>
</ul>
</div>
<div class="grafana-info-box span8" ng-if="ctrl.panelCtrl.editorHelpIndex === 3">
<h5>IT service property</h5>
<ul>
<li>Zabbix returns the following availability information about IT service</li>
<li>Status - current status of the IT service</li>
<li>SLA - SLA for the given time interval</li>
<li>OK time - time the service was in OK state, in seconds</li>
<li>Problem time - time the service was in problem state, in seconds</li>
<li>Down time - time the service was in scheduled downtime, in seconds</li>
</ul>
</div>
<div class="grafana-info-box span8" ng-if="ctrl.panelCtrl.editorHelpIndex === 4">
<h5>Text filter</h5>
<ul>
<li>Use regex to extract a part of the returned value.</li>
</ul>
</div>
</div>
</div>

View File

@@ -1,4 +1,22 @@
import { SelectableValue, DataQuery } from "@grafana/data";
import { SelectableValue, DataQuery, DataSourceJsonData } from "@grafana/data";
export interface ZabbixDSOptions extends DataSourceJsonData {
username: string;
password?: string;
trends: boolean;
trendsFrom: string;
trendsRange: string;
cacheTTL: string;
dbConnectionEnable: boolean;
dbConnectionDatasourceId?: number;
dbConnectionDatasourceName?: string;
dbConnectionRetentionPolicy?: string;
disableReadOnlyUsersAck: boolean;
}
export interface ZabbixSecureJSONData {
password?: string;
}
export interface ZabbixConnectionInfo {
zabbixVersion: string;

View File

@@ -138,37 +138,34 @@ export class Zabbix implements ZabbixConnector {
* }
* ```
*/
// testDataSource() {
// let zabbixVersion;
// let dbConnectorStatus;
// return this.getVersion()
// .then(version => {
// zabbixVersion = version;
// return this.login();
// })
// .then(() => {
// if (this.enableDirectDBConnection) {
// return this.dbConnector.testDataSource();
// } else {
// return Promise.resolve();
// }
// })
// .catch(error => {
// if (error instanceof ZabbixNotImplemented) {
// return Promise.resolve();
// }
// return Promise.reject(error);
// })
// .then(testResult => {
// if (testResult) {
// dbConnectorStatus = {
// dsType: this.dbConnector.datasourceTypeName,
// dsName: this.dbConnector.datasourceName
// };
// }
// return { zabbixVersion, dbConnectorStatus };
// });
// }
testDataSource() {
let zabbixVersion;
let dbConnectorStatus;
return this.getVersion()
.then(version => {
zabbixVersion = version;
return this.getAllGroups();
})
.then(() => {
if (this.enableDirectDBConnection) {
return this.dbConnector.testDataSource();
} else {
return Promise.resolve();
}
})
.catch(error => {
return Promise.reject(error);
})
.then(testResult => {
if (testResult) {
dbConnectorStatus = {
dsType: this.dbConnector.datasourceTypeName,
dsName: this.dbConnector.datasourceName
};
}
return { zabbixVersion, dbConnectorStatus };
});
}
getItemsFromTarget(target, options) {
const parts = ['group', 'host', 'application', 'item'];

View File

@@ -1,13 +1,9 @@
import React, { PureComponent } from 'react';
import { cx, css } from 'emotion';
import { ZBX_ACK_ACTION_ADD_MESSAGE, ZBX_ACK_ACTION_ACK, ZBX_ACK_ACTION_CHANGE_SEVERITY, ZBX_ACK_ACTION_CLOSE } from '../../datasource-zabbix/constants';
import { Button, VerticalGroup, Spinner, Modal, Input, Forms, stylesFactory, withTheme, Themeable } from '@grafana/ui';
import { Button, VerticalGroup, Spinner, Modal, Input, Checkbox, RadioButtonGroup, stylesFactory, withTheme, Themeable } from '@grafana/ui';
import { FAIcon } from '../../components';
import * as grafanaUi from '@grafana/ui';
import { GrafanaTheme } from '@grafana/data';
const Checkbox: any = Forms?.Checkbox || (grafanaUi as any).Checkbox;
const RadioButtonGroup: any = Forms?.RadioButtonGroup || (grafanaUi as any).RadioButtonGroup;
const KEYBOARD_ENTER_KEY = 13;
const KEYBOARD_ESCAPE_KEY = 27;
@@ -239,7 +235,7 @@ export class AckModalUnthemed extends PureComponent<Props, State> {
}
const getStyles = stylesFactory((theme: GrafanaTheme) => {
const red = theme.colors.red || (theme as any).palette.red;
const red = theme.palette.red;
return {
modal: css`
width: 500px;
@@ -257,7 +253,7 @@ const getStyles = stylesFactory((theme: GrafanaTheme) => {
border-color: ${red};
border-radius: 2px;
outline-offset: 2px;
box-shadow: 0 0 0 2px ${theme.colors.pageBg || (theme as any).colors.bg1}, 0 0 0px 4px ${red};
box-shadow: 0 0 0 2px ${theme.colors.bg1}, 0 0 0px 4px ${red};
`,
inputHint: css`
display: inherit;