Fix data alignment for db connection queries

This commit is contained in:
Alexander Zobnin
2021-08-06 12:31:05 +03:00
parent d1f639f568
commit 736f05d398
5 changed files with 36 additions and 17 deletions

View File

@@ -46,8 +46,14 @@ type ZabbixDatasourceSettings struct {
} }
type DBConnectionPostProcessingRequest struct { type DBConnectionPostProcessingRequest struct {
Query QueryModel `json:"query"` Query QueryModel `json:"query"`
Series []*timeseries.TimeSeriesData `json:"series"` TimeRange TimeRangePostProcessingRequest `json:"timeRange"`
Series []*timeseries.TimeSeriesData `json:"series"`
}
type TimeRangePostProcessingRequest struct {
From int64
To int64
} }
type ZabbixAPIResourceRequest struct { type ZabbixAPIResourceRequest struct {

View File

@@ -4,6 +4,7 @@ import (
"encoding/json" "encoding/json"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"time"
"github.com/alexanderzobnin/grafana-zabbix/pkg/zabbix" "github.com/alexanderzobnin/grafana-zabbix/pkg/zabbix"
"github.com/grafana/grafana-plugin-sdk-go/backend/resource/httpadapter" "github.com/grafana/grafana-plugin-sdk-go/backend/resource/httpadapter"
@@ -88,6 +89,9 @@ func (ds *ZabbixDatasource) DBConnectionPostProcessingHandler(rw http.ResponseWr
return return
} }
reqData.Query.TimeRange.From = time.Unix(reqData.TimeRange.From, 0)
reqData.Query.TimeRange.To = time.Unix(reqData.TimeRange.To, 0)
frames, err := dsInstance.applyDataProcessing(req.Context(), &reqData.Query, reqData.Series) frames, err := dsInstance.applyDataProcessing(req.Context(), &reqData.Query, reqData.Series)
resultJson, err := json.Marshal(frames) resultJson, err := json.Marshal(frames)

View File

@@ -319,21 +319,25 @@ export class ZabbixDatasource extends DataSourceApi<ZabbixMetricsQuery, ZabbixDS
/** /**
* Query history for numeric items * Query history for numeric items
*/ */
async queryNumericDataForItems(items, target: ZabbixMetricsQuery, timeRange, useTrends, options) { async queryNumericDataForItems(items, target: ZabbixMetricsQuery, timeRange, useTrends, request) {
let history; let history;
options.valueType = this.getTrendValueType(target); request.valueType = this.getTrendValueType(target);
options.consolidateBy = getConsolidateBy(target) || options.valueType; request.consolidateBy = getConsolidateBy(target) || request.valueType;
if (useTrends) { if (useTrends) {
history = await this.zabbix.getTrends(items, timeRange, options); history = await this.zabbix.getTrends(items, timeRange, request);
} else { } else {
history = await this.zabbix.getHistoryTS(items, timeRange, options); history = await this.zabbix.getHistoryTS(items, timeRange, request);
} }
return await this.invokeDataProcessingQuery(history, target); const range = {
from: timeRange[0],
to: timeRange[1],
};
return await this.invokeDataProcessingQuery(history, target, range);
} }
async invokeDataProcessingQuery(timeSeriesData, query) { async invokeDataProcessingQuery(timeSeriesData, query, timeRange) {
// Request backend for data processing // Request backend for data processing
const requestOptions: BackendSrvRequest = { const requestOptions: BackendSrvRequest = {
url: `/api/datasources/${this.datasourceId}/resources/db-connection-post`, url: `/api/datasources/${this.datasourceId}/resources/db-connection-post`,
@@ -345,6 +349,7 @@ export class ZabbixDatasource extends DataSourceApi<ZabbixMetricsQuery, ZabbixDS
data: { data: {
series: timeSeriesData, series: timeSeriesData,
query, query,
timeRange,
}, },
}; };

View File

@@ -179,10 +179,13 @@ export function dataResponseToTimeSeries(response: DataFrameJSON[], items) {
const itemid = field.name; const itemid = field.name;
const item = _.find(items, { 'itemid': itemid }); const item = _.find(items, { 'itemid': itemid });
let interval = utils.parseItemInterval(item.delay);
// Convert interval to nanoseconds in order to unmarshall it on the backend to time.Duration
let interval = utils.parseItemInterval(item.delay) * 1000000;
if (interval === 0) { if (interval === 0) {
interval = null; interval = null;
} }
const timeSeriesData = { const timeSeriesData = {
ts: s, ts: s,
meta: { meta: {

View File

@@ -2,7 +2,7 @@ import _ from 'lodash';
import moment from 'moment'; import moment from 'moment';
import * as c from './constants'; import * as c from './constants';
import { VariableQuery, VariableQueryTypes } from './types'; import { VariableQuery, VariableQueryTypes } from './types';
import { MappingType, ValueMapping, getValueFormats, DataFrame, FieldType, rangeUtil } from '@grafana/data'; import { DataFrame, FieldType, getValueFormats, MappingType, rangeUtil, ValueMapping } from '@grafana/data';
/* /*
* This regex matches 3 types of variable reference with an optional format specifier * This regex matches 3 types of variable reference with an optional format specifier
@@ -57,7 +57,7 @@ function splitKeyParams(paramStr) {
} else if (symbol === '"' && !quoted) { } else if (symbol === '"' && !quoted) {
quoted = true; quoted = true;
} else if (symbol === '[' && !quoted) { } else if (symbol === '[' && !quoted) {
in_array = true; in_array = true;
} else if (symbol === ']' && !quoted) { } else if (symbol === ']' && !quoted) {
in_array = false; in_array = false;
} else if (symbol === split_symbol && !quoted && !in_array) { } else if (symbol === split_symbol && !quoted && !in_array) {
@@ -218,7 +218,7 @@ export function getRangeScopedVars(range) {
__range_ms: { text: msRange, value: msRange }, __range_ms: { text: msRange, value: msRange },
__range_s: { text: sRange, value: sRange }, __range_s: { text: sRange, value: sRange },
__range: { text: regularRange, value: regularRange }, __range: { text: regularRange, value: regularRange },
__range_series: {text: c.RANGE_VARIABLE_VALUE, value: c.RANGE_VARIABLE_VALUE}, __range_series: { text: c.RANGE_VARIABLE_VALUE, value: c.RANGE_VARIABLE_VALUE },
}; };
} }
@@ -236,7 +236,7 @@ export function escapeRegex(value) {
} }
/** /**
* Parses Zabbix item update interval. Returns 0 in case of custom intervals. * Parses Zabbix item update interval (returns milliseconds). Returns 0 in case of custom intervals.
*/ */
export function parseItemInterval(interval: string): number { export function parseItemInterval(interval: string): number {
const normalizedInterval = normalizeZabbixInterval(interval); const normalizedInterval = normalizeZabbixInterval(interval);
@@ -255,6 +255,7 @@ export function normalizeZabbixInterval(interval: string): string {
return parsedInterval[1] + (parsedInterval.length > 2 ? parsedInterval[2] : 's'); return parsedInterval[1] + (parsedInterval.length > 2 ? parsedInterval[2] : 's');
} }
// Returns interval in milliseconds
export function parseInterval(interval: string): number { export function parseInterval(interval: string): number {
const intervalPattern = /(^[\d]+)(y|M|w|d|h|m|s)/g; const intervalPattern = /(^[\d]+)(y|M|w|d|h|m|s)/g;
const momentInterval: any[] = intervalPattern.exec(interval); const momentInterval: any[] = intervalPattern.exec(interval);
@@ -315,7 +316,7 @@ export function convertToZabbixAPIUrl(url) {
* when waiting for result. * when waiting for result.
*/ */
export function callOnce(func, promiseKeeper) { export function callOnce(func, promiseKeeper) {
return function() { return function () {
if (!promiseKeeper) { if (!promiseKeeper) {
promiseKeeper = Promise.resolve( promiseKeeper = Promise.resolve(
func.apply(this, arguments) func.apply(this, arguments)
@@ -337,7 +338,7 @@ export function callOnce(func, promiseKeeper) {
* @param {*} funcsArray functions to apply * @param {*} funcsArray functions to apply
*/ */
export function sequence(funcsArray) { export function sequence(funcsArray) {
return function(result) { return function (result) {
for (let i = 0; i < funcsArray.length; i++) { for (let i = 0; i < funcsArray.length; i++) {
result = funcsArray[i].call(this, result); result = funcsArray[i].call(this, result);
} }
@@ -399,7 +400,7 @@ export function parseTags(tagStr: string): any[] {
let tags: any[] = _.map(tagStr.split(','), (tag) => tag.trim()); let tags: any[] = _.map(tagStr.split(','), (tag) => tag.trim());
tags = _.map(tags, (tag) => { tags = _.map(tags, (tag) => {
const tagParts = tag.split(':'); const tagParts = tag.split(':');
return {tag: tagParts[0].trim(), value: tagParts[1].trim()}; return { tag: tagParts[0].trim(), value: tagParts[1].trim() };
}); });
return tags; return tags;
} }