Backend: Merge master into the backend branch (#845)
* CI: fix shellcheck issues (#789) Signed-off-by: Mario Trangoni <mjtrangoni@gmail.com> * annotations: fix options in grafana 6.x, fix #813 * fix function editor in Grafana 6.4, closes #810 * add typings for grafana packages * Add $__range_series variable for calculating function over the whole series, #531 * fix tests * Don't set alert styles for react panels, fix #823 * docs: add range variables * docs: percentile reference * fix codespell Co-authored-by: Mario Trangoni <mario@mariotrangoni.de> Co-authored-by: Alexander Zobnin <alexanderzobnin@gmail.com>
This commit is contained in:
committed by
Alexander Zobnin
parent
b4b0c5b8f4
commit
c300debe35
@@ -3,7 +3,7 @@ import React from 'react';
|
||||
import { FunctionDescriptor, FunctionEditorControlsProps, FunctionEditorControls } from './FunctionEditorControls';
|
||||
|
||||
// @ts-ignore
|
||||
import { PopperController, Popper } from '@grafana/ui';
|
||||
import { PopoverController, Popover } from '@grafana/ui';
|
||||
|
||||
interface FunctionEditorProps extends FunctionEditorControlsProps {
|
||||
func: FunctionDescriptor;
|
||||
@@ -66,12 +66,12 @@ class FunctionEditor extends React.PureComponent<FunctionEditorProps, FunctionEd
|
||||
|
||||
render() {
|
||||
return (
|
||||
<PopperController content={this.renderContent} placement="top" hideAfter={300}>
|
||||
<PopoverController content={this.renderContent} placement="top" hideAfter={300}>
|
||||
{(showPopper, hidePopper, popperProps) => {
|
||||
return (
|
||||
<>
|
||||
{this.triggerRef && (
|
||||
<Popper
|
||||
<Popover
|
||||
{...popperProps}
|
||||
referenceElement={this.triggerRef.current}
|
||||
wrapperClassName="popper"
|
||||
@@ -101,7 +101,7 @@ class FunctionEditor extends React.PureComponent<FunctionEditorProps, FunctionEd
|
||||
</>
|
||||
);
|
||||
}}
|
||||
</PopperController>
|
||||
</PopoverController>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,3 +37,5 @@ export const TRIGGER_SEVERITY = [
|
||||
|
||||
/** Minimum interval for SLA over time (1 hour) */
|
||||
export const MIN_SLA_INTERVAL = 3600;
|
||||
|
||||
export const RANGE_VARIABLE_VALUE = 'range_series';
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import _ from 'lodash';
|
||||
import * as utils from './utils';
|
||||
import ts from './timeseries';
|
||||
import ts, { groupBy_perf as groupBy } from './timeseries';
|
||||
|
||||
let downsampleSeries = ts.downsample;
|
||||
let groupBy = ts.groupBy_perf;
|
||||
let groupBy_exported = (interval, groupFunc, datapoints) => groupBy(datapoints, interval, groupFunc);
|
||||
let sumSeries = ts.sumSeries;
|
||||
let delta = ts.delta;
|
||||
|
||||
@@ -132,6 +132,9 @@ export class ZabbixDatasource extends DataSourceApi {
|
||||
let timeFrom = Math.ceil(dateMath.parse(options.range.from) / 1000);
|
||||
let timeTo = Math.ceil(dateMath.parse(options.range.to) / 1000);
|
||||
|
||||
// Add range variables
|
||||
options.scopedVars = Object.assign({}, options.scopedVars, utils.getRangeScopedVars(options.range));
|
||||
|
||||
// Prevent changes of original object
|
||||
let target = _.cloneDeep(t);
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<div class="gf-form-group">
|
||||
<h6>Filter Triggers</h6>
|
||||
<div class="gf-form-inline">
|
||||
<div class="gf-form">
|
||||
<span class="gf-form-label width-10">Group</span>
|
||||
@@ -36,8 +35,9 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="gf-form-group">
|
||||
<h6>Options</h6>
|
||||
<div class="gf-form">
|
||||
<span class="gf-form-label width-10">Minimum severity</span>
|
||||
<span class="gf-form-label width-12">Minimum severity</span>
|
||||
<div class="gf-form-select-wrapper">
|
||||
<select class="gf-form-input gf-size-auto"
|
||||
ng-init='ctrl.annotation.minseverity = ctrl.annotation.minseverity || 0'
|
||||
@@ -54,12 +54,16 @@
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="gf-form-group">
|
||||
<h6>Options</h6>
|
||||
<div class="gf-form">
|
||||
<editor-checkbox text="Show OK events" model="ctrl.annotation.showOkEvents"></editor-checkbox>
|
||||
<editor-checkbox text="Hide acknowledged events" model="ctrl.annotation.hideAcknowledged"></editor-checkbox>
|
||||
<editor-checkbox text="Show hostname" model="ctrl.annotation.showHostname"></editor-checkbox>
|
||||
</div>
|
||||
<gf-form-switch class="gf-form" label-class="width-12"
|
||||
label="Show OK events"
|
||||
checked="ctrl.annotation.showOkEvents">
|
||||
</gf-form-switch>
|
||||
<gf-form-switch class="gf-form" label-class="width-12"
|
||||
label="Hide acknowledged events"
|
||||
checked="ctrl.annotation.hideAcknowledged">
|
||||
</gf-form-switch>
|
||||
<gf-form-switch class="gf-form" label-class="width-12"
|
||||
label="Show hostname"
|
||||
checked="ctrl.annotation.showHostname">
|
||||
</gf-form-switch>
|
||||
</div>
|
||||
|
||||
@@ -2,6 +2,7 @@ import _ from 'lodash';
|
||||
import mocks from '../../test-setup/mocks';
|
||||
import { Datasource } from "../module";
|
||||
import { zabbixTemplateFormat } from "../datasource";
|
||||
import { dateMath } from '@grafana/data';
|
||||
|
||||
describe('ZabbixDatasource', () => {
|
||||
let ctx = {};
|
||||
@@ -41,7 +42,10 @@ describe('ZabbixDatasource', () => {
|
||||
item: {filter: ""}
|
||||
}
|
||||
],
|
||||
range: {from: 'now-7d', to: 'now'}
|
||||
range: {
|
||||
from: dateMath.parse('now-1h'),
|
||||
to: dateMath.parse('now')
|
||||
}
|
||||
};
|
||||
|
||||
it('should return an empty array when no targets are set', (done) => {
|
||||
@@ -59,7 +63,7 @@ describe('ZabbixDatasource', () => {
|
||||
let ranges = ['now-8d', 'now-169h', 'now-1M', 'now-1y'];
|
||||
|
||||
_.forEach(ranges, range => {
|
||||
ctx.options.range.from = range;
|
||||
ctx.options.range.from = dateMath.parse(range);
|
||||
ctx.ds.queryNumericData = jest.fn();
|
||||
ctx.ds.query(ctx.options);
|
||||
|
||||
@@ -76,7 +80,7 @@ describe('ZabbixDatasource', () => {
|
||||
let ranges = ['now-7d', 'now-168h', 'now-1h', 'now-30m', 'now-30s'];
|
||||
|
||||
_.forEach(ranges, range => {
|
||||
ctx.options.range.from = range;
|
||||
ctx.options.range.from = dateMath.parse(range);
|
||||
ctx.ds.queryNumericData = jest.fn();
|
||||
ctx.ds.query(ctx.options);
|
||||
|
||||
@@ -108,24 +112,19 @@ describe('ZabbixDatasource', () => {
|
||||
}
|
||||
]));
|
||||
|
||||
ctx.options = {
|
||||
range: {from: 'now-1h', to: 'now'},
|
||||
targets: [
|
||||
{
|
||||
group: {filter: ""},
|
||||
host: {filter: "Zabbix server"},
|
||||
application: {filter: ""},
|
||||
item: {filter: "System information"},
|
||||
textFilter: "",
|
||||
useCaptureGroups: true,
|
||||
mode: 2,
|
||||
resultFormat: "table",
|
||||
options: {
|
||||
skipEmptyValues: false
|
||||
}
|
||||
}
|
||||
],
|
||||
};
|
||||
ctx.options.targets = [{
|
||||
group: {filter: ""},
|
||||
host: {filter: "Zabbix server"},
|
||||
application: {filter: ""},
|
||||
item: {filter: "System information"},
|
||||
textFilter: "",
|
||||
useCaptureGroups: true,
|
||||
mode: 2,
|
||||
resultFormat: "table",
|
||||
options: {
|
||||
skipEmptyValues: false
|
||||
}
|
||||
}];
|
||||
});
|
||||
|
||||
it('should return data in table format', (done) => {
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
import _ from 'lodash';
|
||||
import * as utils from './utils';
|
||||
import * as c from './constants';
|
||||
|
||||
const POINT_VALUE = 0;
|
||||
const POINT_TIMESTAMP = 1;
|
||||
@@ -94,11 +95,15 @@ function groupBy(datapoints, interval, groupByCallback) {
|
||||
}));
|
||||
}
|
||||
|
||||
function groupBy_perf(datapoints, interval, groupByCallback) {
|
||||
export function groupBy_perf(datapoints, interval, groupByCallback) {
|
||||
if (datapoints.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (interval === c.RANGE_VARIABLE_VALUE) {
|
||||
return groupByRange(datapoints, groupByCallback);
|
||||
}
|
||||
|
||||
let ms_interval = utils.parseInterval(interval);
|
||||
let grouped_series = [];
|
||||
let frame_values = [];
|
||||
@@ -132,6 +137,19 @@ function groupBy_perf(datapoints, interval, groupByCallback) {
|
||||
return grouped_series;
|
||||
}
|
||||
|
||||
export function groupByRange(datapoints, groupByCallback) {
|
||||
const frame_values = [];
|
||||
const frame_start = datapoints[0][POINT_TIMESTAMP];
|
||||
const frame_end = datapoints[datapoints.length - 1][POINT_TIMESTAMP];
|
||||
let point;
|
||||
for (let i=0; i < datapoints.length; i++) {
|
||||
point = datapoints[i];
|
||||
frame_values.push(point[POINT_VALUE]);
|
||||
}
|
||||
const frame_value = groupByCallback(frame_values);
|
||||
return [[frame_value, frame_start], [frame_value, frame_end]];
|
||||
}
|
||||
|
||||
/**
|
||||
* Summarize set of time series into one.
|
||||
* @param {datapoints[]} timeseries array of time series
|
||||
@@ -495,6 +513,7 @@ const exportedFunctions = {
|
||||
downsample,
|
||||
groupBy,
|
||||
groupBy_perf,
|
||||
groupByRange,
|
||||
sumSeries,
|
||||
scale,
|
||||
offset,
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import _ from 'lodash';
|
||||
import moment from 'moment';
|
||||
import kbn from 'grafana/app/core/utils/kbn';
|
||||
import * as c from './constants';
|
||||
|
||||
/**
|
||||
* Expand Zabbix item name
|
||||
@@ -141,6 +143,18 @@ export function isTemplateVariable(str, templateVariables) {
|
||||
}
|
||||
}
|
||||
|
||||
export function getRangeScopedVars(range) {
|
||||
const msRange = range.to.diff(range.from);
|
||||
const sRange = Math.round(msRange / 1000);
|
||||
const regularRange = kbn.secondsToHms(msRange / 1000);
|
||||
return {
|
||||
__range_ms: { text: msRange, value: msRange },
|
||||
__range_s: { text: sRange, value: sRange },
|
||||
__range: { text: regularRange, value: regularRange },
|
||||
__range_series: {text: c.RANGE_VARIABLE_VALUE, value: c.RANGE_VARIABLE_VALUE},
|
||||
};
|
||||
}
|
||||
|
||||
export function buildRegex(str) {
|
||||
var matches = str.match(regexPattern);
|
||||
var pattern = matches[1];
|
||||
|
||||
@@ -32,7 +32,8 @@ export class ZabbixAlertingService {
|
||||
});
|
||||
}
|
||||
|
||||
if (panelIndex >= 0) {
|
||||
// Don't apply alert styles to .panel-container--absolute (it rewrites position from absolute to relative)
|
||||
if (panelIndex >= 0 && !panelContainers[panelIndex].className.includes('panel-container--absolute')) {
|
||||
let alertClass = "panel-has-alert panel-alert-state--ok panel-alert-state--alerting";
|
||||
$(panelContainers[panelIndex]).removeClass(alertClass);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user