mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Merge branch 'master' into postgres-query-builder
This commit is contained in:
commit
de917dfc4d
@ -27,7 +27,7 @@ Grafana will now persist all long term data in the database. How to configure th
|
|||||||
## User sessions
|
## User sessions
|
||||||
|
|
||||||
The second thing to consider is how to deal with user sessions and how to configure your load balancer infront of Grafana.
|
The second thing to consider is how to deal with user sessions and how to configure your load balancer infront of Grafana.
|
||||||
Grafana support two says of storing session data locally on disk or in a database/cache-server.
|
Grafana supports two ways of storing session data: locally on disk or in a database/cache-server.
|
||||||
If you want to store sessions on disk you can use `sticky sessions` in your load balanacer. If you prefer to store session data in a database/cache-server
|
If you want to store sessions on disk you can use `sticky sessions` in your load balanacer. If you prefer to store session data in a database/cache-server
|
||||||
you can use any stateless routing strategy in your load balancer (ex round robin or least connections).
|
you can use any stateless routing strategy in your load balancer (ex round robin or least connections).
|
||||||
|
|
||||||
|
@ -105,9 +105,9 @@ export class GrafanaApp {
|
|||||||
'react',
|
'react',
|
||||||
];
|
];
|
||||||
|
|
||||||
const module_types = ['controllers', 'directives', 'factories', 'services', 'filters', 'routes'];
|
const moduleTypes = ['controllers', 'directives', 'factories', 'services', 'filters', 'routes'];
|
||||||
|
|
||||||
_.each(module_types, type => {
|
_.each(moduleTypes, type => {
|
||||||
const moduleName = 'grafana.' + type;
|
const moduleName = 'grafana.' + type;
|
||||||
this.useModule(angular.module(moduleName, []));
|
this.useModule(angular.module(moduleName, []));
|
||||||
});
|
});
|
||||||
|
@ -84,7 +84,7 @@ function link(scope, elem, attrs) {
|
|||||||
// disable depreacation warning
|
// disable depreacation warning
|
||||||
codeEditor.$blockScrolling = Infinity;
|
codeEditor.$blockScrolling = Infinity;
|
||||||
// Padding hacks
|
// Padding hacks
|
||||||
(<any>codeEditor.renderer).setScrollMargin(15, 15);
|
(codeEditor.renderer as any).setScrollMargin(15, 15);
|
||||||
codeEditor.renderer.setPadding(10);
|
codeEditor.renderer.setPadding(10);
|
||||||
|
|
||||||
setThemeMode();
|
setThemeMode();
|
||||||
@ -152,7 +152,7 @@ function link(scope, elem, attrs) {
|
|||||||
|
|
||||||
if (scope.getCompleter()) {
|
if (scope.getCompleter()) {
|
||||||
// make copy of array as ace seems to share completers array between instances
|
// make copy of array as ace seems to share completers array between instances
|
||||||
const anyEditor = <any>codeEditor;
|
const anyEditor = codeEditor as any;
|
||||||
anyEditor.completers = anyEditor.completers.slice();
|
anyEditor.completers = anyEditor.completers.slice();
|
||||||
anyEditor.completers.push(scope.getCompleter());
|
anyEditor.completers.push(scope.getCompleter());
|
||||||
}
|
}
|
||||||
|
@ -11,9 +11,9 @@ export class Settings {
|
|||||||
datasources: any;
|
datasources: any;
|
||||||
panels: any;
|
panels: any;
|
||||||
appSubUrl: string;
|
appSubUrl: string;
|
||||||
window_title_prefix: string;
|
windowTitlePrefix: string;
|
||||||
buildInfo: BuildInfo;
|
buildInfo: BuildInfo;
|
||||||
new_panel_title: string;
|
newPanelTitle: string;
|
||||||
bootData: any;
|
bootData: any;
|
||||||
externalUserMngLinkUrl: string;
|
externalUserMngLinkUrl: string;
|
||||||
externalUserMngLinkName: string;
|
externalUserMngLinkName: string;
|
||||||
@ -51,7 +51,7 @@ export class Settings {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const bootData = (<any>window).grafanaBootData || { settings: {} };
|
const bootData = (window as any).grafanaBootData || { settings: {} };
|
||||||
const options = bootData.settings;
|
const options = bootData.settings;
|
||||||
options.bootData = bootData;
|
options.bootData = bootData;
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ export class InspectCtrl {
|
|||||||
if (keyValue[1].length > 0) {
|
if (keyValue[1].length > 0) {
|
||||||
result.push({
|
result.push({
|
||||||
key: keyValue[0],
|
key: keyValue[0],
|
||||||
value: (<any>window).unescape(keyValue[1]),
|
value: (window as any).unescape(keyValue[1]),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
let templates = (<any>require).context('../', true, /\.html$/);
|
let templates = (require as any).context('../', true, /\.html$/);
|
||||||
templates.keys().forEach(function(key) {
|
templates.keys().forEach(function(key) {
|
||||||
templates(key);
|
templates(key);
|
||||||
});
|
});
|
||||||
|
@ -12,13 +12,13 @@ export class Analytics {
|
|||||||
dataType: 'script',
|
dataType: 'script',
|
||||||
cache: true,
|
cache: true,
|
||||||
});
|
});
|
||||||
const ga = ((<any>window).ga =
|
const ga = ((window as any).ga =
|
||||||
(<any>window).ga ||
|
(window as any).ga ||
|
||||||
function() {
|
function() {
|
||||||
(ga.q = ga.q || []).push(arguments);
|
(ga.q = ga.q || []).push(arguments);
|
||||||
});
|
});
|
||||||
ga.l = +new Date();
|
ga.l = +new Date();
|
||||||
ga('create', (<any>config).googleAnalyticsId, 'auto');
|
ga('create', (config as any).googleAnalyticsId, 'auto');
|
||||||
ga('set', 'anonymizeIp', true);
|
ga('set', 'anonymizeIp', true);
|
||||||
return ga;
|
return ga;
|
||||||
}
|
}
|
||||||
@ -26,7 +26,7 @@ export class Analytics {
|
|||||||
init() {
|
init() {
|
||||||
this.$rootScope.$on('$viewContentLoaded', () => {
|
this.$rootScope.$on('$viewContentLoaded', () => {
|
||||||
const track = { page: this.$location.url() };
|
const track = { page: this.$location.url() };
|
||||||
const ga = (<any>window).ga || this.gaInit();
|
const ga = (window as any).ga || this.gaInit();
|
||||||
ga('set', track);
|
ga('set', track);
|
||||||
ga('send', 'pageview');
|
ga('send', 'pageview');
|
||||||
});
|
});
|
||||||
@ -35,7 +35,7 @@ export class Analytics {
|
|||||||
|
|
||||||
/** @ngInject */
|
/** @ngInject */
|
||||||
function startAnalytics(googleAnalyticsSrv) {
|
function startAnalytics(googleAnalyticsSrv) {
|
||||||
if ((<any>config).googleAnalyticsId) {
|
if ((config as any).googleAnalyticsId) {
|
||||||
googleAnalyticsSrv.init();
|
googleAnalyticsSrv.init();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -562,5 +562,5 @@ function createCtrlWithStubs(searchResponse: any, tags?: any) {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
return new ManageDashboardsCtrl({}, { getNav: () => {} }, <SearchSrv>searchSrvStub, { isEditor: true });
|
return new ManageDashboardsCtrl({}, { getNav: () => {} }, searchSrvStub as SearchSrv, { isEditor: true });
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ describe('SearchCtrl', () => {
|
|||||||
search: (options: any) => {},
|
search: (options: any) => {},
|
||||||
getDashboardTags: () => {},
|
getDashboardTags: () => {},
|
||||||
};
|
};
|
||||||
const ctrl = new SearchCtrl({ $on: () => {} }, {}, {}, <SearchSrv>searchSrvStub);
|
const ctrl = new SearchCtrl({ $on: () => {} }, {}, {}, searchSrvStub as SearchSrv);
|
||||||
|
|
||||||
describe('Given an empty result', () => {
|
describe('Given an empty result', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
@ -2,32 +2,32 @@
|
|||||||
function outlineFixer() {
|
function outlineFixer() {
|
||||||
const d: any = document;
|
const d: any = document;
|
||||||
|
|
||||||
const style_element = d.createElement('STYLE');
|
const styleElement = d.createElement('STYLE');
|
||||||
const dom_events = 'addEventListener' in d;
|
const domEvents = 'addEventListener' in d;
|
||||||
|
|
||||||
const add_event_listener = function(type, callback) {
|
const addEventListener = function(type, callback) {
|
||||||
// Basic cross-browser event handling
|
// Basic cross-browser event handling
|
||||||
if (dom_events) {
|
if (domEvents) {
|
||||||
d.addEventListener(type, callback);
|
d.addEventListener(type, callback);
|
||||||
} else {
|
} else {
|
||||||
d.attachEvent('on' + type, callback);
|
d.attachEvent('on' + type, callback);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const set_css = function(css_text) {
|
const setCss = function(cssText) {
|
||||||
// Handle setting of <style> element contents in IE8
|
// Handle setting of <style> element contents in IE8
|
||||||
!!style_element.styleSheet ? (style_element.styleSheet.cssText = css_text) : (style_element.innerHTML = css_text);
|
!!styleElement.styleSheet ? (styleElement.styleSheet.cssText = cssText) : (styleElement.innerHTML = cssText);
|
||||||
};
|
};
|
||||||
|
|
||||||
d.getElementsByTagName('HEAD')[0].appendChild(style_element);
|
d.getElementsByTagName('HEAD')[0].appendChild(styleElement);
|
||||||
|
|
||||||
// Using mousedown instead of mouseover, so that previously focused elements don't lose focus ring on mouse move
|
// Using mousedown instead of mouseover, so that previously focused elements don't lose focus ring on mouse move
|
||||||
add_event_listener('mousedown', function() {
|
addEventListener('mousedown', function() {
|
||||||
set_css(':focus{outline:0 !important}::-moz-focus-inner{border:0;}');
|
setCss(':focus{outline:0 !important}::-moz-focus-inner{border:0;}');
|
||||||
});
|
});
|
||||||
|
|
||||||
add_event_listener('keydown', function() {
|
addEventListener('keydown', function() {
|
||||||
set_css('');
|
setCss('');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,8 +26,8 @@ export function tickStep(start: number, stop: number, count: number): number {
|
|||||||
return stop < start ? -step1 : step1;
|
return stop < start ? -step1 : step1;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getScaledDecimals(decimals, tick_size) {
|
export function getScaledDecimals(decimals, tickSize) {
|
||||||
return decimals - Math.floor(Math.log(tick_size) / Math.LN10);
|
return decimals - Math.floor(Math.log(tickSize) / Math.LN10);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -201,10 +201,10 @@ export function getPrecision(num: number): number {
|
|||||||
* Get decimal precision of number stored as a string ("3.14" => 2)
|
* Get decimal precision of number stored as a string ("3.14" => 2)
|
||||||
*/
|
*/
|
||||||
export function getStringPrecision(num: string): number {
|
export function getStringPrecision(num: string): number {
|
||||||
const dot_index = num.indexOf('.');
|
const dotIndex = num.indexOf('.');
|
||||||
if (dot_index === -1) {
|
if (dotIndex === -1) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
return num.length - dot_index - 1;
|
return num.length - dotIndex - 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,6 @@ export class SemVersion {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function isVersionGtOrEq(a: string, b: string): boolean {
|
export function isVersionGtOrEq(a: string, b: string): boolean {
|
||||||
const a_semver = new SemVersion(a);
|
const aSemver = new SemVersion(a);
|
||||||
return a_semver.isGtOrEq(b);
|
return aSemver.isGtOrEq(b);
|
||||||
}
|
}
|
||||||
|
@ -14,33 +14,33 @@ export function makeRegions(annotations, options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getRegions(events, range) {
|
function getRegions(events, range) {
|
||||||
const region_events = _.filter(events, event => {
|
const regionEvents = _.filter(events, event => {
|
||||||
return event.regionId;
|
return event.regionId;
|
||||||
});
|
});
|
||||||
let regions = _.groupBy(region_events, 'regionId');
|
let regions = _.groupBy(regionEvents, 'regionId');
|
||||||
regions = _.compact(
|
regions = _.compact(
|
||||||
_.map(regions, region_events => {
|
_.map(regions, regionEvents => {
|
||||||
const region_obj = _.head(region_events);
|
const regionObj = _.head(regionEvents);
|
||||||
if (region_events && region_events.length > 1) {
|
if (regionEvents && regionEvents.length > 1) {
|
||||||
region_obj.timeEnd = region_events[1].time;
|
regionObj.timeEnd = regionEvents[1].time;
|
||||||
region_obj.isRegion = true;
|
regionObj.isRegion = true;
|
||||||
return region_obj;
|
return regionObj;
|
||||||
} else {
|
} else {
|
||||||
if (region_events && region_events.length) {
|
if (regionEvents && regionEvents.length) {
|
||||||
// Don't change proper region object
|
// Don't change proper region object
|
||||||
if (!region_obj.time || !region_obj.timeEnd) {
|
if (!regionObj.time || !regionObj.timeEnd) {
|
||||||
// This is cut region
|
// This is cut region
|
||||||
if (isStartOfRegion(region_obj)) {
|
if (isStartOfRegion(regionObj)) {
|
||||||
region_obj.timeEnd = range.to.valueOf() - 1;
|
regionObj.timeEnd = range.to.valueOf() - 1;
|
||||||
} else {
|
} else {
|
||||||
// Start time = null
|
// Start time = null
|
||||||
region_obj.timeEnd = region_obj.time;
|
regionObj.timeEnd = regionObj.time;
|
||||||
region_obj.time = range.from.valueOf() + 1;
|
regionObj.time = range.from.valueOf() + 1;
|
||||||
}
|
}
|
||||||
region_obj.isRegion = true;
|
regionObj.isRegion = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return region_obj;
|
return regionObj;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -102,7 +102,7 @@ export class DashboardCtrl implements PanelContainer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setWindowTitleAndTheme() {
|
setWindowTitleAndTheme() {
|
||||||
window.document.title = config.window_title_prefix + this.dashboard.title;
|
window.document.title = config.windowTitlePrefix + this.dashboard.title;
|
||||||
}
|
}
|
||||||
|
|
||||||
showJsonEditor(evt, options) {
|
showJsonEditor(evt, options) {
|
||||||
|
@ -106,7 +106,7 @@ export class DashboardLoaderSrv {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/*jshint -W054 */
|
/*jshint -W054 */
|
||||||
const script_func = new Function(
|
const scriptFunc = new Function(
|
||||||
'ARGS',
|
'ARGS',
|
||||||
'kbn',
|
'kbn',
|
||||||
'dateMath',
|
'dateMath',
|
||||||
@ -119,12 +119,12 @@ export class DashboardLoaderSrv {
|
|||||||
'services',
|
'services',
|
||||||
result.data
|
result.data
|
||||||
);
|
);
|
||||||
const script_result = script_func(this.$routeParams, kbn, dateMath, _, moment, window, document, $, $, services);
|
const scriptResult = scriptFunc(this.$routeParams, kbn, dateMath, _, moment, window, document, $, $, services);
|
||||||
|
|
||||||
// Handle async dashboard scripts
|
// Handle async dashboard scripts
|
||||||
if (_.isFunction(script_result)) {
|
if (_.isFunction(scriptResult)) {
|
||||||
const deferred = this.$q.defer();
|
const deferred = this.$q.defer();
|
||||||
script_result(dashboard => {
|
scriptResult(dashboard => {
|
||||||
this.$timeout(() => {
|
this.$timeout(() => {
|
||||||
deferred.resolve({ data: dashboard });
|
deferred.resolve({ data: dashboard });
|
||||||
});
|
});
|
||||||
@ -132,7 +132,7 @@ export class DashboardLoaderSrv {
|
|||||||
return deferred.promise;
|
return deferred.promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
return { data: script_result };
|
return { data: scriptResult };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,11 +94,11 @@ export function ShareModalCtrl($scope, $rootScope, $location, $timeout, timeSrv,
|
|||||||
const utcOffset = '&tz=UTC' + encodeURIComponent(moment().format('Z'));
|
const utcOffset = '&tz=UTC' + encodeURIComponent(moment().format('Z'));
|
||||||
|
|
||||||
// Older browser does not the internationalization API
|
// Older browser does not the internationalization API
|
||||||
if (!(<any>window).Intl) {
|
if (!(window as any).Intl) {
|
||||||
return utcOffset;
|
return utcOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
const dateFormat = (<any>window).Intl.DateTimeFormat();
|
const dateFormat = (window as any).Intl.DateTimeFormat();
|
||||||
if (!dateFormat.resolvedOptions) {
|
if (!dateFormat.resolvedOptions) {
|
||||||
return utcOffset;
|
return utcOffset;
|
||||||
}
|
}
|
||||||
|
@ -271,8 +271,8 @@ describe('given dashboard with row repeat and panel repeat in horizontal directi
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should panels in self row', () => {
|
it('should panels in self row', () => {
|
||||||
const panel_types = _.map(dashboard.panels, 'type');
|
const panelTypes = _.map(dashboard.panels, 'type');
|
||||||
expect(panel_types).toEqual([
|
expect(panelTypes).toEqual([
|
||||||
'row',
|
'row',
|
||||||
'graph',
|
'graph',
|
||||||
'graph',
|
'graph',
|
||||||
@ -350,8 +350,8 @@ describe('given dashboard with row repeat', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should not repeat only row', function() {
|
it('should not repeat only row', function() {
|
||||||
const panel_types = _.map(dashboard.panels, 'type');
|
const panelTypes = _.map(dashboard.panels, 'type');
|
||||||
expect(panel_types).toEqual(['row', 'graph', 'graph', 'row', 'graph', 'graph', 'row', 'graph']);
|
expect(panelTypes).toEqual(['row', 'graph', 'graph', 'row', 'graph', 'graph', 'row', 'graph']);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should set scopedVars for each panel', function() {
|
it('should set scopedVars for each panel', function() {
|
||||||
@ -399,8 +399,8 @@ describe('given dashboard with row repeat', function() {
|
|||||||
dashboard = new DashboardModel(dashboardJSON);
|
dashboard = new DashboardModel(dashboardJSON);
|
||||||
dashboard.processRepeats();
|
dashboard.processRepeats();
|
||||||
|
|
||||||
const panel_types = _.map(dashboard.panels, 'type');
|
const panelTypes = _.map(dashboard.panels, 'type');
|
||||||
expect(panel_types).toEqual(['row', 'row', 'row', 'graph']);
|
expect(panelTypes).toEqual(['row', 'row', 'row', 'graph']);
|
||||||
expect(dashboard.panels[0].panels).toHaveLength(2);
|
expect(dashboard.panels[0].panels).toHaveLength(2);
|
||||||
expect(dashboard.panels[1].panels).toHaveLength(2);
|
expect(dashboard.panels[1].panels).toHaveLength(2);
|
||||||
});
|
});
|
||||||
@ -441,8 +441,8 @@ describe('given dashboard with row repeat', function() {
|
|||||||
dashboard = new DashboardModel(dashboardJSON);
|
dashboard = new DashboardModel(dashboardJSON);
|
||||||
dashboard.processRepeats();
|
dashboard.processRepeats();
|
||||||
|
|
||||||
const panel_types = _.map(dashboard.panels, 'type');
|
const panelTypes = _.map(dashboard.panels, 'type');
|
||||||
expect(panel_types).toEqual([
|
expect(panelTypes).toEqual([
|
||||||
'row',
|
'row',
|
||||||
'graph',
|
'graph',
|
||||||
'graph',
|
'graph',
|
||||||
@ -488,7 +488,7 @@ describe('given dashboard with row repeat', function() {
|
|||||||
dashboard = new DashboardModel(dashboardJSON);
|
dashboard = new DashboardModel(dashboardJSON);
|
||||||
dashboard.processRepeats();
|
dashboard.processRepeats();
|
||||||
|
|
||||||
const panel_ids = _.flattenDeep(
|
const panelIds = _.flattenDeep(
|
||||||
_.map(dashboard.panels, panel => {
|
_.map(dashboard.panels, panel => {
|
||||||
let ids = [];
|
let ids = [];
|
||||||
if (panel.panels && panel.panels.length) {
|
if (panel.panels && panel.panels.length) {
|
||||||
@ -498,7 +498,7 @@ describe('given dashboard with row repeat', function() {
|
|||||||
return ids;
|
return ids;
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
expect(panel_ids.length).toEqual(_.uniq(panel_ids).length);
|
expect(panelIds.length).toEqual(_.uniq(panelIds).length);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should place new panels in proper order', function() {
|
it('should place new panels in proper order', function() {
|
||||||
@ -511,10 +511,10 @@ describe('given dashboard with row repeat', function() {
|
|||||||
dashboard = new DashboardModel(dashboardJSON);
|
dashboard = new DashboardModel(dashboardJSON);
|
||||||
dashboard.processRepeats();
|
dashboard.processRepeats();
|
||||||
|
|
||||||
const panel_types = _.map(dashboard.panels, 'type');
|
const panelTypes = _.map(dashboard.panels, 'type');
|
||||||
expect(panel_types).toEqual(['row', 'graph', 'graph', 'graph', 'row', 'graph', 'graph', 'graph']);
|
expect(panelTypes).toEqual(['row', 'graph', 'graph', 'graph', 'row', 'graph', 'graph', 'graph']);
|
||||||
const panel_y_positions = _.map(dashboard.panels, p => p.gridPos.y);
|
const panelYPositions = _.map(dashboard.panels, p => p.gridPos.y);
|
||||||
expect(panel_y_positions).toEqual([0, 1, 1, 5, 7, 8, 8, 12]);
|
expect(panelYPositions).toEqual([0, 1, 1, 5, 7, 8, 8, 12]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -566,8 +566,8 @@ describe('given dashboard with row and panel repeat', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should repeat row and panels for each row', () => {
|
it('should repeat row and panels for each row', () => {
|
||||||
const panel_types = _.map(dashboard.panels, 'type');
|
const panelTypes = _.map(dashboard.panels, 'type');
|
||||||
expect(panel_types).toEqual(['row', 'graph', 'graph', 'row', 'graph', 'graph']);
|
expect(panelTypes).toEqual(['row', 'graph', 'graph', 'row', 'graph', 'graph']);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should clean up old repeated panels', () => {
|
it('should clean up old repeated panels', () => {
|
||||||
@ -592,8 +592,8 @@ describe('given dashboard with row and panel repeat', () => {
|
|||||||
dashboard = new DashboardModel(dashboardJSON);
|
dashboard = new DashboardModel(dashboardJSON);
|
||||||
dashboard.processRepeats();
|
dashboard.processRepeats();
|
||||||
|
|
||||||
const panel_types = _.map(dashboard.panels, 'type');
|
const panelTypes = _.map(dashboard.panels, 'type');
|
||||||
expect(panel_types).toEqual(['row', 'graph', 'graph', 'row', 'graph', 'graph']);
|
expect(panelTypes).toEqual(['row', 'graph', 'graph', 'row', 'graph', 'graph']);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should set scopedVars for each row', () => {
|
it('should set scopedVars for each row', () => {
|
||||||
|
@ -4,7 +4,7 @@ import config from 'app/core/config';
|
|||||||
import { LinkSrv } from 'app/features/panellinks/link_srv';
|
import { LinkSrv } from 'app/features/panellinks/link_srv';
|
||||||
|
|
||||||
describe('ShareModalCtrl', () => {
|
describe('ShareModalCtrl', () => {
|
||||||
const ctx = <any>{
|
const ctx = {
|
||||||
timeSrv: {
|
timeSrv: {
|
||||||
timeRange: () => {
|
timeRange: () => {
|
||||||
return { from: new Date(1000), to: new Date(2000) };
|
return { from: new Date(1000), to: new Date(2000) };
|
||||||
@ -26,9 +26,9 @@ describe('ShareModalCtrl', () => {
|
|||||||
templateSrv: {
|
templateSrv: {
|
||||||
fillVariableValuesForUrl: () => {},
|
fillVariableValuesForUrl: () => {},
|
||||||
},
|
},
|
||||||
};
|
} as any;
|
||||||
|
|
||||||
(<any>window).Intl.DateTimeFormat = () => {
|
(window as any).Intl.DateTimeFormat = () => {
|
||||||
return {
|
return {
|
||||||
resolvedOptions: () => {
|
resolvedOptions: () => {
|
||||||
return { timeZone: 'UTC' };
|
return { timeZone: 'UTC' };
|
||||||
|
@ -3,7 +3,7 @@ import { coreModule } from 'app/core/core';
|
|||||||
|
|
||||||
export class ProfileCtrl {
|
export class ProfileCtrl {
|
||||||
user: any;
|
user: any;
|
||||||
old_theme: any;
|
oldTheme: any;
|
||||||
teams: any = [];
|
teams: any = [];
|
||||||
orgs: any = [];
|
orgs: any = [];
|
||||||
userForm: any;
|
userForm: any;
|
||||||
@ -54,7 +54,7 @@ export class ProfileCtrl {
|
|||||||
|
|
||||||
this.backendSrv.put('/api/user/', this.user).then(() => {
|
this.backendSrv.put('/api/user/', this.user).then(() => {
|
||||||
this.contextSrv.user.name = this.user.name || this.user.login;
|
this.contextSrv.user.name = this.user.name || this.user.login;
|
||||||
if (this.old_theme !== this.user.theme) {
|
if (this.oldTheme !== this.user.theme) {
|
||||||
window.location.href = config.appSubUrl + this.$location.path();
|
window.location.href = config.appSubUrl + this.$location.path();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -4,8 +4,8 @@ import { Variable, assignModelProperties, variableTypes } from './variable';
|
|||||||
|
|
||||||
export class IntervalVariable implements Variable {
|
export class IntervalVariable implements Variable {
|
||||||
name: string;
|
name: string;
|
||||||
auto_count: number;
|
auto_count: number; // tslint:disable-line variable-name
|
||||||
auto_min: number;
|
auto_min: number; // tslint:disable-line variable-name
|
||||||
options: any;
|
options: any;
|
||||||
auto: boolean;
|
auto: boolean;
|
||||||
query: string;
|
query: string;
|
||||||
|
@ -4,7 +4,7 @@ import moment from 'moment';
|
|||||||
import $q from 'q';
|
import $q from 'q';
|
||||||
|
|
||||||
describe('VariableSrv', function(this: any) {
|
describe('VariableSrv', function(this: any) {
|
||||||
const ctx = <any>{
|
const ctx = {
|
||||||
datasourceSrv: {},
|
datasourceSrv: {},
|
||||||
timeSrv: {
|
timeSrv: {
|
||||||
timeRange: () => {},
|
timeRange: () => {},
|
||||||
@ -29,7 +29,7 @@ describe('VariableSrv', function(this: any) {
|
|||||||
$location: {
|
$location: {
|
||||||
search: () => {},
|
search: () => {},
|
||||||
},
|
},
|
||||||
};
|
} as any;
|
||||||
|
|
||||||
function describeUpdateVariable(desc, fn) {
|
function describeUpdateVariable(desc, fn) {
|
||||||
describe(desc, () => {
|
describe(desc, () => {
|
||||||
|
@ -17,12 +17,12 @@ describe('VariableSrv init', function(this: any) {
|
|||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
const $injector = <any>{};
|
const $injector = {} as any;
|
||||||
const $rootscope = {
|
const $rootscope = {
|
||||||
$on: () => {},
|
$on: () => {},
|
||||||
};
|
};
|
||||||
|
|
||||||
let ctx = <any>{};
|
let ctx = {} as any;
|
||||||
|
|
||||||
function describeInitScenario(desc, fn) {
|
function describeInitScenario(desc, fn) {
|
||||||
describe(desc, () => {
|
describe(desc, () => {
|
||||||
|
@ -25,10 +25,10 @@ describe('CloudWatchDatasource', function() {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
const backendSrv = {};
|
const backendSrv = {};
|
||||||
const ctx = <any>{
|
const ctx = {
|
||||||
backendSrv,
|
backendSrv,
|
||||||
templateSrv,
|
templateSrv,
|
||||||
};
|
} as any;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
ctx.ds = new CloudWatchDatasource(instanceSettings, {}, backendSrv, templateSrv, timeSrv);
|
ctx.ds = new CloudWatchDatasource(instanceSettings, {}, backendSrv, templateSrv, timeSrv);
|
||||||
|
@ -57,9 +57,9 @@ export class ElasticDatasource {
|
|||||||
|
|
||||||
private get(url) {
|
private get(url) {
|
||||||
const range = this.timeSrv.timeRange();
|
const range = this.timeSrv.timeRange();
|
||||||
const index_list = this.indexPattern.getIndexList(range.from.valueOf(), range.to.valueOf());
|
const indexList = this.indexPattern.getIndexList(range.from.valueOf(), range.to.valueOf());
|
||||||
if (_.isArray(index_list) && index_list.length) {
|
if (_.isArray(indexList) && indexList.length) {
|
||||||
return this.request('GET', index_list[0] + url).then(function(results) {
|
return this.request('GET', indexList[0] + url).then(function(results) {
|
||||||
results.data.$$config = results.config;
|
results.data.$$config = results.config;
|
||||||
return results.data;
|
return results.data;
|
||||||
});
|
});
|
||||||
@ -229,15 +229,15 @@ export class ElasticDatasource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getQueryHeader(searchType, timeFrom, timeTo) {
|
getQueryHeader(searchType, timeFrom, timeTo) {
|
||||||
const query_header: any = {
|
const queryHeader: any = {
|
||||||
search_type: searchType,
|
search_type: searchType,
|
||||||
ignore_unavailable: true,
|
ignore_unavailable: true,
|
||||||
index: this.indexPattern.getIndexList(timeFrom, timeTo),
|
index: this.indexPattern.getIndexList(timeFrom, timeTo),
|
||||||
};
|
};
|
||||||
if (this.esVersion >= 56) {
|
if (this.esVersion >= 56) {
|
||||||
query_header['max_concurrent_shard_requests'] = this.maxConcurrentShardRequests;
|
queryHeader['max_concurrent_shard_requests'] = this.maxConcurrentShardRequests;
|
||||||
}
|
}
|
||||||
return angular.toJson(query_header);
|
return angular.toJson(queryHeader);
|
||||||
}
|
}
|
||||||
|
|
||||||
query(options) {
|
query(options) {
|
||||||
|
@ -67,8 +67,8 @@ export class ElasticMetricAggCtrl {
|
|||||||
}
|
}
|
||||||
switch ($scope.agg.type) {
|
switch ($scope.agg.type) {
|
||||||
case 'cardinality': {
|
case 'cardinality': {
|
||||||
const precision_threshold = $scope.agg.settings.precision_threshold || '';
|
const precisionThreshold = $scope.agg.settings.precision_threshold || '';
|
||||||
$scope.settingsLinkText = 'Precision threshold: ' + precision_threshold;
|
$scope.settingsLinkText = 'Precision threshold: ' + precisionThreshold;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'percentiles': {
|
case 'percentiles': {
|
||||||
|
@ -33,10 +33,10 @@ describe('ElasticDatasource', function(this: any) {
|
|||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
const ctx = <any>{
|
const ctx = {
|
||||||
$rootScope,
|
$rootScope,
|
||||||
backendSrv,
|
backendSrv,
|
||||||
};
|
} as any;
|
||||||
|
|
||||||
function createDatasource(instanceSettings) {
|
function createDatasource(instanceSettings) {
|
||||||
instanceSettings.jsonData = instanceSettings.jsonData || {};
|
instanceSettings.jsonData = instanceSettings.jsonData || {};
|
||||||
|
@ -19,12 +19,12 @@ describe('ElasticQueryBuilder', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('with defaults on es5.x', () => {
|
it('with defaults on es5.x', () => {
|
||||||
const builder_5x = new ElasticQueryBuilder({
|
const builder5x = new ElasticQueryBuilder({
|
||||||
timeField: '@timestamp',
|
timeField: '@timestamp',
|
||||||
esVersion: 5,
|
esVersion: 5,
|
||||||
});
|
});
|
||||||
|
|
||||||
const query = builder_5x.build({
|
const query = builder5x.build({
|
||||||
metrics: [{ type: 'Count', id: '0' }],
|
metrics: [{ type: 'Count', id: '0' }],
|
||||||
timeField: '@timestamp',
|
timeField: '@timestamp',
|
||||||
bucketAggs: [{ type: 'date_histogram', field: '@timestamp', id: '1' }],
|
bucketAggs: [{ type: 'date_histogram', field: '@timestamp', id: '1' }],
|
||||||
@ -134,11 +134,11 @@ describe('ElasticQueryBuilder', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('with filters aggs on es5.x', () => {
|
it('with filters aggs on es5.x', () => {
|
||||||
const builder_5x = new ElasticQueryBuilder({
|
const builder5x = new ElasticQueryBuilder({
|
||||||
timeField: '@timestamp',
|
timeField: '@timestamp',
|
||||||
esVersion: 5,
|
esVersion: 5,
|
||||||
});
|
});
|
||||||
const query = builder_5x.build({
|
const query = builder5x.build({
|
||||||
metrics: [{ type: 'count', id: '1' }],
|
metrics: [{ type: 'count', id: '1' }],
|
||||||
timeField: '@timestamp',
|
timeField: '@timestamp',
|
||||||
bucketAggs: [
|
bucketAggs: [
|
||||||
|
@ -490,8 +490,8 @@ export function GraphiteDatasource(this: any, instanceSettings, $q, backendSrv,
|
|||||||
this._seriesRefLetters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
this._seriesRefLetters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||||
|
|
||||||
this.buildGraphiteParams = function(options, scopedVars) {
|
this.buildGraphiteParams = function(options, scopedVars) {
|
||||||
const graphite_options = ['from', 'until', 'rawData', 'format', 'maxDataPoints', 'cacheTimeout'];
|
const graphiteOptions = ['from', 'until', 'rawData', 'format', 'maxDataPoints', 'cacheTimeout'];
|
||||||
const clean_options = [],
|
const cleanOptions = [],
|
||||||
targets = {};
|
targets = {};
|
||||||
let target, targetValue, i;
|
let target, targetValue, i;
|
||||||
const regex = /\#([A-Z])/g;
|
const regex = /\#([A-Z])/g;
|
||||||
@ -535,16 +535,16 @@ export function GraphiteDatasource(this: any, instanceSettings, $q, backendSrv,
|
|||||||
|
|
||||||
if (!target.hide) {
|
if (!target.hide) {
|
||||||
hasTargets = true;
|
hasTargets = true;
|
||||||
clean_options.push('target=' + encodeURIComponent(targetValue));
|
cleanOptions.push('target=' + encodeURIComponent(targetValue));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_.each(options, function(value, key) {
|
_.each(options, function(value, key) {
|
||||||
if (_.indexOf(graphite_options, key) === -1) {
|
if (_.indexOf(graphiteOptions, key) === -1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (value) {
|
if (value) {
|
||||||
clean_options.push(key + '=' + encodeURIComponent(value));
|
cleanOptions.push(key + '=' + encodeURIComponent(value));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -552,7 +552,7 @@ export function GraphiteDatasource(this: any, instanceSettings, $q, backendSrv,
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
return clean_options;
|
return cleanOptions;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ import gfunc from '../gfunc';
|
|||||||
import { GraphiteQueryCtrl } from '../query_ctrl';
|
import { GraphiteQueryCtrl } from '../query_ctrl';
|
||||||
|
|
||||||
describe('GraphiteQueryCtrl', () => {
|
describe('GraphiteQueryCtrl', () => {
|
||||||
const ctx = <any>{
|
const ctx = {
|
||||||
datasource: {
|
datasource: {
|
||||||
metricFindQuery: jest.fn(() => Promise.resolve([])),
|
metricFindQuery: jest.fn(() => Promise.resolve([])),
|
||||||
getFuncDefs: jest.fn(() => Promise.resolve(gfunc.getFuncDefs('1.0'))),
|
getFuncDefs: jest.fn(() => Promise.resolve(gfunc.getFuncDefs('1.0'))),
|
||||||
@ -15,7 +15,7 @@ describe('GraphiteQueryCtrl', () => {
|
|||||||
panelCtrl: {
|
panelCtrl: {
|
||||||
refresh: jest.fn(),
|
refresh: jest.fn(),
|
||||||
},
|
},
|
||||||
};
|
} as any;
|
||||||
|
|
||||||
ctx.panelCtrl.panel = {
|
ctx.panelCtrl.panel = {
|
||||||
targets: [ctx.target],
|
targets: [ctx.target],
|
||||||
|
@ -3,7 +3,7 @@ import { uiSegmentSrv } from 'app/core/services/segment_srv';
|
|||||||
import { InfluxQueryCtrl } from '../query_ctrl';
|
import { InfluxQueryCtrl } from '../query_ctrl';
|
||||||
|
|
||||||
describe('InfluxDBQueryCtrl', () => {
|
describe('InfluxDBQueryCtrl', () => {
|
||||||
const ctx = <any>{};
|
const ctx = {} as any;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
InfluxQueryCtrl.prototype.datasource = {
|
InfluxQueryCtrl.prototype.datasource = {
|
||||||
|
@ -9,9 +9,9 @@ describe('MySQLDatasource', function() {
|
|||||||
replace: jest.fn(text => text),
|
replace: jest.fn(text => text),
|
||||||
};
|
};
|
||||||
|
|
||||||
const ctx = <any>{
|
const ctx = {
|
||||||
backendSrv,
|
backendSrv,
|
||||||
};
|
} as any;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
ctx.ds = new MysqlDatasource(instanceSettings, backendSrv, {}, templateSrv);
|
ctx.ds = new MysqlDatasource(instanceSettings, backendSrv, {}, templateSrv);
|
||||||
|
@ -277,35 +277,35 @@ export default class OpenTsDatasource {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const metrics_regex = /metrics\((.*)\)/;
|
const metricsRegex = /metrics\((.*)\)/;
|
||||||
const tag_names_regex = /tag_names\((.*)\)/;
|
const tagNamesRegex = /tag_names\((.*)\)/;
|
||||||
const tag_values_regex = /tag_values\((.*?),\s?(.*)\)/;
|
const tagValuesRegex = /tag_values\((.*?),\s?(.*)\)/;
|
||||||
const tag_names_suggest_regex = /suggest_tagk\((.*)\)/;
|
const tagNamesSuggestRegex = /suggest_tagk\((.*)\)/;
|
||||||
const tag_values_suggest_regex = /suggest_tagv\((.*)\)/;
|
const tagValuesSuggestRegex = /suggest_tagv\((.*)\)/;
|
||||||
|
|
||||||
const metrics_query = interpolated.match(metrics_regex);
|
const metricsQuery = interpolated.match(metricsRegex);
|
||||||
if (metrics_query) {
|
if (metricsQuery) {
|
||||||
return this._performSuggestQuery(metrics_query[1], 'metrics').then(responseTransform);
|
return this._performSuggestQuery(metricsQuery[1], 'metrics').then(responseTransform);
|
||||||
}
|
}
|
||||||
|
|
||||||
const tag_names_query = interpolated.match(tag_names_regex);
|
const tagNamesQuery = interpolated.match(tagNamesRegex);
|
||||||
if (tag_names_query) {
|
if (tagNamesQuery) {
|
||||||
return this._performMetricKeyLookup(tag_names_query[1]).then(responseTransform);
|
return this._performMetricKeyLookup(tagNamesQuery[1]).then(responseTransform);
|
||||||
}
|
}
|
||||||
|
|
||||||
const tag_values_query = interpolated.match(tag_values_regex);
|
const tagValuesQuery = interpolated.match(tagValuesRegex);
|
||||||
if (tag_values_query) {
|
if (tagValuesQuery) {
|
||||||
return this._performMetricKeyValueLookup(tag_values_query[1], tag_values_query[2]).then(responseTransform);
|
return this._performMetricKeyValueLookup(tagValuesQuery[1], tagValuesQuery[2]).then(responseTransform);
|
||||||
}
|
}
|
||||||
|
|
||||||
const tag_names_suggest_query = interpolated.match(tag_names_suggest_regex);
|
const tagNamesSuggestQuery = interpolated.match(tagNamesSuggestRegex);
|
||||||
if (tag_names_suggest_query) {
|
if (tagNamesSuggestQuery) {
|
||||||
return this._performSuggestQuery(tag_names_suggest_query[1], 'tagk').then(responseTransform);
|
return this._performSuggestQuery(tagNamesSuggestQuery[1], 'tagk').then(responseTransform);
|
||||||
}
|
}
|
||||||
|
|
||||||
const tag_values_suggest_query = interpolated.match(tag_values_suggest_regex);
|
const tagValuesSuggestQuery = interpolated.match(tagValuesSuggestRegex);
|
||||||
if (tag_values_suggest_query) {
|
if (tagValuesSuggestQuery) {
|
||||||
return this._performSuggestQuery(tag_values_suggest_query[1], 'tagv').then(responseTransform);
|
return this._performSuggestQuery(tagValuesSuggestQuery[1], 'tagv').then(responseTransform);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.$q.when([]);
|
return this.$q.when([]);
|
||||||
@ -440,9 +440,9 @@ export default class OpenTsDatasource {
|
|||||||
if (target.filters && target.filters.length > 0) {
|
if (target.filters && target.filters.length > 0) {
|
||||||
query.filters = angular.copy(target.filters);
|
query.filters = angular.copy(target.filters);
|
||||||
if (query.filters) {
|
if (query.filters) {
|
||||||
for (const filter_key in query.filters) {
|
for (const filterKey in query.filters) {
|
||||||
query.filters[filter_key].filter = this.templateSrv.replace(
|
query.filters[filterKey].filter = this.templateSrv.replace(
|
||||||
query.filters[filter_key].filter,
|
query.filters[filterKey].filter,
|
||||||
options.scopedVars,
|
options.scopedVars,
|
||||||
'pipe'
|
'pipe'
|
||||||
);
|
);
|
||||||
@ -451,8 +451,8 @@ export default class OpenTsDatasource {
|
|||||||
} else {
|
} else {
|
||||||
query.tags = angular.copy(target.tags);
|
query.tags = angular.copy(target.tags);
|
||||||
if (query.tags) {
|
if (query.tags) {
|
||||||
for (const tag_key in query.tags) {
|
for (const tagKey in query.tags) {
|
||||||
query.tags[tag_key] = this.templateSrv.replace(query.tags[tag_key], options.scopedVars, 'pipe');
|
query.tags[tagKey] = this.templateSrv.replace(query.tags[tagKey], options.scopedVars, 'pipe');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,13 +2,13 @@ import OpenTsDatasource from '../datasource';
|
|||||||
import $q from 'q';
|
import $q from 'q';
|
||||||
|
|
||||||
describe('opentsdb', () => {
|
describe('opentsdb', () => {
|
||||||
const ctx = <any>{
|
const ctx = {
|
||||||
backendSrv: {},
|
backendSrv: {},
|
||||||
ds: {},
|
ds: {},
|
||||||
templateSrv: {
|
templateSrv: {
|
||||||
replace: str => str,
|
replace: str => str,
|
||||||
},
|
},
|
||||||
};
|
} as any;
|
||||||
const instanceSettings = { url: '', jsonData: { tsdbVersion: 1 } };
|
const instanceSettings = { url: '', jsonData: { tsdbVersion: 1 } };
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
import { OpenTsQueryCtrl } from '../query_ctrl';
|
import { OpenTsQueryCtrl } from '../query_ctrl';
|
||||||
|
|
||||||
describe('OpenTsQueryCtrl', () => {
|
describe('OpenTsQueryCtrl', () => {
|
||||||
const ctx = <any>{
|
const ctx = {
|
||||||
target: { target: '' },
|
target: { target: '' },
|
||||||
datasource: {
|
datasource: {
|
||||||
tsdbVersion: '',
|
tsdbVersion: '',
|
||||||
getAggregators: () => Promise.resolve([]),
|
getAggregators: () => Promise.resolve([]),
|
||||||
getFilterTypes: () => Promise.resolve([]),
|
getFilterTypes: () => Promise.resolve([]),
|
||||||
},
|
},
|
||||||
};
|
} as any;
|
||||||
|
|
||||||
ctx.panelCtrl = {
|
ctx.panelCtrl = {
|
||||||
panel: {
|
panel: {
|
||||||
|
@ -13,7 +13,7 @@ describe('PostgreSQLDatasource', function() {
|
|||||||
from: moment.utc('2018-04-25 10:00'),
|
from: moment.utc('2018-04-25 10:00'),
|
||||||
to: moment.utc('2018-04-25 11:00'),
|
to: moment.utc('2018-04-25 11:00'),
|
||||||
};
|
};
|
||||||
const ctx = <any>{
|
const ctx = {
|
||||||
backendSrv,
|
backendSrv,
|
||||||
timeSrvMock: {
|
timeSrvMock: {
|
||||||
timeRange: () => ({
|
timeRange: () => ({
|
||||||
@ -22,7 +22,7 @@ describe('PostgreSQLDatasource', function() {
|
|||||||
raw: raw,
|
raw: raw,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
};
|
} as any;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
ctx.ds = new PostgresDatasource(instanceSettings, backendSrv, {}, templateSrv, ctx.timeSrvMock);
|
ctx.ds = new PostgresDatasource(instanceSettings, backendSrv, {}, templateSrv, ctx.timeSrvMock);
|
||||||
|
@ -12,27 +12,27 @@ export default class PrometheusMetricFindQuery {
|
|||||||
}
|
}
|
||||||
|
|
||||||
process() {
|
process() {
|
||||||
const label_values_regex = /^label_values\((?:(.+),\s*)?([a-zA-Z_][a-zA-Z0-9_]+)\)\s*$/;
|
const labelValuesRegex = /^label_values\((?:(.+),\s*)?([a-zA-Z_][a-zA-Z0-9_]+)\)\s*$/;
|
||||||
const metric_names_regex = /^metrics\((.+)\)\s*$/;
|
const metricNamesRegex = /^metrics\((.+)\)\s*$/;
|
||||||
const query_result_regex = /^query_result\((.+)\)\s*$/;
|
const queryResultRegex = /^query_result\((.+)\)\s*$/;
|
||||||
|
|
||||||
const label_values_query = this.query.match(label_values_regex);
|
const labelValuesQuery = this.query.match(labelValuesRegex);
|
||||||
if (label_values_query) {
|
if (labelValuesQuery) {
|
||||||
if (label_values_query[1]) {
|
if (labelValuesQuery[1]) {
|
||||||
return this.labelValuesQuery(label_values_query[2], label_values_query[1]);
|
return this.labelValuesQuery(labelValuesQuery[2], labelValuesQuery[1]);
|
||||||
} else {
|
} else {
|
||||||
return this.labelValuesQuery(label_values_query[2], null);
|
return this.labelValuesQuery(labelValuesQuery[2], null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const metric_names_query = this.query.match(metric_names_regex);
|
const metricNamesQuery = this.query.match(metricNamesRegex);
|
||||||
if (metric_names_query) {
|
if (metricNamesQuery) {
|
||||||
return this.metricNameQuery(metric_names_query[1]);
|
return this.metricNameQuery(metricNamesQuery[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const query_result_query = this.query.match(query_result_regex);
|
const queryResultQuery = this.query.match(queryResultRegex);
|
||||||
if (query_result_query) {
|
if (queryResultQuery) {
|
||||||
return this.queryResultQuery(query_result_query[1]);
|
return this.queryResultQuery(queryResultQuery[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if query contains full metric name, return metric name and label list
|
// if query contains full metric name, return metric name and label list
|
||||||
|
@ -45,9 +45,9 @@ export class ResultTransformer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (const value of metricData.values) {
|
for (const value of metricData.values) {
|
||||||
let dp_value = parseFloat(value[1]);
|
let dpValue = parseFloat(value[1]);
|
||||||
if (_.isNaN(dp_value)) {
|
if (_.isNaN(dpValue)) {
|
||||||
dp_value = null;
|
dpValue = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const timestamp = parseFloat(value[0]) * 1000;
|
const timestamp = parseFloat(value[0]) * 1000;
|
||||||
@ -55,7 +55,7 @@ export class ResultTransformer {
|
|||||||
dps.push([null, t]);
|
dps.push([null, t]);
|
||||||
}
|
}
|
||||||
baseTimestamp = timestamp + stepMs;
|
baseTimestamp = timestamp + stepMs;
|
||||||
dps.push([dp_value, timestamp]);
|
dps.push([dpValue, timestamp]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const endTimestamp = end * 1000;
|
const endTimestamp = end * 1000;
|
||||||
|
@ -15,7 +15,7 @@ describe('Prometheus editor completer', function() {
|
|||||||
|
|
||||||
const editor = {};
|
const editor = {};
|
||||||
|
|
||||||
const backendSrv = <BackendSrv>{};
|
const backendSrv = {} as BackendSrv;
|
||||||
const datasourceStub = new PrometheusDatasource({}, {}, backendSrv, {}, {});
|
const datasourceStub = new PrometheusDatasource({}, {}, backendSrv, {}, {});
|
||||||
|
|
||||||
datasourceStub.performInstantQuery = jest.fn(() =>
|
datasourceStub.performInstantQuery = jest.fn(() =>
|
||||||
|
@ -385,7 +385,7 @@ const HOUR = 60 * MINUTE;
|
|||||||
|
|
||||||
const time = ({ hours = 0, seconds = 0, minutes = 0 }) => moment(hours * HOUR + minutes * MINUTE + seconds * SECOND);
|
const time = ({ hours = 0, seconds = 0, minutes = 0 }) => moment(hours * HOUR + minutes * MINUTE + seconds * SECOND);
|
||||||
|
|
||||||
const ctx = <any>{};
|
const ctx = {} as any;
|
||||||
const instanceSettings = {
|
const instanceSettings = {
|
||||||
url: 'proxied',
|
url: 'proxied',
|
||||||
directUrl: 'direct',
|
directUrl: 'direct',
|
||||||
@ -393,9 +393,9 @@ const instanceSettings = {
|
|||||||
password: 'mupp',
|
password: 'mupp',
|
||||||
jsonData: { httpMethod: 'GET' },
|
jsonData: { httpMethod: 'GET' },
|
||||||
};
|
};
|
||||||
const backendSrv = <any>{
|
const backendSrv = {
|
||||||
datasourceRequest: jest.fn(),
|
datasourceRequest: jest.fn(),
|
||||||
};
|
} as any;
|
||||||
|
|
||||||
const templateSrv = {
|
const templateSrv = {
|
||||||
replace: jest.fn(str => str),
|
replace: jest.fn(str => str),
|
||||||
@ -435,7 +435,7 @@ describe('PrometheusDatasource', () => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
backendSrv.datasourceRequest = jest.fn(() => Promise.resolve(response));
|
backendSrv.datasourceRequest = jest.fn(() => Promise.resolve(response));
|
||||||
ctx.ds = new PrometheusDatasource(instanceSettings, q, <any>backendSrv, templateSrv, timeSrv);
|
ctx.ds = new PrometheusDatasource(instanceSettings, q, backendSrv as any, templateSrv, timeSrv);
|
||||||
|
|
||||||
await ctx.ds.query(query).then(function(data) {
|
await ctx.ds.query(query).then(function(data) {
|
||||||
results = data;
|
results = data;
|
||||||
@ -485,7 +485,7 @@ describe('PrometheusDatasource', () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
backendSrv.datasourceRequest = jest.fn(() => Promise.resolve(response));
|
backendSrv.datasourceRequest = jest.fn(() => Promise.resolve(response));
|
||||||
ctx.ds = new PrometheusDatasource(instanceSettings, q, <any>backendSrv, templateSrv, timeSrv);
|
ctx.ds = new PrometheusDatasource(instanceSettings, q, backendSrv as any, templateSrv, timeSrv);
|
||||||
|
|
||||||
await ctx.ds.query(query).then(function(data) {
|
await ctx.ds.query(query).then(function(data) {
|
||||||
results = data;
|
results = data;
|
||||||
@ -546,7 +546,7 @@ describe('PrometheusDatasource', () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
backendSrv.datasourceRequest = jest.fn(() => Promise.resolve(response));
|
backendSrv.datasourceRequest = jest.fn(() => Promise.resolve(response));
|
||||||
ctx.ds = new PrometheusDatasource(instanceSettings, q, <any>backendSrv, templateSrv, timeSrv);
|
ctx.ds = new PrometheusDatasource(instanceSettings, q, backendSrv as any, templateSrv, timeSrv);
|
||||||
|
|
||||||
await ctx.ds.query(query).then(function(data) {
|
await ctx.ds.query(query).then(function(data) {
|
||||||
results = data;
|
results = data;
|
||||||
@ -601,7 +601,7 @@ describe('PrometheusDatasource', () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
backendSrv.datasourceRequest = jest.fn(() => Promise.resolve(response));
|
backendSrv.datasourceRequest = jest.fn(() => Promise.resolve(response));
|
||||||
ctx.ds = new PrometheusDatasource(instanceSettings, q, <any>backendSrv, templateSrv, timeSrv);
|
ctx.ds = new PrometheusDatasource(instanceSettings, q, backendSrv as any, templateSrv, timeSrv);
|
||||||
|
|
||||||
await ctx.ds.annotationQuery(options).then(function(data) {
|
await ctx.ds.annotationQuery(options).then(function(data) {
|
||||||
results = data;
|
results = data;
|
||||||
@ -641,7 +641,7 @@ describe('PrometheusDatasource', () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
backendSrv.datasourceRequest = jest.fn(() => Promise.resolve(response));
|
backendSrv.datasourceRequest = jest.fn(() => Promise.resolve(response));
|
||||||
ctx.ds = new PrometheusDatasource(instanceSettings, q, <any>backendSrv, templateSrv, timeSrv);
|
ctx.ds = new PrometheusDatasource(instanceSettings, q, backendSrv as any, templateSrv, timeSrv);
|
||||||
await ctx.ds.query(query).then(function(data) {
|
await ctx.ds.query(query).then(function(data) {
|
||||||
results = data;
|
results = data;
|
||||||
});
|
});
|
||||||
@ -678,7 +678,7 @@ describe('PrometheusDatasource', () => {
|
|||||||
const urlExpected = 'proxied/api/v1/query_range?query=test&start=60&end=420&step=10';
|
const urlExpected = 'proxied/api/v1/query_range?query=test&start=60&end=420&step=10';
|
||||||
|
|
||||||
backendSrv.datasourceRequest = jest.fn(() => Promise.resolve(response));
|
backendSrv.datasourceRequest = jest.fn(() => Promise.resolve(response));
|
||||||
ctx.ds = new PrometheusDatasource(instanceSettings, q, <any>backendSrv, templateSrv, timeSrv);
|
ctx.ds = new PrometheusDatasource(instanceSettings, q, backendSrv as any, templateSrv, timeSrv);
|
||||||
await ctx.ds.query(query);
|
await ctx.ds.query(query);
|
||||||
const res = backendSrv.datasourceRequest.mock.calls[0][0];
|
const res = backendSrv.datasourceRequest.mock.calls[0][0];
|
||||||
expect(res.method).toBe('GET');
|
expect(res.method).toBe('GET');
|
||||||
@ -694,7 +694,7 @@ describe('PrometheusDatasource', () => {
|
|||||||
};
|
};
|
||||||
const urlExpected = 'proxied/api/v1/query_range?query=test&start=60&end=420&step=1';
|
const urlExpected = 'proxied/api/v1/query_range?query=test&start=60&end=420&step=1';
|
||||||
backendSrv.datasourceRequest = jest.fn(() => Promise.resolve(response));
|
backendSrv.datasourceRequest = jest.fn(() => Promise.resolve(response));
|
||||||
ctx.ds = new PrometheusDatasource(instanceSettings, q, <any>backendSrv, templateSrv, timeSrv);
|
ctx.ds = new PrometheusDatasource(instanceSettings, q, backendSrv as any, templateSrv, timeSrv);
|
||||||
await ctx.ds.query(query);
|
await ctx.ds.query(query);
|
||||||
const res = backendSrv.datasourceRequest.mock.calls[0][0];
|
const res = backendSrv.datasourceRequest.mock.calls[0][0];
|
||||||
expect(res.method).toBe('GET');
|
expect(res.method).toBe('GET');
|
||||||
@ -715,7 +715,7 @@ describe('PrometheusDatasource', () => {
|
|||||||
};
|
};
|
||||||
const urlExpected = 'proxied/api/v1/query_range?query=test&start=60&end=420&step=10';
|
const urlExpected = 'proxied/api/v1/query_range?query=test&start=60&end=420&step=10';
|
||||||
backendSrv.datasourceRequest = jest.fn(() => Promise.resolve(response));
|
backendSrv.datasourceRequest = jest.fn(() => Promise.resolve(response));
|
||||||
ctx.ds = new PrometheusDatasource(instanceSettings, q, <any>backendSrv, templateSrv, timeSrv);
|
ctx.ds = new PrometheusDatasource(instanceSettings, q, backendSrv as any, templateSrv, timeSrv);
|
||||||
await ctx.ds.query(query);
|
await ctx.ds.query(query);
|
||||||
const res = backendSrv.datasourceRequest.mock.calls[0][0];
|
const res = backendSrv.datasourceRequest.mock.calls[0][0];
|
||||||
expect(res.method).toBe('GET');
|
expect(res.method).toBe('GET');
|
||||||
@ -732,7 +732,7 @@ describe('PrometheusDatasource', () => {
|
|||||||
const start = 60 * 60;
|
const start = 60 * 60;
|
||||||
const urlExpected = 'proxied/api/v1/query_range?query=test&start=' + start + '&end=' + end + '&step=2';
|
const urlExpected = 'proxied/api/v1/query_range?query=test&start=' + start + '&end=' + end + '&step=2';
|
||||||
backendSrv.datasourceRequest = jest.fn(() => Promise.resolve(response));
|
backendSrv.datasourceRequest = jest.fn(() => Promise.resolve(response));
|
||||||
ctx.ds = new PrometheusDatasource(instanceSettings, q, <any>backendSrv, templateSrv, timeSrv);
|
ctx.ds = new PrometheusDatasource(instanceSettings, q, backendSrv as any, templateSrv, timeSrv);
|
||||||
await ctx.ds.query(query);
|
await ctx.ds.query(query);
|
||||||
const res = backendSrv.datasourceRequest.mock.calls[0][0];
|
const res = backendSrv.datasourceRequest.mock.calls[0][0];
|
||||||
expect(res.method).toBe('GET');
|
expect(res.method).toBe('GET');
|
||||||
@ -754,7 +754,7 @@ describe('PrometheusDatasource', () => {
|
|||||||
// times get rounded up to interval
|
// times get rounded up to interval
|
||||||
const urlExpected = 'proxied/api/v1/query_range?query=test&start=50&end=450&step=50';
|
const urlExpected = 'proxied/api/v1/query_range?query=test&start=50&end=450&step=50';
|
||||||
backendSrv.datasourceRequest = jest.fn(() => Promise.resolve(response));
|
backendSrv.datasourceRequest = jest.fn(() => Promise.resolve(response));
|
||||||
ctx.ds = new PrometheusDatasource(instanceSettings, q, <any>backendSrv, templateSrv, timeSrv);
|
ctx.ds = new PrometheusDatasource(instanceSettings, q, backendSrv as any, templateSrv, timeSrv);
|
||||||
await ctx.ds.query(query);
|
await ctx.ds.query(query);
|
||||||
const res = backendSrv.datasourceRequest.mock.calls[0][0];
|
const res = backendSrv.datasourceRequest.mock.calls[0][0];
|
||||||
expect(res.method).toBe('GET');
|
expect(res.method).toBe('GET');
|
||||||
@ -775,7 +775,7 @@ describe('PrometheusDatasource', () => {
|
|||||||
};
|
};
|
||||||
const urlExpected = 'proxied/api/v1/query_range?query=test' + '&start=60&end=420&step=15';
|
const urlExpected = 'proxied/api/v1/query_range?query=test' + '&start=60&end=420&step=15';
|
||||||
backendSrv.datasourceRequest = jest.fn(() => Promise.resolve(response));
|
backendSrv.datasourceRequest = jest.fn(() => Promise.resolve(response));
|
||||||
ctx.ds = new PrometheusDatasource(instanceSettings, q, <any>backendSrv, templateSrv, timeSrv);
|
ctx.ds = new PrometheusDatasource(instanceSettings, q, backendSrv as any, templateSrv, timeSrv);
|
||||||
await ctx.ds.query(query);
|
await ctx.ds.query(query);
|
||||||
const res = backendSrv.datasourceRequest.mock.calls[0][0];
|
const res = backendSrv.datasourceRequest.mock.calls[0][0];
|
||||||
expect(res.method).toBe('GET');
|
expect(res.method).toBe('GET');
|
||||||
@ -797,7 +797,7 @@ describe('PrometheusDatasource', () => {
|
|||||||
// times get aligned to interval
|
// times get aligned to interval
|
||||||
const urlExpected = 'proxied/api/v1/query_range?query=test' + '&start=0&end=500&step=100';
|
const urlExpected = 'proxied/api/v1/query_range?query=test' + '&start=0&end=500&step=100';
|
||||||
backendSrv.datasourceRequest = jest.fn(() => Promise.resolve(response));
|
backendSrv.datasourceRequest = jest.fn(() => Promise.resolve(response));
|
||||||
ctx.ds = new PrometheusDatasource(instanceSettings, q, <any>backendSrv, templateSrv, timeSrv);
|
ctx.ds = new PrometheusDatasource(instanceSettings, q, backendSrv as any, templateSrv, timeSrv);
|
||||||
await ctx.ds.query(query);
|
await ctx.ds.query(query);
|
||||||
const res = backendSrv.datasourceRequest.mock.calls[0][0];
|
const res = backendSrv.datasourceRequest.mock.calls[0][0];
|
||||||
expect(res.method).toBe('GET');
|
expect(res.method).toBe('GET');
|
||||||
@ -819,7 +819,7 @@ describe('PrometheusDatasource', () => {
|
|||||||
const start = 0;
|
const start = 0;
|
||||||
const urlExpected = 'proxied/api/v1/query_range?query=test' + '&start=' + start + '&end=' + end + '&step=100';
|
const urlExpected = 'proxied/api/v1/query_range?query=test' + '&start=' + start + '&end=' + end + '&step=100';
|
||||||
backendSrv.datasourceRequest = jest.fn(() => Promise.resolve(response));
|
backendSrv.datasourceRequest = jest.fn(() => Promise.resolve(response));
|
||||||
ctx.ds = new PrometheusDatasource(instanceSettings, q, <any>backendSrv, templateSrv, timeSrv);
|
ctx.ds = new PrometheusDatasource(instanceSettings, q, backendSrv as any, templateSrv, timeSrv);
|
||||||
await ctx.ds.query(query);
|
await ctx.ds.query(query);
|
||||||
const res = backendSrv.datasourceRequest.mock.calls[0][0];
|
const res = backendSrv.datasourceRequest.mock.calls[0][0];
|
||||||
expect(res.method).toBe('GET');
|
expect(res.method).toBe('GET');
|
||||||
@ -841,7 +841,7 @@ describe('PrometheusDatasource', () => {
|
|||||||
const start = 0;
|
const start = 0;
|
||||||
const urlExpected = 'proxied/api/v1/query_range?query=test' + '&start=' + start + '&end=' + end + '&step=60';
|
const urlExpected = 'proxied/api/v1/query_range?query=test' + '&start=' + start + '&end=' + end + '&step=60';
|
||||||
backendSrv.datasourceRequest = jest.fn(() => Promise.resolve(response));
|
backendSrv.datasourceRequest = jest.fn(() => Promise.resolve(response));
|
||||||
ctx.ds = new PrometheusDatasource(instanceSettings, q, <any>backendSrv, templateSrv, timeSrv);
|
ctx.ds = new PrometheusDatasource(instanceSettings, q, backendSrv as any, templateSrv, timeSrv);
|
||||||
await ctx.ds.query(query);
|
await ctx.ds.query(query);
|
||||||
const res = backendSrv.datasourceRequest.mock.calls[0][0];
|
const res = backendSrv.datasourceRequest.mock.calls[0][0];
|
||||||
expect(res.method).toBe('GET');
|
expect(res.method).toBe('GET');
|
||||||
@ -884,7 +884,7 @@ describe('PrometheusDatasource', () => {
|
|||||||
|
|
||||||
templateSrv.replace = jest.fn(str => str);
|
templateSrv.replace = jest.fn(str => str);
|
||||||
backendSrv.datasourceRequest = jest.fn(() => Promise.resolve(response));
|
backendSrv.datasourceRequest = jest.fn(() => Promise.resolve(response));
|
||||||
ctx.ds = new PrometheusDatasource(instanceSettings, q, <any>backendSrv, templateSrv, timeSrv);
|
ctx.ds = new PrometheusDatasource(instanceSettings, q, backendSrv as any, templateSrv, timeSrv);
|
||||||
await ctx.ds.query(query);
|
await ctx.ds.query(query);
|
||||||
const res = backendSrv.datasourceRequest.mock.calls[0][0];
|
const res = backendSrv.datasourceRequest.mock.calls[0][0];
|
||||||
expect(res.method).toBe('GET');
|
expect(res.method).toBe('GET');
|
||||||
@ -923,7 +923,7 @@ describe('PrometheusDatasource', () => {
|
|||||||
'&start=60&end=420&step=10';
|
'&start=60&end=420&step=10';
|
||||||
backendSrv.datasourceRequest = jest.fn(() => Promise.resolve(response));
|
backendSrv.datasourceRequest = jest.fn(() => Promise.resolve(response));
|
||||||
templateSrv.replace = jest.fn(str => str);
|
templateSrv.replace = jest.fn(str => str);
|
||||||
ctx.ds = new PrometheusDatasource(instanceSettings, q, <any>backendSrv, templateSrv, timeSrv);
|
ctx.ds = new PrometheusDatasource(instanceSettings, q, backendSrv as any, templateSrv, timeSrv);
|
||||||
await ctx.ds.query(query);
|
await ctx.ds.query(query);
|
||||||
const res = backendSrv.datasourceRequest.mock.calls[0][0];
|
const res = backendSrv.datasourceRequest.mock.calls[0][0];
|
||||||
expect(res.method).toBe('GET');
|
expect(res.method).toBe('GET');
|
||||||
@ -963,7 +963,7 @@ describe('PrometheusDatasource', () => {
|
|||||||
'&start=0&end=500&step=100';
|
'&start=0&end=500&step=100';
|
||||||
backendSrv.datasourceRequest = jest.fn(() => Promise.resolve(response));
|
backendSrv.datasourceRequest = jest.fn(() => Promise.resolve(response));
|
||||||
templateSrv.replace = jest.fn(str => str);
|
templateSrv.replace = jest.fn(str => str);
|
||||||
ctx.ds = new PrometheusDatasource(instanceSettings, q, <any>backendSrv, templateSrv, timeSrv);
|
ctx.ds = new PrometheusDatasource(instanceSettings, q, backendSrv as any, templateSrv, timeSrv);
|
||||||
await ctx.ds.query(query);
|
await ctx.ds.query(query);
|
||||||
const res = backendSrv.datasourceRequest.mock.calls[0][0];
|
const res = backendSrv.datasourceRequest.mock.calls[0][0];
|
||||||
expect(res.method).toBe('GET');
|
expect(res.method).toBe('GET');
|
||||||
@ -1009,7 +1009,7 @@ describe('PrometheusDatasource', () => {
|
|||||||
|
|
||||||
templateSrv.replace = jest.fn(str => str);
|
templateSrv.replace = jest.fn(str => str);
|
||||||
backendSrv.datasourceRequest = jest.fn(() => Promise.resolve(response));
|
backendSrv.datasourceRequest = jest.fn(() => Promise.resolve(response));
|
||||||
ctx.ds = new PrometheusDatasource(instanceSettings, q, <any>backendSrv, templateSrv, timeSrv);
|
ctx.ds = new PrometheusDatasource(instanceSettings, q, backendSrv as any, templateSrv, timeSrv);
|
||||||
await ctx.ds.query(query);
|
await ctx.ds.query(query);
|
||||||
const res = backendSrv.datasourceRequest.mock.calls[0][0];
|
const res = backendSrv.datasourceRequest.mock.calls[0][0];
|
||||||
expect(res.method).toBe('GET');
|
expect(res.method).toBe('GET');
|
||||||
@ -1049,7 +1049,7 @@ describe('PrometheusDatasource', () => {
|
|||||||
'&start=60&end=420&step=15';
|
'&start=60&end=420&step=15';
|
||||||
|
|
||||||
backendSrv.datasourceRequest = jest.fn(() => Promise.resolve(response));
|
backendSrv.datasourceRequest = jest.fn(() => Promise.resolve(response));
|
||||||
ctx.ds = new PrometheusDatasource(instanceSettings, q, <any>backendSrv, templateSrv, timeSrv);
|
ctx.ds = new PrometheusDatasource(instanceSettings, q, backendSrv as any, templateSrv, timeSrv);
|
||||||
await ctx.ds.query(query);
|
await ctx.ds.query(query);
|
||||||
const res = backendSrv.datasourceRequest.mock.calls[0][0];
|
const res = backendSrv.datasourceRequest.mock.calls[0][0];
|
||||||
expect(res.method).toBe('GET');
|
expect(res.method).toBe('GET');
|
||||||
@ -1094,7 +1094,7 @@ describe('PrometheusDatasource', () => {
|
|||||||
'&step=60';
|
'&step=60';
|
||||||
backendSrv.datasourceRequest = jest.fn(() => Promise.resolve(response));
|
backendSrv.datasourceRequest = jest.fn(() => Promise.resolve(response));
|
||||||
templateSrv.replace = jest.fn(str => str);
|
templateSrv.replace = jest.fn(str => str);
|
||||||
ctx.ds = new PrometheusDatasource(instanceSettings, q, <any>backendSrv, templateSrv, timeSrv);
|
ctx.ds = new PrometheusDatasource(instanceSettings, q, backendSrv as any, templateSrv, timeSrv);
|
||||||
await ctx.ds.query(query);
|
await ctx.ds.query(query);
|
||||||
const res = backendSrv.datasourceRequest.mock.calls[0][0];
|
const res = backendSrv.datasourceRequest.mock.calls[0][0];
|
||||||
expect(res.method).toBe('GET');
|
expect(res.method).toBe('GET');
|
||||||
@ -1155,7 +1155,7 @@ describe('PrometheusDatasource for POST', () => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
backendSrv.datasourceRequest = jest.fn(() => Promise.resolve(response));
|
backendSrv.datasourceRequest = jest.fn(() => Promise.resolve(response));
|
||||||
ctx.ds = new PrometheusDatasource(instanceSettings, q, <any>backendSrv, templateSrv, timeSrv);
|
ctx.ds = new PrometheusDatasource(instanceSettings, q, backendSrv as any, templateSrv, timeSrv);
|
||||||
await ctx.ds.query(query).then(function(data) {
|
await ctx.ds.query(query).then(function(data) {
|
||||||
results = data;
|
results = data;
|
||||||
});
|
});
|
||||||
|
@ -484,22 +484,22 @@ class GraphElement {
|
|||||||
const defaultTicks = this.panelWidth / 50;
|
const defaultTicks = this.panelWidth / 50;
|
||||||
|
|
||||||
if (this.data.length && bucketSize) {
|
if (this.data.length && bucketSize) {
|
||||||
const tick_values = [];
|
const tickValues = [];
|
||||||
for (const d of this.data) {
|
for (const d of this.data) {
|
||||||
for (const point of d.data) {
|
for (const point of d.data) {
|
||||||
tick_values[point[0]] = true;
|
tickValues[point[0]] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ticks = Object.keys(tick_values).map(v => Number(v));
|
ticks = Object.keys(tickValues).map(v => Number(v));
|
||||||
min = _.min(ticks);
|
min = _.min(ticks);
|
||||||
max = _.max(ticks);
|
max = _.max(ticks);
|
||||||
|
|
||||||
// Adjust tick step
|
// Adjust tick step
|
||||||
let tickStep = bucketSize;
|
let tickStep = bucketSize;
|
||||||
let ticks_num = Math.floor((max - min) / tickStep);
|
let ticksNum = Math.floor((max - min) / tickStep);
|
||||||
while (ticks_num > defaultTicks) {
|
while (ticksNum > defaultTicks) {
|
||||||
tickStep = tickStep * 2;
|
tickStep = tickStep * 2;
|
||||||
ticks_num = Math.ceil((max - min) / tickStep);
|
ticksNum = Math.ceil((max - min) / tickStep);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expand ticks for pretty view
|
// Expand ticks for pretty view
|
||||||
|
@ -62,7 +62,7 @@ export default function GraphTooltip(this: any, elem, dashboard, scope, getSerie
|
|||||||
let results: any = [[], [], []];
|
let results: any = [[], [], []];
|
||||||
|
|
||||||
//now we know the current X (j) position for X and Y values
|
//now we know the current X (j) position for X and Y values
|
||||||
let last_value = 0; //needed for stacked values
|
let lastValue = 0; //needed for stacked values
|
||||||
|
|
||||||
let minDistance, minTime;
|
let minDistance, minTime;
|
||||||
|
|
||||||
@ -106,8 +106,8 @@ export default function GraphTooltip(this: any, elem, dashboard, scope, getSerie
|
|||||||
} else if (!series.stack) {
|
} else if (!series.stack) {
|
||||||
value = series.data[hoverIndex][1];
|
value = series.data[hoverIndex][1];
|
||||||
} else {
|
} else {
|
||||||
last_value += series.data[hoverIndex][1];
|
lastValue += series.data[hoverIndex][1];
|
||||||
value = last_value;
|
value = lastValue;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
value = series.data[hoverIndex][1];
|
value = series.data[hoverIndex][1];
|
||||||
|
@ -47,12 +47,12 @@ export function convertValuesToHistogram(values: number[], bucketSize: number, m
|
|||||||
histogram[bound] = histogram[bound] + 1;
|
histogram[bound] = histogram[bound] + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const histogam_series = _.map(histogram, (count, bound) => {
|
const histogamSeries = _.map(histogram, (count, bound) => {
|
||||||
return [Number(bound), count];
|
return [Number(bound), count];
|
||||||
});
|
});
|
||||||
|
|
||||||
// Sort by Y axis values
|
// Sort by Y axis values
|
||||||
return _.sortBy(histogam_series, point => point[0]);
|
return _.sortBy(histogamSeries, point => point[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -28,7 +28,7 @@ import moment from 'moment';
|
|||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
import { graphDirective } from '../graph';
|
import { graphDirective } from '../graph';
|
||||||
|
|
||||||
const ctx = <any>{};
|
const ctx = {} as any;
|
||||||
let ctrl;
|
let ctrl;
|
||||||
const scope = {
|
const scope = {
|
||||||
ctrl: {},
|
ctrl: {},
|
||||||
@ -47,7 +47,7 @@ describe('grafanaGraph', function() {
|
|||||||
lightTheme: false,
|
lightTheme: false,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
GraphCtrl.prototype = <any>{
|
GraphCtrl.prototype = {
|
||||||
...MetricsPanelCtrl.prototype,
|
...MetricsPanelCtrl.prototype,
|
||||||
...PanelCtrl.prototype,
|
...PanelCtrl.prototype,
|
||||||
...GraphCtrl.prototype,
|
...GraphCtrl.prototype,
|
||||||
@ -88,7 +88,7 @@ describe('grafanaGraph', function() {
|
|||||||
from: moment([2015, 1, 1, 10]),
|
from: moment([2015, 1, 1, 10]),
|
||||||
to: moment([2015, 1, 1, 22]),
|
to: moment([2015, 1, 1, 22]),
|
||||||
},
|
},
|
||||||
};
|
} as any;
|
||||||
|
|
||||||
ctx.data = [];
|
ctx.data = [];
|
||||||
ctx.data.push(
|
ctx.data.push(
|
||||||
|
@ -30,7 +30,7 @@ describe('GraphCtrl', () => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const ctx = <any>{};
|
const ctx = {} as any;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
ctx.ctrl = new GraphCtrl(scope, injector, {});
|
ctx.ctrl = new GraphCtrl(scope, injector, {});
|
||||||
|
@ -97,7 +97,7 @@ const colorSchemes = [
|
|||||||
{ name: 'YlOrRd', value: 'interpolateYlOrRd', invert: 'dark' },
|
{ name: 'YlOrRd', value: 'interpolateYlOrRd', invert: 'dark' },
|
||||||
];
|
];
|
||||||
|
|
||||||
const ds_support_histogram_sort = ['prometheus', 'elasticsearch'];
|
const dsSupportHistogramSort = ['prometheus', 'elasticsearch'];
|
||||||
|
|
||||||
export class HeatmapCtrl extends MetricsPanelCtrl {
|
export class HeatmapCtrl extends MetricsPanelCtrl {
|
||||||
static templateUrl = 'module.html';
|
static templateUrl = 'module.html';
|
||||||
@ -221,7 +221,7 @@ export class HeatmapCtrl extends MetricsPanelCtrl {
|
|||||||
let xBucketSize, yBucketSize, bucketsData, tsBuckets;
|
let xBucketSize, yBucketSize, bucketsData, tsBuckets;
|
||||||
|
|
||||||
// Try to sort series by bucket bound, if datasource doesn't do it.
|
// Try to sort series by bucket bound, if datasource doesn't do it.
|
||||||
if (!_.includes(ds_support_histogram_sort, panelDatasource)) {
|
if (!_.includes(dsSupportHistogramSort, panelDatasource)) {
|
||||||
this.series.sort(sortSeriesByLabel);
|
this.series.sort(sortSeriesByLabel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -253,16 +253,16 @@ function pushToXBuckets(buckets, point, bucketNum, seriesName) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add series name to point for future identification
|
// Add series name to point for future identification
|
||||||
const point_ext = _.concat(point, seriesName);
|
const pointExt = _.concat(point, seriesName);
|
||||||
|
|
||||||
if (buckets[bucketNum] && buckets[bucketNum].values) {
|
if (buckets[bucketNum] && buckets[bucketNum].values) {
|
||||||
buckets[bucketNum].values.push(value);
|
buckets[bucketNum].values.push(value);
|
||||||
buckets[bucketNum].points.push(point_ext);
|
buckets[bucketNum].points.push(pointExt);
|
||||||
} else {
|
} else {
|
||||||
buckets[bucketNum] = {
|
buckets[bucketNum] = {
|
||||||
x: bucketNum,
|
x: bucketNum,
|
||||||
values: [value],
|
values: [value],
|
||||||
points: [point_ext],
|
points: [pointExt],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -335,17 +335,17 @@ function getLogScaleBucketBounds(value, yBucketSplitFactor, logBase) {
|
|||||||
return { bottom: 0, top: 0 };
|
return { bottom: 0, top: 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
const value_log = logp(value, logBase);
|
const valueLog = logp(value, logBase);
|
||||||
let pow, powTop;
|
let pow, powTop;
|
||||||
if (yBucketSplitFactor === 1 || !yBucketSplitFactor) {
|
if (yBucketSplitFactor === 1 || !yBucketSplitFactor) {
|
||||||
pow = Math.floor(value_log);
|
pow = Math.floor(valueLog);
|
||||||
powTop = pow + 1;
|
powTop = pow + 1;
|
||||||
} else {
|
} else {
|
||||||
const additional_bucket_size = 1 / yBucketSplitFactor;
|
const additionalBucketSize = 1 / yBucketSplitFactor;
|
||||||
let additional_log = value_log - Math.floor(value_log);
|
let additionalLog = valueLog - Math.floor(valueLog);
|
||||||
additional_log = Math.floor(additional_log / additional_bucket_size) * additional_bucket_size;
|
additionalLog = Math.floor(additionalLog / additionalBucketSize) * additionalBucketSize;
|
||||||
pow = Math.floor(value_log) + additional_log;
|
pow = Math.floor(valueLog) + additionalLog;
|
||||||
powTop = pow + additional_bucket_size;
|
powTop = pow + additionalBucketSize;
|
||||||
}
|
}
|
||||||
bottom = Math.pow(logBase, pow);
|
bottom = Math.pow(logBase, pow);
|
||||||
top = Math.pow(logBase, powTop);
|
top = Math.pow(logBase, powTop);
|
||||||
@ -427,46 +427,46 @@ function getDistance(a: number, b: number, logBase = 1): number {
|
|||||||
* @param objB
|
* @param objB
|
||||||
*/
|
*/
|
||||||
function isHeatmapDataEqual(objA: any, objB: any): boolean {
|
function isHeatmapDataEqual(objA: any, objB: any): boolean {
|
||||||
let is_eql = !emptyXOR(objA, objB);
|
let isEql = !emptyXOR(objA, objB);
|
||||||
|
|
||||||
_.forEach(objA, (xBucket: XBucket, x) => {
|
_.forEach(objA, (xBucket: XBucket, x) => {
|
||||||
if (objB[x]) {
|
if (objB[x]) {
|
||||||
if (emptyXOR(xBucket.buckets, objB[x].buckets)) {
|
if (emptyXOR(xBucket.buckets, objB[x].buckets)) {
|
||||||
is_eql = false;
|
isEql = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_.forEach(xBucket.buckets, (yBucket: YBucket, y) => {
|
_.forEach(xBucket.buckets, (yBucket: YBucket, y) => {
|
||||||
if (objB[x].buckets && objB[x].buckets[y]) {
|
if (objB[x].buckets && objB[x].buckets[y]) {
|
||||||
if (objB[x].buckets[y].values) {
|
if (objB[x].buckets[y].values) {
|
||||||
is_eql = _.isEqual(_.sortBy(yBucket.values), _.sortBy(objB[x].buckets[y].values));
|
isEql = _.isEqual(_.sortBy(yBucket.values), _.sortBy(objB[x].buckets[y].values));
|
||||||
if (!is_eql) {
|
if (!isEql) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
is_eql = false;
|
isEql = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
is_eql = false;
|
isEql = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!is_eql) {
|
if (!isEql) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
is_eql = false;
|
isEql = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return is_eql;
|
return isEql;
|
||||||
}
|
}
|
||||||
|
|
||||||
function emptyXOR(foo: any, bar: any): boolean {
|
function emptyXOR(foo: any, bar: any): boolean {
|
||||||
|
@ -117,23 +117,23 @@ export class HeatmapRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getYAxisWidth(elem) {
|
getYAxisWidth(elem) {
|
||||||
const axis_text = elem.selectAll('.axis-y text').nodes();
|
const axisText = elem.selectAll('.axis-y text').nodes();
|
||||||
const max_text_width = _.max(
|
const maxTextWidth = _.max(
|
||||||
_.map(axis_text, text => {
|
_.map(axisText, text => {
|
||||||
// Use SVG getBBox method
|
// Use SVG getBBox method
|
||||||
return text.getBBox().width;
|
return text.getBBox().width;
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
return max_text_width;
|
return maxTextWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
getXAxisHeight(elem) {
|
getXAxisHeight(elem) {
|
||||||
const axis_line = elem.select('.axis-x line');
|
const axisLine = elem.select('.axis-x line');
|
||||||
if (!axis_line.empty()) {
|
if (!axisLine.empty()) {
|
||||||
const axis_line_position = parseFloat(elem.select('.axis-x line').attr('y2'));
|
const axisLinePosition = parseFloat(elem.select('.axis-x line').attr('y2'));
|
||||||
const canvas_width = parseFloat(elem.attr('height'));
|
const canvasWidth = parseFloat(elem.attr('height'));
|
||||||
return canvas_width - axis_line_position;
|
return canvasWidth - axisLinePosition;
|
||||||
} else {
|
} else {
|
||||||
// Default height
|
// Default height
|
||||||
return 30;
|
return 30;
|
||||||
@ -180,42 +180,42 @@ export class HeatmapRenderer {
|
|||||||
|
|
||||||
addYAxis() {
|
addYAxis() {
|
||||||
let ticks = Math.ceil(this.chartHeight / DEFAULT_Y_TICK_SIZE_PX);
|
let ticks = Math.ceil(this.chartHeight / DEFAULT_Y_TICK_SIZE_PX);
|
||||||
let tick_interval = ticksUtils.tickStep(this.data.heatmapStats.min, this.data.heatmapStats.max, ticks);
|
let tickInterval = ticksUtils.tickStep(this.data.heatmapStats.min, this.data.heatmapStats.max, ticks);
|
||||||
let { y_min, y_max } = this.wideYAxisRange(this.data.heatmapStats.min, this.data.heatmapStats.max, tick_interval);
|
let { yMin, yMax } = this.wideYAxisRange(this.data.heatmapStats.min, this.data.heatmapStats.max, tickInterval);
|
||||||
|
|
||||||
// Rewrite min and max if it have been set explicitly
|
// Rewrite min and max if it have been set explicitly
|
||||||
y_min = this.panel.yAxis.min !== null ? this.panel.yAxis.min : y_min;
|
yMin = this.panel.yAxis.min !== null ? this.panel.yAxis.min : yMin;
|
||||||
y_max = this.panel.yAxis.max !== null ? this.panel.yAxis.max : y_max;
|
yMax = this.panel.yAxis.max !== null ? this.panel.yAxis.max : yMax;
|
||||||
|
|
||||||
// Adjust ticks after Y range widening
|
// Adjust ticks after Y range widening
|
||||||
tick_interval = ticksUtils.tickStep(y_min, y_max, ticks);
|
tickInterval = ticksUtils.tickStep(yMin, yMax, ticks);
|
||||||
ticks = Math.ceil((y_max - y_min) / tick_interval);
|
ticks = Math.ceil((yMax - yMin) / tickInterval);
|
||||||
|
|
||||||
const decimalsAuto = ticksUtils.getPrecision(tick_interval);
|
const decimalsAuto = ticksUtils.getPrecision(tickInterval);
|
||||||
let decimals = this.panel.yAxis.decimals === null ? decimalsAuto : this.panel.yAxis.decimals;
|
let decimals = this.panel.yAxis.decimals === null ? decimalsAuto : this.panel.yAxis.decimals;
|
||||||
// Calculate scaledDecimals for log scales using tick size (as in jquery.flot.js)
|
// Calculate scaledDecimals for log scales using tick size (as in jquery.flot.js)
|
||||||
const flot_tick_size = ticksUtils.getFlotTickSize(y_min, y_max, ticks, decimalsAuto);
|
const flotTickSize = ticksUtils.getFlotTickSize(yMin, yMax, ticks, decimalsAuto);
|
||||||
const scaledDecimals = ticksUtils.getScaledDecimals(decimals, flot_tick_size);
|
const scaledDecimals = ticksUtils.getScaledDecimals(decimals, flotTickSize);
|
||||||
this.ctrl.decimals = decimals;
|
this.ctrl.decimals = decimals;
|
||||||
this.ctrl.scaledDecimals = scaledDecimals;
|
this.ctrl.scaledDecimals = scaledDecimals;
|
||||||
|
|
||||||
// Set default Y min and max if no data
|
// Set default Y min and max if no data
|
||||||
if (_.isEmpty(this.data.buckets)) {
|
if (_.isEmpty(this.data.buckets)) {
|
||||||
y_max = 1;
|
yMax = 1;
|
||||||
y_min = -1;
|
yMin = -1;
|
||||||
ticks = 3;
|
ticks = 3;
|
||||||
decimals = 1;
|
decimals = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.data.yAxis = {
|
this.data.yAxis = {
|
||||||
min: y_min,
|
min: yMin,
|
||||||
max: y_max,
|
max: yMax,
|
||||||
ticks: ticks,
|
ticks: ticks,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.scope.yScale = this.yScale = d3
|
this.scope.yScale = this.yScale = d3
|
||||||
.scaleLinear()
|
.scaleLinear()
|
||||||
.domain([y_min, y_max])
|
.domain([yMin, yMax])
|
||||||
.range([this.chartHeight, 0]);
|
.range([this.chartHeight, 0]);
|
||||||
|
|
||||||
const yAxis = d3
|
const yAxis = d3
|
||||||
@ -245,67 +245,67 @@ export class HeatmapRenderer {
|
|||||||
|
|
||||||
// Wide Y values range and anjust to bucket size
|
// Wide Y values range and anjust to bucket size
|
||||||
wideYAxisRange(min, max, tickInterval) {
|
wideYAxisRange(min, max, tickInterval) {
|
||||||
const y_widing = (max * (this.dataRangeWidingFactor - 1) - min * (this.dataRangeWidingFactor - 1)) / 2;
|
const yWiding = (max * (this.dataRangeWidingFactor - 1) - min * (this.dataRangeWidingFactor - 1)) / 2;
|
||||||
let y_min, y_max;
|
let yMin, yMax;
|
||||||
|
|
||||||
if (tickInterval === 0) {
|
if (tickInterval === 0) {
|
||||||
y_max = max * this.dataRangeWidingFactor;
|
yMax = max * this.dataRangeWidingFactor;
|
||||||
y_min = min - min * (this.dataRangeWidingFactor - 1);
|
yMin = min - min * (this.dataRangeWidingFactor - 1);
|
||||||
tickInterval = (y_max - y_min) / 2;
|
tickInterval = (yMax - yMin) / 2;
|
||||||
} else {
|
} else {
|
||||||
y_max = Math.ceil((max + y_widing) / tickInterval) * tickInterval;
|
yMax = Math.ceil((max + yWiding) / tickInterval) * tickInterval;
|
||||||
y_min = Math.floor((min - y_widing) / tickInterval) * tickInterval;
|
yMin = Math.floor((min - yWiding) / tickInterval) * tickInterval;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't wide axis below 0 if all values are positive
|
// Don't wide axis below 0 if all values are positive
|
||||||
if (min >= 0 && y_min < 0) {
|
if (min >= 0 && yMin < 0) {
|
||||||
y_min = 0;
|
yMin = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return { y_min, y_max };
|
return { yMin, yMax };
|
||||||
}
|
}
|
||||||
|
|
||||||
addLogYAxis() {
|
addLogYAxis() {
|
||||||
const log_base = this.panel.yAxis.logBase;
|
const logBase = this.panel.yAxis.logBase;
|
||||||
let { y_min, y_max } = this.adjustLogRange(this.data.heatmapStats.minLog, this.data.heatmapStats.max, log_base);
|
let { yMin, yMax } = this.adjustLogRange(this.data.heatmapStats.minLog, this.data.heatmapStats.max, logBase);
|
||||||
|
|
||||||
y_min =
|
yMin =
|
||||||
this.panel.yAxis.min && this.panel.yAxis.min !== '0' ? this.adjustLogMin(this.panel.yAxis.min, log_base) : y_min;
|
this.panel.yAxis.min && this.panel.yAxis.min !== '0' ? this.adjustLogMin(this.panel.yAxis.min, logBase) : yMin;
|
||||||
y_max = this.panel.yAxis.max !== null ? this.adjustLogMax(this.panel.yAxis.max, log_base) : y_max;
|
yMax = this.panel.yAxis.max !== null ? this.adjustLogMax(this.panel.yAxis.max, logBase) : yMax;
|
||||||
|
|
||||||
// Set default Y min and max if no data
|
// Set default Y min and max if no data
|
||||||
if (_.isEmpty(this.data.buckets)) {
|
if (_.isEmpty(this.data.buckets)) {
|
||||||
y_max = Math.pow(log_base, 2);
|
yMax = Math.pow(logBase, 2);
|
||||||
y_min = 1;
|
yMin = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.scope.yScale = this.yScale = d3
|
this.scope.yScale = this.yScale = d3
|
||||||
.scaleLog()
|
.scaleLog()
|
||||||
.base(this.panel.yAxis.logBase)
|
.base(this.panel.yAxis.logBase)
|
||||||
.domain([y_min, y_max])
|
.domain([yMin, yMax])
|
||||||
.range([this.chartHeight, 0]);
|
.range([this.chartHeight, 0]);
|
||||||
|
|
||||||
const domain = this.yScale.domain();
|
const domain = this.yScale.domain();
|
||||||
const tick_values = this.logScaleTickValues(domain, log_base);
|
const tickValues = this.logScaleTickValues(domain, logBase);
|
||||||
|
|
||||||
const decimalsAuto = ticksUtils.getPrecision(y_min);
|
const decimalsAuto = ticksUtils.getPrecision(yMin);
|
||||||
const decimals = this.panel.yAxis.decimals || decimalsAuto;
|
const decimals = this.panel.yAxis.decimals || decimalsAuto;
|
||||||
|
|
||||||
// Calculate scaledDecimals for log scales using tick size (as in jquery.flot.js)
|
// Calculate scaledDecimals for log scales using tick size (as in jquery.flot.js)
|
||||||
const flot_tick_size = ticksUtils.getFlotTickSize(y_min, y_max, tick_values.length, decimalsAuto);
|
const flotTickSize = ticksUtils.getFlotTickSize(yMin, yMax, tickValues.length, decimalsAuto);
|
||||||
const scaledDecimals = ticksUtils.getScaledDecimals(decimals, flot_tick_size);
|
const scaledDecimals = ticksUtils.getScaledDecimals(decimals, flotTickSize);
|
||||||
this.ctrl.decimals = decimals;
|
this.ctrl.decimals = decimals;
|
||||||
this.ctrl.scaledDecimals = scaledDecimals;
|
this.ctrl.scaledDecimals = scaledDecimals;
|
||||||
|
|
||||||
this.data.yAxis = {
|
this.data.yAxis = {
|
||||||
min: y_min,
|
min: yMin,
|
||||||
max: y_max,
|
max: yMax,
|
||||||
ticks: tick_values.length,
|
ticks: tickValues.length,
|
||||||
};
|
};
|
||||||
|
|
||||||
const yAxis = d3
|
const yAxis = d3
|
||||||
.axisLeft(this.yScale)
|
.axisLeft(this.yScale)
|
||||||
.tickValues(tick_values)
|
.tickValues(tickValues)
|
||||||
.tickFormat(this.tickValueFormatter(decimals, scaledDecimals))
|
.tickFormat(this.tickValueFormatter(decimals, scaledDecimals))
|
||||||
.tickSizeInner(0 - this.width)
|
.tickSizeInner(0 - this.width)
|
||||||
.tickSizeOuter(0)
|
.tickSizeOuter(0)
|
||||||
@ -322,7 +322,7 @@ export class HeatmapRenderer {
|
|||||||
this.heatmap.select('.axis-y').attr('transform', 'translate(' + posX + ',' + posY + ')');
|
this.heatmap.select('.axis-y').attr('transform', 'translate(' + posX + ',' + posY + ')');
|
||||||
|
|
||||||
// Set first tick as pseudo 0
|
// Set first tick as pseudo 0
|
||||||
if (y_min < 1) {
|
if (yMin < 1) {
|
||||||
this.heatmap
|
this.heatmap
|
||||||
.select('.axis-y')
|
.select('.axis-y')
|
||||||
.select('.tick text')
|
.select('.tick text')
|
||||||
@ -344,7 +344,7 @@ export class HeatmapRenderer {
|
|||||||
.domain([0, tsBuckets.length - 1])
|
.domain([0, tsBuckets.length - 1])
|
||||||
.range([this.chartHeight, 0]);
|
.range([this.chartHeight, 0]);
|
||||||
|
|
||||||
const tick_values = _.map(tsBuckets, (b, i) => i);
|
const tickValues = _.map(tsBuckets, (b, i) => i);
|
||||||
const decimalsAuto = _.max(_.map(tsBuckets, ticksUtils.getStringPrecision));
|
const decimalsAuto = _.max(_.map(tsBuckets, ticksUtils.getStringPrecision));
|
||||||
const decimals = this.panel.yAxis.decimals === null ? decimalsAuto : this.panel.yAxis.decimals;
|
const decimals = this.panel.yAxis.decimals === null ? decimalsAuto : this.panel.yAxis.decimals;
|
||||||
this.ctrl.decimals = decimals;
|
this.ctrl.decimals = decimals;
|
||||||
@ -364,7 +364,7 @@ export class HeatmapRenderer {
|
|||||||
|
|
||||||
const yAxis = d3
|
const yAxis = d3
|
||||||
.axisLeft(this.yScale)
|
.axisLeft(this.yScale)
|
||||||
.tickValues(tick_values)
|
.tickValues(tickValues)
|
||||||
.tickFormat(tickFormatter)
|
.tickFormat(tickFormatter)
|
||||||
.tickSizeInner(0 - this.width)
|
.tickSizeInner(0 - this.width)
|
||||||
.tickSizeOuter(0)
|
.tickSizeOuter(0)
|
||||||
@ -389,19 +389,19 @@ export class HeatmapRenderer {
|
|||||||
|
|
||||||
// Adjust data range to log base
|
// Adjust data range to log base
|
||||||
adjustLogRange(min, max, logBase) {
|
adjustLogRange(min, max, logBase) {
|
||||||
let y_min, y_max;
|
let yMin, yMax;
|
||||||
|
|
||||||
y_min = this.data.heatmapStats.minLog;
|
yMin = this.data.heatmapStats.minLog;
|
||||||
if (this.data.heatmapStats.minLog > 1 || !this.data.heatmapStats.minLog) {
|
if (this.data.heatmapStats.minLog > 1 || !this.data.heatmapStats.minLog) {
|
||||||
y_min = 1;
|
yMin = 1;
|
||||||
} else {
|
} else {
|
||||||
y_min = this.adjustLogMin(this.data.heatmapStats.minLog, logBase);
|
yMin = this.adjustLogMin(this.data.heatmapStats.minLog, logBase);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adjust max Y value to log base
|
// Adjust max Y value to log base
|
||||||
y_max = this.adjustLogMax(this.data.heatmapStats.max, logBase);
|
yMax = this.adjustLogMax(this.data.heatmapStats.max, logBase);
|
||||||
|
|
||||||
return { y_min, y_max };
|
return { yMin, yMax };
|
||||||
}
|
}
|
||||||
|
|
||||||
adjustLogMax(max, base) {
|
adjustLogMax(max, base) {
|
||||||
@ -418,17 +418,17 @@ export class HeatmapRenderer {
|
|||||||
const tickValues = [];
|
const tickValues = [];
|
||||||
|
|
||||||
if (domainMin < 1) {
|
if (domainMin < 1) {
|
||||||
const under_one_ticks = Math.floor(ticksUtils.logp(domainMin, base));
|
const underOneTicks = Math.floor(ticksUtils.logp(domainMin, base));
|
||||||
for (let i = under_one_ticks; i < 0; i++) {
|
for (let i = underOneTicks; i < 0; i++) {
|
||||||
const tick_value = Math.pow(base, i);
|
const tickValue = Math.pow(base, i);
|
||||||
tickValues.push(tick_value);
|
tickValues.push(tickValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const ticks = Math.ceil(ticksUtils.logp(domainMax, base));
|
const ticks = Math.ceil(ticksUtils.logp(domainMax, base));
|
||||||
for (let i = 0; i <= ticks; i++) {
|
for (let i = 0; i <= ticks; i++) {
|
||||||
const tick_value = Math.pow(base, i);
|
const tickValue = Math.pow(base, i);
|
||||||
tickValues.push(tick_value);
|
tickValues.push(tickValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
return tickValues;
|
return tickValues;
|
||||||
@ -490,7 +490,7 @@ export class HeatmapRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
addHeatmapCanvas() {
|
addHeatmapCanvas() {
|
||||||
const heatmap_elem = this.$heatmap[0];
|
const heatmapElem = this.$heatmap[0];
|
||||||
|
|
||||||
this.width = Math.floor(this.$heatmap.width()) - this.padding.right;
|
this.width = Math.floor(this.$heatmap.width()) - this.padding.right;
|
||||||
this.height = Math.floor(this.$heatmap.height()) - this.padding.bottom;
|
this.height = Math.floor(this.$heatmap.height()) - this.padding.bottom;
|
||||||
@ -503,7 +503,7 @@ export class HeatmapRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.heatmap = d3
|
this.heatmap = d3
|
||||||
.select(heatmap_elem)
|
.select(heatmapElem)
|
||||||
.append('svg')
|
.append('svg')
|
||||||
.attr('width', this.width)
|
.attr('width', this.width)
|
||||||
.attr('height', this.height);
|
.attr('height', this.height);
|
||||||
@ -514,10 +514,10 @@ export class HeatmapRenderer {
|
|||||||
this.addAxes();
|
this.addAxes();
|
||||||
|
|
||||||
if (this.panel.yAxis.logBase !== 1 && this.panel.dataFormat !== 'tsbuckets') {
|
if (this.panel.yAxis.logBase !== 1 && this.panel.dataFormat !== 'tsbuckets') {
|
||||||
const log_base = this.panel.yAxis.logBase;
|
const logBase = this.panel.yAxis.logBase;
|
||||||
const domain = this.yScale.domain();
|
const domain = this.yScale.domain();
|
||||||
const tick_values = this.logScaleTickValues(domain, log_base);
|
const tickValues = this.logScaleTickValues(domain, logBase);
|
||||||
this.data.buckets = mergeZeroBuckets(this.data.buckets, _.min(tick_values));
|
this.data.buckets = mergeZeroBuckets(this.data.buckets, _.min(tickValues));
|
||||||
}
|
}
|
||||||
|
|
||||||
const cardsData = this.data.cards;
|
const cardsData = this.data.cards;
|
||||||
@ -565,9 +565,9 @@ export class HeatmapRenderer {
|
|||||||
const color = d3.select(event.target).style('fill');
|
const color = d3.select(event.target).style('fill');
|
||||||
const highlightColor = d3.color(color).darker(2);
|
const highlightColor = d3.color(color).darker(2);
|
||||||
const strokeColor = d3.color(color).brighter(4);
|
const strokeColor = d3.color(color).brighter(4);
|
||||||
const current_card = d3.select(event.target);
|
const currentCard = d3.select(event.target);
|
||||||
this.tooltip.originalFillColor = color;
|
this.tooltip.originalFillColor = color;
|
||||||
current_card
|
currentCard
|
||||||
.style('fill', highlightColor.toString())
|
.style('fill', highlightColor.toString())
|
||||||
.style('stroke', strokeColor.toString())
|
.style('stroke', strokeColor.toString())
|
||||||
.style('stroke-width', 1);
|
.style('stroke-width', 1);
|
||||||
@ -611,8 +611,8 @@ export class HeatmapRenderer {
|
|||||||
let w;
|
let w;
|
||||||
if (this.xScale(d.x) < 0) {
|
if (this.xScale(d.x) < 0) {
|
||||||
// Cut card left to prevent overlay
|
// Cut card left to prevent overlay
|
||||||
const cutted_width = this.xScale(d.x) + this.cardWidth;
|
const cuttedWidth = this.xScale(d.x) + this.cardWidth;
|
||||||
w = cutted_width > 0 ? cutted_width : 0;
|
w = cuttedWidth > 0 ? cuttedWidth : 0;
|
||||||
} else if (this.xScale(d.x) + this.cardWidth > this.chartWidth) {
|
} else if (this.xScale(d.x) + this.cardWidth > this.chartWidth) {
|
||||||
// Cut card right to prevent overlay
|
// Cut card right to prevent overlay
|
||||||
w = this.chartWidth - this.xScale(d.x) - this.cardPadding;
|
w = this.chartWidth - this.xScale(d.x) - this.cardPadding;
|
||||||
|
@ -2,7 +2,7 @@ import moment from 'moment';
|
|||||||
import { HeatmapCtrl } from '../heatmap_ctrl';
|
import { HeatmapCtrl } from '../heatmap_ctrl';
|
||||||
|
|
||||||
describe('HeatmapCtrl', function() {
|
describe('HeatmapCtrl', function() {
|
||||||
const ctx = <any>{};
|
const ctx = {} as any;
|
||||||
|
|
||||||
const $injector = {
|
const $injector = {
|
||||||
get: () => {},
|
get: () => {},
|
||||||
|
@ -2,7 +2,7 @@ import { SingleStatCtrl } from '../module';
|
|||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
|
|
||||||
describe('SingleStatCtrl', function() {
|
describe('SingleStatCtrl', function() {
|
||||||
const ctx = <any>{};
|
const ctx = {} as any;
|
||||||
const epoch = 1505826363746;
|
const epoch = 1505826363746;
|
||||||
Date.now = () => epoch;
|
Date.now = () => epoch;
|
||||||
|
|
||||||
|
@ -185,7 +185,7 @@ export class TableRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const numericValue = Number(value);
|
const numericValue = Number(value);
|
||||||
if (numericValue === NaN) {
|
if (isNaN(numericValue)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,11 +194,11 @@ export class TableRenderer {
|
|||||||
|
|
||||||
renderRowVariables(rowIndex) {
|
renderRowVariables(rowIndex) {
|
||||||
const scopedVars = {};
|
const scopedVars = {};
|
||||||
let cell_variable;
|
let cellVariable;
|
||||||
const row = this.table.rows[rowIndex];
|
const row = this.table.rows[rowIndex];
|
||||||
for (let i = 0; i < row.length; i++) {
|
for (let i = 0; i < row.length; i++) {
|
||||||
cell_variable = `__cell_${i}`;
|
cellVariable = `__cell_${i}`;
|
||||||
scopedVars[cell_variable] = { value: row[i] };
|
scopedVars[cellVariable] = { value: row[i] };
|
||||||
}
|
}
|
||||||
return scopedVars;
|
return scopedVars;
|
||||||
}
|
}
|
||||||
@ -324,11 +324,11 @@ export class TableRenderer {
|
|||||||
|
|
||||||
for (let y = 0; y < this.table.rows.length; y++) {
|
for (let y = 0; y < this.table.rows.length; y++) {
|
||||||
const row = this.table.rows[y];
|
const row = this.table.rows[y];
|
||||||
const new_row = [];
|
const newRow = [];
|
||||||
for (let i = 0; i < this.table.columns.length; i++) {
|
for (let i = 0; i < this.table.columns.length; i++) {
|
||||||
new_row.push(this.formatColumnValue(i, row[i]));
|
newRow.push(this.formatColumnValue(i, row[i]));
|
||||||
}
|
}
|
||||||
rows.push(new_row);
|
rows.push(newRow);
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
columns: this.table.columns,
|
columns: this.table.columns,
|
||||||
|
@ -21,7 +21,7 @@ angular.module('grafana.directives', []);
|
|||||||
angular.module('grafana.filters', []);
|
angular.module('grafana.filters', []);
|
||||||
angular.module('grafana.routes', ['ngRoute']);
|
angular.module('grafana.routes', ['ngRoute']);
|
||||||
|
|
||||||
const context = (<any>require).context('../', true, /specs\.(tsx?|js)/);
|
const context = (require as any).context('../', true, /specs\.(tsx?|js)/);
|
||||||
for (const key of context.keys()) {
|
for (const key of context.keys()) {
|
||||||
context(key);
|
context(key);
|
||||||
}
|
}
|
||||||
|
@ -18,5 +18,5 @@ jest.mock('app/features/plugins/plugin_loader', () => ({}));
|
|||||||
|
|
||||||
configure({ adapter: new Adapter() });
|
configure({ adapter: new Adapter() });
|
||||||
|
|
||||||
const global = <any>window;
|
const global = window as any;
|
||||||
global.$ = global.jQuery = $;
|
global.$ = global.jQuery = $;
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
declare var global: NodeJS.Global;
|
declare var global: NodeJS.Global;
|
||||||
|
|
||||||
(<any>global).requestAnimationFrame = callback => {
|
(global as any).requestAnimationFrame = callback => {
|
||||||
setTimeout(callback, 0);
|
setTimeout(callback, 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
(<any>Promise.prototype).finally = function(onFinally) {
|
(Promise.prototype as any).finally = function(onFinally) {
|
||||||
return this.then(
|
return this.then(
|
||||||
/* onFulfilled */
|
/* onFulfilled */
|
||||||
res => Promise.resolve(onFinally()).then(() => res),
|
res => Promise.resolve(onFinally()).then(() => res),
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
const _global = <any>window;
|
const _global = window as any;
|
||||||
const beforeEach = _global.beforeEach;
|
const beforeEach = _global.beforeEach;
|
||||||
const afterEach = _global.afterEach;
|
const afterEach = _global.afterEach;
|
||||||
const before = _global.before;
|
const before = _global.before;
|
||||||
|
13
tslint.json
13
tslint.json
@ -29,6 +29,7 @@
|
|||||||
"label-position": true,
|
"label-position": true,
|
||||||
"max-line-length": [true, 150],
|
"max-line-length": [true, 150],
|
||||||
"member-access": [true, "no-public"],
|
"member-access": [true, "no-public"],
|
||||||
|
"no-angle-bracket-type-assertion": true,
|
||||||
"no-arg": true,
|
"no-arg": true,
|
||||||
"no-bitwise": false,
|
"no-bitwise": false,
|
||||||
"no-console": [true, "debug", "info", "time", "timeEnd", "trace"],
|
"no-console": [true, "debug", "info", "time", "timeEnd", "trace"],
|
||||||
@ -37,6 +38,8 @@
|
|||||||
"no-empty": false,
|
"no-empty": false,
|
||||||
"no-eval": true,
|
"no-eval": true,
|
||||||
"no-inferrable-types": true,
|
"no-inferrable-types": true,
|
||||||
|
"no-namespace": [true, "allow-declarations"],
|
||||||
|
"no-reference": true,
|
||||||
"no-shadowed-variable": false,
|
"no-shadowed-variable": false,
|
||||||
"no-string-literal": false,
|
"no-string-literal": false,
|
||||||
"no-switch-case-fall-through": false,
|
"no-switch-case-fall-through": false,
|
||||||
@ -56,7 +59,15 @@
|
|||||||
"variable-declaration": "nospace"
|
"variable-declaration": "nospace"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"variable-name": [true, "ban-keywords"],
|
"variable-name": [
|
||||||
|
true,
|
||||||
|
"check-format",
|
||||||
|
"ban-keywords",
|
||||||
|
"allow-leading-underscore",
|
||||||
|
"allow-trailing-underscore",
|
||||||
|
"allow-pascal-case"
|
||||||
|
],
|
||||||
|
"use-isnan": true,
|
||||||
"whitespace": [true, "check-branch", "check-decl", "check-type", "check-preblock"]
|
"whitespace": [true, "check-branch", "check-decl", "check-type", "check-preblock"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user