feat: initial commit

This commit is contained in:
Thom Lamb
2026-06-23 11:18:54 -05:00
parent fc3ce9a074
commit 1bb980f070
790 changed files with 149255 additions and 218 deletions
@@ -0,0 +1,115 @@
'use strict';
var _angular = require('angular');
var _angular2 = _interopRequireDefault(_angular);
var _lodash = require('lodash');
var _lodash2 = _interopRequireDefault(_lodash);
var _jquery = require('jquery');
var _jquery2 = _interopRequireDefault(_jquery);
var _dfunc = require('./dfunc');
var _dfunc2 = _interopRequireDefault(_dfunc);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
_angular2.default.module('grafana.directives').directive('datadogAddFunc', function ($compile) {
var inputTemplate = '<input type="text"' + ' class="gf-form-input"' + ' spellcheck="false" style="display:none"></input>';
var buttonTemplate = '<a class="gf-form-label query-part dropdown-toggle"' + ' tabindex="1" gf-dropdown="functionMenu" data-toggle="dropdown">' + '<i class="fa fa-plus"></i></a>';
return {
link: function link($scope, elem) {
var categories = _dfunc2.default.getCategories();
var allFunctions = getAllFunctionNames(categories);
var ctrl = $scope.ctrl;
$scope.functionMenu = createFunctionDropDownMenu(categories);
var $input = (0, _jquery2.default)(inputTemplate);
var $button = (0, _jquery2.default)(buttonTemplate);
$input.appendTo(elem);
$button.appendTo(elem);
$input.attr('data-provide', 'typeahead');
$input.typeahead({
source: allFunctions,
minLength: 1,
items: 10,
updater: function updater(value) {
var funcDef = _dfunc2.default.getFuncDef(value);
if (!funcDef) {
// try find close match
value = value.toLowerCase();
funcDef = _lodash2.default.find(allFunctions, function (funcName) {
return funcName.toLowerCase().indexOf(value) === 0;
});
if (!funcDef) {
return;
}
}
$scope.$apply(function () {
ctrl.addFunction(funcDef);
});
$input.trigger('blur');
return '';
}
});
$button.click(function () {
$button.hide();
$input.show();
$input.focus();
});
$input.keyup(function () {
elem.toggleClass('open', $input.val() === '');
});
$input.blur(function () {
// clicking the function dropdown menu wont
// work if you remove class at once
setTimeout(function () {
$input.val('');
$input.hide();
$button.show();
elem.removeClass('open');
}, 200);
});
$compile(elem.contents())($scope);
}
};
});
function getAllFunctionNames(categories) {
return _lodash2.default.reduce(categories, function (list, category) {
_lodash2.default.each(category, function (func) {
list.push(func.name);
});
return list;
}, []);
}
function createFunctionDropDownMenu(categories) {
return _lodash2.default.map(categories, function (list, category) {
return {
text: category,
submenu: _lodash2.default.map(list, function (value) {
return {
text: value.name,
click: "ctrl.addFunction('" + value.name + "')"
};
})
};
});
}
//# sourceMappingURL=add_datadog_func.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,422 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.DataDogDatasource = undefined;
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _lodash = require('lodash');
var _lodash2 = _interopRequireDefault(_lodash);
var _showdownMin = require('./showdown.min.js');
var _showdownMin2 = _interopRequireDefault(_showdownMin);
var _query_builder = require('./query_builder');
var queryBuilder = _interopRequireWildcard(_query_builder);
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var DataDogDatasource = exports.DataDogDatasource = function () {
function DataDogDatasource(instanceSettings, backendSrv, templateSrv) {
_classCallCheck(this, DataDogDatasource);
this.type = instanceSettings.type;
this.url = instanceSettings.url;
this.name = instanceSettings.name;
this.api_key = instanceSettings.jsonData.api_key;
this.application_key = instanceSettings.jsonData.app_key;
this.supportMetrics = true;
this.backendSrv = backendSrv;
this.templateSrv = templateSrv;
this._cached_metrics = false;
}
// Function to check Datasource health
_createClass(DataDogDatasource, [{
key: 'testDatasource',
value: function testDatasource() {
return this.invokeDataDogApiRequest('/downtime').then(function () {
return {
status: "success",
title: "Success",
message: "Data source is working"
};
}).catch(function (error) {
var message = "Connection error";
if (error && error.message) {
message = error.message;
}
return {
status: "error",
title: "Error",
message: message
};
});
}
}, {
key: 'tagFindQuery',
value: function tagFindQuery() {
return this.getTagsFromCache().then(function (tags) {
return _lodash2.default.map(tags, function (hosts, tag) {
return {
text: tag,
value: tag
};
});
});
}
}, {
key: 'metricFindQuery',
value: function metricFindQuery(query) {
var _this = this;
if (query === 'tag') {
return this.tagFindQuery();
}
if (this._cached_metrics) {
return Promise.resolve(this._cached_metrics);
}
if (this.fetching) {
return this.fetching;
}
var d = new Date();
d.setDate(d.getDate() - 1);
var from = Math.floor(d.getTime() / 1000);
this.fetching = this.getMetrics(from).then(function (metrics) {
_this._cached_metrics = _lodash2.default.map(metrics, function (metric) {
return {
text: metric,
value: metric
};
});
return _this._cached_metrics;
});
return this.fetching;
}
}, {
key: 'getTagKeys',
value: function getTagKeys() {
return this.getTagsFromCache().then(function (tagsHosts) {
var tags = Object.keys(tagsHosts);
var kv = mapTagsToKVPairs(tags);
var grafanaTags = Object.keys(kv);
return grafanaTags.map(function (tag) {
return {
text: tag,
value: tag
};
});
});
}
}, {
key: 'getTagValues',
value: function getTagValues(options) {
return this.getTagsFromCache().then(function (tagsHosts) {
var tags = Object.keys(tagsHosts);
var kv = mapTagsToKVPairs(tags);
var grafanaValues = kv[options.key];
return grafanaValues.map(function (val) {
return {
text: val,
value: val
};
});
});
}
}, {
key: 'query',
value: function query(options) {
var from = Math.floor(options.range.from.valueOf() / 1000);
var to = Math.floor(options.range.to.valueOf() / 1000);
var targets = options.targets.filter(function (t) {
return !t.hide;
});
if (targets.length <= 0) {
return Promise.resolve({ data: [] });
}
// add global adhoc filters
var adhocFilters = this.templateSrv.getAdhocFilters(this.name);
var queries = _lodash2.default.map(targets, function (target) {
var query = void 0;
if (target.rawQuery) {
query = target.query;
} else {
query = queryBuilder.buildQuery(target, adhocFilters);
}
return query;
});
var queryString = queries.join(',');
queryString = this.templateSrv.replace(queryString, options.scopedVars, dataDogTagFormat);
var params = {
from: from,
to: to,
query: queryString
};
return this.invokeDataDogApiRequest('/query', params).then(function (result) {
var dataResponse = _lodash2.default.map(result.series, function (series, i) {
var target = targets[i];
return {
'target': target.alias || series.expression,
'datapoints': _lodash2.default.map(series.pointlist, function (point) {
return [point[1], point[0]];
})
};
});
return { data: dataResponse };
});
}
}, {
key: 'annotationQuery',
value: function annotationQuery(options) {
var timeFrom = Math.floor(options.range.from.valueOf() / 1000);
var timeTo = Math.floor(options.range.to.valueOf() / 1000);
var _options$annotation = options.annotation,
priority = _options$annotation.priority,
sources = _options$annotation.sources,
tags = _options$annotation.tags;
return this.getEventStream(timeFrom, timeTo, priority, sources, tags).then(function (eventStreams) {
var eventAnnotations = eventStreams.map(function (eventStream) {
var allEvents = eventStream.children;
var filteredEvents = _lodash2.default.filter(allEvents, function (event) {
return event.alert_type !== 'success';
});
return _lodash2.default.map(filteredEvents, function (event) {
var renderedText = eventStream.text;
if (isDataDogMarkdown(eventStream.text)) {
renderedText = convertDataDogMdToHtml(eventStream.text);
}
return {
annotation: options.annotation,
time: event.date_happened * 1000,
title: eventStream.title,
text: renderedText,
tags: eventStream.tags
};
});
});
return _lodash2.default.flatten(eventAnnotations);
});
}
}, {
key: 'getHosts',
value: function getHosts() {
return this.searchEntities('hosts');
}
// entity should be 'hosts' or 'metrics'
// http://docs.datadoghq.com/api/?lang=console#search
}, {
key: 'searchEntities',
value: function searchEntities(entity) {
var params = { q: '' };
if (entity) {
params.q = entity + ':';
}
return this.invokeDataDogApiRequest('/search', params).then(function (result) {
if (result && result.results) {
return result.results[entity];
}
});
}
}, {
key: 'getMetrics',
value: function getMetrics(timeFrom) {
var params = {};
if (timeFrom) {
params.from = timeFrom;
}
return this.invokeDataDogApiRequest('/metrics', params).then(function (result) {
if (result.metrics) {
return result.metrics;
} else {
return [];
}
});
}
}, {
key: 'getTagsHosts',
value: function getTagsHosts() {
return this.invokeDataDogApiRequest('/tags/hosts').then(function (result) {
if (result && result.tags) {
return result.tags;
}
});
}
}, {
key: 'getTagsFromCache',
value: function getTagsFromCache() {
var _this2 = this;
var getTags = void 0;
if (this._cached_tags && this._cached_tags.length) {
getTags = Promise.resolve(this._cached_tags);
} else {
getTags = this.getTagsHosts().then(function (tags) {
_this2._cached_tags = tags;
return tags;
});
}
return getTags;
}
}, {
key: 'getEventStream',
value: function getEventStream(timeFrom, timeTo, priority, sources, tags) {
var params = {
start: timeFrom,
end: timeTo
};
if (priority) {
params.priority = priority;
}
if (sources) {
params.sources = sources;
}
if (tags) {
params.tags = tags;
}
return this.invokeDataDogApiRequest('/events', params).then(function (result) {
if (result.events) {
return result.events;
} else {
return [];
}
});
}
}, {
key: 'invokeDataDogApiRequest',
value: function invokeDataDogApiRequest(url) {
var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
// Set auth params
params.api_key = this.api_key;
params.application_key = this.application_key;
return this.backendSrv.datasourceRequest({
method: 'GET',
url: this.url + url,
params: params
}).then(function (response) {
if (response.data) {
return response.data;
} else {
throw { message: 'DataDog API request error' };
}
}).catch(function (error) {
var message = 'DataDog API request error';
if (error.statusText) {
message = error.status + ' ' + error.statusText;
throw { message: message };
} else if (error.err.statusText) {
throw { message: error.err.statusText };
} else {
throw { message: message };
}
});
}
}]);
return DataDogDatasource;
}();
/*
* Convert tags to key-value pairs
* [region:east, region:nw] => {region: [east, nw]}
*/
function mapTagsToKVPairs(tags) {
var kv_tags = _lodash2.default.filter(tags, function (tag) {
return tag.indexOf(':') !== -1;
});
var kv_pairs = kv_tags.map(function (tag) {
return tag.split(':', 2); // Limit to 2
});
var kv_object = {};
kv_pairs.forEach(function (pair) {
var key = pair[0];
var val = pair[1];
if (kv_object[key]) {
kv_object[key].push(val);
} else {
kv_object[key] = [val];
}
});
return kv_object;
}
/*
* Convert DataDog event text from markdown to pure HTML
* http://docs.datadoghq.com/guides/markdown/
*/
function convertDataDogMdToHtml(str) {
var MD_START = '%%%\n';
var MD_END = '\n%%%';
var md_start_index = str.indexOf(MD_START) + MD_START.length;
var md_end_index = str.indexOf(MD_END);
var md = str.substring(md_start_index, md_end_index);
md = removeImagesFromDataDogMarkdown(md);
var converter = new _showdownMin2.default.Converter();
return converter.makeHtml(md);
}
function isDataDogMarkdown(str) {
var MD_START = '%%%\n';
return str.indexOf(MD_START) >= 0;
}
function removeImagesFromDataDogMarkdown(str) {
var dataDogImagePattern = /\[{0,1}\!\[.*\]\(https{0,1}\:\/\/p\.datadoghq\.com\/snapshot.+\)/g;
return str.replace(dataDogImagePattern, '');
}
function dataDogTagFormat(value) {
if (_lodash2.default.isArray(value)) {
return value.join(',');
}
return value;
}
//# sourceMappingURL=datasource.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,295 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _lodash = require('lodash');
var _lodash2 = _interopRequireDefault(_lodash);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var index = [];
var categories = {
Arithmatic: [],
Interpolation: [],
Timeshift: [],
Rate: [],
Smoothing: [],
Rollup: [],
Rank: [],
Count: [],
Regression: [],
Algorithms: []
};
function addFuncDef(funcDef) {
funcDef.params = funcDef.params || [];
funcDef.defaultParams = funcDef.defaultParams || [];
funcDef.append = funcDef.append || false;
if (funcDef.category) {
funcDef.category.push(funcDef);
}
index[funcDef.name] = funcDef;
index[funcDef.name] = funcDef;
}
addFuncDef({
name: 'abs',
category: categories.Arithmatic
});
addFuncDef({
name: 'log2',
category: categories.Arithmatic
});
addFuncDef({
name: 'cumsum',
category: categories.Arithmatic
});
addFuncDef({
name: 'integral',
category: categories.Arithmatic
});
addFuncDef({
name: 'fill',
category: categories.Interpolation,
params: [{ name: "fill", type: 'string', options: ['null', 'zero', 'linear', 'last'] }, { name: "limit", type: 'int', optional: true }],
defaultParams: ['zero'],
append: true
});
addFuncDef({
name: 'hour_before',
category: categories.Timeshift
});
addFuncDef({
name: 'day_before',
category: categories.Timeshift
});
addFuncDef({
name: 'week_before',
category: categories.Timeshift
});
addFuncDef({
name: 'month_before',
category: categories.Timeshift
});
addFuncDef({
name: 'per_second',
category: categories.Rate
});
addFuncDef({
name: 'per_minute',
category: categories.Rate
});
addFuncDef({
name: 'per_hour',
category: categories.Rate
});
addFuncDef({
name: 'dt',
category: categories.Rate
});
addFuncDef({
name: 'diff',
category: categories.Rate
});
addFuncDef({
name: 'derivative',
category: categories.Rate
});
addFuncDef({
name: 'ewma_3',
category: categories.Smoothing
});
addFuncDef({
name: 'ewma_5',
category: categories.Smoothing
});
addFuncDef({
name: 'ewma_10',
category: categories.Smoothing
});
addFuncDef({
name: 'ewma_20',
category: categories.Smoothing
});
addFuncDef({
name: 'median_3',
category: categories.Smoothing
});
addFuncDef({
name: 'median_5',
category: categories.Smoothing
});
addFuncDef({
name: 'median_7',
category: categories.Smoothing
});
addFuncDef({
name: 'median_9',
category: categories.Smoothing
});
addFuncDef({
name: 'rollup',
category: categories.Rollup,
params: [{ name: "rollup", type: 'string', options: ['sum', 'avg', 'min', 'max'] }, { name: "period", type: 'int' }],
defaultParams: ['sum', 600],
append: true
});
addFuncDef({
name: 'count_nonzero',
category: categories.Count
});
addFuncDef({
name: 'count_not_null',
category: categories.Count
});
addFuncDef({
name: 'top',
category: categories.Rank,
params: [{ name: "top", type: 'int', options: [5, 10, 15] }, { name: "aggr", type: 'string', options: ['mean', 'min', 'max', 'area', 'l2norm', 'last'] }, { name: "dir", type: 'string', options: ['asc', 'desc'] }],
defaultParams: [5, 'mean', 'dir']
});
addFuncDef({
name: 'robust_trend',
category: categories.Regression
});
addFuncDef({
name: 'piecewise_constant',
category: categories.Regression
});
addFuncDef({
name: 'anomalies',
category: categories.Algorithms,
params: [{ name: "anomalies", type: 'string', options: ['basic', 'agile', 'robust', 'adaptive'] }, { name: "bonds", type: 'int', options: [1, 2, 3, 4, 5, 6] }],
defaultParams: ['basic', 2]
});
addFuncDef({
name: 'anomalies',
category: categories.Algorithms,
params: [{ name: "anomalies", type: 'string', options: ['basic', 'agile', 'robust', 'adaptive'] }, { name: "bonds", type: 'int', options: [1, 2, 3, 4, 5, 6] }],
defaultParams: ['basic', 2]
});
addFuncDef({
name: 'outliers',
category: categories.Algorithms,
params: [{ name: "outliers", type: 'string', options: ['DBSCAN', 'MAD', 'scaledDBSCAN', 'scaledMAD'] }, { name: "tolerance", type: 'int', options: [0.33, 0.5, 1, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0] }],
defaultParams: ['basic', 2]
});
_lodash2.default.each(categories, function (funcList, catName) {
categories[catName] = _lodash2.default.sortBy(funcList, 'name');
});
function FuncInstance(funcDef, options) {
this.def = funcDef;
this.params = [];
if (options && options.withDefaultParams) {
this.params = funcDef.defaultParams.slice(0);
}
this.updateText();
}
FuncInstance.prototype.render = function (metricExp) {
var str = this.def.name + '(';
var parameters = _lodash2.default.map(this.params, function (value) {
return value;
});
if (metricExp && !this.def.append) {
parameters.unshift(metricExp);
}
var funcRender = str + parameters.join(', ') + ')';
console.log(funcRender, this.def.append);
if (this.def.append) {
return metricExp + '.' + funcRender;
} else {
return funcRender;
}
};
FuncInstance.prototype.updateParam = function (strValue, index) {
// handle optional parameters
// if string contains ',' and next param is optional, split and update both
if (strValue === '' && this.def.params[index].optional) {
this.params.splice(index, 1);
} else {
this.params[index] = strValue;
}
this.updateText();
};
FuncInstance.prototype.updateText = function () {
if (this.params.length === 0) {
this.text = this.def.name + '()';
return;
}
var text = this.def.name + '(';
text += this.params.join(', ');
text += ')';
this.text = text;
};
var createFuncInstance = function createFuncInstance(funcDef, options) {
if (_lodash2.default.isString(funcDef)) {
if (!index[funcDef]) {
throw { message: 'Method not found ' + name };
}
funcDef = index[funcDef];
}
return new FuncInstance(funcDef, options);
};
var getFuncDef = function getFuncDef(name) {
return index[name];
};
var getCategories = function getCategories() {
return categories;
};
var foo;
exports.default = foo = {
createFuncInstance: createFuncInstance,
getFuncDef: getFuncDef,
getCategories: getCategories
};
//# sourceMappingURL=dfunc.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,247 @@
'use strict';
var _angular = require('angular');
var _angular2 = _interopRequireDefault(_angular);
var _lodash = require('lodash');
var _lodash2 = _interopRequireDefault(_lodash);
var _jquery = require('jquery');
var _jquery2 = _interopRequireDefault(_jquery);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
'use strict';
_angular2.default.module('grafana.directives').directive('datadogFuncEditor', function ($compile, templateSrv) {
var funcSpanTemplate = '<a ng-click="">{{func.def.name}}</a><span>(</span>';
var paramTemplate = '<input type="text" style="display:none"' + ' class="input-mini tight-form-func-param"></input>';
var funcControlsTemplate = '<div class="tight-form-func-controls">' + '<span class="pointer fa fa-arrow-left"></span>' + '<span class="pointer fa fa-question-circle"></span>' + '<span class="pointer fa fa-remove" ></span>' + '<span class="pointer fa fa-arrow-right"></span>' + '</div>';
return {
restrict: 'A',
link: function postLink($scope, elem) {
var $funcLink = (0, _jquery2.default)(funcSpanTemplate);
var $funcControls = (0, _jquery2.default)(funcControlsTemplate);
var ctrl = $scope.ctrl;
var func = $scope.func;
var funcDef = func.def;
var scheduledRelink = false;
var paramCountAtLink = 0;
function clickFuncParam(paramIndex) {
/*jshint validthis:true */
var $link = (0, _jquery2.default)(this);
var $input = $link.next();
$input.val(func.params[paramIndex]);
$input.css('width', $link.width() + 16 + 'px');
$link.hide();
$input.show();
$input.focus();
$input.select();
var typeahead = $input.data('typeahead');
if (typeahead) {
$input.val('');
typeahead.lookup();
}
}
function scheduledRelinkIfNeeded() {
if (paramCountAtLink === func.params.length) {
return;
}
if (!scheduledRelink) {
scheduledRelink = true;
setTimeout(function () {
relink();
scheduledRelink = false;
}, 200);
}
}
function inputBlur(paramIndex) {
/*jshint validthis:true */
var $input = (0, _jquery2.default)(this);
var $link = $input.prev();
var newValue = $input.val();
if (newValue !== '' || func.def.params[paramIndex].optional) {
$link.html(templateSrv.highlightVariablesAsHtml(newValue));
func.updateParam($input.val(), paramIndex);
scheduledRelinkIfNeeded();
$scope.$apply(function () {
ctrl.targetChanged();
});
$input.hide();
$link.show();
}
}
function inputKeyPress(paramIndex, e) {
/*jshint validthis:true */
if (e.which === 13) {
inputBlur.call(this, paramIndex);
}
}
function inputKeyDown() {
/*jshint validthis:true */
this.style.width = (3 + this.value.length) * 8 + 'px';
}
function addTypeahead($input, paramIndex) {
$input.attr('data-provide', 'typeahead');
var options = funcDef.params[paramIndex].options;
if (funcDef.params[paramIndex].type === 'int') {
options = _lodash2.default.map(options, function (val) {
return val.toString();
});
}
$input.typeahead({
source: options,
minLength: 0,
items: 20,
updater: function updater(value) {
setTimeout(function () {
inputBlur.call($input[0], paramIndex);
}, 0);
return value;
}
});
var typeahead = $input.data('typeahead');
typeahead.lookup = function () {
this.query = this.$element.val() || '';
return this.process(this.source);
};
}
function toggleFuncControls() {
var targetDiv = elem.closest('.tight-form');
if (elem.hasClass('show-function-controls')) {
elem.removeClass('show-function-controls');
targetDiv.removeClass('has-open-function');
$funcControls.hide();
return;
}
elem.addClass('show-function-controls');
targetDiv.addClass('has-open-function');
$funcControls.show();
}
function addElementsAndCompile() {
$funcControls.appendTo(elem);
$funcLink.appendTo(elem);
_lodash2.default.each(funcDef.params, function (param, index) {
if (param.optional && func.params.length <= index) {
return;
}
if (index > 0) {
(0, _jquery2.default)('<span>, </span>').appendTo(elem);
}
var paramValue = templateSrv.highlightVariablesAsHtml(func.params[index]);
var $paramLink = (0, _jquery2.default)('<a ng-click="" class="datadog-func-param-link">' + paramValue + '</a>');
var $input = (0, _jquery2.default)(paramTemplate);
paramCountAtLink++;
$paramLink.appendTo(elem);
$input.appendTo(elem);
$input.blur(_lodash2.default.partial(inputBlur, index));
$input.keyup(inputKeyDown);
$input.keypress(_lodash2.default.partial(inputKeyPress, index));
$paramLink.click(_lodash2.default.partial(clickFuncParam, index));
if (funcDef.params[index].options) {
addTypeahead($input, index);
}
});
(0, _jquery2.default)('<span>)</span>').appendTo(elem);
$compile(elem.contents())($scope);
}
function ifJustAddedFocusFistParam() {
if ($scope.func.added) {
$scope.func.added = false;
setTimeout(function () {
elem.find('.datadog-func-param-link').first().click();
}, 10);
}
}
function registerFuncControlsToggle() {
$funcLink.click(toggleFuncControls);
}
function registerFuncControlsActions() {
$funcControls.click(function (e) {
var $target = (0, _jquery2.default)(e.target);
if ($target.hasClass('fa-remove')) {
toggleFuncControls();
$scope.$apply(function () {
ctrl.removeFunction($scope.func);
});
return;
}
if ($target.hasClass('fa-arrow-left')) {
$scope.$apply(function () {
_lodash2.default.move(ctrl.functions, $scope.$index, $scope.$index - 1);
ctrl.targetChanged();
});
return;
}
if ($target.hasClass('fa-arrow-right')) {
$scope.$apply(function () {
_lodash2.default.move(ctrl.functions, $scope.$index, $scope.$index + 1);
ctrl.targetChanged();
});
return;
}
if ($target.hasClass('fa-question-circle')) {
window.open("http://docs.datadoghq.com/graphing/#apply-more-advanced-functions", '_blank');
return;
}
});
}
function relink() {
elem.children().remove();
addElementsAndCompile();
ifJustAddedFocusFistParam();
registerFuncControlsToggle();
registerFuncControlsActions();
}
relink();
}
};
});
//# sourceMappingURL=func_editor.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,37 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.AnnotationsQueryCtrl = exports.QueryOptionsCtrl = exports.ConfigCtrl = exports.QueryCtrl = exports.Datasource = undefined;
var _datasource = require('./datasource');
var _query_ctrl = require('./query_ctrl');
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var DataDogConfigCtrl = function DataDogConfigCtrl() {
_classCallCheck(this, DataDogConfigCtrl);
};
DataDogConfigCtrl.templateUrl = "partials/config.html";
var DataDogQueryOptionsCtrl = function DataDogQueryOptionsCtrl() {
_classCallCheck(this, DataDogQueryOptionsCtrl);
};
DataDogQueryOptionsCtrl.templateUrl = "partials/query.options.html";
var DataDogAnnotationsQueryCtrl = function DataDogAnnotationsQueryCtrl() {
_classCallCheck(this, DataDogAnnotationsQueryCtrl);
};
DataDogAnnotationsQueryCtrl.templateUrl = 'partials/annotations.editor.html';
exports.Datasource = _datasource.DataDogDatasource;
exports.QueryCtrl = _query_ctrl.DataDogQueryCtrl;
exports.ConfigCtrl = DataDogConfigCtrl;
exports.QueryOptionsCtrl = DataDogQueryOptionsCtrl;
exports.AnnotationsQueryCtrl = DataDogAnnotationsQueryCtrl;
//# sourceMappingURL=module.js.map
@@ -0,0 +1 @@
{"version":3,"sources":["../../src/module.js"],"names":["DataDogConfigCtrl","templateUrl","DataDogQueryOptionsCtrl","DataDogAnnotationsQueryCtrl","Datasource","QueryCtrl","ConfigCtrl","QueryOptionsCtrl","AnnotationsQueryCtrl"],"mappings":";;;;;;;AAAA;;AACA;;;;IAEMA,iB;;;;AACNA,kBAAkBC,WAAlB,GAAgC,sBAAhC;;IAEMC,uB;;;;AACNA,wBAAwBD,WAAxB,GAAsC,6BAAtC;;IAEME,2B;;;;AACNA,4BAA4BF,WAA5B,GAA0C,kCAA1C;;QAGuBG,U;QACDC,S;QACCC,U,GAArBN,iB;QAC2BO,gB,GAA3BL,uB;QAC+BM,oB,GAA/BL,2B","file":"module.js","sourcesContent":["import {DataDogDatasource} from './datasource';\nimport {DataDogQueryCtrl} from './query_ctrl';\n\nclass DataDogConfigCtrl {}\nDataDogConfigCtrl.templateUrl = \"partials/config.html\";\n\nclass DataDogQueryOptionsCtrl {}\nDataDogQueryOptionsCtrl.templateUrl = \"partials/query.options.html\";\n\nclass DataDogAnnotationsQueryCtrl {}\nDataDogAnnotationsQueryCtrl.templateUrl = 'partials/annotations.editor.html';\n\nexport {\n DataDogDatasource as Datasource,\n DataDogQueryCtrl as QueryCtrl,\n DataDogConfigCtrl as ConfigCtrl,\n DataDogQueryOptionsCtrl as QueryOptionsCtrl,\n DataDogAnnotationsQueryCtrl as AnnotationsQueryCtrl\n};\n"]}
@@ -0,0 +1,84 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.buildQuery = buildQuery;
var _lodash = require('lodash');
var _lodash2 = _interopRequireDefault(_lodash);
var _dfunc = require('./dfunc');
var _dfunc2 = _interopRequireDefault(_dfunc);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function buildQuery(target, adhocFilters) {
var aggregation = target.aggregation,
metric = target.metric,
tags = target.tags,
functions = target.functions;
var query = aggregation + ':' + metric;
var functionInstances = getFunctionInstances(functions);
if (tags && tags.length || adhocFilters && adhocFilters.length) {
query += '{';
if (tags && tags.length) {
query += tags.join(',');
}
if (adhocFilters && adhocFilters.length) {
var adhocTags = buildAdHocFilterString(adhocFilters);
if (tags && tags.length) {
query += ',';
}
query += adhocTags;
}
query += '}';
} else {
query += '{*}';
}
if (target.as) {
query += '.' + target.as + '()';
}
var groupedFuncs = _lodash2.default.groupBy(functionInstances, function (func) {
if (func.def.append) {
return 'appends';
} else {
return 'wraps';
}
});
_lodash2.default.each(groupedFuncs.appends, function (func) {
query += '.' + func.render();
});
_lodash2.default.each(groupedFuncs.wraps, function (func) {
query = func.render(query);
});
return query;
}
function getFunctionInstances(functions) {
return _lodash2.default.map(functions, function (func) {
var f = _dfunc2.default.createFuncInstance(func.funcDef, { withDefaultParams: false });
f.params = func.params.slice();
return f;
});
}
function buildAdHocFilterString(adhocFilters) {
return adhocFilters.map(function (filter) {
return filter.key + ':' + filter.value;
}).join(',');
}
//# sourceMappingURL=query_builder.js.map
@@ -0,0 +1 @@
{"version":3,"sources":["../../src/query_builder.js"],"names":["buildQuery","target","adhocFilters","aggregation","metric","tags","functions","query","functionInstances","getFunctionInstances","length","join","adhocTags","buildAdHocFilterString","as","groupedFuncs","groupBy","func","def","append","each","appends","render","wraps","map","f","createFuncInstance","funcDef","withDefaultParams","params","slice","filter","key","value"],"mappings":";;;;;QAGgBA,U,GAAAA,U;;AAHhB;;;;AACA;;;;;;AAEO,SAASA,UAAT,CAAoBC,MAApB,EAA4BC,YAA5B,EAA0C;AAAA,MAC1CC,WAD0C,GACFF,MADE,CAC1CE,WAD0C;AAAA,MAC7BC,MAD6B,GACFH,MADE,CAC7BG,MAD6B;AAAA,MACrBC,IADqB,GACFJ,MADE,CACrBI,IADqB;AAAA,MACfC,SADe,GACFL,MADE,CACfK,SADe;;AAE/C,MAAIC,QAAWJ,WAAX,SAA0BC,MAA9B;;AAEA,MAAII,oBAAqBC,qBAAqBH,SAArB,CAAzB;;AAEA,MAAKD,QAAQA,KAAKK,MAAd,IAA0BR,gBAAgBA,aAAaQ,MAA3D,EAAoE;AAClEH,aAAS,GAAT;;AAEA,QAAIF,QAAQA,KAAKK,MAAjB,EAAyB;AACvBH,eAASF,KAAKM,IAAL,CAAU,GAAV,CAAT;AACD;;AAED,QAAIT,gBAAgBA,aAAaQ,MAAjC,EAAyC;AACvC,UAAIE,YAAYC,uBAAuBX,YAAvB,CAAhB;AACA,UAAIG,QAAQA,KAAKK,MAAjB,EAAyB;AACvBH,iBAAS,GAAT;AACD;AACDA,eAASK,SAAT;AACD;;AAEDL,aAAS,GAAT;AACD,GAhBD,MAgBO;AACLA,aAAS,KAAT;AACD;;AAED,MAAIN,OAAOa,EAAX,EAAe;AACbP,aAAS,MAAMN,OAAOa,EAAb,GAAkB,IAA3B;AACD;;AAED,MAAIC,eAAe,iBAAEC,OAAF,CAAUR,iBAAV,EAA6B,gBAAQ;AACtD,QAAIS,KAAKC,GAAL,CAASC,MAAb,EAAqB;AACnB,aAAO,SAAP;AACD,KAFD,MAEO;AACL,aAAO,OAAP;AACD;AACF,GANkB,CAAnB;;AAQA,mBAAEC,IAAF,CAAOL,aAAaM,OAApB,EAA6B,gBAAQ;AACnCd,aAAS,MAAMU,KAAKK,MAAL,EAAf;AACD,GAFD;;AAIA,mBAAEF,IAAF,CAAOL,aAAaQ,KAApB,EAA2B,gBAAQ;AACjChB,YAAQU,KAAKK,MAAL,CAAYf,KAAZ,CAAR;AACD,GAFD;;AAIA,SAAOA,KAAP;AACD;;AAED,SAASE,oBAAT,CAA8BH,SAA9B,EAAyC;AACvC,SAAO,iBAAEkB,GAAF,CAAMlB,SAAN,EAAiB,gBAAQ;AAC9B,QAAImB,IAAI,gBAAMC,kBAAN,CAAyBT,KAAKU,OAA9B,EAAuC,EAACC,mBAAmB,KAApB,EAAvC,CAAR;AACAH,MAAEI,MAAF,GAAWZ,KAAKY,MAAL,CAAYC,KAAZ,EAAX;AACA,WAAOL,CAAP;AACD,GAJM,CAAP;AAKD;;AAED,SAASZ,sBAAT,CAAgCX,YAAhC,EAA8C;AAC5C,SAAOA,aAAasB,GAAb,CAAiB,kBAAU;AAChC,WAAOO,OAAOC,GAAP,GAAa,GAAb,GAAmBD,OAAOE,KAAjC;AACD,GAFM,EAEJtB,IAFI,CAEC,GAFD,CAAP;AAGD","file":"query_builder.js","sourcesContent":["import _ from 'lodash';\nimport dfunc from './dfunc';\n\nexport function buildQuery(target, adhocFilters) {\n let {aggregation, metric, tags, functions} = target;\n let query = `${aggregation}:${metric}`;\n\n let functionInstances = getFunctionInstances(functions);\n\n if ((tags && tags.length) || (adhocFilters && adhocFilters.length)) {\n query += '{';\n\n if (tags && tags.length) {\n query += tags.join(',');\n }\n\n if (adhocFilters && adhocFilters.length) {\n let adhocTags = buildAdHocFilterString(adhocFilters);\n if (tags && tags.length) {\n query += ',';\n }\n query += adhocTags;\n }\n\n query += '}';\n } else {\n query += '{*}';\n }\n\n if (target.as) {\n query += '.' + target.as + '()';\n }\n\n var groupedFuncs = _.groupBy(functionInstances, func => {\n if (func.def.append) {\n return 'appends';\n } else {\n return 'wraps';\n }\n });\n\n _.each(groupedFuncs.appends, func => {\n query += '.' + func.render();\n });\n\n _.each(groupedFuncs.wraps, func => {\n query = func.render(query);\n });\n\n return query;\n}\n\nfunction getFunctionInstances(functions) {\n return _.map(functions, func => {\n var f = dfunc.createFuncInstance(func.funcDef, {withDefaultParams: false});\n f.params = func.params.slice();\n return f;\n });\n}\n\nfunction buildAdHocFilterString(adhocFilters) {\n return adhocFilters.map(filter => {\n return filter.key + ':' + filter.value;\n }).join(',');\n}\n"]}
@@ -0,0 +1,230 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.DataDogQueryCtrl = undefined;
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _lodash = require('lodash');
var _lodash2 = _interopRequireDefault(_lodash);
var _dfunc = require('./dfunc');
var _dfunc2 = _interopRequireDefault(_dfunc);
var _sdk = require('app/plugins/sdk');
require('./func_editor');
require('./add_datadog_func');
var _query_builder = require('./query_builder');
var queryBuilder = _interopRequireWildcard(_query_builder);
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
var DataDogQueryCtrl = exports.DataDogQueryCtrl = function (_QueryCtrl) {
_inherits(DataDogQueryCtrl, _QueryCtrl);
function DataDogQueryCtrl($scope, $injector, uiSegmentSrv, templateSrv) {
_classCallCheck(this, DataDogQueryCtrl);
var _this = _possibleConstructorReturn(this, (DataDogQueryCtrl.__proto__ || Object.getPrototypeOf(DataDogQueryCtrl)).call(this, $scope, $injector));
_this.removeText = '-- remove tag --';
_this.uiSegmentSrv = uiSegmentSrv;
_this.templateSrv = templateSrv;
if (_this.target.aggregation) {
_this.aggregationSegment = new uiSegmentSrv.newSegment(_this.target.aggregation);
} else {
_this.aggregationSegment = new uiSegmentSrv.newSegment({
value: 'Select Aggregation',
fake: true,
custom: false
});
}
if (_this.target.metric) {
_this.metricSegment = new uiSegmentSrv.newSegment(_this.target.metric);
} else {
_this.metricSegment = new uiSegmentSrv.newSegment({
value: 'Select Metric',
fake: true,
custom: false
});
}
_this.target.tags = _this.target.tags || [];
_this.tagSegments = _this.target.tags.map(uiSegmentSrv.newSegment);
_this.fixTagSegments();
_this.functions = [];
_this.target.functions = _this.target.functions || [];
_this.functions = _lodash2.default.map(_this.target.functions, function (func) {
var f = _dfunc2.default.createFuncInstance(func.funcDef, { withDefaultParams: false });
f.params = func.params.slice();
return f;
});
if (_this.target.as) {
_this.asSegment = uiSegmentSrv.newSegment(_this.target.as);
} else {
_this.asSegment = uiSegmentSrv.newSegment({
value: 'Select As',
fake: true,
custom: false
});
}
return _this;
}
_createClass(DataDogQueryCtrl, [{
key: 'toggleEditorMode',
value: function toggleEditorMode() {
this.target.rawQuery = !this.target.rawQuery;
}
}, {
key: 'getMetrics',
value: function getMetrics() {
return this.datasource.metricFindQuery().then(this.uiSegmentSrv.transformToSegments(true));
}
}, {
key: 'getAggregations',
value: function getAggregations() {
return Promise.resolve([{ text: 'avg by', value: 'avg' }, { text: 'max by', value: 'max' }, { text: 'min by', value: 'min' }, { text: 'sub by', value: 'sum' }]);
}
}, {
key: 'getAs',
value: function getAs() {
return Promise.resolve([{ text: 'None', value: 'None' }, { text: 'as_count', value: 'as_count' }, { text: 'as_rate', value: 'as_rate' }]);
}
}, {
key: 'getTags',
value: function getTags(segment) {
var _this2 = this;
return this.datasource.tagFindQuery().then(this.uiSegmentSrv.transformToSegments(true)).then(function (results) {
if (segment.type !== 'plus-button') {
var removeSegment = _this2.uiSegmentSrv.newFake(_this2.removeText);
results.unshift(removeSegment);
}
return results;
});
}
}, {
key: 'aggregationChanged',
value: function aggregationChanged() {
this.target.aggregation = this.aggregationSegment.value;
this.panelCtrl.refresh();
}
}, {
key: 'metricChanged',
value: function metricChanged() {
this.target.metric = this.metricSegment.value;
this.panelCtrl.refresh();
}
}, {
key: 'asChanged',
value: function asChanged() {
if (this.asSegment.value === 'None') {
this.target.as = null;
} else {
this.target.as = this.asSegment.value;
}
this.panelCtrl.refresh();
}
}, {
key: 'fixTagSegments',
value: function fixTagSegments() {
var count = this.tagSegments.length;
var lastSegment = this.tagSegments[Math.max(count - 1, 0)];
if (!lastSegment || lastSegment.type !== 'plus-button') {
this.tagSegments.push(this.uiSegmentSrv.newPlusButton());
}
}
}, {
key: 'targetChanged',
value: function targetChanged() {
if (this.error) {
return;
}
this.panelCtrl.refresh();
}
}, {
key: 'persistFunctions',
value: function persistFunctions() {
this.target.functions = _lodash2.default.map(this.functions, function (func) {
return {
funcDef: func.def.name,
params: func.params.slice()
};
});
}
}, {
key: 'removeFunction',
value: function removeFunction(func) {
this.functions = _lodash2.default.without(this.functions, func);
this.persistFunctions();
this.targetChanged();
}
}, {
key: 'addFunction',
value: function addFunction(funcDef) {
var func = _dfunc2.default.createFuncInstance(funcDef, { withDefaultParams: true });
func.added = true;
this.functions.push(func);
this.persistFunctions();
this.targetChanged();
}
}, {
key: 'tagSegmentUpdated',
value: function tagSegmentUpdated(segment, index) {
if (segment.value === this.removeText) {
this.tagSegments.splice(index, 1);
}
var realSegments = _lodash2.default.filter(this.tagSegments, function (segment) {
return segment.value;
});
this.target.tags = realSegments.map(function (segment) {
return segment.value;
});
this.tagSegments = _lodash2.default.map(this.target.tags, this.uiSegmentSrv.newSegment);
this.fixTagSegments();
this.panelCtrl.refresh();
}
}, {
key: 'getCollapsedText',
value: function getCollapsedText() {
if (this.target.rawQuery) {
return this.target.query;
} else {
return queryBuilder.buildQuery(this.target);
}
}
}]);
return DataDogQueryCtrl;
}(_sdk.QueryCtrl);
DataDogQueryCtrl.templateUrl = 'partials/query.editor.html';
//# sourceMappingURL=query_ctrl.js.map
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,79 @@
"use strict";
var _module = require("../module");
var _q = require("q");
var _q2 = _interopRequireDefault(_q);
var _sinon = require("sinon");
var _sinon2 = _interopRequireDefault(_sinon);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
describe('DataDogDatasource', function () {
var ctx = {};
beforeEach(function () {
ctx.$q = _q2.default;
ctx.backendSrv = {
datasourceRequest: function datasourceRequest() {
return ctx.$q.when({
status: 200
});
}
};
ctx.templateSrv = {
replace: function replace(str) {
return str;
},
getAdhocFilters: function getAdhocFilters() {
return [];
}
};
var instanceSettings = {
url: 'https://app.datadoghq.com/api/v1',
jsonData: {
api_key: '0000deadbeaf0000',
app_key: '0000abcd0000abcd'
}
};
ctx.ds = new _module.Datasource(instanceSettings, ctx.backendSrv, ctx.templateSrv);
});
describe('When doing DataDog API request', function () {
beforeEach(function () {
var targets = [{ query: 'avg:system.load.5{*}', rawQuery: true }];
ctx.options = {
range: {
from: 12340000,
to: 12340000
},
targets: targets
};
});
it('should send request with proper params', function (done) {
var expected_params = {
method: 'GET',
url: 'https://app.datadoghq.com/api/v1/query',
params: {
api_key: '0000deadbeaf0000',
application_key: '0000abcd0000abcd',
from: 12340,
to: 12340,
query: 'avg:system.load.5{*}'
}
};
var datasourceRequest = _sinon2.default.spy(ctx.ds.backendSrv, 'datasourceRequest');
ctx.ds.query(ctx.options);
expect(datasourceRequest).to.have.been.calledWith(expected_params);
done();
});
});
});
//# sourceMappingURL=datasource_spec.js.map
@@ -0,0 +1 @@
{"version":3,"sources":["../../../spec/datasource_spec.js"],"names":["describe","ctx","beforeEach","$q","backendSrv","datasourceRequest","when","status","templateSrv","replace","str","getAdhocFilters","instanceSettings","url","jsonData","api_key","app_key","ds","targets","query","rawQuery","options","range","from","to","it","done","expected_params","method","params","application_key","spy","expect","have","been","calledWith"],"mappings":";;AAAA;;AACA;;;;AACA;;;;;;AAEAA,SAAS,mBAAT,EAA8B,YAAM;AAClC,MAAIC,MAAM,EAAV;;AAEAC,aAAW,YAAW;AACpBD,QAAIE,EAAJ;AACAF,QAAIG,UAAJ,GAAiB;AACfC,yBAAmB,6BAAM;AACvB,eAAOJ,IAAIE,EAAJ,CAAOG,IAAP,CAAY;AACjBC,kBAAQ;AADS,SAAZ,CAAP;AAGD;AALc,KAAjB;AAOAN,QAAIO,WAAJ,GAAkB;AAChBC,eAAS,iBAACC,GAAD;AAAA,eAASA,GAAT;AAAA,OADO;AAEhBC,uBAAiB;AAAA,eAAM,EAAN;AAAA;AAFD,KAAlB;;AAKA,QAAIC,mBAAmB;AACrBC,WAAK,kCADgB;AAErBC,gBAAU;AACRC,iBAAS,kBADD;AAERC,iBAAS;AAFD;AAFW,KAAvB;AAOAf,QAAIgB,EAAJ,GAAS,uBAAeL,gBAAf,EAAiCX,IAAIG,UAArC,EAAiDH,IAAIO,WAArD,CAAT;AACD,GAtBD;;AAwBAR,WAAS,gCAAT,EAA2C,YAAM;AAC/CE,eAAW,YAAW;AACpB,UAAIgB,UAAU,CACZ,EAAEC,OAAO,sBAAT,EAAiCC,UAAU,IAA3C,EADY,CAAd;;AAIAnB,UAAIoB,OAAJ,GAAc;AACZC,eAAO;AACLC,gBAAM,QADD;AAELC,cAAI;AAFC,SADK;AAKZN,iBAASA;AALG,OAAd;AAOD,KAZD;;AAcAO,OAAG,wCAAH,EAA6C,UAACC,IAAD,EAAU;AACrD,UAAIC,kBAAkB;AACpBC,gBAAQ,KADY;AAEpBf,aAAK,wCAFe;AAGpBgB,gBAAQ;AACNd,mBAAS,kBADH;AAENe,2BAAiB,kBAFX;AAGNP,gBAAM,KAHA;AAINC,cAAI,KAJE;AAKNL,iBAAO;AALD;AAHY,OAAtB;AAWA,UAAId,oBAAoB,gBAAM0B,GAAN,CAAU9B,IAAIgB,EAAJ,CAAOb,UAAjB,EAA6B,mBAA7B,CAAxB;;AAEAH,UAAIgB,EAAJ,CAAOE,KAAP,CAAalB,IAAIoB,OAAjB;AACAW,aAAO3B,iBAAP,EAA0BmB,EAA1B,CAA6BS,IAA7B,CAAkCC,IAAlC,CAAuCC,UAAvC,CAAkDR,eAAlD;AACAD;AACD,KAjBD;AAkBD,GAjCD;AAkCD,CA7DD","file":"datasource_spec.js","sourcesContent":["import {Datasource} from \"../module\";\nimport Q from \"q\";\nimport sinon from 'sinon';\n\ndescribe('DataDogDatasource', () => {\n let ctx = {};\n\n beforeEach(function() {\n ctx.$q = Q;\n ctx.backendSrv = {\n datasourceRequest: () => {\n return ctx.$q.when({\n status: 200\n });\n }\n };\n ctx.templateSrv = {\n replace: (str) => str,\n getAdhocFilters: () => []\n };\n\n let instanceSettings = {\n url: 'https://app.datadoghq.com/api/v1',\n jsonData: {\n api_key: '0000deadbeaf0000',\n app_key: '0000abcd0000abcd'\n }\n };\n ctx.ds = new Datasource(instanceSettings, ctx.backendSrv, ctx.templateSrv);\n });\n\n describe('When doing DataDog API request', () => {\n beforeEach(function() {\n let targets = [\n { query: 'avg:system.load.5{*}', rawQuery: true }\n ];\n\n ctx.options = {\n range: {\n from: 12340000,\n to: 12340000\n },\n targets: targets\n };\n });\n\n it('should send request with proper params', (done) => {\n let expected_params = {\n method: 'GET',\n url: 'https://app.datadoghq.com/api/v1/query',\n params: {\n api_key: '0000deadbeaf0000',\n application_key: '0000abcd0000abcd',\n from: 12340,\n to: 12340,\n query: 'avg:system.load.5{*}'\n }\n };\n let datasourceRequest = sinon.spy(ctx.ds.backendSrv, 'datasourceRequest');\n\n ctx.ds.query(ctx.options);\n expect(datasourceRequest).to.have.been.calledWith(expected_params);\n done();\n });\n });\n});\n"]}
@@ -0,0 +1,84 @@
'use strict';
var _dfunc = require('../dfunc');
var _dfunc2 = _interopRequireDefault(_dfunc);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
describe('when creating func instance from func names', function () {
it('should return func instance', function () {
var func = _dfunc2.default.createFuncInstance('top');
expect(func).to.be.ok;
expect(func.def.name).to.equal('top');
expect(func.def.params.length).to.equal(3);
expect(func.def.defaultParams.length).to.equal(3);
});
it('should return func instance from funcDef', function () {
var func = _dfunc2.default.createFuncInstance('top');
var func2 = _dfunc2.default.createFuncInstance(func.def);
expect(func2).to.be.ok;
});
it('func instance should have text representation', function () {
var func = _dfunc2.default.createFuncInstance('top');
func.params[0] = 5;
func.params[1] = 'mean';
func.params[2] = 'dir';
func.updateText();
expect(func.text).to.equal("top(5, mean, dir)");
});
});
describe('when rendering func instance', function () {
it('should handle single metric param', function () {
var func = _dfunc2.default.createFuncInstance('abs');
expect(func.render('a')).to.equal("abs(a)");
});
it('should include default params if options enable it', function () {
var func = _dfunc2.default.createFuncInstance('top', { withDefaultParams: true });
expect(func.render('a')).to.equal("top(a, 5, mean, dir)");
});
it('should handle int or interval params with number', function () {
var func = _dfunc2.default.createFuncInstance('anomalies');
func.params[0] = 'basic';
func.params[1] = '5';
expect(func.render('hello')).to.equal("anomalies(hello, basic, 5)");
});
});
describe('when requesting function categories', function () {
it('should return function categories', function () {
var catIndex = _dfunc2.default.getCategories();
expect(catIndex.Arithmatic.length).to.be.greaterThan(3);
});
});
describe('when updating func param', function () {
it('should update param value and update text representation', function () {
var func = _dfunc2.default.createFuncInstance('top', { withDefaultParams: true });
func.updateParam('10', 0);
expect(func.params[0]).to.be.equal('10');
func.updateText();
expect(func.text).to.be.equal('top(10, mean, dir)');
});
it('should parse numbers as float', function () {
var func = _dfunc2.default.createFuncInstance('outliers');
func.updateParam('0.5', 1);
expect(func.params[1]).to.be.equal('0.5');
});
});
describe('when updating func param with optional second parameter', function () {
it('should update value and text', function () {
var func = _dfunc2.default.createFuncInstance('fill');
func.updateParam('null', 0);
expect(func.params[0]).to.be.equal('null');
});
});
//# sourceMappingURL=dfunc_spec.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,194 @@
'use strict';
var _module = require('../module');
require('app/core/services/segment_srv');
var _sinon = require('sinon');
var _sinon2 = _interopRequireDefault(_sinon);
var _dfunc = require('../dfunc');
var _dfunc2 = _interopRequireDefault(_dfunc);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
describe('DataDogQueryCtrl', function () {
var ctx = {};
beforeEach(angularMocks.module('grafana.core'));
beforeEach(angularMocks.module('grafana.controllers'));
beforeEach(angularMocks.module('grafana.services'));
beforeEach(ctx.providePhase());
beforeEach(angularMocks.inject(function ($rootScope, $controller, $q) {
ctx.$q = $q;
ctx.scope = $rootScope.$new();
ctx.target = {};
ctx.datasource.metricFindQuery = _sinon2.default.stub().returns(ctx.$q.when([]));
ctx.panelCtrl = { panel: {} };
ctx.panelCtrl.refresh = _sinon2.default.spy();
ctx.ctrl = $controller(_module.QueryCtrl, { $scope: ctx.scope }, {
panelCtrl: ctx.panelCtrl,
datasource: ctx.datasource,
target: ctx.target
});
ctx.scope.$digest();
}));
describe('init', function () {
it('should validate metric key exists', function () {
expect(ctx.datasource.metricFindQuery.getCall(0).args[0]).to.be('test.prod.*');
});
it('should delete last segment if no metrics are found', function () {
expect(ctx.ctrl.segments[2].value).to.be('select metric');
});
it('should parse expression and build function model', function () {
expect(ctx.ctrl.functions.length).to.be(2);
});
});
describe('when adding function', function () {
beforeEach(function () {
ctx.ctrl.target.target = 'test.prod.*.count';
ctx.ctrl.datasource.metricFindQuery = _sinon2.default.stub().returns(ctx.$q.when([{ expandable: false }]));
ctx.ctrl.parseTarget();
ctx.ctrl.addFunction(gfunc.getFuncDef('aliasByNode'));
});
it('should add function with correct node number', function () {
expect(ctx.ctrl.functions[0].params[0]).to.be(2);
});
it('should update target', function () {
expect(ctx.ctrl.target.target).to.be('aliasByNode(test.prod.*.count, 2)');
});
it('should call refresh', function () {
expect(ctx.panelCtrl.refresh.called).to.be(true);
});
});
describe('when adding function before any metric segment', function () {
beforeEach(function () {
ctx.ctrl.target.target = '';
ctx.ctrl.datasource.metricFindQuery.returns(ctx.$q.when([{ expandable: true }]));
ctx.ctrl.parseTarget();
ctx.ctrl.addFunction(gfunc.getFuncDef('asPercent'));
});
it('should add function and remove select metric link', function () {
expect(ctx.ctrl.segments.length).to.be(0);
});
});
describe('when initalizing target without metric expression and only function', function () {
beforeEach(function () {
ctx.ctrl.target.target = 'asPercent(#A, #B)';
ctx.ctrl.datasource.metricFindQuery.returns(ctx.$q.when([]));
ctx.ctrl.parseTarget();
ctx.scope.$digest();
});
it('should not add select metric segment', function () {
expect(ctx.ctrl.segments.length).to.be(0);
});
it('should add both series refs as params', function () {
expect(ctx.ctrl.functions[0].params.length).to.be(2);
});
});
describe('when initializing a target with single param func using variable', function () {
beforeEach(function () {
ctx.ctrl.target.target = 'movingAverage(prod.count, $var)';
ctx.ctrl.datasource.metricFindQuery.returns(ctx.$q.when([]));
ctx.ctrl.parseTarget();
});
it('should add 2 segments', function () {
expect(ctx.ctrl.segments.length).to.be(2);
});
it('should add function param', function () {
expect(ctx.ctrl.functions[0].params.length).to.be(1);
});
});
describe('when initalizing target without metric expression and function with series-ref', function () {
beforeEach(function () {
ctx.ctrl.target.target = 'asPercent(metric.node.count, #A)';
ctx.ctrl.datasource.metricFindQuery.returns(ctx.$q.when([]));
ctx.ctrl.parseTarget();
});
it('should add segments', function () {
expect(ctx.ctrl.segments.length).to.be(3);
});
it('should have correct func params', function () {
expect(ctx.ctrl.functions[0].params.length).to.be(1);
});
});
describe('when getting altSegments and metricFindQuery retuns empty array', function () {
beforeEach(function () {
ctx.ctrl.target.target = 'test.count';
ctx.ctrl.datasource.metricFindQuery.returns(ctx.$q.when([]));
ctx.ctrl.parseTarget();
ctx.ctrl.getAltSegments(1).then(function (results) {
ctx.altSegments = results;
});
ctx.scope.$digest();
});
it('should have no segments', function () {
expect(ctx.altSegments.length).to.be(0);
});
});
describe('targetChanged', function () {
beforeEach(function () {
ctx.ctrl.datasource.metricFindQuery = _sinon2.default.stub().returns(ctx.$q.when([{ expandable: false }]));
ctx.ctrl.parseTarget();
ctx.ctrl.target.target = '';
ctx.ctrl.targetChanged();
});
it('should rebuld target after expression model', function () {
expect(ctx.ctrl.target.target).to.be('aliasByNode(scaleToSeconds(test.prod.*, 1), 2)');
});
it('should call panelCtrl.refresh', function () {
expect(ctx.panelCtrl.refresh.called).to.be(true);
});
});
describe('when updating targets with nested query', function () {
beforeEach(function () {
ctx.ctrl.target.target = 'scaleToSeconds(#A)';
ctx.ctrl.datasource.metricFindQuery = _sinon2.default.stub().returns(ctx.$q.when([{ expandable: false }]));
ctx.ctrl.parseTarget();
ctx.ctrl.panelCtrl.panel.targets = [{
target: 'nested.query.count',
refId: 'A'
}];
ctx.ctrl.updateModelTarget();
});
it('target should remain the same', function () {
expect(ctx.ctrl.target.target).to.be('scaleToSeconds(#A)');
});
it('targetFull should include nexted queries', function () {
expect(ctx.ctrl.target.targetFull).to.be('scaleToSeconds(nested.query.count)');
});
});
});
//# sourceMappingURL=query_ctrl_soon.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,64 @@
'use strict';
var _prunk = require('prunk');
var _prunk2 = _interopRequireDefault(_prunk);
var _jsdom = require('jsdom');
var _chai = require('chai');
var _chai2 = _interopRequireDefault(_chai);
var _sinonChai = require('sinon-chai');
var _sinonChai2 = _interopRequireDefault(_sinonChai);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
// Mock angular module
// JSHint options
/* globals global: false */
var angularMocks = {
module: function module() {
return {
directive: function directive() {}
};
}
};
var datemathMock = {
parse: function parse() {}
};
var momentMock = {
duration: function duration(num, str) {
return 60;
}
};
// Mock Grafana modules that are not available outside of the core project
// Required for loading module.js
_prunk2.default.mock('./css/query-editor.css!', 'no css, dude.');
_prunk2.default.mock('app/plugins/sdk', {
QueryCtrl: null
});
_prunk2.default.mock('app/core/utils/datemath', datemathMock);
_prunk2.default.mock('moment', momentMock);
_prunk2.default.mock('angular', angularMocks);
_prunk2.default.mock('jquery', 'module not found');
// Setup jsdom
// Required for loading angularjs
global.document = (0, _jsdom.jsdom)('<html><head><script></script></head><body></body></html>');
global.window = global.document.parentWindow;
global.navigator = window.navigator = {};
global.Node = window.Node;
// Setup Chai
_chai2.default.should();
_chai2.default.use(_sinonChai2.default);
global.assert = _chai2.default.assert;
global.expect = _chai2.default.expect;
//# sourceMappingURL=test-main.js.map
@@ -0,0 +1 @@
{"version":3,"sources":["../../../spec/test-main.js"],"names":["angularMocks","module","directive","datemathMock","parse","momentMock","duration","num","str","mock","QueryCtrl","global","document","window","parentWindow","navigator","Node","should","use","assert","expect"],"mappings":";;AAGA;;;;AACA;;AACA;;;;AACA;;;;;;AAEA;AARA;AACA;;AAQA,IAAIA,eAAe;AACjBC,UAAQ,kBAAW;AACjB,WAAO;AACLC,iBAAW,qBAAW,CAAE;AADnB,KAAP;AAGD;AALgB,CAAnB;;AAQA,IAAIC,eAAe;AACjBC,SAAO,iBAAW,CAAE;AADH,CAAnB;;AAIA,IAAIC,aAAa;AACfC,YAAU,kBAASC,GAAT,EAAcC,GAAd,EAAmB;AAC3B,WAAO,EAAP;AACD;AAHc,CAAjB;;AAMA;AACA;AACA,gBAAMC,IAAN,CAAW,yBAAX,EAAsC,eAAtC;AACA,gBAAMA,IAAN,CAAW,iBAAX,EAA8B;AAC5BC,aAAW;AADiB,CAA9B;AAGA,gBAAMD,IAAN,CAAW,yBAAX,EAAsCN,YAAtC;AACA,gBAAMM,IAAN,CAAW,QAAX,EAAqBJ,UAArB;AACA,gBAAMI,IAAN,CAAW,SAAX,EAAsBT,YAAtB;AACA,gBAAMS,IAAN,CAAW,QAAX,EAAqB,kBAArB;;AAEA;AACA;AACAE,OAAOC,QAAP,GAAkB,kBAAM,0DAAN,CAAlB;AACAD,OAAOE,MAAP,GAAgBF,OAAOC,QAAP,CAAgBE,YAAhC;AACAH,OAAOI,SAAP,GAAmBF,OAAOE,SAAP,GAAmB,EAAtC;AACAJ,OAAOK,IAAP,GAAcH,OAAOG,IAArB;;AAEA;AACA,eAAKC,MAAL;AACA,eAAKC,GAAL;AACAP,OAAOQ,MAAP,GAAgB,eAAKA,MAArB;AACAR,OAAOS,MAAP,GAAgB,eAAKA,MAArB","file":"test-main.js","sourcesContent":["// JSHint options\n/* globals global: false */\n\nimport prunk from 'prunk';\nimport {jsdom} from 'jsdom';\nimport chai from 'chai';\nimport sinonChai from 'sinon-chai';\n\n// Mock angular module\nvar angularMocks = {\n module: function() {\n return {\n directive: function() {}\n };\n }\n};\n\nvar datemathMock = {\n parse: function() {}\n};\n\nvar momentMock = {\n duration: function(num, str) {\n return 60;\n }\n};\n\n// Mock Grafana modules that are not available outside of the core project\n// Required for loading module.js\nprunk.mock('./css/query-editor.css!', 'no css, dude.');\nprunk.mock('app/plugins/sdk', {\n QueryCtrl: null\n});\nprunk.mock('app/core/utils/datemath', datemathMock);\nprunk.mock('moment', momentMock);\nprunk.mock('angular', angularMocks);\nprunk.mock('jquery', 'module not found');\n\n// Setup jsdom\n// Required for loading angularjs\nglobal.document = jsdom('<html><head><script></script></head><body></body></html>');\nglobal.window = global.document.parentWindow;\nglobal.navigator = window.navigator = {};\nglobal.Node = window.Node;\n\n// Setup Chai\nchai.should();\nchai.use(sinonChai);\nglobal.assert = chai.assert;\nglobal.expect = chai.expect;\n"]}