diff --git a/public/app/core/core.ts b/public/app/core/core.ts index 0b120dd85b7..c216151f2dc 100644 --- a/public/app/core/core.ts +++ b/public/app/core/core.ts @@ -16,6 +16,8 @@ import "./directives/password_strenght"; import "./directives/spectrum_picker"; import "./directives/tags"; import "./directives/value_select_dropdown"; +import "./directives/plugin_directive_loader"; +import "./directives/rebuild_on_change"; import "./directives/give_focus"; import './jquery_extended'; import './partials'; diff --git a/public/app/core/directives/plugin_directive_loader.ts b/public/app/core/directives/plugin_directive_loader.ts new file mode 100644 index 00000000000..b6abb91b065 --- /dev/null +++ b/public/app/core/directives/plugin_directive_loader.ts @@ -0,0 +1,92 @@ +/// + +import angular from 'angular'; +import _ from 'lodash'; + +import coreModule from '../core_module'; + +function pluginDirectiveLoader($compile, datasourceSrv) { + + function getPluginComponentDirective(options) { + return function() { + return { + templateUrl: options.Component.templateUrl, + restrict: 'E', + controller: options.Component, + controllerAs: 'ctrl', + bindToController: true, + scope: options.bindings, + link: (scope, elem, attrs, ctrl) => { + if (ctrl.link) { + ctrl.link(scope, elem, attrs, ctrl); + } + } + }; + }; + } + + function getModule(scope, attrs) { + switch (attrs.type) { + case "metrics-query-editor": + let datasource = scope.target.datasource || scope.ctrl.panel.datasource; + return datasourceSrv.get(datasource).then(ds => { + if (!scope.target.refId) { + scope.target.refId = 'A'; + } + + return System.import(ds.meta.module).then(dsModule => { + return { + name: 'metrics-query-editor-' + ds.meta.id, + bindings: {target: "=", panelCtrl: "="}, + attrs: {"target": "target", "panel-ctrl": "ctrl"}, + Component: dsModule.MetricsQueryEditor + }; + }); + }); + case 'datasource-config-view': + return System.import(scope.datasourceMeta.module).then(function(dsModule) { + return { + name: 'ds-config-' + scope.datasourceMeta.id, + bindings: {meta: "=", current: "="}, + attrs: {meta: "datasourceMeta", current: "current"}, + Component: dsModule.ConfigView, + }; + }); + } + } + + function appendAndCompile(scope, elem, componentInfo) { + console.log('compile', elem, componentInfo); + var child = angular.element(document.createElement(componentInfo.name)); + _.each(componentInfo.attrs, (value, key) => { + child.attr(key, value); + }); + + $compile(child)(scope); + + elem.empty(); + elem.append(child); + } + + function registerPluginComponent(scope, elem, attrs, componentInfo) { + if (!componentInfo.Component.registered) { + var directiveName = attrs.$normalize(componentInfo.name); + var directiveFn = getPluginComponentDirective(componentInfo); + coreModule.directive(directiveName, directiveFn); + componentInfo.Component.registered = true; + } + + appendAndCompile(scope, elem, componentInfo); + } + + return { + restrict: 'E', + link: function(scope, elem, attrs) { + getModule(scope, attrs).then(function (componentInfo) { + registerPluginComponent(scope, elem, attrs, componentInfo); + }); + } + }; +} + +coreModule.directive('pluginDirectiveLoader', pluginDirectiveLoader); diff --git a/public/app/core/directives/rebuild_on_change.ts b/public/app/core/directives/rebuild_on_change.ts new file mode 100644 index 00000000000..3a9399c61ed --- /dev/null +++ b/public/app/core/directives/rebuild_on_change.ts @@ -0,0 +1,58 @@ +/// + +import angular from 'angular'; +import _ from 'lodash'; +import $ from 'jquery'; + +import coreModule from '../core_module'; + +function getBlockNodes(nodes) { + var node = nodes[0]; + var endNode = nodes[nodes.length - 1]; + var blockNodes; + + for (var i = 1; node !== endNode && (node = node.nextSibling); i++) { + if (blockNodes || nodes[i] !== node) { + if (!blockNodes) { + blockNodes = $([].slice.call(nodes, 0, i)); + } + blockNodes.push(node); + } + } + + return blockNodes || nodes; +} + +function rebuildOnChange($compile) { + + return { + transclude: true, + priority: 600, + restrict: 'A', + link: function(scope, elem, attrs, ctrl, transclude) { + var childScope, previousElements; + var uncompiledHtml; + + scope.$watch(attrs.rebuildOnChange, function rebuildOnChangeAction(value) { + + if (childScope) { + childScope.$destroy(); + childScope = null; + elem.empty(); + } + + if (value) { + if (!childScope) { + transclude(function(clone, newScope) { + childScope = newScope; + elem.append($compile(clone)(childScope)); + }); + } + } + + }); + } + }; +} + +coreModule.directive('rebuildOnChange', rebuildOnChange); diff --git a/public/app/features/datasources/partials/edit.html b/public/app/features/datasources/partials/edit.html index 3ebae573ebd..5b9facb83a8 100644 --- a/public/app/features/datasources/partials/edit.html +++ b/public/app/features/datasources/partials/edit.html @@ -41,7 +41,12 @@
- +
+ + +
+ +
Testing....
diff --git a/public/app/features/panel/panel_directive.ts b/public/app/features/panel/panel_directive.ts index ab3d6001e67..63484785d75 100644 --- a/public/app/features/panel/panel_directive.ts +++ b/public/app/features/panel/panel_directive.ts @@ -50,7 +50,7 @@ var module = angular.module('grafana.directives'); module.directive('grafanaPanel', function() { return { restrict: 'E', - templateUrl: 'app/features/panel/partials/panel.html', + templateUrl: 'public/app/features/panel/partials/panel.html', transclude: true, scope: { ctrl: "=" }, link: function(scope, elem) { diff --git a/public/app/features/panel/query_editor.ts b/public/app/features/panel/query_editor.ts index c456f42cc40..8e43019fdf3 100644 --- a/public/app/features/panel/query_editor.ts +++ b/public/app/features/panel/query_editor.ts @@ -5,105 +5,6 @@ import _ from 'lodash'; var directivesModule = angular.module('grafana.directives'); -function pluginDirectiveLoader($compile, datasourceSrv) { - - function getPluginComponentDirective(options) { - return function() { - return { - templateUrl: options.Component.templateUrl, - restrict: 'E', - controller: options.Component, - controllerAs: 'ctrl', - bindToController: true, - scope: options.bindings, - link: (scope, elem, attrs, ctrl) => { - if (ctrl.link) { - ctrl.link(scope, elem, attrs, ctrl); - } - } - }; - }; - } - - function getModule(scope, attrs) { - switch (attrs.type) { - case "metrics-query-editor": { - let datasource = scope.target.datasource || scope.ctrl.panel.datasource; - return datasourceSrv.get(datasource).then(ds => { - if (!scope.target.refId) { - scope.target.refId = 'A'; - } - - return System.import(ds.meta.module).then(dsModule => { - return { - name: 'metrics-query-editor-' + ds.meta.id, - bindings: {target: "=", panelCtrl: "="}, - attrs: {"target": "target", "panel-ctrl": "ctrl"}, - Component: dsModule.MetricsQueryEditor - }; - }); - }); - } - } - } - - function appendAndCompile(scope, elem, componentInfo) { - var child = angular.element(document.createElement(componentInfo.name)); - _.each(componentInfo.attrs, (value, key) => { - child.attr(key, value); - }); - - $compile(child)(scope); - - elem.empty(); - elem.append(child); - } - - function registerPluginComponent(scope, elem, attrs, componentInfo) { - if (!componentInfo.Component.registered) { - var directiveName = attrs.$normalize(componentInfo.name); - var directiveFn = getPluginComponentDirective(componentInfo); - directivesModule.directive(directiveName, directiveFn); - componentInfo.Component.registered = true; - } - - appendAndCompile(scope, elem, componentInfo); - } - - return { - restrict: 'E', - link: function(scope, elem, attrs) { - getModule(scope, attrs).then(function (componentInfo) { - registerPluginComponent(scope, elem, attrs, componentInfo); - }); - } - }; -} - -/** @ngInject */ -function metricsQueryEditor(dynamicDirectiveSrv, datasourceSrv) { - return dynamicDirectiveSrv.create({ - watchPath: "ctrl.panel.datasource", - directive: scope => { - let datasource = scope.target.datasource || scope.ctrl.panel.datasource; - return datasourceSrv.get(datasource).then(ds => { - scope.datasource = ds; - - if (!scope.target.refId) { - scope.target.refId = 'A'; - } - - return System.import(ds.meta.module).then(dsModule => { - return { - name: 'metrics-query-editor-' + ds.meta.id, - fn: dsModule.metricsQueryEditor, - }; - }); - }); - } - }); -} - /** @ngInject */ function metricsQueryOptions(dynamicDirectiveSrv, datasourceSrv) { return dynamicDirectiveSrv.create({ @@ -121,6 +22,4 @@ function metricsQueryOptions(dynamicDirectiveSrv, datasourceSrv) { }); } -directivesModule.directive('pluginDirectiveLoader', pluginDirectiveLoader); -directivesModule.directive('metricsQueryEditor', metricsQueryEditor); directivesModule.directive('metricsQueryOptions', metricsQueryOptions); diff --git a/public/app/plugins/datasource/graphite/module.js b/public/app/plugins/datasource/graphite/module.js index 64f0945aef3..a1d4ed5fc2b 100644 --- a/public/app/plugins/datasource/graphite/module.js +++ b/public/app/plugins/datasource/graphite/module.js @@ -23,11 +23,16 @@ function (GraphiteDatasource) { return {templateUrl: 'public/app/plugins/datasource/graphite/partials/config.html'}; } + function ConfigView() { + } + ConfigView.templateUrl = 'public/app/plugins/datasource/graphite/partials/config.html'; + return { Datasource: GraphiteDatasource, configView: configView, annotationsQueryEditor: annotationsQueryEditor, metricsQueryEditor: metricsQueryEditor, metricsQueryOptions: metricsQueryOptions, + ConfigView: ConfigView }; }); diff --git a/public/app/plugins/datasource/prometheus/datasource.d.ts b/public/app/plugins/datasource/prometheus/datasource.d.ts deleted file mode 100644 index a50d7ca49cc..00000000000 --- a/public/app/plugins/datasource/prometheus/datasource.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -declare var Datasource: any; -export default Datasource; - diff --git a/public/app/plugins/datasource/prometheus/datasource.js b/public/app/plugins/datasource/prometheus/datasource.js deleted file mode 100644 index 6b35a966e85..00000000000 --- a/public/app/plugins/datasource/prometheus/datasource.js +++ /dev/null @@ -1,282 +0,0 @@ -define([ - 'angular', - 'lodash', - 'moment', - 'app/core/utils/datemath', - './query_ctrl', -], -function (angular, _, moment, dateMath) { - 'use strict'; - - var durationSplitRegexp = /(\d+)(ms|s|m|h|d|w|M|y)/; - - /** @ngInject */ - function PrometheusDatasource(instanceSettings, $q, backendSrv, templateSrv) { - this.type = 'prometheus'; - this.editorSrc = 'app/features/prometheus/partials/query.editor.html'; - this.name = instanceSettings.name; - this.supportMetrics = true; - this.url = instanceSettings.url; - this.directUrl = instanceSettings.directUrl; - this.basicAuth = instanceSettings.basicAuth; - this.withCredentials = instanceSettings.withCredentials; - this.lastErrors = {}; - - this._request = function(method, url) { - var options = { - url: this.url + url, - method: method - }; - - if (this.basicAuth || this.withCredentials) { - options.withCredentials = true; - } - if (this.basicAuth) { - options.headers = { - "Authorization": this.basicAuth - }; - } - - return backendSrv.datasourceRequest(options); - }; - - // Called once per panel (graph) - this.query = function(options) { - var start = getPrometheusTime(options.range.from, false); - var end = getPrometheusTime(options.range.to, true); - - var queries = []; - options = _.clone(options); - _.each(options.targets, _.bind(function(target) { - if (!target.expr || target.hide) { - return; - } - - var query = {}; - query.expr = templateSrv.replace(target.expr, options.scopedVars); - - var interval = target.interval || options.interval; - var intervalFactor = target.intervalFactor || 1; - target.step = query.step = this.calculateInterval(interval, intervalFactor); - var range = Math.ceil(end - start); - // Prometheus drop query if range/step > 11000 - // calibrate step if it is too big - if (query.step !== 0 && range / query.step > 11000) { - target.step = query.step = Math.ceil(range / 11000); - } - - queries.push(query); - }, this)); - - // 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 allQueryPromise = _.map(queries, _.bind(function(query) { - return this.performTimeSeriesQuery(query, start, end); - }, this)); - - var self = this; - return $q.all(allQueryPromise) - .then(function(allResponse) { - var result = []; - - _.each(allResponse, function(response, index) { - if (response.status === 'error') { - self.lastErrors.query = response.error; - throw response.error; - } - delete self.lastErrors.query; - - _.each(response.data.data.result, function(metricData) { - result.push(transformMetricData(metricData, options.targets[index], start, end)); - }); - }); - - return { data: result }; - }); - }; - - this.performTimeSeriesQuery = function(query, start, end) { - var url = '/api/v1/query_range?query=' + encodeURIComponent(query.expr) + '&start=' + start + '&end=' + end + '&step=' + query.step; - return this._request('GET', url); - }; - - this.performSuggestQuery = function(query) { - var url = '/api/v1/label/__name__/values'; - - return this._request('GET', url).then(function(result) { - return _.filter(result.data.data, function (metricName) { - return metricName.indexOf(query) !== 1; - }); - }); - }; - - this.metricFindQuery = function(query) { - if (!query) { return $q.when([]); } - - var interpolated; - try { - interpolated = templateSrv.replace(query); - } - catch (err) { - return $q.reject(err); - } - - var label_values_regex = /^label_values\(([^,]+)(?:,\s*(.+))?\)$/; - var metric_names_regex = /^metrics\((.+)\)$/; - - var url; - var label_values_query = interpolated.match(label_values_regex); - if (label_values_query) { - if (!label_values_query[2]) { - // return label values globally - url = '/api/v1/label/' + label_values_query[1] + '/values'; - - return this._request('GET', url).then(function(result) { - return _.map(result.data.data, function(value) { - return {text: value}; - }); - }); - } else { - url = '/api/v1/series?match[]=' + encodeURIComponent(label_values_query[1]); - - return this._request('GET', url) - .then(function(result) { - return _.map(result.data.data, function(metric) { - return { - text: metric[label_values_query[2]], - expandable: true - }; - }); - }); - } - } - - var metric_names_query = interpolated.match(metric_names_regex); - if (metric_names_query) { - url = '/api/v1/label/__name__/values'; - - return this._request('GET', url) - .then(function(result) { - return _.chain(result.data.data) - .filter(function(metricName) { - var r = new RegExp(metric_names_query[1]); - return r.test(metricName); - }) - .map(function(matchedMetricName) { - return { - text: matchedMetricName, - expandable: true - }; - }) - .value(); - }); - } else { - // if query contains full metric name, return metric name and label list - url = '/api/v1/series?match[]=' + encodeURIComponent(interpolated); - - return this._request('GET', url) - .then(function(result) { - return _.map(result.data.data, function(metric) { - return { - text: getOriginalMetricName(metric), - expandable: true - }; - }); - }); - } - }; - - this.testDatasource = function() { - return this.metricFindQuery('metrics(.*)').then(function() { - return { status: 'success', message: 'Data source is working', title: 'Success' }; - }); - }; - - PrometheusDatasource.prototype.calculateInterval = function(interval, intervalFactor) { - var m = interval.match(durationSplitRegexp); - var dur = moment.duration(parseInt(m[1]), m[2]); - var sec = dur.asSeconds(); - if (sec < 1) { - sec = 1; - } - - return Math.ceil(sec * intervalFactor); - }; - - function transformMetricData(md, options, start, end) { - var dps = [], - metricLabel = null; - - metricLabel = createMetricLabel(md.metric, options); - - var stepMs = parseInt(options.step) * 1000; - var baseTimestamp = start * 1000; - _.each(md.values, function(value) { - var dp_value = parseFloat(value[1]); - if (_.isNaN(dp_value)) { - dp_value = null; - } - - var timestamp = value[0] * 1000; - for (var t = baseTimestamp; t < timestamp; t += stepMs) { - dps.push([null, t]); - } - baseTimestamp = timestamp + stepMs; - dps.push([dp_value, timestamp]); - }); - - var endTimestamp = end * 1000; - for (var t = baseTimestamp; t <= endTimestamp; t += stepMs) { - dps.push([null, t]); - } - - return { target: metricLabel, datapoints: dps }; - } - - function createMetricLabel(labelData, options) { - if (_.isUndefined(options) || _.isEmpty(options.legendFormat)) { - return getOriginalMetricName(labelData); - } - - var originalSettings = _.templateSettings; - _.templateSettings = { - interpolate: /\{\{(.+?)\}\}/g - }; - - var template = _.template(templateSrv.replace(options.legendFormat)); - var metricName; - try { - metricName = template(labelData); - } catch (e) { - metricName = '{}'; - } - - _.templateSettings = originalSettings; - - return metricName; - } - - function getOriginalMetricName(labelData) { - var metricName = labelData.__name__ || ''; - delete labelData.__name__; - var labelPart = _.map(_.pairs(labelData), function(label) { - return label[0] + '="' + label[1] + '"'; - }).join(','); - return metricName + '{' + labelPart + '}'; - } - - function getPrometheusTime(date, roundUp) { - if (_.isString(date)) { - date = dateMath.parse(date, roundUp); - } - return (date.valueOf() / 1000).toFixed(0); - } - } - - return PrometheusDatasource; -}); diff --git a/public/app/plugins/datasource/prometheus/datasource.ts b/public/app/plugins/datasource/prometheus/datasource.ts new file mode 100644 index 00000000000..9b754b58eb3 --- /dev/null +++ b/public/app/plugins/datasource/prometheus/datasource.ts @@ -0,0 +1,278 @@ +/// + +import angular from 'angular'; +import _ from 'lodash'; +import moment from 'moment'; + +import * as dateMath from 'app/core/utils/datemath'; + +var durationSplitRegexp = /(\d+)(ms|s|m|h|d|w|M|y)/; + +/** @ngInject */ +function PrometheusDatasource(instanceSettings, $q, backendSrv, templateSrv) { + this.type = 'prometheus'; + this.editorSrc = 'app/features/prometheus/partials/query.editor.html'; + this.name = instanceSettings.name; + this.supportMetrics = true; + this.url = instanceSettings.url; + this.directUrl = instanceSettings.directUrl; + this.basicAuth = instanceSettings.basicAuth; + this.withCredentials = instanceSettings.withCredentials; + this.lastErrors = {}; + + this._request = function(method, url) { + var options: any = { + url: this.url + url, + method: method + }; + + if (this.basicAuth || this.withCredentials) { + options.withCredentials = true; + } + if (this.basicAuth) { + options.headers = { + "Authorization": this.basicAuth + }; + } + + return backendSrv.datasourceRequest(options); + }; + + // Called once per panel (graph) + this.query = function(options) { + var start = getPrometheusTime(options.range.from, false); + var end = getPrometheusTime(options.range.to, true); + + var queries = []; + options = _.clone(options); + _.each(options.targets, _.bind(function(target) { + if (!target.expr || target.hide) { + return; + } + + var query: any = {}; + query.expr = templateSrv.replace(target.expr, options.scopedVars); + + var interval = target.interval || options.interval; + var intervalFactor = target.intervalFactor || 1; + target.step = query.step = this.calculateInterval(interval, intervalFactor); + var range = Math.ceil(end - start); + // Prometheus drop query if range/step > 11000 + // calibrate step if it is too big + if (query.step !== 0 && range / query.step > 11000) { + target.step = query.step = Math.ceil(range / 11000); + } + + queries.push(query); + }, this)); + + // 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 allQueryPromise = _.map(queries, _.bind(function(query) { + return this.performTimeSeriesQuery(query, start, end); + }, this)); + + var self = this; + return $q.all(allQueryPromise) + .then(function(allResponse) { + var result = []; + + _.each(allResponse, function(response, index) { + if (response.status === 'error') { + self.lastErrors.query = response.error; + throw response.error; + } + delete self.lastErrors.query; + + _.each(response.data.data.result, function(metricData) { + result.push(transformMetricData(metricData, options.targets[index], start, end)); + }); + }); + + return { data: result }; + }); + }; + + this.performTimeSeriesQuery = function(query, start, end) { + var url = '/api/v1/query_range?query=' + encodeURIComponent(query.expr) + '&start=' + start + '&end=' + end + '&step=' + query.step; + return this._request('GET', url); + }; + + this.performSuggestQuery = function(query) { + var url = '/api/v1/label/__name__/values'; + + return this._request('GET', url).then(function(result) { + return _.filter(result.data.data, function (metricName) { + return metricName.indexOf(query) !== 1; + }); + }); + }; + + this.metricFindQuery = function(query) { + if (!query) { return $q.when([]); } + + var interpolated; + try { + interpolated = templateSrv.replace(query); + } catch (err) { + return $q.reject(err); + } + + var label_values_regex = /^label_values\(([^,]+)(?:,\s*(.+))?\)$/; + var metric_names_regex = /^metrics\((.+)\)$/; + + var url; + var label_values_query = interpolated.match(label_values_regex); + if (label_values_query) { + if (!label_values_query[2]) { + // return label values globally + url = '/api/v1/label/' + label_values_query[1] + '/values'; + + return this._request('GET', url).then(function(result) { + return _.map(result.data.data, function(value) { + return {text: value}; + }); + }); + } else { + url = '/api/v1/series?match[]=' + encodeURIComponent(label_values_query[1]); + + return this._request('GET', url) + .then(function(result) { + return _.map(result.data.data, function(metric) { + return { + text: metric[label_values_query[2]], + expandable: true + }; + }); + }); + } + } + + var metric_names_query = interpolated.match(metric_names_regex); + if (metric_names_query) { + url = '/api/v1/label/__name__/values'; + + return this._request('GET', url) + .then(function(result) { + return _.chain(result.data.data) + .filter(function(metricName) { + var r = new RegExp(metric_names_query[1]); + return r.test(metricName); + }) + .map(function(matchedMetricName) { + return { + text: matchedMetricName, + expandable: true + }; + }) + .value(); + }); + } else { + // if query contains full metric name, return metric name and label list + url = '/api/v1/series?match[]=' + encodeURIComponent(interpolated); + + return this._request('GET', url) + .then(function(result) { + return _.map(result.data.data, function(metric) { + return { + text: getOriginalMetricName(metric), + expandable: true + }; + }); + }); + } + }; + + this.testDatasource = function() { + return this.metricFindQuery('metrics(.*)').then(function() { + return { status: 'success', message: 'Data source is working', title: 'Success' }; + }); + }; + + PrometheusDatasource.prototype.calculateInterval = function(interval, intervalFactor) { + var m = interval.match(durationSplitRegexp); + var dur = moment.duration(parseInt(m[1]), m[2]); + var sec = dur.asSeconds(); + if (sec < 1) { + sec = 1; + } + + return Math.ceil(sec * intervalFactor); + }; + + function transformMetricData(md, options, start, end) { + var dps = [], + metricLabel = null; + + metricLabel = createMetricLabel(md.metric, options); + + var stepMs = parseInt(options.step) * 1000; + var baseTimestamp = start * 1000; + _.each(md.values, function(value) { + var dp_value = parseFloat(value[1]); + if (_.isNaN(dp_value)) { + dp_value = null; + } + + var timestamp = value[0] * 1000; + for (var t = baseTimestamp; t < timestamp; t += stepMs) { + dps.push([null, t]); + } + baseTimestamp = timestamp + stepMs; + dps.push([dp_value, timestamp]); + }); + + var endTimestamp = end * 1000; + for (var t = baseTimestamp; t <= endTimestamp; t += stepMs) { + dps.push([null, t]); + } + + return { target: metricLabel, datapoints: dps }; + } + + function createMetricLabel(labelData, options) { + if (_.isUndefined(options) || _.isEmpty(options.legendFormat)) { + return getOriginalMetricName(labelData); + } + + var originalSettings = _.templateSettings; + _.templateSettings = { + interpolate: /\{\{(.+?)\}\}/g + }; + + var template = _.template(templateSrv.replace(options.legendFormat)); + var metricName; + try { + metricName = template(labelData); + } catch (e) { + metricName = '{}'; + } + + _.templateSettings = originalSettings; + + return metricName; + } + + function getOriginalMetricName(labelData) { + var metricName = labelData.__name__ || ''; + delete labelData.__name__; + var labelPart = _.map(_.pairs(labelData), function(label) { + return label[0] + '="' + label[1] + '"'; + }).join(','); + return metricName + '{' + labelPart + '}'; + } + + function getPrometheusTime(date, roundUp): number { + if (_.isString(date)) { + date = dateMath.parse(date, roundUp); + } + return Math.floor(date.valueOf() / 1000); + } +} + +export {PrometheusDatasource}; diff --git a/public/app/plugins/datasource/prometheus/module.js b/public/app/plugins/datasource/prometheus/module.js deleted file mode 100644 index 042224c2e38..00000000000 --- a/public/app/plugins/datasource/prometheus/module.js +++ /dev/null @@ -1,20 +0,0 @@ -define([ - './datasource', -], -function (PromDatasource) { - 'use strict'; - - function metricsQueryEditor() { - return {controller: 'PrometheusQueryCtrl', templateUrl: 'public/app/plugins/datasource/prometheus/partials/query.editor.html'}; - } - - function configView() { - return {templateUrl: 'public/app/plugins/datasource/prometheus/partials/config.html'}; - } - - return { - Datasource: PromDatasource, - metricsQueryEditor: metricsQueryEditor, - configView: configView, - }; -}); diff --git a/public/app/plugins/datasource/prometheus/module.ts b/public/app/plugins/datasource/prometheus/module.ts new file mode 100644 index 00000000000..b04bd10004d --- /dev/null +++ b/public/app/plugins/datasource/prometheus/module.ts @@ -0,0 +1,23 @@ +import {PrometheusDatasource} from './datasource'; +import {PrometheusQueryCtrl} from './query_ctrl'; + + + + + // function metricsQueryEditor() { + // return {controller: 'PrometheusQueryCtrl', templateUrl: 'public/app/plugins/datasource/prometheus/partials/query.editor.html'}; + // } + // + // function configView() { + // return {templateUrl: ''}; + // } + +class PrometheusConfigViewCtrl { + static templateUrl = 'public/app/plugins/datasource/prometheus/partials/config.html'; +} + +export { + PrometheusDatasource as Datasource, + PrometheusQueryCtrl as MetricsQueryEditor, + PrometheusConfigViewCtrl as ConfigView +}; diff --git a/public/app/plugins/datasource/prometheus/query_ctrl.js b/public/app/plugins/datasource/prometheus/query_ctrl.js deleted file mode 100644 index b78152c62d0..00000000000 --- a/public/app/plugins/datasource/prometheus/query_ctrl.js +++ /dev/null @@ -1,67 +0,0 @@ -define([ - 'angular', - 'lodash', -], -function (angular, _) { - 'use strict'; - - var module = angular.module('grafana.controllers'); - - module.controller('PrometheusQueryCtrl', function($scope, templateSrv) { - $scope.panelCtrl = $scope.ctrl; - $scope.panel = $scope.panelCtrl.panel; - - $scope.init = function() { - var target = $scope.target; - - target.expr = target.expr || ''; - target.intervalFactor = target.intervalFactor || 2; - - $scope.metric = ''; - $scope.resolutions = _.map([1,2,3,4,5,10], function(f) { - return {factor: f, label: '1/' + f}; - }); - - $scope.$on('typeahead-updated', function() { - $scope.$apply($scope.inputMetric); - $scope.refreshMetricData(); - }); - }; - - $scope.refreshMetricData = function() { - if (!_.isEqual($scope.oldTarget, $scope.target)) { - $scope.oldTarget = angular.copy($scope.target); - $scope.paneCtrl.refresh(); - } - }; - - $scope.inputMetric = function() { - $scope.target.expr += $scope.target.metric; - $scope.metric = ''; - }; - - $scope.suggestMetrics = function(query, callback) { - $scope.datasource - .performSuggestQuery(query) - .then(callback); - }; - - $scope.linkToPrometheus = function() { - var range = Math.ceil(($scope.range.to.valueOf() - $scope.range.from.valueOf()) / 1000); - var endTime = $scope.range.to.utc().format('YYYY-MM-DD HH:mm'); - var expr = { - expr: templateSrv.replace($scope.target.expr, $scope.panel.scopedVars), - range_input: range + 's', - end_input: endTime, - step_input: '', - stacked: $scope.panel.stack, - tab: 0 - }; - var hash = encodeURIComponent(JSON.stringify([expr])); - return $scope.datasource.directUrl + '/graph#' + hash; - }; - - $scope.init(); - }); - -}); diff --git a/public/app/plugins/datasource/prometheus/query_ctrl.ts b/public/app/plugins/datasource/prometheus/query_ctrl.ts new file mode 100644 index 00000000000..e0fd9aea02d --- /dev/null +++ b/public/app/plugins/datasource/prometheus/query_ctrl.ts @@ -0,0 +1,66 @@ +/// + +import angular from 'angular'; +import _ from 'lodash'; +import moment from 'moment'; + +import * as dateMath from 'app/core/utils/datemath'; + +function PrometheusQueryCtrl($scope, templateSrv) { + $scope.panelCtrl = $scope.ctrl; + $scope.panel = $scope.panelCtrl.panel; + + $scope.init = function() { + var target = $scope.target; + + target.expr = target.expr || ''; + target.intervalFactor = target.intervalFactor || 2; + + $scope.metric = ''; + $scope.resolutions = _.map([1,2,3,4,5,10], function(f) { + return {factor: f, label: '1/' + f}; + }); + + $scope.$on('typeahead-updated', function() { + $scope.$apply($scope.inputMetric); + $scope.refreshMetricData(); + }); + }; + + $scope.refreshMetricData = function() { + if (!_.isEqual($scope.oldTarget, $scope.target)) { + $scope.oldTarget = angular.copy($scope.target); + $scope.paneCtrl.refresh(); + } + }; + + $scope.inputMetric = function() { + $scope.target.expr += $scope.target.metric; + $scope.metric = ''; + }; + + $scope.suggestMetrics = function(query, callback) { + $scope.datasource + .performSuggestQuery(query) + .then(callback); + }; + + $scope.linkToPrometheus = function() { + var range = Math.ceil(($scope.range.to.valueOf() - $scope.range.from.valueOf()) / 1000); + var endTime = $scope.range.to.utc().format('YYYY-MM-DD HH:mm'); + var expr = { + expr: templateSrv.replace($scope.target.expr, $scope.panel.scopedVars), + range_input: range + 's', + end_input: endTime, + step_input: '', + stacked: $scope.panel.stack, + tab: 0 + }; + var hash = encodeURIComponent(JSON.stringify([expr])); + return $scope.datasource.directUrl + '/graph#' + hash; + }; + + $scope.init(); +} + +export {PrometheusQueryCtrl}; diff --git a/public/views/index.html b/public/views/index.html index 728cd084c88..1d612e53385 100644 --- a/public/views/index.html +++ b/public/views/index.html @@ -59,7 +59,6 @@ -