diff --git a/public/app/plugins/datasource/opentsdb/datasource.js b/public/app/plugins/datasource/opentsdb/datasource.js deleted file mode 100644 index 7315485c6db..00000000000 --- a/public/app/plugins/datasource/opentsdb/datasource.js +++ /dev/null @@ -1,476 +0,0 @@ -define([ - 'angular', - 'lodash', - 'app/core/utils/datemath', - 'moment', -], -function (angular, _, dateMath) { - 'use strict'; - - /** @ngInject */ - function OpenTsDatasource(instanceSettings, $q, backendSrv, templateSrv) { - this.type = 'opentsdb'; - this.url = instanceSettings.url; - this.name = instanceSettings.name; - this.withCredentials = instanceSettings.withCredentials; - this.basicAuth = instanceSettings.basicAuth; - instanceSettings.jsonData = instanceSettings.jsonData || {}; - this.tsdbVersion = instanceSettings.jsonData.tsdbVersion || 1; - this.tsdbResolution = instanceSettings.jsonData.tsdbResolution || 1; - this.supportMetrics = true; - this.tagKeys = {}; - - // Called once per panel (graph) - this.query = function(options) { - var start = convertToTSDBTime(options.rangeRaw.from, false); - var end = convertToTSDBTime(options.rangeRaw.to, true); - var qs = []; - - _.each(options.targets, function(target) { - if (!target.metric) { return; } - qs.push(convertTargetToQuery(target, options, this.tsdbVersion)); - }.bind(this)); - - var queries = _.compact(qs); - - // No valid targets, return the empty result to save a round trip. - if (_.isEmpty(queries)) { - var d = $q.defer(); - d.resolve({ data: [] }); - return d.promise; - } - - var groupByTags = {}; - _.each(queries, function(query) { - if (query.filters && query.filters.length > 0) { - _.each(query.filters, function(val) { - groupByTags[val.tagk] = true; - }); - } else { - _.each(query.tags, function(val, key) { - groupByTags[key] = true; - }); - } - }); - - options.targets = _.filter(options.targets, function(query) { - return query.hide !== true; - }); - - return this.performTimeSeriesQuery(queries, start, end).then(function(response) { - var metricToTargetMapping = mapMetricsToTargets(response.data, options, this.tsdbVersion); - var result = _.map(response.data, function(metricData, index) { - index = metricToTargetMapping[index]; - if (index === -1) { - index = 0; - } - this._saveTagKeys(metricData); - - return transformMetricData(metricData, groupByTags, options.targets[index], options, this.tsdbResolution); - }.bind(this)); - return { data: result }; - }.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 = { - text: annotation.description, - time: Math.floor(annotation.startTime) * 1000, - annotation: options.annotation - }; - - eventList.push(event); - }); - } - } - return eventList; - - }.bind(this)); - }; - - this.targetContainsTemplate = function(target) { - if (target.filters && target.filters.length > 0) { - for (var i = 0; i < target.filters.length; i++) { - if (templateSrv.variableExists(target.filters[i].filter)) { - return true; - } - } - } - - if (target.tags && Object.keys(target.tags).length > 0) { - for (var tagKey in target.tags) { - if (templateSrv.variableExists(target.tags[tagKey])) { - return true; - } - } - } - - return false; - }; - - this.performTimeSeriesQuery = function(queries, start, end) { - var msResolution = false; - if (this.tsdbResolution === 2) { - msResolution = true; - } - var reqBody = { - start: start, - queries: queries, - msResolution: msResolution, - globalAnnotations: true - }; - if (this.tsdbVersion === 3) { - reqBody.showQuery = true; - } - - // Relative queries (e.g. last hour) don't include an end time - if (end) { - reqBody.end = end; - } - - var options = { - method: 'POST', - url: this.url + '/api/query', - data: reqBody - }; - - this._addCredentialOptions(options); - return backendSrv.datasourceRequest(options); - }; - - this.suggestTagKeys = function(metric) { - return $q.when(this.tagKeys[metric] || []); - }; - - this._saveTagKeys = function(metricData) { - var tagKeys = Object.keys(metricData.tags); - _.each(metricData.aggregateTags, function(tag) { - tagKeys.push(tag); - }); - - this.tagKeys[metricData.metric] = tagKeys; - }; - - this._performSuggestQuery = function(query, type) { - return this._get('/api/suggest', {type: type, q: query, max: 1000}).then(function(result) { - return result.data; - }); - }; - - this._performMetricKeyValueLookup = function(metric, keys) { - - if(!metric || !keys) { - return $q.when([]); - } - - var keysArray = keys.split(",").map(function(key) { - return key.trim(); - }); - var key = keysArray[0]; - var keysQuery = key + "=*"; - - if (keysArray.length > 1) { - keysQuery += "," + keysArray.splice(1).join(","); - } - - var m = metric + "{" + keysQuery + "}"; - - return this._get('/api/search/lookup', {m: m, limit: 3000}).then(function(result) { - result = result.data.results; - var tagvs = []; - _.each(result, function(r) { - if (tagvs.indexOf(r.tags[key]) === -1) { - tagvs.push(r.tags[key]); - } - }); - return tagvs; - }); - }; - - this._performMetricKeyLookup = function(metric) { - if(!metric) { return $q.when([]); } - - return this._get('/api/search/lookup', {m: metric, limit: 1000}).then(function(result) { - result = result.data.results; - var tagks = []; - _.each(result, function(r) { - _.each(r.tags, function(tagv, tagk) { - if(tagks.indexOf(tagk) === -1) { - tagks.push(tagk); - } - }); - }); - return tagks; - }); - }; - - this._get = function(relativeUrl, params) { - var options = { - method: 'GET', - url: this.url + relativeUrl, - params: params, - }; - - this._addCredentialOptions(options); - - return backendSrv.datasourceRequest(options); - }; - - this._addCredentialOptions = function(options) { - if (this.basicAuth || this.withCredentials) { - options.withCredentials = true; - } - if (this.basicAuth) { - options.headers = {"Authorization": this.basicAuth}; - } - }; - - this.metricFindQuery = function(query) { - if (!query) { return $q.when([]); } - - var interpolated; - try { - interpolated = templateSrv.replace(query, {}, 'distributed'); - } - catch (err) { - return $q.reject(err); - } - - var responseTransform = function(result) { - return _.map(result, function(value) { - return {text: value}; - }); - }; - - var metrics_regex = /metrics\((.*)\)/; - var tag_names_regex = /tag_names\((.*)\)/; - var tag_values_regex = /tag_values\((.*?),\s?(.*)\)/; - var tag_names_suggest_regex = /suggest_tagk\((.*)\)/; - var tag_values_suggest_regex = /suggest_tagv\((.*)\)/; - - var metrics_query = interpolated.match(metrics_regex); - if (metrics_query) { - return this._performSuggestQuery(metrics_query[1], 'metrics').then(responseTransform); - } - - var tag_names_query = interpolated.match(tag_names_regex); - if (tag_names_query) { - return this._performMetricKeyLookup(tag_names_query[1]).then(responseTransform); - } - - var tag_values_query = interpolated.match(tag_values_regex); - if (tag_values_query) { - return this._performMetricKeyValueLookup(tag_values_query[1], tag_values_query[2]).then(responseTransform); - } - - var tag_names_suggest_query = interpolated.match(tag_names_suggest_regex); - if (tag_names_suggest_query) { - return this._performSuggestQuery(tag_names_suggest_query[1], 'tagk').then(responseTransform); - } - - var tag_values_suggest_query = interpolated.match(tag_values_suggest_regex); - if (tag_values_suggest_query) { - return this._performSuggestQuery(tag_values_suggest_query[1], 'tagv').then(responseTransform); - } - - return $q.when([]); - }; - - this.testDatasource = function() { - return this._performSuggestQuery('cpu', 'metrics').then(function () { - return { status: "success", message: "Data source is working" }; - }); - }; - - var aggregatorsPromise = null; - this.getAggregators = function() { - if (aggregatorsPromise) { return aggregatorsPromise; } - - aggregatorsPromise = this._get('/api/aggregators').then(function(result) { - if (result.data && _.isArray(result.data)) { - return result.data.sort(); - } - return []; - }); - return aggregatorsPromise; - }; - - var filterTypesPromise = null; - this.getFilterTypes = function() { - if (filterTypesPromise) { return filterTypesPromise; } - - filterTypesPromise = this._get('/api/config/filters').then(function(result) { - if (result.data) { - return Object.keys(result.data).sort(); - } - return []; - }); - return filterTypesPromise; - }; - - function transformMetricData(md, groupByTags, target, options, tsdbResolution) { - var metricLabel = createMetricLabel(md, target, groupByTags, options); - var dps = []; - - // TSDB returns datapoints has a hash of ts => value. - // Can't use _.pairs(invert()) because it stringifies keys/values - _.each(md.dps, function (v, k) { - if (tsdbResolution === 2) { - dps.push([v, k * 1]); - } else { - dps.push([v, k * 1000]); - } - }); - - return { target: metricLabel, datapoints: dps }; - } - - function createMetricLabel(md, target, groupByTags, options) { - if (target.alias) { - var scopedVars = _.clone(options.scopedVars || {}); - _.each(md.tags, function(value, key) { - scopedVars['tag_' + key] = {value: value}; - }); - return templateSrv.replace(target.alias, scopedVars); - } - - var label = md.metric; - var tagData = []; - - if (!_.isEmpty(md.tags)) { - _.each(_.toPairs(md.tags), function(tag) { - if (_.has(groupByTags, tag[0])) { - tagData.push(tag[0] + "=" + tag[1]); - } - }); - } - - if (!_.isEmpty(tagData)) { - label += "{" + tagData.join(", ") + "}"; - } - - return label; - } - - function convertTargetToQuery(target, options, tsdbVersion) { - if (!target.metric || target.hide) { - return null; - } - - var query = { - metric: templateSrv.replace(target.metric, options.scopedVars, 'pipe'), - aggregator: "avg" - }; - - if (target.aggregator) { - query.aggregator = templateSrv.replace(target.aggregator); - } - - if (target.shouldComputeRate) { - query.rate = true; - query.rateOptions = { - counter: !!target.isCounter - }; - - if (target.counterMax && target.counterMax.length) { - query.rateOptions.counterMax = parseInt(target.counterMax); - } - - if (target.counterResetValue && target.counterResetValue.length) { - query.rateOptions.resetValue = parseInt(target.counterResetValue); - } - - if(tsdbVersion >= 2) { - query.rateOptions.dropResets = !query.rateOptions.counterMax && - (!query.rateOptions.ResetValue || query.rateOptions.ResetValue === 0); - } - } - - if (!target.disableDownsampling) { - var interval = templateSrv.replace(target.downsampleInterval || options.interval); - - if (interval.match(/\.[0-9]+s/)) { - interval = parseFloat(interval)*1000 + "ms"; - } - - query.downsample = interval + "-" + target.downsampleAggregator; - - if (target.downsampleFillPolicy && target.downsampleFillPolicy !== "none") { - query.downsample += "-" + target.downsampleFillPolicy; - } - } - - if (target.filters && target.filters.length > 0) { - query.filters = angular.copy(target.filters); - if (query.filters){ - for (var filter_key in query.filters) { - query.filters[filter_key].filter = templateSrv.replace(query.filters[filter_key].filter, options.scopedVars, 'pipe'); - } - } - } else { - query.tags = angular.copy(target.tags); - if (query.tags){ - for (var tag_key in query.tags) { - query.tags[tag_key] = templateSrv.replace(query.tags[tag_key], options.scopedVars, 'pipe'); - } - } - } - - if (target.explicitTags) { - query.explicitTags = true; - } - - return query; - } - - function mapMetricsToTargets(metrics, options, tsdbVersion) { - var interpolatedTagValue, arrTagV; - return _.map(metrics, function(metricData) { - if (tsdbVersion === 3) { - return metricData.query.index; - } else { - return _.findIndex(options.targets, function(target) { - if (target.filters && target.filters.length > 0) { - return target.metric === metricData.metric; - } else { - return target.metric === metricData.metric && - _.every(target.tags, function(tagV, tagK) { - interpolatedTagValue = templateSrv.replace(tagV, options.scopedVars, 'pipe'); - arrTagV = interpolatedTagValue.split('|'); - return _.includes(arrTagV, metricData.tags[tagK]) || interpolatedTagValue === "*"; - }); - } - }); - } - }); - } - - function convertToTSDBTime(date, roundUp) { - if (date === 'now') { - return null; - } - - date = dateMath.parse(date, roundUp); - return date.valueOf(); - } - } - - return OpenTsDatasource; -}); diff --git a/public/app/plugins/datasource/opentsdb/datasource.ts b/public/app/plugins/datasource/opentsdb/datasource.ts new file mode 100644 index 00000000000..39ad6c64e11 --- /dev/null +++ b/public/app/plugins/datasource/opentsdb/datasource.ts @@ -0,0 +1,513 @@ +import angular from 'angular'; +import _ from 'lodash'; +import * as dateMath from 'app/core/utils/datemath'; + +export default class OpenTsDatasource { + type: any; + url: any; + name: any; + withCredentials: any; + basicAuth: any; + tsdbVersion: any; + tsdbResolution: any; + supportMetrics: any; + tagKeys: any; + + aggregatorsPromise: any; + filterTypesPromise: any; + + /** @ngInject */ + constructor(instanceSettings, private $q, private backendSrv, private templateSrv) { + this.type = 'opentsdb'; + this.url = instanceSettings.url; + this.name = instanceSettings.name; + this.withCredentials = instanceSettings.withCredentials; + this.basicAuth = instanceSettings.basicAuth; + instanceSettings.jsonData = instanceSettings.jsonData || {}; + this.tsdbVersion = instanceSettings.jsonData.tsdbVersion || 1; + this.tsdbResolution = instanceSettings.jsonData.tsdbResolution || 1; + this.supportMetrics = true; + this.tagKeys = {}; + + this.aggregatorsPromise = null; + this.filterTypesPromise = null; + } + + // Called once per panel (graph) + query(options) { + var start = this.convertToTSDBTime(options.rangeRaw.from, false); + var end = this.convertToTSDBTime(options.rangeRaw.to, true); + var qs = []; + + _.each( + options.targets, + function(target) { + if (!target.metric) { + return; + } + qs.push(this.convertTargetToQuery(target, options, this.tsdbVersion)); + }.bind(this) + ); + + var queries = _.compact(qs); + + // No valid targets, return the empty result to save a round trip. + if (_.isEmpty(queries)) { + var d = this.$q.defer(); + d.resolve({ data: [] }); + return d.promise; + } + + var groupByTags = {}; + _.each(queries, function(query) { + if (query.filters && query.filters.length > 0) { + _.each(query.filters, function(val) { + groupByTags[val.tagk] = true; + }); + } else { + _.each(query.tags, function(val, key) { + groupByTags[key] = true; + }); + } + }); + + options.targets = _.filter(options.targets, function(query) { + return query.hide !== true; + }); + + return this.performTimeSeriesQuery(queries, start, end).then( + function(response) { + var metricToTargetMapping = this.mapMetricsToTargets(response.data, options, this.tsdbVersion); + var result = _.map( + response.data, + function(metricData, index) { + index = metricToTargetMapping[index]; + if (index === -1) { + index = 0; + } + this._saveTagKeys(metricData); + + return this.transformMetricData( + metricData, + groupByTags, + options.targets[index], + options, + this.tsdbResolution + ); + }.bind(this) + ); + return { data: result }; + }.bind(this) + ); + } + + annotationQuery(options) { + var start = this.convertToTSDBTime(options.rangeRaw.from, false); + var end = this.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 = { + text: annotation.description, + time: Math.floor(annotation.startTime) * 1000, + annotation: options.annotation, + }; + + eventList.push(event); + }); + } + } + return eventList; + }.bind(this) + ); + } + + targetContainsTemplate(target) { + if (target.filters && target.filters.length > 0) { + for (var i = 0; i < target.filters.length; i++) { + if (this.templateSrv.variableExists(target.filters[i].filter)) { + return true; + } + } + } + + if (target.tags && Object.keys(target.tags).length > 0) { + for (var tagKey in target.tags) { + if (this.templateSrv.variableExists(target.tags[tagKey])) { + return true; + } + } + } + + return false; + } + + performTimeSeriesQuery(queries, start, end) { + var msResolution = false; + if (this.tsdbResolution === 2) { + msResolution = true; + } + var reqBody: any = { + start: start, + queries: queries, + msResolution: msResolution, + globalAnnotations: true, + }; + if (this.tsdbVersion === 3) { + reqBody.showQuery = true; + } + + // Relative queries (e.g. last hour) don't include an end time + if (end) { + reqBody.end = end; + } + + var options = { + method: 'POST', + url: this.url + '/api/query', + data: reqBody, + }; + + this._addCredentialOptions(options); + return this.backendSrv.datasourceRequest(options); + } + + suggestTagKeys(metric) { + return this.$q.when(this.tagKeys[metric] || []); + } + + _saveTagKeys(metricData) { + var tagKeys = Object.keys(metricData.tags); + _.each(metricData.aggregateTags, function(tag) { + tagKeys.push(tag); + }); + + this.tagKeys[metricData.metric] = tagKeys; + } + + _performSuggestQuery(query, type) { + return this._get('/api/suggest', { type: type, q: query, max: 1000 }).then(function(result) { + return result.data; + }); + } + + _performMetricKeyValueLookup(metric, keys) { + if (!metric || !keys) { + return this.$q.when([]); + } + + var keysArray = keys.split(',').map(function(key) { + return key.trim(); + }); + var key = keysArray[0]; + var keysQuery = key + '=*'; + + if (keysArray.length > 1) { + keysQuery += ',' + keysArray.splice(1).join(','); + } + + var m = metric + '{' + keysQuery + '}'; + + return this._get('/api/search/lookup', { m: m, limit: 3000 }).then(function(result) { + result = result.data.results; + var tagvs = []; + _.each(result, function(r) { + if (tagvs.indexOf(r.tags[key]) === -1) { + tagvs.push(r.tags[key]); + } + }); + return tagvs; + }); + } + + _performMetricKeyLookup(metric) { + if (!metric) { + return this.$q.when([]); + } + + return this._get('/api/search/lookup', { m: metric, limit: 1000 }).then(function(result) { + result = result.data.results; + var tagks = []; + _.each(result, function(r) { + _.each(r.tags, function(tagv, tagk) { + if (tagks.indexOf(tagk) === -1) { + tagks.push(tagk); + } + }); + }); + return tagks; + }); + } + + _get(relativeUrl, params?) { + var options = { + method: 'GET', + url: this.url + relativeUrl, + params: params, + }; + + this._addCredentialOptions(options); + + return this.backendSrv.datasourceRequest(options); + } + + _addCredentialOptions(options) { + if (this.basicAuth || this.withCredentials) { + options.withCredentials = true; + } + if (this.basicAuth) { + options.headers = { Authorization: this.basicAuth }; + } + } + + metricFindQuery(query) { + if (!query) { + return this.$q.when([]); + } + + var interpolated; + try { + interpolated = this.templateSrv.replace(query, {}, 'distributed'); + } catch (err) { + return this.$q.reject(err); + } + + var responseTransform = function(result) { + return _.map(result, function(value) { + return { text: value }; + }); + }; + + var metrics_regex = /metrics\((.*)\)/; + var tag_names_regex = /tag_names\((.*)\)/; + var tag_values_regex = /tag_values\((.*?),\s?(.*)\)/; + var tag_names_suggest_regex = /suggest_tagk\((.*)\)/; + var tag_values_suggest_regex = /suggest_tagv\((.*)\)/; + + var metrics_query = interpolated.match(metrics_regex); + if (metrics_query) { + return this._performSuggestQuery(metrics_query[1], 'metrics').then(responseTransform); + } + + var tag_names_query = interpolated.match(tag_names_regex); + if (tag_names_query) { + return this._performMetricKeyLookup(tag_names_query[1]).then(responseTransform); + } + + var tag_values_query = interpolated.match(tag_values_regex); + if (tag_values_query) { + return this._performMetricKeyValueLookup(tag_values_query[1], tag_values_query[2]).then(responseTransform); + } + + var tag_names_suggest_query = interpolated.match(tag_names_suggest_regex); + if (tag_names_suggest_query) { + return this._performSuggestQuery(tag_names_suggest_query[1], 'tagk').then(responseTransform); + } + + var tag_values_suggest_query = interpolated.match(tag_values_suggest_regex); + if (tag_values_suggest_query) { + return this._performSuggestQuery(tag_values_suggest_query[1], 'tagv').then(responseTransform); + } + + return this.$q.when([]); + } + + testDatasource() { + return this._performSuggestQuery('cpu', 'metrics').then(function() { + return { status: 'success', message: 'Data source is working' }; + }); + } + + getAggregators() { + if (this.aggregatorsPromise) { + return this.aggregatorsPromise; + } + + this.aggregatorsPromise = this._get('/api/aggregators').then(function(result) { + if (result.data && _.isArray(result.data)) { + return result.data.sort(); + } + return []; + }); + return this.aggregatorsPromise; + } + + getFilterTypes() { + if (this.filterTypesPromise) { + return this.filterTypesPromise; + } + + this.filterTypesPromise = this._get('/api/config/filters').then(function(result) { + if (result.data) { + return Object.keys(result.data).sort(); + } + return []; + }); + return this.filterTypesPromise; + } + + transformMetricData(md, groupByTags, target, options, tsdbResolution) { + var metricLabel = this.createMetricLabel(md, target, groupByTags, options); + var dps = []; + + // TSDB returns datapoints has a hash of ts => value. + // Can't use _.pairs(invert()) because it stringifies keys/values + _.each(md.dps, function(v, k) { + if (tsdbResolution === 2) { + dps.push([v, k * 1]); + } else { + dps.push([v, k * 1000]); + } + }); + + return { target: metricLabel, datapoints: dps }; + } + + createMetricLabel(md, target, groupByTags, options) { + if (target.alias) { + var scopedVars = _.clone(options.scopedVars || {}); + _.each(md.tags, function(value, key) { + scopedVars['tag_' + key] = { value: value }; + }); + return this.templateSrv.replace(target.alias, scopedVars); + } + + var label = md.metric; + var tagData = []; + + if (!_.isEmpty(md.tags)) { + _.each(_.toPairs(md.tags), function(tag) { + if (_.has(groupByTags, tag[0])) { + tagData.push(tag[0] + '=' + tag[1]); + } + }); + } + + if (!_.isEmpty(tagData)) { + label += '{' + tagData.join(', ') + '}'; + } + + return label; + } + + convertTargetToQuery(target, options, tsdbVersion) { + if (!target.metric || target.hide) { + return null; + } + + var query: any = { + metric: this.templateSrv.replace(target.metric, options.scopedVars, 'pipe'), + aggregator: 'avg', + }; + + if (target.aggregator) { + query.aggregator = this.templateSrv.replace(target.aggregator); + } + + if (target.shouldComputeRate) { + query.rate = true; + query.rateOptions = { + counter: !!target.isCounter, + }; + + if (target.counterMax && target.counterMax.length) { + query.rateOptions.counterMax = parseInt(target.counterMax); + } + + if (target.counterResetValue && target.counterResetValue.length) { + query.rateOptions.resetValue = parseInt(target.counterResetValue); + } + + if (tsdbVersion >= 2) { + query.rateOptions.dropResets = + !query.rateOptions.counterMax && (!query.rateOptions.ResetValue || query.rateOptions.ResetValue === 0); + } + } + + if (!target.disableDownsampling) { + var interval = this.templateSrv.replace(target.downsampleInterval || options.interval); + + if (interval.match(/\.[0-9]+s/)) { + interval = parseFloat(interval) * 1000 + 'ms'; + } + + query.downsample = interval + '-' + target.downsampleAggregator; + + if (target.downsampleFillPolicy && target.downsampleFillPolicy !== 'none') { + query.downsample += '-' + target.downsampleFillPolicy; + } + } + + if (target.filters && target.filters.length > 0) { + query.filters = angular.copy(target.filters); + if (query.filters) { + for (var filter_key in query.filters) { + query.filters[filter_key].filter = this.templateSrv.replace( + query.filters[filter_key].filter, + options.scopedVars, + 'pipe' + ); + } + } + } else { + query.tags = angular.copy(target.tags); + if (query.tags) { + for (var tag_key in query.tags) { + query.tags[tag_key] = this.templateSrv.replace(query.tags[tag_key], options.scopedVars, 'pipe'); + } + } + } + + if (target.explicitTags) { + query.explicitTags = true; + } + + return query; + } + + mapMetricsToTargets(metrics, options, tsdbVersion) { + var interpolatedTagValue, arrTagV; + return _.map(metrics, function(metricData) { + if (tsdbVersion === 3) { + return metricData.query.index; + } else { + return _.findIndex(options.targets, function(target) { + if (target.filters && target.filters.length > 0) { + return target.metric === metricData.metric; + } else { + return ( + target.metric === metricData.metric && + _.every(target.tags, function(tagV, tagK) { + interpolatedTagValue = this.templateSrv.replace(tagV, options.scopedVars, 'pipe'); + arrTagV = interpolatedTagValue.split('|'); + return _.includes(arrTagV, metricData.tags[tagK]) || interpolatedTagValue === '*'; + }) + ); + } + }); + } + }); + } + + convertToTSDBTime(date, roundUp) { + if (date === 'now') { + return null; + } + + date = dateMath.parse(date, roundUp); + return date.valueOf(); + } +}