From 1efe34e6cf5ffa0e604be526169ff10c3b5dadba Mon Sep 17 00:00:00 2001 From: David Kaltschmidt Date: Mon, 16 Jul 2018 12:40:55 +0200 Subject: [PATCH 1/2] Make prometheus value formatting more robust - prometheus datasources passes its own interpolator function to the template server - that function relies on incoming values being strings - some template variables may be non-strings, e.g., `__interval_ms`, which throws an error This PR makes this more robust. --- public/app/plugins/datasource/prometheus/datasource.ts | 10 ++++++++-- .../datasource/prometheus/specs/datasource.jest.ts | 3 +++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/public/app/plugins/datasource/prometheus/datasource.ts b/public/app/plugins/datasource/prometheus/datasource.ts index 9ccda65a145..35b04066552 100644 --- a/public/app/plugins/datasource/prometheus/datasource.ts +++ b/public/app/plugins/datasource/prometheus/datasource.ts @@ -17,11 +17,17 @@ export function alignRange(start, end, step) { } export function prometheusRegularEscape(value) { - return value.replace(/'/g, "\\\\'"); + if (typeof value === 'string') { + return value.replace(/'/g, "\\\\'"); + } + return value; } export function prometheusSpecialRegexEscape(value) { - return prometheusRegularEscape(value.replace(/\\/g, '\\\\\\\\').replace(/[$^*{}\[\]+?.()]/g, '\\\\$&')); + if (typeof value === 'string') { + return prometheusRegularEscape(value.replace(/\\/g, '\\\\\\\\').replace(/[$^*{}\[\]+?.()]/g, '\\\\$&')); + } + return value; } export class PrometheusDatasource { diff --git a/public/app/plugins/datasource/prometheus/specs/datasource.jest.ts b/public/app/plugins/datasource/prometheus/specs/datasource.jest.ts index 219b990e5dd..15798a33cd2 100644 --- a/public/app/plugins/datasource/prometheus/specs/datasource.jest.ts +++ b/public/app/plugins/datasource/prometheus/specs/datasource.jest.ts @@ -166,6 +166,9 @@ describe('PrometheusDatasource', () => { }); describe('Prometheus regular escaping', function() { + it('should not escape non-string', function() { + expect(prometheusRegularEscape(12)).toEqual(12); + }); it('should not escape simple string', function() { expect(prometheusRegularEscape('cryptodepression')).toEqual('cryptodepression'); }); From 1f74b298c4ee3f5777f9b10d5ce5f6da8f4fc8ac Mon Sep 17 00:00:00 2001 From: David Kaltschmidt Date: Mon, 16 Jul 2018 13:02:36 +0200 Subject: [PATCH 2/2] Remove string casting for template variables in prometheus --- .../app/features/panel/metrics_panel_ctrl.ts | 2 +- .../datasource/prometheus/datasource.ts | 2 +- .../prometheus/specs/datasource_specs.ts | 36 +++++++++---------- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/public/app/features/panel/metrics_panel_ctrl.ts b/public/app/features/panel/metrics_panel_ctrl.ts index 6eb6d3b3b00..75c0de3bc6e 100644 --- a/public/app/features/panel/metrics_panel_ctrl.ts +++ b/public/app/features/panel/metrics_panel_ctrl.ts @@ -222,7 +222,7 @@ class MetricsPanelCtrl extends PanelCtrl { // and add built in variables interval and interval_ms var scopedVars = Object.assign({}, this.panel.scopedVars, { __interval: { text: this.interval, value: this.interval }, - __interval_ms: { text: String(this.intervalMs), value: String(this.intervalMs) }, + __interval_ms: { text: this.intervalMs, value: this.intervalMs }, }); var metricsQuery = { diff --git a/public/app/plugins/datasource/prometheus/datasource.ts b/public/app/plugins/datasource/prometheus/datasource.ts index 35b04066552..69ce6f440c5 100644 --- a/public/app/plugins/datasource/prometheus/datasource.ts +++ b/public/app/plugins/datasource/prometheus/datasource.ts @@ -202,7 +202,7 @@ export class PrometheusDatasource { interval = adjustedInterval; scopedVars = Object.assign({}, options.scopedVars, { __interval: { text: interval + 's', value: interval + 's' }, - __interval_ms: { text: String(interval * 1000), value: String(interval * 1000) }, + __interval_ms: { text: interval * 1000, value: interval * 1000 }, }); } query.step = interval; diff --git a/public/app/plugins/datasource/prometheus/specs/datasource_specs.ts b/public/app/plugins/datasource/prometheus/specs/datasource_specs.ts index 09aa934dd63..c5da671b757 100644 --- a/public/app/plugins/datasource/prometheus/specs/datasource_specs.ts +++ b/public/app/plugins/datasource/prometheus/specs/datasource_specs.ts @@ -452,7 +452,7 @@ describe('PrometheusDatasource', function() { interval: '10s', scopedVars: { __interval: { text: '10s', value: '10s' }, - __interval_ms: { text: String(10 * 1000), value: String(10 * 1000) }, + __interval_ms: { text: 10 * 1000, value: 10 * 1000 }, }, }; var urlExpected = @@ -463,8 +463,8 @@ describe('PrometheusDatasource', function() { expect(query.scopedVars.__interval.text).to.be('10s'); expect(query.scopedVars.__interval.value).to.be('10s'); - expect(query.scopedVars.__interval_ms.text).to.be(String(10 * 1000)); - expect(query.scopedVars.__interval_ms.value).to.be(String(10 * 1000)); + expect(query.scopedVars.__interval_ms.text).to.be(10 * 1000); + expect(query.scopedVars.__interval_ms.value).to.be(10 * 1000); }); it('should be min interval when it is greater than auto interval', function() { var query = { @@ -479,7 +479,7 @@ describe('PrometheusDatasource', function() { interval: '5s', scopedVars: { __interval: { text: '5s', value: '5s' }, - __interval_ms: { text: String(5 * 1000), value: String(5 * 1000) }, + __interval_ms: { text: 5 * 1000, value: 5 * 1000 }, }, }; var urlExpected = @@ -490,8 +490,8 @@ describe('PrometheusDatasource', function() { expect(query.scopedVars.__interval.text).to.be('5s'); expect(query.scopedVars.__interval.value).to.be('5s'); - expect(query.scopedVars.__interval_ms.text).to.be(String(5 * 1000)); - expect(query.scopedVars.__interval_ms.value).to.be(String(5 * 1000)); + expect(query.scopedVars.__interval_ms.text).to.be(5 * 1000); + expect(query.scopedVars.__interval_ms.value).to.be(5 * 1000); }); it('should account for intervalFactor', function() { var query = { @@ -507,7 +507,7 @@ describe('PrometheusDatasource', function() { interval: '10s', scopedVars: { __interval: { text: '10s', value: '10s' }, - __interval_ms: { text: String(10 * 1000), value: String(10 * 1000) }, + __interval_ms: { text: 10 * 1000, value: 10 * 1000 }, }, }; var urlExpected = @@ -518,8 +518,8 @@ describe('PrometheusDatasource', function() { expect(query.scopedVars.__interval.text).to.be('10s'); expect(query.scopedVars.__interval.value).to.be('10s'); - expect(query.scopedVars.__interval_ms.text).to.be(String(10 * 1000)); - expect(query.scopedVars.__interval_ms.value).to.be(String(10 * 1000)); + expect(query.scopedVars.__interval_ms.text).to.be(10 * 1000); + expect(query.scopedVars.__interval_ms.value).to.be(10 * 1000); }); it('should be interval * intervalFactor when greater than min interval', function() { var query = { @@ -535,7 +535,7 @@ describe('PrometheusDatasource', function() { interval: '5s', scopedVars: { __interval: { text: '5s', value: '5s' }, - __interval_ms: { text: String(5 * 1000), value: String(5 * 1000) }, + __interval_ms: { text: 5 * 1000, value: 5 * 1000 }, }, }; var urlExpected = @@ -546,8 +546,8 @@ describe('PrometheusDatasource', function() { expect(query.scopedVars.__interval.text).to.be('5s'); expect(query.scopedVars.__interval.value).to.be('5s'); - expect(query.scopedVars.__interval_ms.text).to.be(String(5 * 1000)); - expect(query.scopedVars.__interval_ms.value).to.be(String(5 * 1000)); + expect(query.scopedVars.__interval_ms.text).to.be(5 * 1000); + expect(query.scopedVars.__interval_ms.value).to.be(5 * 1000); }); it('should be min interval when greater than interval * intervalFactor', function() { var query = { @@ -563,7 +563,7 @@ describe('PrometheusDatasource', function() { interval: '5s', scopedVars: { __interval: { text: '5s', value: '5s' }, - __interval_ms: { text: String(5 * 1000), value: String(5 * 1000) }, + __interval_ms: { text: 5 * 1000, value: 5 * 1000 }, }, }; var urlExpected = @@ -574,8 +574,8 @@ describe('PrometheusDatasource', function() { expect(query.scopedVars.__interval.text).to.be('5s'); expect(query.scopedVars.__interval.value).to.be('5s'); - expect(query.scopedVars.__interval_ms.text).to.be(String(5 * 1000)); - expect(query.scopedVars.__interval_ms.value).to.be(String(5 * 1000)); + expect(query.scopedVars.__interval_ms.text).to.be(5 * 1000); + expect(query.scopedVars.__interval_ms.value).to.be(5 * 1000); }); it('should be determined by the 11000 data points limit, accounting for intervalFactor', function() { var query = { @@ -590,7 +590,7 @@ describe('PrometheusDatasource', function() { interval: '5s', scopedVars: { __interval: { text: '5s', value: '5s' }, - __interval_ms: { text: String(5 * 1000), value: String(5 * 1000) }, + __interval_ms: { text: 5 * 1000, value: 5 * 1000 }, }, }; var end = 7 * 24 * 60 * 60; @@ -609,8 +609,8 @@ describe('PrometheusDatasource', function() { expect(query.scopedVars.__interval.text).to.be('5s'); expect(query.scopedVars.__interval.value).to.be('5s'); - expect(query.scopedVars.__interval_ms.text).to.be(String(5 * 1000)); - expect(query.scopedVars.__interval_ms.value).to.be(String(5 * 1000)); + expect(query.scopedVars.__interval_ms.text).to.be(5 * 1000); + expect(query.scopedVars.__interval_ms.value).to.be(5 * 1000); }); }); });