Merge remote-tracking branch 'origin/master' into develop

Conflicts:
	src/datasource-zabbix/partials/query.editor.html
	src/datasource-zabbix/query.controller.js
This commit is contained in:
Alexander Zobnin
2016-04-28 19:15:22 +03:00
8 changed files with 142 additions and 198 deletions

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:6c46b44d6db23e898c29e72a3c3df3f36d62d712206b3453c18c173fcbcc5529 oid sha256:dc8ff42dbfa78458edcf931377156775973b87037b358daf82ecd5a3e49787b7
size 139772 size 138620

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:98e41015ed5e6738645065a057af30ce46482ec6797e4cbe85d9990e1fdce5be oid sha256:4932343924aa2416b72e46344e61335f2c0c4472575b919ee0629933d2c74b3e
size 140142 size 139070

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:fcaa6263d827d3344eb88fec28b1b3b084856af80174551e8c0725c3fd99e982 oid sha256:ef6860cefddd6ead2fe97d1ff3ebaa14320e8b0366fc094c13a47a6502e62f42
size 132477 size 131496

View File

@@ -17,14 +17,20 @@ select _Zabbix_ from dropdown list.
![Configure Zabbix data source](../img/installation-datasource_config.png) ![Configure Zabbix data source](../img/installation-datasource_config.png)
### Http settings ### HTTP settings
- **Url**: set Zabbix API url (full path with `api_jsonrpc.php`). - **Url**: set Zabbix API url (full path with `api_jsonrpc.php`).
- **Access**: can be either _proxy_ or _direct_. - **Access**:
- **Proxy**: access via Grafana backend
- **Direct**: access from browser.
- **Http Auth**: configure if you use proxy authentication. - **Http Auth**: configure if you use proxy authentication.
- **Basic Auth**: - **Basic Auth**:
- **With Credentials**: - **With Credentials**:
Proxy access means that the Grafana backend will proxy all requests from the browser, and send them on to the Data Source. This is useful because it can eliminate CORS (Cross Origin Site Resource) issues, as well as eliminate the need to disseminate authentication details to the Data Source to the browser.
Direct access is still supported because in some cases it may be useful to access a Data Source directly depending on the use case and topology of Grafana, the user, and the Data Source.
### Zabbix API details ### Zabbix API details
- **User** and **Password**: setup login for access to Zabbix API. Also check user's permissions - **User** and **Password**: setup login for access to Zabbix API. Also check user's permissions

View File

@@ -3,11 +3,43 @@ page_description: Installation instructions for Grafana-Zabbix.
# Installation # Installation
## From release package ## Using grafana-cli tool
Download [latest release](https://github.com/alexanderzobnin/grafana-zabbix/releases/latest) Get list of available plugins
for relative Grafana version. Unpack archive and copy *grafana-zabbix* into your grafana
plugins directory (default `/var/lib/grafana/plugins` if your installing grafana with package). ```sh
Restart grafana-server and the plugin should be automatically detected and used. grafana-cli plugins list-remote
```
Install zabbix plugin
```sh
grafana-cli plugins install alexanderzobnin-zabbix-app
```
Restart grafana after installing plugins
```sh
service grafana-server restart
```
Read more about installing plugins in [Grafana docs](http://docs.grafana.org/plugins/installation/)
## From special repo
You can use [grafana-zabbix-app](https://github.com/alexanderzobnin/grafana-zabbix-app) repo,
which contains latest builded version of plugin.
```sh
cd /var/lib/grafana/plugins
git clone https://github.com/alexanderzobnin/grafana-zabbix-app
```
Then restart grafana server.
Using this way you can easy upgrade plugin just running
```sh
cd /var/lib/grafana/plugins/grafana-zabbix-app
git pull
service grafana-server restart
```
## Building from sources ## Building from sources
You need NodeJS, npm and Grunt for building plugin from sources. Read more about required versions You need NodeJS, npm and Grunt for building plugin from sources. Read more about required versions
@@ -39,22 +71,6 @@ grunt
Restart Grafana server Restart Grafana server
```sh ```sh
sudo service grafana-server restart service grafana-server restart
systemctl restart grafana-server systemctl restart grafana-server
``` ```
## Using grafana-cli tool
Get list of available plugins
```sh
grafana-cli plugins list-remote
```
Install zabbix plugin
```sh
grafana-cli plugins install zabbix-app
```
Read more in [Grafana docs](http://docs.grafana.org/plugins/installation/)

View File

@@ -8,10 +8,10 @@ angular
.module('grafana.directives') .module('grafana.directives')
.directive('addMetricFunction', function($compile) { .directive('addMetricFunction', function($compile) {
var inputTemplate = '<input type="text"'+ var inputTemplate = '<input type="text"'+
' class="tight-form-input input-medium tight-form-input"' + ' class="gf-form-input"' +
' spellcheck="false" style="display:none"></input>'; ' spellcheck="false" style="display:none"></input>';
var buttonTemplate = '<a class="tight-form-item tight-form-func dropdown-toggle"' + var buttonTemplate = '<a class="gf-form-label tight-form-func dropdown-toggle query-part"' +
' tabindex="1" gf-dropdown="functionMenu" data-toggle="dropdown">' + ' tabindex="1" gf-dropdown="functionMenu" data-toggle="dropdown">' +
'<i class="fa fa-plus"></i></a>'; '<i class="fa fa-plus"></i></a>';

View File

@@ -1,226 +1,149 @@
<div class="tight-form"> <query-editor-row query-ctrl="ctrl" can-collapse="false">
<ul class="tight-form-list pull-right">
<li class="tight-form-item small" ng-show="ctrl.target.datasource">
<em>{{ctrl.target.datasource}}</em>
</li>
<li class="tight-form-item">
<div class="dropdown">
<a class="pointer dropdown-toggle"
data-toggle="dropdown"
tabindex="1">
<i class="fa fa-bars"></i>
</a>
<ul class="dropdown-menu pull-right" role="menu">
<!-- Switch editor mode --> <div class="gf-form-inline">
<li role="menuitem" ng-show="ctrl.target.mode"> <div class="gf-form max-width-20">
<a class="pointer" tabindex="1" <label class="gf-form-label width-7">Query Mode</label>
ng-click="ctrl.switchEditorMode(0)">Numeric metrics</a> <div class="gf-form-select-wrapper max-width-20">
</li> <select class="gf-form-input"
<li role="menuitem" ng-show="ctrl.target.mode != 1"> ng-change="ctrl.switchEditorMode(ctrl.target.mode)"
<a class="pointer" tabindex="1" ng-model="ctrl.target.mode"
ng-click="ctrl.switchEditorMode(1)">IT services</a> ng-options="v.mode as v.text for (k, v) in ctrl.editorModes">
</li> </select>
<li role="menuitem" ng-show="ctrl.target.mode != 2"> </div>
<a class="pointer" tabindex="1" </div>
ng-click="ctrl.switchEditorMode(2)">Text metrics</a> <div class="gf-form gf-form--grow">
</li> <div class="gf-form-label gf-form-label--grow"></div>
<li class="divider" role="menuitem"></li> </div>
<!-- From app/features/panel/partials/query_editor_row.html -->
<li role="menuitem">
<a tabindex="1" ng-click="ctrl.duplicateQuery()">Duplicate</a>
</li>
<li role="menuitem">
<a tabindex="1" ng-click="ctrl.moveQuery(-1)">Move up</a>
</li>
<li role="menuitem">
<a tabindex="1" ng-click="ctrl.moveQuery(1)">Move down</a>
</li>
</ul>
</div> </div>
</li>
<li class="tight-form-item last">
<a class="pointer" tabindex="1" ng-click="ctrl.removeQuery(target)">
<i class="fa fa-trash"></i>
</a>
</li>
</ul>
<ul class="tight-form-list">
<li class="tight-form-item" style="min-width: 15px; text-align: center">
{{ctrl.target.refId}}
</li>
<li>
<a class="tight-form-item" ng-click="ctrl.toggleHideQuery()" role="menuitem">
<i class="fa fa-eye"></i>
</a>
</li>
</ul>
<!-- IT Service editor --> <!-- IT Service editor -->
<ul class="tight-form-list" role="menu" ng-show="ctrl.target.mode == 1"> <div class="gf-form-inline" ng-show="ctrl.target.mode == 1">
<li class="tight-form-item query-keyword input-small">IT Service</li> <div class="gf-form max-width-20">
<li> <label class="gf-form-label width-7">IT Service</label>
<select class="tight-form-input input-large" <div class="gf-form-select-wrapper max-width-20">
<select class="gf-form-input"
ng-change="ctrl.selectITService()" ng-change="ctrl.selectITService()"
ng-model="ctrl.target.itservice" ng-model="ctrl.target.itservice"
bs-tooltip="ctrl.target.itservice.name.length > 25 ? ctrl.target.itservice.name : ''" bs-tooltip="ctrl.target.itservice.name.length > 25 ? ctrl.target.itservice.name : ''"
ng-options="itservice.name for itservice in ctrl.itserviceList track by itservice.name"> ng-options="itservice.name for itservice in ctrl.itserviceList track by itservice.name">
<option value="">-- Select IT service --</option> <option value="">-- Select IT service --</option>
</select> </select>
</li> </div>
<li class="tight-form-item query-keyword input-medium">IT service property</li> </div>
<li> <div class="gf-form">
<select class="tight-form-input input-medium" <label class="gf-form-label">IT service property</label>
<div class="gf-form-select-wrapper">
<select class="gf-form-input"
ng-change="ctrl.selectITService()" ng-change="ctrl.selectITService()"
ng-model="ctrl.target.slaProperty" ng-model="ctrl.target.slaProperty"
ng-options="slaProperty.name for slaProperty in ctrl.slaPropertyList track by slaProperty.name"> ng-options="slaProperty.name for slaProperty in ctrl.slaPropertyList track by slaProperty.name">
<option value="">-- Property --</option> <option value="">-- Property --</option>
</select> </select>
</li> </div>
</ul> </div>
<div class="gf-form gf-form--grow">
<div class="gf-form-label gf-form-label--grow"></div>
</div>
</div>
<ul class="tight-form-list" role="menu" ng-hide="ctrl.target.mode == 1"> <div class="gf-form-inline" ng-hide="ctrl.target.mode == 1">
<!-- Select Group -->
<!-- Select Host Group --> <div class="gf-form max-width-20">
<li class="tight-form-item query-keyword input-small" style="width: 6em">Group</li> <label class="gf-form-label width-7">Group</label>
<li>
<input type="text" <input type="text"
ng-model="ctrl.target.group.filter" ng-model="ctrl.target.group.filter"
bs-typeahead="ctrl.getGroupNames" bs-typeahead="ctrl.getGroupNames"
ng-blur="ctrl.onTargetBlur()" ng-blur="ctrl.onTargetBlur()"
data-min-length=0 data-min-length=0
data-items=100 data-items=100
class="input-medium tight-form-input" class="gf-form-input"
ng-class="{ ng-class="{
'zbx-variable': ctrl.isVariable(ctrl.target.group.filter), 'zbx-variable': ctrl.isVariable(ctrl.target.group.filter),
'zbx-regex': ctrl.isRegex(ctrl.target.group.filter) 'zbx-regex': ctrl.isRegex(ctrl.target.group.filter)
}"> }"></input>
</li> </div>
<!-- Select Host --> <!-- Select Host -->
<li class="tight-form-item query-keyword input-small" style="width: 3em">Host</li> <div class="gf-form">
<li> <label class="gf-form-label width-7">Host</label>
<input type="text" <input type="text"
ng-model="ctrl.target.host.filter" ng-model="ctrl.target.host.filter"
bs-typeahead="ctrl.getHostNames" bs-typeahead="ctrl.getHostNames"
ng-blur="ctrl.onTargetBlur()" ng-blur="ctrl.onTargetBlur()"
data-min-length=0 data-min-length=0
data-items=100 data-items=100
class="input-large tight-form-input" class="gf-form-input"
ng-class="{ ng-class="{
'zbx-variable': ctrl.isVariable(ctrl.target.host.filter), 'zbx-variable': ctrl.isVariable(ctrl.target.host.filter),
'zbx-regex': ctrl.isRegex(ctrl.target.host.filter) 'zbx-regex': ctrl.isRegex(ctrl.target.host.filter)
}"> }">
</li> </div>
</ul>
<div class="clearfix"></div>
</div>
<div class="tight-form" ng-hide="ctrl.target.mode == 1"> <gf-form-switch class="gf-form" ng-hide="ctrl.target.mode == 2"
<ul class="tight-form-list" role="menu"> label="Show disabled items" checked="ctrl.target.showDisabledItems" on-change="ctrl.onTargetBlur()">
</gf-form-switch>
<div class="gf-form gf-form--grow">
<div class="gf-form-label gf-form-label--grow"></div>
</div>
</div>
<div class="gf-form-inline" ng-hide="ctrl.target.mode == 1">
<!-- Select Application --> <!-- Select Application -->
<li class="tight-form-item query-keyword tight-form-align" style="width: 6em">Application</li> <div class="gf-form max-width-20">
<li> <label class="gf-form-label width-7">Application</label>
<input type="text" <input type="text"
ng-model="ctrl.target.application.filter" ng-model="ctrl.target.application.filter"
bs-typeahead="ctrl.getApplicationNames" bs-typeahead="ctrl.getApplicationNames"
ng-blur="ctrl.onTargetBlur()" ng-blur="ctrl.onTargetBlur()"
data-min-length=0 data-min-length=0
data-items=100 data-items=100
class="input-medium tight-form-input" class="gf-form-input"
ng-class="{ ng-class="{
'zbx-variable': ctrl.isVariable(ctrl.target.application.filter), 'zbx-variable': ctrl.isVariable(ctrl.target.application.filter),
'zbx-regex': ctrl.isRegex(ctrl.target.application.filter) 'zbx-regex': ctrl.isRegex(ctrl.target.application.filter)
}"> }">
</li> </div>
<!-- Select Item --> <!-- Select Item -->
<li class="tight-form-item query-keyword input-small" style="width: 3em">Item</li> <div class="gf-form">
<li> <label class="gf-form-label width-7">Item</label>
<input type="text" <input type="text"
ng-model="ctrl.target.item.filter" ng-model="ctrl.target.item.filter"
bs-typeahead="ctrl.getItemNames" bs-typeahead="ctrl.getItemNames"
ng-blur="ctrl.onTargetBlur()" ng-blur="ctrl.onTargetBlur()"
data-min-length=0 data-min-length=0
data-items=100 data-items=100
class="input-large tight-form-input" class="gf-form-input"
ng-class="{ ng-class="{
'zbx-variable': ctrl.isVariable(ctrl.target.item.filter), 'zbx-variable': ctrl.isVariable(ctrl.target.item.filter),
'zbx-regex': ctrl.isRegex(ctrl.target.item.filter) 'zbx-regex': ctrl.isRegex(ctrl.target.item.filter)
}"> }">
</li> </div>
<li class="tight-form-item last"> <div class="gf-form">
<a ng-click="ctrl.toggleQueryOptions()"> <label class="gf-form-label">Options</label>
<i class="fa fa-caret-down" ng-show="ctrl.showQueryOptions"></i> <div ng-repeat="func in ctrl.target.functions" class="gf-form-label query-part" metric-function-editor></div>
<i class="fa fa-caret-right" ng-hide="ctrl.showQueryOptions"></i> </div>
{{ctrl.queryOptionsText}} <div class="gf-form dropdown" add-metric-function>
</a> </div>
</li> <div class="gf-form gf-form--grow">
</ul> <div class="gf-form-label gf-form-label--grow"></div>
<div class="clearfix"></div>
</div>
<!-- Functions -->
<div class="tight-form" ng-show="!ctrl.target.mode">
<ul class="tight-form-list" role="menu">
<li class="tight-form-item query-keyword tight-form-align" style="width: 6em">Functions</li>
<li ng-repeat="func in ctrl.target.functions">
<span metric-function-editor class="tight-form-item tight-form-func"></span>
</li>
<li class="dropdown" add-metric-function></li>
</ul>
<div class="clearfix"></div>
</div>
<!-- Query options -->
<div class="tight-form" ng-if="ctrl.showQueryOptions">
<div class="tight-form-inner-box">
<div class="tight-form last">
<ul class="tight-form-list">
<li class="tight-form-item" style="width: 170px">
Show disabled items
</li>
<li class="tight-form-item last">
<editor-checkbox text=""
model="ctrl.target.options.showDisabledItems"
change="ctrl.onQueryOptionChange()">
</editor-checkbox>
</li>
</ul>
<div class="clearfix"></div>
</div> </div>
</div> </div>
</div>
<div class="tight-form" ng-show="ctrl.target.mode == 2">
<ul class="tight-form-list" role="menu">
<div class="gf-form-inline" ng-show="ctrl.target.mode == 2">
<!-- Text metric regex --> <!-- Text metric regex -->
<li class="tight-form-item query-keyword tight-form-align" style="width: 6em" ng-show="ctrl.target.mode == 2"> <div class="gf-form max-width-20">
Text filter <label class="gf-form-label width-7">Text filter</label>
</li>
<li ng-show="ctrl.target.mode == 2">
<input type="text" <input type="text"
class="tight-form-input" style="width: 417px" class="gf-form-input"
ng-model="ctrl.target.textFilter" ng-model="ctrl.target.textFilter"
spellcheck='false' spellcheck='false'
placeholder="Text filter (regex)" placeholder="Text filter (regex)"
ng-blur="ctrl.targetBlur()"> ng-blur="ctrl.onTargetBlur()">
</li> </div>
<li class="tight-form-item" ng-show="ctrl.target.mode == 2">
Use capture groups&nbsp;
<input class="cr1" id="ctrl.target.useCaptureGroups" type="checkbox"
ng-model="ctrl.target.useCaptureGroups"
ng-checked="ctrl.target.useCaptureGroups"
ng-change="ctrl.targetBlur()">
<label for="ctrl.target.useCaptureGroups" class="cr1"></label>
</li>
</ul>
<div class="clearfix"></div> <gf-form-switch class="gf-form" label="Use capture groups" checked="ctrl.target.useCaptureGroups" on-change="ctrl.onTargetBlur()">
</div> </gf-form-switch>
</div>
</query-editor-row>

View File

@@ -26,9 +26,9 @@ export class ZabbixQueryController extends QueryCtrl {
this.templateSrv = templateSrv; this.templateSrv = templateSrv;
this.editorModes = { this.editorModes = {
0: 'num', 0: {value: 'num', text: 'Numeric metrics', mode: 0},
1: 'itservice', 1: {value: 'itservice', text: 'IT Services', mode: 1},
2: 'text' 2: {value: 'text', text: 'Text metrics', mode: 2}
}; };
// Map functions for bs-typeahead // Map functions for bs-typeahead
@@ -63,8 +63,7 @@ export class ZabbixQueryController extends QueryCtrl {
functions: [], functions: [],
options: { options: {
showDisabledItems: false showDisabledItems: false
}, }
refId: "A"
}; };
_.defaults(target, targetDefaults); _.defaults(target, targetDefaults);
@@ -102,7 +101,7 @@ export class ZabbixQueryController extends QueryCtrl {
initFilters() { initFilters() {
var self = this; var self = this;
var itemtype = self.editorModes[self.target.mode]; var itemtype = self.editorModes[self.target.mode].value;
return this.$q.when(this.suggestGroups()) return this.$q.when(this.suggestGroups())
.then(() => {return self.suggestHosts();}) .then(() => {return self.suggestHosts();})
.then(() => {return self.suggestApps();}) .then(() => {return self.suggestApps();})