mirror of
https://github.com/grafana/grafana.git
synced 2025-07-31 20:52:23 +08:00
Can render graph
This commit is contained in:
@ -5,7 +5,7 @@ import React, { Component } from 'react';
|
|||||||
import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
|
import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
import { TimeRange, LoadingState, DataQueryResponse, TimeSeries } from 'app/types';
|
import { TimeRange, LoadingState, DataQueryOptions, DataQueryResponse, TimeSeries } from 'app/types';
|
||||||
|
|
||||||
interface RenderProps {
|
interface RenderProps {
|
||||||
loading: LoadingState;
|
loading: LoadingState;
|
||||||
@ -82,14 +82,14 @@ export class DataPanel extends Component<Props, State> {
|
|||||||
const dataSourceSrv = getDatasourceSrv();
|
const dataSourceSrv = getDatasourceSrv();
|
||||||
const ds = await dataSourceSrv.get(datasource);
|
const ds = await dataSourceSrv.get(datasource);
|
||||||
|
|
||||||
const queryOptions = {
|
const queryOptions: DataQueryOptions = {
|
||||||
timezone: 'browser',
|
timezone: 'browser',
|
||||||
panelId: panelId,
|
panelId: panelId,
|
||||||
dashboardId: dashboardId,
|
dashboardId: dashboardId,
|
||||||
range: timeRange,
|
range: timeRange,
|
||||||
rangeRaw: timeRange.raw,
|
rangeRaw: timeRange.raw,
|
||||||
interval: '1s',
|
interval: '1s',
|
||||||
intervalMs: 1000,
|
intervalMs: 60000,
|
||||||
targets: queries,
|
targets: queries,
|
||||||
maxDataPoints: 500,
|
maxDataPoints: 500,
|
||||||
scopedVars: {},
|
scopedVars: {},
|
||||||
|
@ -339,6 +339,7 @@ class GraphElement {
|
|||||||
|
|
||||||
callPlot(options, incrementRenderCounter) {
|
callPlot(options, incrementRenderCounter) {
|
||||||
try {
|
try {
|
||||||
|
console.log('plot', this.sortedSeries);
|
||||||
this.plot = $.plot(this.elem, this.sortedSeries, options);
|
this.plot = $.plot(this.elem, this.sortedSeries, options);
|
||||||
if (this.ctrl.renderError) {
|
if (this.ctrl.renderError) {
|
||||||
delete this.ctrl.error;
|
delete this.ctrl.error;
|
||||||
|
@ -4,12 +4,10 @@ import React, { PureComponent } from 'react';
|
|||||||
|
|
||||||
// Components
|
// Components
|
||||||
import Graph from 'app/viz/Graph';
|
import Graph from 'app/viz/Graph';
|
||||||
|
|
||||||
// Utils
|
|
||||||
import { getTimeSeriesVMs } from 'app/viz/state/timeSeries';
|
import { getTimeSeriesVMs } from 'app/viz/state/timeSeries';
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
import { PanelProps } from 'app/types';
|
import { PanelProps, NullValueMode } from 'app/types';
|
||||||
|
|
||||||
interface Options {
|
interface Options {
|
||||||
showBars: boolean;
|
showBars: boolean;
|
||||||
@ -26,10 +24,13 @@ export class Graph2 extends PureComponent<Props> {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { timeSeries, timeRange } = this.props;
|
const { timeSeries, timeRange } = this.props;
|
||||||
const viewModels = getTimeSeriesVMs({ timeSeries });
|
|
||||||
console.log(viewModels);
|
|
||||||
|
|
||||||
return <Graph timeSeries={viewModels} timeRange={timeRange} />;
|
const vmSeries = getTimeSeriesVMs({
|
||||||
|
timeSeries: timeSeries,
|
||||||
|
nullValueMode: NullValueMode.Ignore,
|
||||||
|
});
|
||||||
|
|
||||||
|
return <Graph timeSeries={vmSeries} timeRange={timeRange} />;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,8 @@ import {
|
|||||||
TimeSeries,
|
TimeSeries,
|
||||||
TimeSeriesVM,
|
TimeSeriesVM,
|
||||||
TimeSeriesVMs,
|
TimeSeriesVMs,
|
||||||
|
TimeSeriesStats,
|
||||||
|
NullValueMode,
|
||||||
DataQuery,
|
DataQuery,
|
||||||
DataQueryResponse,
|
DataQueryResponse,
|
||||||
DataQueryOptions,
|
DataQueryOptions,
|
||||||
@ -62,6 +64,8 @@ export {
|
|||||||
TimeSeries,
|
TimeSeries,
|
||||||
TimeSeriesVM,
|
TimeSeriesVM,
|
||||||
TimeSeriesVMs,
|
TimeSeriesVMs,
|
||||||
|
NullValueMode,
|
||||||
|
TimeSeriesStats,
|
||||||
DataQuery,
|
DataQuery,
|
||||||
DataQueryResponse,
|
DataQueryResponse,
|
||||||
DataQueryOptions,
|
DataQueryOptions,
|
||||||
|
@ -33,6 +33,30 @@ export interface TimeSeriesVM {
|
|||||||
label: string;
|
label: string;
|
||||||
color: string;
|
color: string;
|
||||||
data: TimeSeriesValue[][];
|
data: TimeSeriesValue[][];
|
||||||
|
stats: TimeSeriesStats;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TimeSeriesStats {
|
||||||
|
total: number;
|
||||||
|
max: number;
|
||||||
|
min: number;
|
||||||
|
logmin: number;
|
||||||
|
avg: number | null;
|
||||||
|
current: number | null;
|
||||||
|
first: number | null;
|
||||||
|
delta: number;
|
||||||
|
diff: number | null;
|
||||||
|
range: number | null;
|
||||||
|
timeStep: number;
|
||||||
|
count: number;
|
||||||
|
allIsNull: boolean;
|
||||||
|
allIsZero: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum NullValueMode {
|
||||||
|
Null = 'null',
|
||||||
|
Ignore = 'connected',
|
||||||
|
AsZero = 'null as zero',
|
||||||
}
|
}
|
||||||
|
|
||||||
/** View model projection of many time series */
|
/** View model projection of many time series */
|
||||||
@ -56,6 +80,10 @@ export interface DataQueryOptions {
|
|||||||
panelId: number;
|
panelId: number;
|
||||||
dashboardId: number;
|
dashboardId: number;
|
||||||
cacheTimeout?: string;
|
cacheTimeout?: string;
|
||||||
|
interval: string;
|
||||||
|
intervalMs: number;
|
||||||
|
maxDataPoints: number;
|
||||||
|
scopedVars: object;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DataSourceApi {
|
export interface DataSourceApi {
|
||||||
|
@ -108,6 +108,7 @@ export class Graph extends PureComponent<GraphProps> {
|
|||||||
...dynamicOptions,
|
...dynamicOptions,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
console.log('plot', timeSeries, options);
|
||||||
$.plot(this.element, timeSeries, options);
|
$.plot(this.element, timeSeries, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,19 +1,166 @@
|
|||||||
|
// Libraries
|
||||||
|
import _ from 'lodash';
|
||||||
|
|
||||||
|
// Utils
|
||||||
import colors from 'app/core/utils/colors';
|
import colors from 'app/core/utils/colors';
|
||||||
import { TimeSeries, TimeSeriesVMs } from 'app/types';
|
|
||||||
|
// Types
|
||||||
|
import { TimeSeries, TimeSeriesVMs, NullValueMode } from 'app/types';
|
||||||
|
|
||||||
interface Options {
|
interface Options {
|
||||||
timeSeries: TimeSeries[];
|
timeSeries: TimeSeries[];
|
||||||
|
nullValueMode: NullValueMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getTimeSeriesVMs({ timeSeries }: Options): TimeSeriesVMs {
|
export function getTimeSeriesVMs({ timeSeries, nullValueMode }: Options): TimeSeriesVMs {
|
||||||
const vmSeries = timeSeries.map((item, index) => {
|
const vmSeries = timeSeries.map((item, index) => {
|
||||||
const colorIndex = index % colors.length;
|
const colorIndex = index % colors.length;
|
||||||
const label = item.target;
|
const label = item.target;
|
||||||
|
const result = [];
|
||||||
|
|
||||||
|
// stat defaults
|
||||||
|
let total = 0;
|
||||||
|
let max = -Number.MAX_VALUE;
|
||||||
|
let min = Number.MAX_VALUE;
|
||||||
|
let logmin = Number.MAX_VALUE;
|
||||||
|
let avg = null;
|
||||||
|
let current = null;
|
||||||
|
let first = null;
|
||||||
|
let delta = 0;
|
||||||
|
let diff = null;
|
||||||
|
let range = null;
|
||||||
|
let timeStep = Number.MAX_VALUE;
|
||||||
|
let allIsNull = true;
|
||||||
|
let allIsZero = true;
|
||||||
|
|
||||||
|
const ignoreNulls = nullValueMode === NullValueMode.Ignore;
|
||||||
|
const nullAsZero = nullValueMode === NullValueMode.AsZero;
|
||||||
|
|
||||||
|
let currentTime;
|
||||||
|
let currentValue;
|
||||||
|
let nonNulls = 0;
|
||||||
|
let previousTime;
|
||||||
|
let previousValue = 0;
|
||||||
|
let previousDeltaUp = true;
|
||||||
|
|
||||||
|
for (let i = 0; i < item.datapoints.length; i++) {
|
||||||
|
currentValue = item.datapoints[i][0];
|
||||||
|
currentTime = item.datapoints[i][1];
|
||||||
|
|
||||||
|
// Due to missing values we could have different timeStep all along the series
|
||||||
|
// so we have to find the minimum one (could occur with aggregators such as ZimSum)
|
||||||
|
if (previousTime !== undefined) {
|
||||||
|
const currentStep = currentTime - previousTime;
|
||||||
|
if (currentStep < timeStep) {
|
||||||
|
timeStep = currentStep;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
previousTime = currentTime;
|
||||||
|
|
||||||
|
if (currentValue === null) {
|
||||||
|
if (ignoreNulls) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (nullAsZero) {
|
||||||
|
currentValue = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentValue !== null) {
|
||||||
|
if (_.isNumber(currentValue)) {
|
||||||
|
total += currentValue;
|
||||||
|
allIsNull = false;
|
||||||
|
nonNulls++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentValue > max) {
|
||||||
|
max = currentValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentValue < min) {
|
||||||
|
min = currentValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (first === null) {
|
||||||
|
first = currentValue;
|
||||||
|
} else {
|
||||||
|
if (previousValue > currentValue) {
|
||||||
|
// counter reset
|
||||||
|
previousDeltaUp = false;
|
||||||
|
if (i === item.datapoints.length - 1) {
|
||||||
|
// reset on last
|
||||||
|
delta += currentValue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (previousDeltaUp) {
|
||||||
|
delta += currentValue - previousValue; // normal increment
|
||||||
|
} else {
|
||||||
|
delta += currentValue; // account for counter reset
|
||||||
|
}
|
||||||
|
previousDeltaUp = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
previousValue = currentValue;
|
||||||
|
|
||||||
|
if (currentValue < logmin && currentValue > 0) {
|
||||||
|
logmin = currentValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentValue !== 0) {
|
||||||
|
allIsZero = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result.push([currentTime, currentValue]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (max === -Number.MAX_VALUE) {
|
||||||
|
max = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (min === Number.MAX_VALUE) {
|
||||||
|
min = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.length && !allIsNull) {
|
||||||
|
avg = total / nonNulls;
|
||||||
|
current = result[result.length - 1][1];
|
||||||
|
if (current === null && result.length > 1) {
|
||||||
|
current = result[result.length - 2][1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (max !== null && min !== null) {
|
||||||
|
range = max - min;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current !== null && first !== null) {
|
||||||
|
diff = current - first;
|
||||||
|
}
|
||||||
|
|
||||||
|
const count = result.length;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
data: item.datapoints,
|
data: result,
|
||||||
label: label,
|
label: label,
|
||||||
color: colors[colorIndex],
|
color: colors[colorIndex],
|
||||||
|
stats: {
|
||||||
|
total,
|
||||||
|
min,
|
||||||
|
max,
|
||||||
|
current,
|
||||||
|
logmin,
|
||||||
|
avg,
|
||||||
|
diff,
|
||||||
|
delta,
|
||||||
|
timeStep,
|
||||||
|
range,
|
||||||
|
count,
|
||||||
|
first,
|
||||||
|
allIsZero,
|
||||||
|
allIsNull,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user