mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
refactoring of graphite panel to be more datasource agnostic, start of experimental influxdb support
This commit is contained in:
parent
ed2770e380
commit
e3f56f2645
@ -69,8 +69,7 @@
|
|||||||
"nullPointMode": "connected",
|
"nullPointMode": "connected",
|
||||||
"steppedLine": false,
|
"steppedLine": false,
|
||||||
"tooltip": {
|
"tooltip": {
|
||||||
"value_type": "cumulative",
|
"value_type": "cumulative"
|
||||||
"query_as_alias": true
|
|
||||||
},
|
},
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
|
@ -289,7 +289,7 @@ function (angular, $, kbn, moment, _) {
|
|||||||
seriesInfo = item.series.info;
|
seriesInfo = item.series.info;
|
||||||
format = scope.panel.y_formats[seriesInfo.yaxis - 1];
|
format = scope.panel.y_formats[seriesInfo.yaxis - 1];
|
||||||
|
|
||||||
if (seriesInfo.alias || scope.panel.tooltip.query_as_alias) {
|
if (seriesInfo.alias) {
|
||||||
group = '<small style="font-size:0.9em;">' +
|
group = '<small style="font-size:0.9em;">' +
|
||||||
'<i class="icon-circle" style="color:'+item.series.color+';"></i>' + ' ' +
|
'<i class="icon-circle" style="color:'+item.series.color+';"></i>' + ' ' +
|
||||||
(seriesInfo.alias || seriesInfo.query)+
|
(seriesInfo.alias || seriesInfo.query)+
|
||||||
|
@ -88,8 +88,7 @@ function (angular, $) {
|
|||||||
var nameAsPath = name.replace(".", "/");
|
var nameAsPath = name.replace(".", "/");
|
||||||
$scope.require([
|
$scope.require([
|
||||||
'jquery',
|
'jquery',
|
||||||
'text!panels/'+nameAsPath+'/module.html',
|
'text!panels/'+nameAsPath+'/module.html'
|
||||||
'text!panels/'+nameAsPath+'/editor.html'
|
|
||||||
], function ($, moduleTemplate) {
|
], function ($, moduleTemplate) {
|
||||||
var $module = $(moduleTemplate);
|
var $module = $(moduleTemplate);
|
||||||
// top level controllers
|
// top level controllers
|
||||||
|
@ -27,27 +27,23 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="panel-full-edit-tabs" ng-if="editMode">
|
<div class="panel-full-edit-tabs" ng-if="editMode">
|
||||||
<div ng-model="editor.index" bs-tabs>
|
<div ng-model="editor.index" bs-tabs>
|
||||||
<div ng-repeat="tab in editorTabs" data-title="{{tab}}">
|
<div ng-repeat="tab in editorTabs" data-title="{{tab}}">
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- <div class="tab-content" ng-show="editorTabs[editor.index] == 'General'">
|
<div class="tab-content" ng-repeat="tab in panelMeta.fullEditorTabs" ng-show="editorTabs[editor.index] == tab.title">
|
||||||
<div ng-include src="'app/partials/panelgeneral.html'"></div>
|
<div ng-include src="tab.src"></div>
|
||||||
|
|
||||||
<div class="editor-row" ng-show="datasources.length > 0">
|
<div class="editor-row" ng-show="editor.index === 0">
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<div class="editor-option">
|
<h5>Datasource options</h5>
|
||||||
<label class="small">Datasource</label>
|
<div class="editor-option">
|
||||||
<select class="input-large" ng-options="obj.value as obj.name for obj in datasources" ng-model="panel.datasource" ng-change="datasourceChanged()"></select>
|
<label class="small">Datasource name</label>
|
||||||
</div>
|
<select class="input-large" ng-options="obj.value as obj.name for obj in datasources" ng-model="panel.datasource" ng-change="datasourceChanged()"></select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
-->
|
</div>
|
||||||
<div class="tab-content" ng-repeat="tab in panelMeta.editorTabs" ng-show="editorTabs[editor.index] == tab.title">
|
|
||||||
<div ng-include src="tab.src"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
@ -38,15 +38,15 @@ function (angular, app, $, _, kbn, moment, timeSeries) {
|
|||||||
|
|
||||||
$scope.panelMeta = {
|
$scope.panelMeta = {
|
||||||
modals : [],
|
modals : [],
|
||||||
|
editorTabs: [],
|
||||||
|
|
||||||
editorTabs : [
|
fullEditorTabs : [
|
||||||
{
|
{
|
||||||
title: 'General',
|
title: 'General',
|
||||||
src:'app/partials/panelgeneral.html'
|
src:'app/partials/panelgeneral.html'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title:'Targets',
|
title: 'Metrics',
|
||||||
src:'app/panels/graphite/editor.html'
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title:'Axes & Grid',
|
title:'Axes & Grid',
|
||||||
@ -80,7 +80,7 @@ function (angular, app, $, _, kbn, moment, timeSeries) {
|
|||||||
],
|
],
|
||||||
|
|
||||||
status : "Unstable",
|
status : "Unstable",
|
||||||
description : "Graphite graphing panel <br /><br />"
|
description : "Graphs panel"
|
||||||
};
|
};
|
||||||
|
|
||||||
// Set and populate defaults
|
// Set and populate defaults
|
||||||
@ -224,21 +224,18 @@ function (angular, app, $, _, kbn, moment, timeSeries) {
|
|||||||
$scope.fullscreen = false;
|
$scope.fullscreen = false;
|
||||||
$scope.options = false;
|
$scope.options = false;
|
||||||
$scope.editor = {index: 1};
|
$scope.editor = {index: 1};
|
||||||
$scope.editorTabs = _.pluck($scope.panelMeta.editorTabs,'title');
|
$scope.editorTabs = _.pluck($scope.panelMeta.fullEditorTabs,'title');
|
||||||
$scope.hiddenSeries = {};
|
$scope.hiddenSeries = {};
|
||||||
|
|
||||||
$scope.datasources = datasourceSrv.listOptions();
|
$scope.datasources = datasourceSrv.listOptions();
|
||||||
$scope.datasource = datasourceSrv.get($scope.panel.datasource);
|
$scope.datasourceChanged();
|
||||||
|
|
||||||
// Always show the query if an alias isn't set. Users can set an alias if the query is too
|
|
||||||
// long
|
|
||||||
$scope.panel.tooltip.query_as_alias = true;
|
|
||||||
|
|
||||||
$scope.get_data();
|
$scope.get_data();
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.datasourceChanged = function() {
|
$scope.datasourceChanged = function() {
|
||||||
$scope.datasource = datasourceSrv.get($scope.panel.datasource);
|
$scope.datasource = datasourceSrv.get($scope.panel.datasource);
|
||||||
|
$scope.panelMeta.fullEditorTabs[1].src = $scope.datasource.editorSrc;
|
||||||
$scope.get_data();
|
$scope.get_data();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
<div class="editor-row">
|
<div class="editor-row">
|
||||||
|
|
||||||
<div ng-repeat="target in panel.targets"
|
<div ng-repeat="target in panel.targets"
|
||||||
@ -75,7 +76,7 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li ng-repeat="func in functions">
|
<li ng-repeat="func in functions">
|
||||||
<a class="grafana-target-segment grafana-target-function dropdown-toggle" bs-popover="'app/panels/graphite/funcEditor.html'" data-placement="bottom">
|
<a class="grafana-target-segment grafana-target-function dropdown-toggle" bs-popover="'app/partials/graphite/funcEditor.html'" data-placement="bottom">
|
||||||
{{func.text}}
|
{{func.text}}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
1
src/app/partials/influxdb/editor.html
Normal file
1
src/app/partials/influxdb/editor.html
Normal file
@ -0,0 +1 @@
|
|||||||
|
<h5>InfluxDB<h5>
|
@ -1,6 +1,6 @@
|
|||||||
<div ng-include="'app/partials/panelgeneral.html'"></div>
|
<div ng-include="'app/partials/panelgeneral.html'"></div>
|
||||||
<div ng-include="edit_path(panel.type)"></div>
|
<div ng-if="!panelMeta.fullEditorTabs" ng-include="edit_path(panel.type)"></div>
|
||||||
<div ng-repeat="tab in panelMeta.editorTabs">
|
<div ng-repeat="tab in panelMeta.editorTabs">
|
||||||
<h5>{{tab.title}}</h5>
|
<h5>{{tab.title}}</h5>
|
||||||
<div ng-include="tab.src"></div>
|
<div ng-include="tab.src"></div>
|
||||||
</div>
|
</div>
|
@ -1,24 +1,20 @@
|
|||||||
<div class="editor-row">
|
<div class="editor-row">
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<strong>{{panelMeta.status}}</strong> // <span ng-bind-html="panelMeta.description"></span>
|
<h5>General options</h5>
|
||||||
|
<div class="editor-option">
|
||||||
|
<label class="small">Title</label><input type="text" class="input-medium" ng-model='panel.title'></input>
|
||||||
|
</div>
|
||||||
|
<div class="editor-option" ng-hide="panel.sizeable == false">
|
||||||
|
<label class="small">Span</label> <select class="input-mini" ng-model="panel.span" ng-options="f for f in [0,1,2,3,4,5,6,7,8,9,10,11,12]"></select>
|
||||||
|
</div>
|
||||||
|
<div class="editor-option">
|
||||||
|
<label class="small">Editable</label><input type="checkbox" ng-model="panel.editable" ng-checked="panel.editable">
|
||||||
|
</div>
|
||||||
|
<div class="editor-option" ng-show="!_.isUndefined(panel.spyable)">
|
||||||
|
<label class="small">
|
||||||
|
Inspect <i class="icon-question-sign" bs-tooltip="'Allow query reveal via <i class=icon-eye-open></i>'"></i>
|
||||||
|
</label>
|
||||||
|
<input type="checkbox" ng-model="panel.spyable" ng-checked="panel.spyable">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="editor-row">
|
</div>
|
||||||
<div class="section">
|
|
||||||
<div class="editor-option">
|
|
||||||
<label class="small">Title</label><input type="text" class="input-medium" ng-model='panel.title'></input>
|
|
||||||
</div>
|
|
||||||
<div class="editor-option" ng-hide="panel.sizeable == false">
|
|
||||||
<label class="small">Span</label> <select class="input-mini" ng-model="panel.span" ng-options="f for f in [0,1,2,3,4,5,6,7,8,9,10,11,12]"></select>
|
|
||||||
</div>
|
|
||||||
<div class="editor-option">
|
|
||||||
<label class="small">Editable</label><input type="checkbox" ng-model="panel.editable" ng-checked="panel.editable">
|
|
||||||
</div>
|
|
||||||
<div class="editor-option" ng-show="!_.isUndefined(panel.spyable)">
|
|
||||||
<label class="small">
|
|
||||||
Inspect <i class="icon-question-sign" bs-tooltip="'Allow query reveal via <i class=icon-eye-open></i>'"></i>
|
|
||||||
</label>
|
|
||||||
<input type="checkbox" ng-model="panel.spyable" ng-checked="panel.spyable">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
@ -7,6 +7,5 @@ define([
|
|||||||
'./datasourceSrv',
|
'./datasourceSrv',
|
||||||
'./keyboardManager',
|
'./keyboardManager',
|
||||||
'./annotationsSrv',
|
'./annotationsSrv',
|
||||||
'./graphite/graphiteDatasource',
|
|
||||||
],
|
],
|
||||||
function () {});
|
function () {});
|
@ -1,25 +1,32 @@
|
|||||||
define([
|
define([
|
||||||
'angular',
|
'angular',
|
||||||
'underscore',
|
'underscore',
|
||||||
'config'
|
'config',
|
||||||
|
'./graphite/graphiteDatasource',
|
||||||
|
'./influxdb/influxdbDatasource',
|
||||||
],
|
],
|
||||||
function (angular, _, config) {
|
function (angular, _, config) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var module = angular.module('kibana.services');
|
var module = angular.module('kibana.services');
|
||||||
|
|
||||||
module.service('datasourceSrv', function($q, filterSrv, $http, GraphiteDatasource) {
|
module.service('datasourceSrv', function($q, filterSrv, $http, GraphiteDatasource, InfluxDatasource) {
|
||||||
|
|
||||||
var defaultDatasource = _.findWhere(_.values(config.datasources), { default: true } );
|
var defaultDatasource = _.findWhere(_.values(config.datasources), { default: true } );
|
||||||
|
|
||||||
this.default = new GraphiteDatasource(defaultDatasource);
|
this.default = new GraphiteDatasource(defaultDatasource);
|
||||||
|
|
||||||
this.get = function(name) {
|
this.get = function(name) {
|
||||||
if (!name) {
|
if (!name) { return this.default; }
|
||||||
return this.default;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new GraphiteDatasource(config.datasources[name]);
|
var ds = config.datasources[name];
|
||||||
|
|
||||||
|
switch(ds.type) {
|
||||||
|
case 'graphite':
|
||||||
|
return new GraphiteDatasource(ds);
|
||||||
|
case 'influxdb':
|
||||||
|
return new InfluxDatasource(ds);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.listOptions = function() {
|
this.listOptions = function() {
|
||||||
|
@ -17,6 +17,7 @@ function (angular, _, $, config, kbn, moment) {
|
|||||||
this.type = 'graphite';
|
this.type = 'graphite';
|
||||||
this.basicAuth = datasource.basicAuth;
|
this.basicAuth = datasource.basicAuth;
|
||||||
this.url = datasource.url;
|
this.url = datasource.url;
|
||||||
|
this.editorSrc = 'app/partials/graphite/editor.html';
|
||||||
}
|
}
|
||||||
|
|
||||||
GraphiteDatasource.prototype.query = function(options) {
|
GraphiteDatasource.prototype.query = function(options) {
|
||||||
|
77
src/app/services/influxdb/influxdbDatasource.js
Normal file
77
src/app/services/influxdb/influxdbDatasource.js
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
define([
|
||||||
|
'angular',
|
||||||
|
'underscore',
|
||||||
|
],
|
||||||
|
function (angular, _) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var module = angular.module('kibana.services');
|
||||||
|
|
||||||
|
module.factory('InfluxDatasource', function($q, $http) {
|
||||||
|
|
||||||
|
function InfluxDatasource(datasource) {
|
||||||
|
this.type = 'influxDB';
|
||||||
|
this.editorSrc = 'app/partials/influxDB/editor.html';
|
||||||
|
this.url = datasource.url;
|
||||||
|
this.username = datasource.username;
|
||||||
|
this.password = datasource.password;
|
||||||
|
}
|
||||||
|
|
||||||
|
InfluxDatasource.prototype.query = function() {
|
||||||
|
|
||||||
|
var q = "select value from request_count where time > now() - 1h group by time(1m)";
|
||||||
|
|
||||||
|
var output = { data: [] };
|
||||||
|
|
||||||
|
return this.doInfluxRequest(q).then(function(results) {
|
||||||
|
|
||||||
|
_.each(results.data, function(series) {
|
||||||
|
var timeCol = series.columns.indexOf('time');
|
||||||
|
|
||||||
|
_.each(series.columns, function(column, index) {
|
||||||
|
if (column === "time" || column === "sequence_number") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("series:"+series.name + ": "+series.points.length + " points");
|
||||||
|
|
||||||
|
var target = series.name + "." + column;
|
||||||
|
var datapoints = [];
|
||||||
|
|
||||||
|
for(var i=0; i < series.points.length; i++) {
|
||||||
|
var t = Math.floor(series.points[i][timeCol] / 1000);
|
||||||
|
var v = series.points[i][index];
|
||||||
|
datapoints[i] = [v,t];
|
||||||
|
}
|
||||||
|
|
||||||
|
output.data.push({ target:target, datapoints:datapoints });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return output;
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
InfluxDatasource.prototype.doInfluxRequest = function(query) {
|
||||||
|
var params = {
|
||||||
|
u: this.username,
|
||||||
|
p: this.password,
|
||||||
|
q: query
|
||||||
|
};
|
||||||
|
|
||||||
|
var options = {
|
||||||
|
method: 'GET',
|
||||||
|
url: this.url + '/series',
|
||||||
|
params: params,
|
||||||
|
};
|
||||||
|
|
||||||
|
return $http(options);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
return InfluxDatasource;
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user