diff --git a/packages/grafana-ui/src/components/GraphNG/utils.ts b/packages/grafana-ui/src/components/GraphNG/utils.ts index b865a33f1e6..5b1ade91f54 100755 --- a/packages/grafana-ui/src/components/GraphNG/utils.ts +++ b/packages/grafana-ui/src/components/GraphNG/utils.ts @@ -43,6 +43,7 @@ export function mapDimesions(match: XYFieldMatchers, frame: DataFrame, frames?: export function alignDataFrames(frames: DataFrame[], fields?: XYFieldMatchers): AlignedFrameWithGapTest | null { const valuesFromFrames: AlignedData[] = []; const sourceFields: Field[] = []; + let spanNulls = false; // Default to timeseries config if (!fields) { @@ -79,6 +80,10 @@ export function alignDataFrames(frames: DataFrame[], fields?: XYFieldMatchers): } alignedData.push(values); + if (field.config.custom.spanNulls) { + spanNulls = true; + } + // This will cache an appropriate field name in the field state getFieldDisplayName(field, frame, frames); sourceFields.push(field); @@ -92,12 +97,22 @@ export function alignDataFrames(frames: DataFrame[], fields?: XYFieldMatchers): } // do the actual alignment (outerJoin on the first arrays) - const { data: alignedData, isGap } = outerJoinValues(valuesFromFrames); + let { data: alignedData, isGap } = outerJoinValues(valuesFromFrames); if (alignedData!.length !== sourceFields.length) { throw new Error('outerJoinValues lost a field?'); } + // Wrap the gap function when span nulls exists + if (spanNulls) { + isGap = (u: uPlot, seriesIdx: number, dataIdx: number) => { + if (sourceFields[seriesIdx].config?.custom?.spanNulls) { + return false; + } + return isGap(u, seriesIdx, dataIdx); + }; + } + // Replace the values from the outer-join field return { frame: { diff --git a/packages/grafana-ui/src/components/uPlot/config.ts b/packages/grafana-ui/src/components/uPlot/config.ts index a150c4e6c21..07f4879f787 100644 --- a/packages/grafana-ui/src/components/uPlot/config.ts +++ b/packages/grafana-ui/src/components/uPlot/config.ts @@ -55,6 +55,8 @@ export interface AxisConfig { export interface GraphFieldConfig extends LineConfig, AreaConfig, PointsConfig, AxisConfig { mode?: GraphMode; + + spanNulls?: boolean; } export const graphFieldOptions = { diff --git a/public/app/plugins/panel/graph3/module.tsx b/public/app/plugins/panel/graph3/module.tsx index 2ceee4b145a..7ce99ad1737 100644 --- a/public/app/plugins/panel/graph3/module.tsx +++ b/public/app/plugins/panel/graph3/module.tsx @@ -82,6 +82,17 @@ export const plugin = new PanelPlugin(GraphPanel) }, showIf: c => c.points !== PointMode.Never, }) + .addRadio({ + path: 'spanNulls', + name: 'Null values', + defaultValue: false, + settings: { + options: [ + { label: 'Gaps', value: false }, + { label: 'Connected', value: true }, + ], + }, + }) .addRadio({ path: 'axisPlacement', name: 'Placement',