Commit e31a3a64 by Torkel Ödegaard

OpenTSDB: Alias patterns (reference tag values), syntax is: or [[tag_tagname]],…

OpenTSDB: Alias patterns (reference tag values), syntax is:  or [[tag_tagname]], Closes #1344, match opentsdb response to query, Fixes #1601
parent da833cbc
......@@ -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
......
......@@ -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; }
......
......@@ -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 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 };
}, options));
});
};
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;
......
......@@ -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"
......
......@@ -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' } }]);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment