OpenTSDB: Alias patterns (reference tag values), syntax is: or [[tag_tagname]], Closes #1344, match opentsdb response to query, Fixes #1601

This commit is contained in:
Torkel Ödegaard 2015-03-25 12:27:33 +01:00
parent da833cbc58
commit e31a3a64e1
5 changed files with 69 additions and 27 deletions

View File

@ -20,6 +20,7 @@
- [Issue #599](https://github.com/grafana/grafana/issues/599). Graph: Added right y axis label setting and graph support
- [Issue #1253](https://github.com/grafana/grafana/issues/1253). Graph & Singlestat: Users can now set decimal precision for legend and tooltips (override auto precision)
- [Issue #1255](https://github.com/grafana/grafana/issues/1255). Templating: Dashboard will now wait to load until all template variables that have refresh on load set or are initialized via url to be fully loaded and so all variables are in valid state before panels start issuing metric requests.
- [Issue #1344](https://github.com/grafana/grafana/issues/1344). OpenTSDB: Alias patterns (reference tag values), syntax is: $tag_tagname or [[tag_tagname]]
**Fixes**
- [Issue #1298](https://github.com/grafana/grafana/issues/1298). InfluxDB: Fix handling of empty array in templating variable query

View File

@ -63,13 +63,18 @@ function (angular, _) {
});
};
this.replace = function(target) {
this.replace = function(target, scopedVars) {
if (!target) { return; }
var value;
this._regex.lastIndex = 0;
return target.replace(this._regex, function(match, g1, g2) {
if (scopedVars) {
value = scopedVars[g1 || g2];
if (value) { return value.value; }
}
value = self._values[g1 || g2];
if (!value) { return match; }
@ -77,7 +82,7 @@ function (angular, _) {
});
};
this.replaceWithText = function(target) {
this.replaceWithText = function(target, scopedVars) {
if (!target) { return; }
var value;
@ -85,6 +90,11 @@ function (angular, _) {
this._regex.lastIndex = 0;
return target.replace(this._regex, function(match, g1, g2) {
if (scopedVars) {
var option = scopedVars[g1 || g2];
if (option) { return option.text; }
}
value = self._values[g1 || g2];
text = self._texts[g1 || g2];
if (!value) { return match; }

View File

@ -46,13 +46,14 @@ function (angular, _, kbn) {
});
});
return this.performTimeSeriesQuery(queries, start, end)
.then(_.bind(function(response) {
var result = _.map(response.data, _.bind(function(metricData, index) {
return transformMetricData(metricData, groupByTags, this.targets[index]);
}, this));
return { data: result };
}, options));
return this.performTimeSeriesQuery(queries, start, end).then(function(response) {
var metricToTargetMapping = mapMetricsToTargets(response.data, options.targets);
var result = _.map(response.data, function(metricData, index) {
index = metricToTargetMapping[index];
return transformMetricData(metricData, groupByTags, options.targets[index]);
});
return { data: result };
});
};
OpenTSDBDatasource.prototype.performTimeSeriesQuery = function(queries, start, end) {
@ -90,19 +91,8 @@ function (angular, _, kbn) {
};
function transformMetricData(md, groupByTags, options) {
var dps = [],
tagData = [],
metricLabel = null;
if (!_.isEmpty(md.tags)) {
_.each(_.pairs(md.tags), function(tag) {
if (_.has(groupByTags, tag[0])) {
tagData.push(tag[0] + "=" + tag[1]);
}
});
}
metricLabel = createMetricLabel(md.metric, tagData, options);
var metricLabel = createMetricLabel(md, options, groupByTags);
var dps = [];
// TSDB returns datapoints has a hash of ts => value.
// Can't use _.pairs(invert()) because it stringifies keys/values
@ -113,16 +103,31 @@ function (angular, _, kbn) {
return { target: metricLabel, datapoints: dps };
}
function createMetricLabel(metric, tagData, options) {
function createMetricLabel(md, options, groupByTags) {
if (!_.isUndefined(options) && options.alias) {
return options.alias;
var scopedVars = {};
_.each(md.tags, function(value, key) {
scopedVars['tag_' + key] = {value: value};
});
return templateSrv.replace(options.alias, scopedVars);
}
var label = md.metric;
var tagData = [];
if (!_.isEmpty(md.tags)) {
_.each(_.pairs(md.tags), function(tag) {
if (_.has(groupByTags, tag[0])) {
tagData.push(tag[0] + "=" + tag[1]);
}
});
}
if (!_.isEmpty(tagData)) {
metric += "{" + tagData.join(", ") + "}";
label += "{" + tagData.join(", ") + "}";
}
return metric;
return label;
}
function convertTargetToQuery(target, interval) {
@ -174,6 +179,15 @@ function (angular, _, kbn) {
return query;
}
function mapMetricsToTargets(metrics, targets) {
return _.map(metrics, function(metricData) {
return _.findIndex(targets, function(target) {
return target.metric === metricData.metric &&
_.all(target.tags, function(tagV, tagK) { return metricData.tags[tagK] !== void 0; });
});
});
}
function convertToTSDBTime(date) {
if (date === 'now') {
return null;

View File

@ -81,10 +81,11 @@
<li class="tight-form-item">
Alias:
<tip>Use patterns like $tag_tagname to replace part of the alias for a tag value</tip>
</li>
<li>
<input type="text"
class="tight-form-input input-medium"
class="tight-form-input input-large"
ng-model="target.alias"
spellcheck='false'
placeholder="series alias"

View File

@ -29,6 +29,22 @@ define([
});
});
describe('replace can pass scoped vars', function() {
beforeEach(function() {
_templateSrv.init([{ name: 'test', current: { value: 'oogle' } }]);
});
it('should replace $test with scoped value', function() {
var target = _templateSrv.replace('this.$test.filters', {'test': {value: 'mupp', text: 'asd'}});
expect(target).to.be('this.mupp.filters');
});
it('should replace $test with scoped text', function() {
var target = _templateSrv.replaceWithText('this.$test.filters', {'test': {value: 'mupp', text: 'asd'}});
expect(target).to.be('this.asd.filters');
});
});
describe('can check if variable exists', function() {
beforeEach(function() {
_templateSrv.init([{ name: 'test', current: { value: 'oogle' } }]);