diff --git a/packages/grafana-data/src/types/data.ts b/packages/grafana-data/src/types/data.ts index 7fe6ae08961..77f7c47d47b 100644 --- a/packages/grafana-data/src/types/data.ts +++ b/packages/grafana-data/src/types/data.ts @@ -43,7 +43,7 @@ export interface QueryResultMeta { * Legacy data source specific, should be moved to custom * */ gmdMeta?: any[]; // used by cloudwatch - alignmentPeriod?: string; // used by cloud monitoring + alignmentPeriod?: number; // used by cloud monitoring searchWords?: string[]; // used by log models and loki limit?: number; // used by log models and loki json?: boolean; // used to keep track of old json doc values diff --git a/packages/grafana-data/src/valueFormats/valueFormats.ts b/packages/grafana-data/src/valueFormats/valueFormats.ts index f11f0347730..ea1e4b87f54 100644 --- a/packages/grafana-data/src/valueFormats/valueFormats.ts +++ b/packages/grafana-data/src/valueFormats/valueFormats.ts @@ -32,7 +32,7 @@ export interface ValueFormatCategory { formats: ValueFormat[]; } -interface ValueFormatterIndex { +export interface ValueFormatterIndex { [id: string]: ValueFormatter; } diff --git a/public/app/core/directives/misc.ts b/public/app/core/directives/misc.ts index 4695d943ea7..b9e2f4b675c 100644 --- a/public/app/core/directives/misc.ts +++ b/public/app/core/directives/misc.ts @@ -14,7 +14,7 @@ function tip($compile: any) { ''; _t = _t.replace(/{/g, '\\{').replace(/}/g, '\\}'); elem.replaceWith($compile(angular.element(_t))(scope)); diff --git a/public/app/core/services/context_srv.ts b/public/app/core/services/context_srv.ts index b6a3c8f08cc..0b2d5ec4a98 100644 --- a/public/app/core/services/context_srv.ts +++ b/public/app/core/services/context_srv.ts @@ -61,7 +61,7 @@ export class ContextSrv { if (!config.minRefreshInterval) { return true; } - return kbn.interval_to_ms(interval) >= kbn.interval_to_ms(config.minRefreshInterval); + return kbn.intervalToMs(interval) >= kbn.intervalToMs(config.minRefreshInterval); } getValidInterval(interval: string) { diff --git a/public/app/core/utils/kbn.test.ts b/public/app/core/utils/kbn.test.ts index 80dd53ed5b3..3bf5b44cfe7 100644 --- a/public/app/core/utils/kbn.test.ts +++ b/public/app/core/utils/kbn.test.ts @@ -53,7 +53,7 @@ describe('Chcek KBN value formats', () => { describe('describe_interval', () => { it('falls back to seconds if input is a number', () => { - expect(kbn.describe_interval('123')).toEqual({ + expect(kbn.describeInterval('123')).toEqual({ sec: 1, type: 's', count: 123, @@ -61,7 +61,7 @@ describe('describe_interval', () => { }); it('parses a valid time unt string correctly', () => { - expect(kbn.describe_interval('123h')).toEqual({ + expect(kbn.describeInterval('123h')).toEqual({ sec: 3600, type: 'h', count: 123, @@ -69,7 +69,7 @@ describe('describe_interval', () => { }); it('fails if input is invalid', () => { - expect(() => kbn.describe_interval('123xyz')).toThrow(); - expect(() => kbn.describe_interval('xyz')).toThrow(); + expect(() => kbn.describeInterval('123xyz')).toThrow(); + expect(() => kbn.describeInterval('xyz')).toThrow(); }); }); diff --git a/public/app/core/utils/kbn.ts b/public/app/core/utils/kbn.ts index 4fc19c35c62..cc991b12fd5 100644 --- a/public/app/core/utils/kbn.ts +++ b/public/app/core/utils/kbn.ts @@ -1,319 +1,291 @@ -import { has } from 'lodash'; import { + DecimalCount, + deprecationWarning, + formattedValueToString, getValueFormat, - getValueFormatterIndex, getValueFormats, + getValueFormatterIndex, stringToJsRegex, TimeRange, - deprecationWarning, - DecimalCount, - formattedValueToString, + ValueFormatterIndex, } from '@grafana/data'; +import { has } from 'lodash'; -const kbn: any = {}; - -kbn.valueFormats = {}; - -kbn.regexEscape = (value: string) => { - return value.replace(/[\\^$*+?.()|[\]{}\/]/g, '\\$&'); -}; - -///// HELPER FUNCTIONS ///// - -kbn.round_interval = (interval: number) => { - switch (true) { - // 0.015s - case interval < 15: - return 10; // 0.01s - // 0.035s - case interval < 35: - return 20; // 0.02s - // 0.075s - case interval < 75: - return 50; // 0.05s - // 0.15s - case interval < 150: - return 100; // 0.1s - // 0.35s - case interval < 350: - return 200; // 0.2s - // 0.75s - case interval < 750: - return 500; // 0.5s - // 1.5s - case interval < 1500: - return 1000; // 1s - // 3.5s - case interval < 3500: - return 2000; // 2s - // 7.5s - case interval < 7500: - return 5000; // 5s - // 12.5s - case interval < 12500: - return 10000; // 10s - // 17.5s - case interval < 17500: - return 15000; // 15s - // 25s - case interval < 25000: - return 20000; // 20s - // 45s - case interval < 45000: - return 30000; // 30s - // 1.5m - case interval < 90000: - return 60000; // 1m - // 3.5m - case interval < 210000: - return 120000; // 2m - // 7.5m - case interval < 450000: - return 300000; // 5m - // 12.5m - case interval < 750000: - return 600000; // 10m - // 12.5m - case interval < 1050000: - return 900000; // 15m - // 25m - case interval < 1500000: - return 1200000; // 20m - // 45m - case interval < 2700000: - return 1800000; // 30m - // 1.5h - case interval < 5400000: - return 3600000; // 1h - // 2.5h - case interval < 9000000: - return 7200000; // 2h - // 4.5h - case interval < 16200000: - return 10800000; // 3h - // 9h - case interval < 32400000: - return 21600000; // 6h - // 1d - case interval < 86400000: - return 43200000; // 12h - // 1w - case interval < 604800000: - return 86400000; // 1d - // 3w - case interval < 1814400000: - return 604800000; // 1w - // 6w - case interval < 3628800000: - return 2592000000; // 30d - default: - return 31536000000; // 1y - } -}; - -kbn.secondsToHms = (seconds: number) => { - const numyears = Math.floor(seconds / 31536000); - if (numyears) { - return numyears + 'y'; - } - const numdays = Math.floor((seconds % 31536000) / 86400); - if (numdays) { - return numdays + 'd'; - } - const numhours = Math.floor(((seconds % 31536000) % 86400) / 3600); - if (numhours) { - return numhours + 'h'; - } - const numminutes = Math.floor((((seconds % 31536000) % 86400) % 3600) / 60); - if (numminutes) { - return numminutes + 'm'; - } - const numseconds = Math.floor((((seconds % 31536000) % 86400) % 3600) % 60); - if (numseconds) { - return numseconds + 's'; - } - const nummilliseconds = Math.floor(seconds * 1000.0); - if (nummilliseconds) { - return nummilliseconds + 'ms'; - } - - return 'less than a millisecond'; //'just now' //or other string you like; -}; - -kbn.secondsToHhmmss = (seconds: number) => { - const strings: string[] = []; - const numhours = Math.floor(seconds / 3600); - const numminutes = Math.floor((seconds % 3600) / 60); - const numseconds = Math.floor((seconds % 3600) % 60); - numhours > 9 ? strings.push('' + numhours) : strings.push('0' + numhours); - numminutes > 9 ? strings.push('' + numminutes) : strings.push('0' + numminutes); - numseconds > 9 ? strings.push('' + numseconds) : strings.push('0' + numseconds); - return strings.join(':'); -}; - -kbn.to_percent = (nr: number, outof: number) => { - return Math.floor((nr / outof) * 10000) / 100 + '%'; -}; - -kbn.addslashes = (str: string) => { - str = str.replace(/\\/g, '\\\\'); - str = str.replace(/\'/g, "\\'"); - str = str.replace(/\"/g, '\\"'); - str = str.replace(/\0/g, '\\0'); - return str; -}; - -kbn.interval_regex = /(\d+(?:\.\d+)?)(ms|[Mwdhmsy])/; - -// histogram & trends -kbn.intervals_in_seconds = { - y: 31536000, - M: 2592000, - w: 604800, - d: 86400, - h: 3600, - m: 60, - s: 1, - ms: 0.001, -}; - -kbn.calculateInterval = (range: TimeRange, resolution: number, lowLimitInterval: string[]) => { - let lowLimitMs = 1; // 1 millisecond default low limit - let intervalMs; - - if (lowLimitInterval) { - if (lowLimitInterval[0] === '>') { - lowLimitInterval = lowLimitInterval.slice(1); +const kbn = { + valueFormats: {} as ValueFormatterIndex, + intervalRegex: /(\d+(?:\.\d+)?)(ms|[Mwdhmsy])/, + intervalsInSeconds: { + y: 31536000, + M: 2592000, + w: 604800, + d: 86400, + h: 3600, + m: 60, + s: 1, + ms: 0.001, + } as { [index: string]: number }, + regexEscape: (value: string) => value.replace(/[\\^$*+?.()|[\]{}\/]/g, '\\$&'), + roundInterval: (interval: number) => { + switch (true) { + // 0.015s + case interval < 15: + return 10; // 0.01s + // 0.035s + case interval < 35: + return 20; // 0.02s + // 0.075s + case interval < 75: + return 50; // 0.05s + // 0.15s + case interval < 150: + return 100; // 0.1s + // 0.35s + case interval < 350: + return 200; // 0.2s + // 0.75s + case interval < 750: + return 500; // 0.5s + // 1.5s + case interval < 1500: + return 1000; // 1s + // 3.5s + case interval < 3500: + return 2000; // 2s + // 7.5s + case interval < 7500: + return 5000; // 5s + // 12.5s + case interval < 12500: + return 10000; // 10s + // 17.5s + case interval < 17500: + return 15000; // 15s + // 25s + case interval < 25000: + return 20000; // 20s + // 45s + case interval < 45000: + return 30000; // 30s + // 1.5m + case interval < 90000: + return 60000; // 1m + // 3.5m + case interval < 210000: + return 120000; // 2m + // 7.5m + case interval < 450000: + return 300000; // 5m + // 12.5m + case interval < 750000: + return 600000; // 10m + // 12.5m + case interval < 1050000: + return 900000; // 15m + // 25m + case interval < 1500000: + return 1200000; // 20m + // 45m + case interval < 2700000: + return 1800000; // 30m + // 1.5h + case interval < 5400000: + return 3600000; // 1h + // 2.5h + case interval < 9000000: + return 7200000; // 2h + // 4.5h + case interval < 16200000: + return 10800000; // 3h + // 9h + case interval < 32400000: + return 21600000; // 6h + // 1d + case interval < 86400000: + return 43200000; // 12h + // 1w + case interval < 604800000: + return 86400000; // 1d + // 3w + case interval < 1814400000: + return 604800000; // 1w + // 6w + case interval < 3628800000: + return 2592000000; // 30d + default: + return 31536000000; // 1y + } + }, + secondsToHms: (seconds: number) => { + const numYears = Math.floor(seconds / 31536000); + if (numYears) { + return numYears + 'y'; + } + const numDays = Math.floor((seconds % 31536000) / 86400); + if (numDays) { + return numDays + 'd'; + } + const numHours = Math.floor(((seconds % 31536000) % 86400) / 3600); + if (numHours) { + return numHours + 'h'; + } + const numMinutes = Math.floor((((seconds % 31536000) % 86400) % 3600) / 60); + if (numMinutes) { + return numMinutes + 'm'; + } + const numSeconds = Math.floor((((seconds % 31536000) % 86400) % 3600) % 60); + if (numSeconds) { + return numSeconds + 's'; + } + const numMilliseconds = Math.floor(seconds * 1000.0); + if (numMilliseconds) { + return numMilliseconds + 'ms'; } - lowLimitMs = kbn.interval_to_ms(lowLimitInterval); - } - intervalMs = kbn.round_interval((range.to.valueOf() - range.from.valueOf()) / resolution); - if (lowLimitMs > intervalMs) { - intervalMs = lowLimitMs; - } + return 'less than a millisecond'; //'just now' //or other string you like; + }, + secondsToHhmmss: (seconds: number) => { + const strings: string[] = []; + const numHours = Math.floor(seconds / 3600); + const numMinutes = Math.floor((seconds % 3600) / 60); + const numSeconds = Math.floor((seconds % 3600) % 60); + numHours > 9 ? strings.push('' + numHours) : strings.push('0' + numHours); + numMinutes > 9 ? strings.push('' + numMinutes) : strings.push('0' + numMinutes); + numSeconds > 9 ? strings.push('' + numSeconds) : strings.push('0' + numSeconds); + return strings.join(':'); + }, + toPercent: (nr: number, outOf: number) => Math.floor((nr / outOf) * 10000) / 100 + '%', + addSlashes: (str: string) => { + str = str.replace(/\\/g, '\\\\'); + str = str.replace(/\'/g, "\\'"); + str = str.replace(/\"/g, '\\"'); + str = str.replace(/\0/g, '\\0'); + return str; + }, + describeInterval: (str: string) => { + // Default to seconds if no unit is provided + if (Number(str)) { + return { + sec: kbn.intervalsInSeconds.s, + type: 's', + count: parseInt(str, 10), + }; + } - return { - intervalMs: intervalMs, - interval: kbn.secondsToHms(intervalMs / 1000), - }; -}; + const matches = str.match(kbn.intervalRegex); + if (!matches || !has(kbn.intervalsInSeconds, matches[2])) { + throw new Error( + `Invalid interval string, has to be either unit-less or end with one of the following units: "${Object.keys( + kbn.intervalsInSeconds + ).join(', ')}"` + ); + } else { + return { + sec: kbn.intervalsInSeconds[matches[2]], + type: matches[2], + count: parseInt(matches[1], 10), + }; + } + }, + intervalToSeconds: (str: string): number => { + const info = kbn.describeInterval(str); + return info.sec * info.count; + }, + intervalToMs: (str: string) => { + const info = kbn.describeInterval(str); + return info.sec * 1000 * info.count; + }, + calculateInterval: (range: TimeRange, resolution: number, lowLimitInterval?: string) => { + let lowLimitMs = 1; // 1 millisecond default low limit + let intervalMs; + + if (lowLimitInterval) { + if (lowLimitInterval[0] === '>') { + lowLimitInterval = lowLimitInterval.slice(1); + } + lowLimitMs = kbn.intervalToMs(lowLimitInterval); + } + + intervalMs = kbn.roundInterval((range.to.valueOf() - range.from.valueOf()) / resolution); + if (lowLimitMs > intervalMs) { + intervalMs = lowLimitMs; + } -kbn.describe_interval = (str: string) => { - // Default to seconds if no unit is provided - if (Number(str)) { return { - sec: kbn.intervals_in_seconds.s, - type: 's', - count: parseInt(str, 10), + intervalMs: intervalMs, + interval: kbn.secondsToHms(intervalMs / 1000), }; - } - - const matches = str.match(kbn.interval_regex); - if (!matches || !has(kbn.intervals_in_seconds, matches[2])) { - throw new Error( - `Invalid interval string, has to be either unit-less or end with one of the following units: "${Object.keys( - kbn.intervals_in_seconds - ).join(', ')}"` + }, + queryColorDot: (color: string, diameter: string) => { + return ( + '
' ); - } else { - return { - sec: kbn.intervals_in_seconds[matches[2]], - type: matches[2], - count: parseInt(matches[1], 10), - }; - } -}; - -kbn.interval_to_ms = (str: string) => { - const info = kbn.describe_interval(str); - return info.sec * 1000 * info.count; -}; - -kbn.interval_to_seconds = (str: string): number => { - const info = kbn.describe_interval(str); - return info.sec * info.count; -}; - -kbn.query_color_dot = (color: string, diameter: string) => { - return ( - '' - ); -}; - -kbn.slugifyForUrl = (str: string) => { - return str - .toLowerCase() - .replace(/[^\w ]+/g, '') - .replace(/ +/g, '-'); -}; - -/** deprecated since 6.1, use grafana/data */ -kbn.stringToJsRegex = (str: string) => { - deprecationWarning('kbn.ts', 'kbn.stringToJsRegex()', '@grafana/data'); - return stringToJsRegex(str); -}; - -kbn.toFixed = (value: number | null, decimals: number) => { - if (value === null) { - return ''; - } - - const factor = decimals ? Math.pow(10, Math.max(0, decimals)) : 1; - const formatted = String(Math.round(value * factor) / factor); - - // if exponent return directly - if (formatted.indexOf('e') !== -1 || value === 0) { - return formatted; - } - - // If tickDecimals was specified, ensure that we have exactly that - // much precision; otherwise default to the value's own precision. - if (decimals != null) { - const decimalPos = formatted.indexOf('.'); - const precision = decimalPos === -1 ? 0 : formatted.length - decimalPos - 1; - if (precision < decimals) { - return (precision ? formatted : formatted + '.') + String(factor).substr(1, decimals - precision); + }, + slugifyForUrl: (str: string) => { + return str + .toLowerCase() + .replace(/[^\w ]+/g, '') + .replace(/ +/g, '-'); + }, + /** deprecated since 6.1, use grafana/data */ + stringToJsRegex: (str: string) => { + deprecationWarning('kbn.ts', 'kbn.stringToJsRegex()', '@grafana/data'); + return stringToJsRegex(str); + }, + toFixed: (value: number | null, decimals: number) => { + if (value === null) { + return ''; } - } - return formatted; + const factor = decimals ? Math.pow(10, Math.max(0, decimals)) : 1; + const formatted = String(Math.round(value * factor) / factor); + + // if exponent return directly + if (formatted.indexOf('e') !== -1 || value === 0) { + return formatted; + } + + // If tickDecimals was specified, ensure that we have exactly that + // much precision; otherwise default to the value's own precision. + if (decimals != null) { + const decimalPos = formatted.indexOf('.'); + const precision = decimalPos === -1 ? 0 : formatted.length - decimalPos - 1; + if (precision < decimals) { + return (precision ? formatted : formatted + '.') + String(factor).substr(1, decimals - precision); + } + } + + return formatted; + }, + toFixedScaled: ( + value: number, + decimals: number, + scaledDecimals: number | null, + additionalDecimals: number, + ext: number + ) => { + if (scaledDecimals === null) { + return kbn.toFixed(value, decimals) + ext; + } else { + return kbn.toFixed(value, scaledDecimals + additionalDecimals) + ext; + } + }, + roundValue: (num: number, decimals: number) => { + if (num === null) { + return null; + } + const n = Math.pow(10, decimals); + const formatted = (n * num).toFixed(decimals); + return Math.round(parseFloat(formatted)) / n; + }, + // FORMAT MENU + getUnitFormats: getValueFormats, }; -kbn.toFixedScaled = ( - value: number, - decimals: number, - scaledDecimals: number | null, - additionalDecimals: number, - ext: number -) => { - if (scaledDecimals === null) { - return kbn.toFixed(value, decimals) + ext; - } else { - return kbn.toFixed(value, scaledDecimals + additionalDecimals) + ext; - } -}; - -kbn.roundValue = (num: number, decimals: number) => { - if (num === null) { - return null; - } - const n = Math.pow(10, decimals); - const formatted = (n * num).toFixed(decimals); - return Math.round(parseFloat(formatted)) / n; -}; - -///// FORMAT MENU ///// - -kbn.getUnitFormats = () => { - return getValueFormats(); -}; - -// -// Backward compatible layer for value formats to support old plugins -// +/** + * Backward compatible layer for value formats to support old plugins + */ if (typeof Proxy !== 'undefined') { kbn.valueFormats = new Proxy(kbn.valueFormats, { get(target, name, receiver) { diff --git a/public/app/features/alerting/AlertTabCtrl.ts b/public/app/features/alerting/AlertTabCtrl.ts index 5da5fae2f8f..f38ce575031 100644 --- a/public/app/features/alerting/AlertTabCtrl.ts +++ b/public/app/features/alerting/AlertTabCtrl.ts @@ -253,7 +253,7 @@ export class AlertTabCtrl { this.frequencyWarning = ''; try { - const frequencySecs = kbn.interval_to_seconds(this.alert.frequency); + const frequencySecs = kbn.intervalToSeconds(this.alert.frequency); if (frequencySecs < this.alertingMinIntervalSecs) { this.frequencyWarning = 'A minimum evaluation interval of ' + diff --git a/public/app/features/api-keys/ApiKeysPage.tsx b/public/app/features/api-keys/ApiKeysPage.tsx index 39699a0a8cd..37a85290326 100644 --- a/public/app/features/api-keys/ApiKeysPage.tsx +++ b/public/app/features/api-keys/ApiKeysPage.tsx @@ -37,7 +37,7 @@ const timeRangeValidationEvents: ValidationEvents = { return true; } try { - kbn.interval_to_seconds(value); + kbn.intervalToSeconds(value); return true; } catch { return false; @@ -125,7 +125,7 @@ export class ApiKeysPage extends PureComponent