Merge branch 'master' into backend

This commit is contained in:
Alexander Zobnin
2020-01-16 12:21:22 +03:00
9 changed files with 486 additions and 425 deletions

View File

@@ -105,6 +105,19 @@ calculates moving average over 60 points (if metric has 1 second resolution it m
``` ```
--- ---
### _percentile_
```
percentile(interval, N)
```
Takes a series of values and a window size and consolidate all its points fallen in the given _interval_ into one point by Nth percentile.
Examples:
```
percentile(1h, 99)
percentile($__range_series, 95) - 95th percentile over all series values
```
---
### _removeAboveValue_ ### _removeAboveValue_
``` ```
removeAboveValue(N) removeAboveValue(N)
@@ -159,16 +172,16 @@ This will add metrics together and return the sum at each datapoint. This method
--- ---
### _percentile_ ### _percentileAgg_
``` ```
percentile(interval, N) percentileAgg(interval, N)
``` ```
Takes all timeseries and consolidate all its points fallen in the given _interval_ into one point by Nth percentile. Takes all timeseries and consolidate all its points fallen in the given _interval_ into one point by Nth percentile.
Examples: Examples:
``` ```
percentile(1h, 99) percentileAgg(1h, 99)
percentile($__range_series, 95) - 95th percentile over all values percentileAgg($__range_series, 95) - 95th percentile over all values
``` ```
--- ---

View File

@@ -30,10 +30,10 @@
"@babel/preset-env": "^7.8.3", "@babel/preset-env": "^7.8.3",
"@babel/preset-react": "^7.8.3", "@babel/preset-react": "^7.8.3",
"@emotion/core": "^10.0.27", "@emotion/core": "^10.0.27",
"@grafana/data": "canary", "@grafana/data": "^6.5.3",
"@grafana/runtime": "canary", "@grafana/runtime": "^6.5.3",
"@grafana/toolkit": "canary", "@grafana/toolkit": "^6.5.3",
"@grafana/ui": "canary", "@grafana/ui": "^6.5.3",
"@types/classnames": "^2.2.9", "@types/classnames": "^2.2.9",
"@types/grafana": "github:CorpGlory/types-grafana", "@types/grafana": "github:CorpGlory/types-grafana",
"@types/jest": "^23.1.1", "@types/jest": "^23.1.1",

View File

@@ -1,6 +1,6 @@
import React, { FC } from 'react'; import React, { FC } from 'react';
import { css, cx } from 'emotion'; import { css, cx } from 'emotion';
import { Themeable, withTheme, Input, EventsWithValidation, ValidationEvents } from '@grafana/ui'; import { withTheme, Input, EventsWithValidation, ValidationEvents, Themeable } from '@grafana/ui';
import { GrafanaTheme } from '@grafana/data'; import { GrafanaTheme } from '@grafana/data';
import { isRegex, variableRegex } from '../utils'; import { isRegex, variableRegex } from '../utils';

View File

@@ -2,6 +2,14 @@ import _ from 'lodash';
import * as utils from './utils'; import * as utils from './utils';
import ts, { groupBy_perf as groupBy } from './timeseries'; import ts, { groupBy_perf as groupBy } from './timeseries';
let SUM = ts.SUM;
let COUNT = ts.COUNT;
let AVERAGE = ts.AVERAGE;
let MIN = ts.MIN;
let MAX = ts.MAX;
let MEDIAN = ts.MEDIAN;
let PERCENTILE = ts.PERCENTILE;
let downsampleSeries = ts.downsample; let downsampleSeries = ts.downsample;
let groupBy_exported = (interval, groupFunc, datapoints) => groupBy(datapoints, interval, groupFunc); let groupBy_exported = (interval, groupFunc, datapoints) => groupBy(datapoints, interval, groupFunc);
let sumSeries = ts.sumSeries; let sumSeries = ts.sumSeries;
@@ -11,14 +19,7 @@ let scale = (factor, datapoints) => ts.scale_perf(datapoints, factor);
let offset = (delta, datapoints) => ts.offset(datapoints, delta); let offset = (delta, datapoints) => ts.offset(datapoints, delta);
let simpleMovingAverage = (n, datapoints) => ts.simpleMovingAverage(datapoints, n); let simpleMovingAverage = (n, datapoints) => ts.simpleMovingAverage(datapoints, n);
let expMovingAverage = (a, datapoints) => ts.expMovingAverage(datapoints, a); let expMovingAverage = (a, datapoints) => ts.expMovingAverage(datapoints, a);
let percentile = (interval, n, datapoints) => groupBy(datapoints, interval, _.partial(PERCENTILE, n));
let SUM = ts.SUM;
let COUNT = ts.COUNT;
let AVERAGE = ts.AVERAGE;
let MIN = ts.MIN;
let MAX = ts.MAX;
let MEDIAN = ts.MEDIAN;
let PERCENTILE = ts.PERCENTILE;
function limit(order, n, orderByFunc, timeseries) { function limit(order, n, orderByFunc, timeseries) {
let orderByCallback = aggregationFunctions[orderByFunc]; let orderByCallback = aggregationFunctions[orderByFunc];
@@ -120,7 +121,7 @@ function aggregateWrapper(groupByCallback, interval, datapoints) {
return groupBy(sortedPoints, interval, groupByCallback); return groupBy(sortedPoints, interval, groupByCallback);
} }
function percentile(interval, n, datapoints) { function percentileAgg(interval, n, datapoints) {
const flattenedPoints = ts.flattenDatapoints(datapoints); const flattenedPoints = ts.flattenDatapoints(datapoints);
// groupBy_perf works with sorted series only // groupBy_perf works with sorted series only
const sortedPoints = ts.sortByTime(flattenedPoints); const sortedPoints = ts.sortByTime(flattenedPoints);
@@ -153,10 +154,11 @@ let metricFunctions = {
rate: rate, rate: rate,
movingAverage: simpleMovingAverage, movingAverage: simpleMovingAverage,
exponentialMovingAverage: expMovingAverage, exponentialMovingAverage: expMovingAverage,
percentile: percentile,
transformNull: transformNull, transformNull: transformNull,
aggregateBy: aggregateByWrapper, aggregateBy: aggregateByWrapper,
// Predefined aggs // Predefined aggs
percentile: percentile, percentileAgg: percentileAgg,
average: _.partial(aggregateWrapper, AVERAGE), average: _.partial(aggregateWrapper, AVERAGE),
min: _.partial(aggregateWrapper, MIN), min: _.partial(aggregateWrapper, MIN),
max: _.partial(aggregateWrapper, MAX), max: _.partial(aggregateWrapper, MAX),

View File

@@ -85,6 +85,16 @@ addFuncDef({
defaultParams: [0.2], defaultParams: [0.2],
}); });
addFuncDef({
name: 'percentile',
category: 'Transform',
params: [
{ name: 'interval', type: 'string' },
{ name: 'percent', type: 'float', options: [25, 50, 75, 90, 95, 99, 99.9] }
],
defaultParams: ['1m', 95],
});
addFuncDef({ addFuncDef({
name: 'removeAboveValue', name: 'removeAboveValue',
category: 'Transform', category: 'Transform',
@@ -140,7 +150,7 @@ addFuncDef({
}); });
addFuncDef({ addFuncDef({
name: 'percentile', name: 'percentileAgg',
category: 'Aggregate', category: 'Aggregate',
params: [ params: [
{ name: 'interval', type: 'string' }, { name: 'interval', type: 'string' },

View File

@@ -57,30 +57,30 @@ type TimeSeriesPoints = TimePoint[];
type TimeSeriesSlice = TimeSeries[]; type TimeSeriesSlice = TimeSeries[];
interface TimeSeries { interface TimeSeries {
name: string; name: string;
points: TimeSeriesPoints; points: TimeSeriesPoints;
tags: { [key: string]: string }; tags: { [key: string]: string };
} }
interface TableColumn { interface TableColumn {
text: string; text: string;
} }
interface Table { interface Table {
columns: TableColumn[]; columns: TableColumn[];
rows: RowValues[]; rows: RowValues[];
} }
interface QueryResult { interface QueryResult {
error: string; error: string;
refId: string; refId: string;
meta: any; meta: any;
series: TimeSeriesSlice[]; series: TimeSeriesSlice[];
tables: Table[]; tables: Table[];
} }
export interface TSDBResponse { export interface TSDBResponse {
results: { [key: string]: QueryResult }; results: { [key: string]: QueryResult };
message: string; message: string;
} }

View File

@@ -82,6 +82,10 @@ jest.mock('grafana/app/core/config', () => {
jest.mock('jquery', () => 'module not found', {virtual: true}); jest.mock('jquery', () => 'module not found', {virtual: true});
// jest.mock('@grafana/ui', () => {
// return {};
// }, {virtual: true});
// Required for loading angularjs // Required for loading angularjs
let dom = new JSDOM('<html><head><script></script></head><body></body></html>'); let dom = new JSDOM('<html><head><script></script></head><body></body></html>');
// Setup jsdom // Setup jsdom

View File

@@ -27,8 +27,8 @@ module.exports = {
}, },
externals: [ externals: [
// remove the line below if you don't want to use builtin versions // remove the line below if you don't want to use builtin versions
'jquery', 'lodash', 'moment', 'angular', 'jquery', 'lodash', 'moment', 'angular', 'emotion',
'react', 'react-dom', '@grafana/ui', '@grafana/runtime','@grafana/data', 'react', 'react-dom', '@grafana/ui', '@grafana/data',
function (context, request, callback) { function (context, request, callback) {
var prefix = 'grafana/'; var prefix = 'grafana/';
if (request.indexOf(prefix) === 0) { if (request.indexOf(prefix) === 0) {

814
yarn.lock

File diff suppressed because it is too large Load Diff