mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Merge branch 'master' into dashboard-thing
This commit is contained in:
commit
d8b11adfd5
12
.github/ISSUE_TEMPLATE.md
vendored
Normal file
12
.github/ISSUE_TEMPLATE.md
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
Thank you! For helping us make Grafana even better.
|
||||
|
||||
To help us respond to your issues faster, please make sure to add as much information as possible.
|
||||
|
||||
If this issue is about a plugin, please open the issue in that repository.
|
||||
|
||||
Start your issues title with [Feature Request] / [Bug] / [Question] or no tag if your unsure.
|
||||
|
||||
Ex
|
||||
* What grafana version are you using?
|
||||
* What datasource are you using?
|
||||
* What OS are you running grafana on?
|
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
* Link the PR to an issue for new features
|
||||
* Rebase your PR if it gets out of sync with master
|
@ -25,6 +25,7 @@
|
||||
* **graph**: Template variables can now be used in TimeShift and TimeFrom, closes[#1960](https://github.com/grafana/grafana/issues/1960)
|
||||
* **Tooltip**: Optionally add milliseconds to timestamp in tool tip, closes[#2248](https://github.com/grafana/grafana/issues/2248)
|
||||
* **Opentsdb**: Support milliseconds when using openTSDB datasource, closes [#2865](https://github.com/grafana/grafana/issues/2865)
|
||||
* **Opentsdb**: Add support for annotations, closes[#664](https://github.com/grafana/grafana/issues/664)
|
||||
|
||||
### Bug fixes
|
||||
* **Playlist**: Fix for memory leak when running a playlist, closes [#3794](https://github.com/grafana/grafana/pull/3794)
|
||||
|
@ -8,7 +8,7 @@ page_keywords: grafana, plugins, documentation
|
||||
|
||||
# Datasources
|
||||
|
||||
Datasource plugins enables people to develop plugins for any database that commuicates over http. Its up to the plugin to transform the data into time series data so that any grafana panel can then show it.
|
||||
Datasource plugins enables people to develop plugins for any database that communicates over http. Its up to the plugin to transform the data into time series data so that any grafana panel can then show it.
|
||||
|
||||
To interact with the rest of grafana the plugins module file can export 5 different components.
|
||||
|
||||
@ -54,7 +54,7 @@ Request object passed to datasource.query function
|
||||
```
|
||||
|
||||
There are two different kind of results for datasources.
|
||||
Time series and table. Time series is the most common format and is suppoert by all datasources and panels. Table format is only support by the Influxdb datasource and table panel. But we might se more of this in the future.
|
||||
Time series and table. Time series is the most common format and is supported by all datasources and panels. Table format is only support by the Influxdb datasource and table panel. But we might see more of this in the future.
|
||||
|
||||
Time series response from datasource.query
|
||||
An array of
|
||||
|
@ -17,13 +17,13 @@ This class have to inherit from sdk.PanelCtrl or sdk.MetricsPanelCtrl and be exp
|
||||
};
|
||||
```
|
||||
|
||||
This class will be instancieted once for every panel of its kind in a dashboard and treated as an AngularJs controller.
|
||||
This class will be instantiated once for every panel of its kind in a dashboard and treated as an AngularJs controller.
|
||||
|
||||
## MetricsPanelCtrl or PanelCtrl
|
||||
|
||||
MetricsPanelCtrl inherits from PanelCtrl and adds some common features for datasource usage. So if your Panel will be working with a datasource you should inherit from MetricsPanelCtrl. If dont need to access any datasource then you should inherit from PanelCtrl instead.
|
||||
MetricsPanelCtrl inherits from PanelCtrl and adds some common features for datasource usage. So if your Panel will be working with a datasource you should inherit from MetricsPanelCtrl. If don't need to access any datasource then you should inherit from PanelCtrl instead.
|
||||
|
||||
## Implementing a MetricsPanelCtrl
|
||||
|
||||
If you choose to inherit from MetricsPanelCtrl you should implement a function called refreshData that will take an datasource as inparameter when its time to get new data. Its recommended that the refreshData function calls the issueQueries in the base class but its not mandatory. An examples of such implementation can be found in our [example panel](https://github.com/grafana/grafana/blob/master/examples/panel-boilerplate-es5/module.js#L27-L38)
|
||||
If you choose to inherit from MetricsPanelCtrl you should implement a function called refreshData that will take a datasource as in parameter when its time to get new data. Its recommended that the refreshData function calls the issueQueries in the base class but its not mandatory. An examples of such implementation can be found in our [example panel](https://github.com/grafana/grafana/blob/master/examples/panel-boilerplate-es5/module.js#L27-L38)
|
||||
|
||||
|
@ -34,6 +34,12 @@
|
||||
"updated": "2015-02-10"
|
||||
},
|
||||
|
||||
"includes": [
|
||||
{"type": "dashboard", "name": "Nginx Connection stats", "path": "dashboards/nginx_connection_stats.json"},
|
||||
{"type": "panel", "name": "Nginx Panel"},
|
||||
{"type": "datasource", "name": "Nginx Datasource"}
|
||||
],
|
||||
|
||||
"dependencies": {
|
||||
"grafanaVersion": "3.x.x",
|
||||
"plugins": [
|
||||
|
12
examples/nginx-app/src/datasource/datasource.js
Normal file
12
examples/nginx-app/src/datasource/datasource.js
Normal file
@ -0,0 +1,12 @@
|
||||
export default class NginxDatasource {
|
||||
|
||||
constructor() {}
|
||||
|
||||
query(options) {
|
||||
return [];
|
||||
}
|
||||
|
||||
testDatasource() {
|
||||
return false;
|
||||
}
|
||||
}
|
5
examples/nginx-app/src/datasource/module.js
Normal file
5
examples/nginx-app/src/datasource/module.js
Normal file
@ -0,0 +1,5 @@
|
||||
import {Datasource} from './datasource';
|
||||
|
||||
export {
|
||||
Datasource
|
||||
};
|
5
examples/nginx-app/src/datasource/plugin.json
Normal file
5
examples/nginx-app/src/datasource/plugin.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"type": "datasource",
|
||||
"name": "Nginx Datasource",
|
||||
"id": "nginx-datasource"
|
||||
}
|
@ -212,7 +212,7 @@ function (angular, $, _, moment) {
|
||||
var i, j, k;
|
||||
var oldVersion = this.schemaVersion;
|
||||
var panelUpgrades = [];
|
||||
this.schemaVersion = 10;
|
||||
this.schemaVersion = 11;
|
||||
|
||||
if (oldVersion === this.schemaVersion) {
|
||||
return;
|
||||
@ -401,6 +401,14 @@ function (angular, $, _, moment) {
|
||||
});
|
||||
}
|
||||
|
||||
if (oldVersion < 11) {
|
||||
// update template variables
|
||||
_.each(this.templating.list, function(templateVariable) {
|
||||
if (templateVariable.refresh) { templateVariable.refresh = 1; }
|
||||
if (!templateVariable.refresh) { templateVariable.refresh = 0; }
|
||||
});
|
||||
}
|
||||
|
||||
if (panelUpgrades.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
@ -54,11 +54,11 @@
|
||||
<div class="gf-form-group position-center">
|
||||
<div class="gf-form">
|
||||
<span class="gf-form-label width-5">Include</span>
|
||||
<editor-checkbox text="Current time range" model="options.forCurrent" change="updated()"></editor-checkbox>
|
||||
<editor-checkbox text="Current time range" model="options.forCurrent" change="buildUrl()"></editor-checkbox>
|
||||
</div>
|
||||
<div class="gf-form">
|
||||
<span class="gf-form-label width-5">Include</span>
|
||||
<editor-checkbox text="Template variables" model="options.includeTemplateVars" change="updated()"></editor-checkbox>
|
||||
<editor-checkbox text="Template variables" model="options.includeTemplateVars" change="buildUrl()"></editor-checkbox>
|
||||
</div>
|
||||
<div class="gf-form">
|
||||
<span class="gf-form-label width-5">Theme</span>
|
||||
|
@ -1,5 +1,4 @@
|
||||
define([
|
||||
'angular',
|
||||
define(['angular',
|
||||
'lodash',
|
||||
'require',
|
||||
'app/core/config',
|
||||
|
@ -1,5 +1,5 @@
|
||||
<navbar title="Plugins" title-url="plugins" icon="icon-gf icon-gf-apps">
|
||||
<a href="plugins" class="navbar-page-btn">
|
||||
<a href="plugins/{{ctrl.model.pluginId}}/edit" class="navbar-page-btn">
|
||||
{{ctrl.model.name}}
|
||||
</a>
|
||||
</navbar>
|
||||
|
@ -12,13 +12,19 @@ function (angular, _) {
|
||||
var replacementDefaults = {
|
||||
type: 'query',
|
||||
datasource: null,
|
||||
refresh: false,
|
||||
refresh: 0,
|
||||
name: '',
|
||||
options: [],
|
||||
includeAll: false,
|
||||
multi: false,
|
||||
};
|
||||
|
||||
$scope.refreshOptions = [
|
||||
{value: 0, text: "Never"},
|
||||
{value: 1, text: "On Dashboard Load"},
|
||||
{value: 2, text: "On Time Range Change"},
|
||||
];
|
||||
|
||||
$scope.init = function() {
|
||||
$scope.mode = 'list';
|
||||
|
||||
|
@ -170,9 +170,9 @@
|
||||
<input type="text" class="gf-form-input" ng-model='current.regex' placeholder="/.*-(.*)-.*/" ng-model-onblur ng-change="runQuery()"></input>
|
||||
</div>
|
||||
<div class="gf-form">
|
||||
<span class="gf-form-label width-7">Update</span>
|
||||
<editor-checkbox text="On Dashboard Load" model="current.refresh"></editor-checkbox>
|
||||
<tip>Check if you want values to be updated on dashboard load, will slow down dashboard load time</tip>
|
||||
<span class="gf-form-label width-7">Refresh</span>
|
||||
<select class="gf-form-input max-width-14" ng-model="current.refresh" ng-options="f.value as f.text for f in refreshOptions"></select>
|
||||
<tip>When to update the values of this variable, will slow down dashboard load / time change</tip>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -13,11 +13,25 @@ function (angular, _, kbn) {
|
||||
|
||||
function getNoneOption() { return { text: 'None', value: '', isNone: true }; }
|
||||
|
||||
$rootScope.onAppEvent('time-range-changed', function() {
|
||||
var variable = _.findWhere(self.variables, { type: 'interval' });
|
||||
if (variable) {
|
||||
self.updateAutoInterval(variable);
|
||||
// update time variant variables
|
||||
$rootScope.onAppEvent('refresh', function() {
|
||||
|
||||
// look for interval variables
|
||||
var intervalVariable = _.findWhere(self.variables, { type: 'interval' });
|
||||
if (intervalVariable) {
|
||||
self.updateAutoInterval(intervalVariable);
|
||||
}
|
||||
|
||||
// update variables with refresh === 2
|
||||
var promises = self.variables
|
||||
.filter(function(variable) {
|
||||
return variable.refresh === 2;
|
||||
}).map(function(variable) {
|
||||
return self.updateOptions(variable);
|
||||
});
|
||||
|
||||
return $q.all(promises);
|
||||
|
||||
}, $rootScope);
|
||||
|
||||
this.init = function(dashboard) {
|
||||
@ -60,7 +74,7 @@ function (angular, _, kbn) {
|
||||
if (urlValue !== void 0) {
|
||||
return self.setVariableFromUrl(variable, urlValue).then(lock.resolve);
|
||||
}
|
||||
else if (variable.refresh) {
|
||||
else if (variable.refresh === 'On Dashboard Load' || variable.refresh === 'On Time Change and Dashboard Load') {
|
||||
return self.updateOptions(variable).then(function() {
|
||||
if (_.isEmpty(variable.current) && variable.options.length) {
|
||||
console.log("setting current for %s", variable.name);
|
||||
|
@ -69,6 +69,40 @@ function (angular, _, dateMath) {
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
this.annotationQuery = function(options) {
|
||||
var start = convertToTSDBTime(options.rangeRaw.from, false);
|
||||
var end = convertToTSDBTime(options.rangeRaw.to, true);
|
||||
var qs = [];
|
||||
var eventList = [];
|
||||
|
||||
qs.push({ aggregator:"sum", metric:options.annotation.target });
|
||||
|
||||
var queries = _.compact(qs);
|
||||
|
||||
return this.performTimeSeriesQuery(queries, start, end).then(function(results) {
|
||||
if(results.data[0]) {
|
||||
var annotationObject = results.data[0].annotations;
|
||||
if(options.annotation.isGlobal){
|
||||
annotationObject = results.data[0].globalAnnotations;
|
||||
}
|
||||
if(annotationObject) {
|
||||
_.each(annotationObject, function(annotation) {
|
||||
var event = {
|
||||
title: annotation.description,
|
||||
time: Math.floor(annotation.startTime) * 1000,
|
||||
text: annotation.notes,
|
||||
annotation: options.annotation
|
||||
};
|
||||
|
||||
eventList.push(event);
|
||||
});
|
||||
}
|
||||
}
|
||||
return eventList;
|
||||
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
this.performTimeSeriesQuery = function(queries, start, end) {
|
||||
var msResolution = false;
|
||||
if (this.tsdbResolution === 2) {
|
||||
@ -77,7 +111,8 @@ function (angular, _, dateMath) {
|
||||
var reqBody = {
|
||||
start: start,
|
||||
queries: queries,
|
||||
msResolution: msResolution
|
||||
msResolution: msResolution,
|
||||
globalAnnotations: true
|
||||
};
|
||||
|
||||
// Relative queries (e.g. last hour) don't include an end time
|
||||
|
@ -2,9 +2,13 @@ import {OpenTsDatasource} from './datasource';
|
||||
import {OpenTsQueryCtrl} from './query_ctrl';
|
||||
import {OpenTsConfigCtrl} from './config_ctrl';
|
||||
|
||||
class AnnotationsQueryCtrl {
|
||||
static templateUrl = 'partials/annotations.editor.html';
|
||||
}
|
||||
|
||||
export {
|
||||
OpenTsDatasource as Datasource,
|
||||
OpenTsQueryCtrl as QueryCtrl,
|
||||
OpenTsConfigCtrl as ConfigCtrl,
|
||||
AnnotationsQueryCtrl as AnnotationsQueryCtrl
|
||||
};
|
||||
|
||||
|
@ -0,0 +1,10 @@
|
||||
<div class="gf-form-group">
|
||||
<div class="gf-form">
|
||||
<span class="gf-form-label width-13">OpenTSDB metrics query</span>
|
||||
<input type="text" class="gf-form-input" ng-model='ctrl.annotation.target' placeholder="events.eventname"></input>
|
||||
</div>
|
||||
<div class="gf-form">
|
||||
<span class="gf-form-label width-13">Show Global Annotations?</span>
|
||||
<editor-checkbox text="" model="ctrl.annotation.isGlobal"></editor-checkbox>
|
||||
</div>
|
||||
</div>
|
@ -4,5 +4,6 @@
|
||||
"id": "opentsdb",
|
||||
|
||||
"metrics": true,
|
||||
"defaultMatchFormat": "pipe"
|
||||
"defaultMatchFormat": "pipe",
|
||||
"annotations": true
|
||||
}
|
||||
|
@ -258,6 +258,6 @@
|
||||
"annotations": {
|
||||
"enable": false
|
||||
},
|
||||
"refresh": false,
|
||||
"refresh": "Never",
|
||||
"version": 6
|
||||
}
|
||||
|
@ -194,7 +194,7 @@ define([
|
||||
});
|
||||
|
||||
it('dashboard schema version should be set to latest', function() {
|
||||
expect(model.schemaVersion).to.be(10);
|
||||
expect(model.schemaVersion).to.be(11);
|
||||
});
|
||||
|
||||
});
|
||||
|
5394
public/vendor/moment.js
vendored
5394
public/vendor/moment.js
vendored
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user