mirror of
https://github.com/grafana/grafana.git
synced 2026-09-05 04:40:13 -05:00
Timeseries: Time regions migration (#66998)
Co-authored-by: Ryan McKinley <ryantxu@gmail.com>
This commit is contained in:
co-authored by
Ryan McKinley
parent
5c4ecf7a86
commit
2beee35567
@@ -9,7 +9,7 @@
|
||||
Migrate
|
||||
</button>
|
||||
</p>
|
||||
<p>Some features like colored time regions and negative transforms are not supported in the new panel yet.</p>
|
||||
<p>Some features are not supported in the new panel yet.</p>
|
||||
</div>
|
||||
|
||||
<gf-form-switch
|
||||
|
||||
@@ -521,6 +521,37 @@ exports[`Graph Migrations stepped line 1`] = `
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Graph Migrations time regions should migrate 1`] = `
|
||||
{
|
||||
"alert": undefined,
|
||||
"datasource": {
|
||||
"type": "datasource",
|
||||
"uid": "gdev-testdata",
|
||||
},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"custom": {
|
||||
"drawStyle": "points",
|
||||
"spanNulls": false,
|
||||
},
|
||||
},
|
||||
"overrides": [],
|
||||
},
|
||||
"options": {
|
||||
"legend": {
|
||||
"calcs": [],
|
||||
"displayMode": "list",
|
||||
"placement": "bottom",
|
||||
"showLegend": true,
|
||||
},
|
||||
"tooltip": {
|
||||
"mode": "single",
|
||||
"sort": "none",
|
||||
},
|
||||
},
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Graph Migrations transforms should preserve "constant" transform 1`] = `
|
||||
{
|
||||
"defaults": {
|
||||
|
||||
@@ -2,17 +2,32 @@ import { cloneDeep } from 'lodash';
|
||||
|
||||
import { PanelModel, FieldConfigSource, FieldMatcherID, ReducerID } from '@grafana/data';
|
||||
import { TooltipDisplayMode, SortOrder } from '@grafana/schema';
|
||||
import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv';
|
||||
import { DashboardModel, PanelModel as PanelModelState } from 'app/features/dashboard/state';
|
||||
import { createDashboardModelFixture } from 'app/features/dashboard/state/__fixtures__/dashboardFixtures';
|
||||
import { GrafanaQueryType } from 'app/plugins/datasource/grafana/types';
|
||||
|
||||
import { graphPanelChangedHandler } from './migrations';
|
||||
|
||||
describe('Graph Migrations', () => {
|
||||
let prevFieldConfig: FieldConfigSource;
|
||||
let dashboard: DashboardModel;
|
||||
|
||||
beforeEach(() => {
|
||||
prevFieldConfig = {
|
||||
defaults: {},
|
||||
overrides: [],
|
||||
};
|
||||
|
||||
dashboard = createDashboardModelFixture({
|
||||
id: 74,
|
||||
version: 7,
|
||||
annotations: {},
|
||||
links: [],
|
||||
panels: [],
|
||||
});
|
||||
|
||||
getDashboardSrv().setCurrent(dashboard);
|
||||
});
|
||||
|
||||
it('simple bars', () => {
|
||||
@@ -82,6 +97,36 @@ describe('Graph Migrations', () => {
|
||||
expect(panel.fieldConfig.overrides[1].matcher.id).toBe(FieldMatcherID.byRegexp);
|
||||
});
|
||||
|
||||
describe('time regions', () => {
|
||||
test('should migrate', () => {
|
||||
const old = {
|
||||
angular: {
|
||||
timeRegions: [
|
||||
{
|
||||
colorMode: 'red',
|
||||
fill: true,
|
||||
fillColor: 'rgba(234, 112, 112, 0.12)',
|
||||
fromDayOfWeek: 1,
|
||||
line: true,
|
||||
lineColor: 'rgba(237, 46, 24, 0.60)',
|
||||
op: 'time',
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
const panel = { datasource: { type: 'datasource', uid: 'gdev-testdata' } } as PanelModel;
|
||||
dashboard.panels.push(new PanelModelState(panel));
|
||||
panel.options = graphPanelChangedHandler(panel, 'graph', old, prevFieldConfig);
|
||||
expect(dashboard.panels).toHaveLength(1);
|
||||
expect(dashboard.annotations.list).toHaveLength(2); // built-in + time region
|
||||
expect(
|
||||
dashboard.annotations.list.filter((annotation) => annotation.target?.queryType === GrafanaQueryType.TimeRegions)
|
||||
).toHaveLength(1);
|
||||
expect(panel).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe('legend', () => {
|
||||
test('without values', () => {
|
||||
const old = {
|
||||
|
||||
@@ -31,12 +31,19 @@ import {
|
||||
StackingMode,
|
||||
SortOrder,
|
||||
GraphTransform,
|
||||
AnnotationQuery,
|
||||
ComparisonOperation,
|
||||
} from '@grafana/schema';
|
||||
import { TimeRegionConfig } from 'app/core/utils/timeRegions';
|
||||
import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv';
|
||||
import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv';
|
||||
import { GrafanaQuery, GrafanaQueryType } from 'app/plugins/datasource/grafana/types';
|
||||
|
||||
import { defaultGraphConfig } from './config';
|
||||
import { PanelOptions } from './panelcfg.gen';
|
||||
|
||||
let dashboardRefreshDebouncer: ReturnType<typeof setTimeout> | null = null;
|
||||
|
||||
/**
|
||||
* This is called when the panel changes from another panel
|
||||
*/
|
||||
@@ -48,10 +55,25 @@ export const graphPanelChangedHandler: PanelTypeChangedHandler = (
|
||||
) => {
|
||||
// Changing from angular/flot panel to react/uPlot
|
||||
if (prevPluginId === 'graph' && prevOptions.angular) {
|
||||
const { fieldConfig, options } = graphToTimeseriesOptions({
|
||||
const { fieldConfig, options, annotations } = graphToTimeseriesOptions({
|
||||
...prevOptions.angular,
|
||||
fieldConfig: prevFieldConfig,
|
||||
panel: panel,
|
||||
});
|
||||
|
||||
const dashboard = getDashboardSrv().getCurrent();
|
||||
if (dashboard && annotations?.length > 0) {
|
||||
dashboard.annotations.list = [...dashboard.annotations.list, ...annotations];
|
||||
|
||||
// Trigger a full dashboard refresh when annotations change
|
||||
if (dashboardRefreshDebouncer == null) {
|
||||
dashboardRefreshDebouncer = setTimeout(() => {
|
||||
dashboardRefreshDebouncer = null;
|
||||
getTimeSrv().refreshTimeModel();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
panel.fieldConfig = fieldConfig; // Mutates the incoming panel
|
||||
panel.alert = prevOptions.angular.alert;
|
||||
return options;
|
||||
@@ -63,7 +85,13 @@ export const graphPanelChangedHandler: PanelTypeChangedHandler = (
|
||||
return {};
|
||||
};
|
||||
|
||||
export function graphToTimeseriesOptions(angular: any): { fieldConfig: FieldConfigSource; options: PanelOptions } {
|
||||
export function graphToTimeseriesOptions(angular: any): {
|
||||
fieldConfig: FieldConfigSource;
|
||||
options: PanelOptions;
|
||||
annotations: AnnotationQuery[];
|
||||
} {
|
||||
let annotations: AnnotationQuery[] = [];
|
||||
|
||||
const overrides: ConfigOverrideRule[] = angular.fieldConfig?.overrides ?? [];
|
||||
const yaxes = angular.yaxes ?? [];
|
||||
let y1 = getFieldConfigFromOldAxis(yaxes[0]);
|
||||
@@ -362,6 +390,55 @@ export function graphToTimeseriesOptions(angular: any): { fieldConfig: FieldConf
|
||||
}
|
||||
}
|
||||
|
||||
// timeRegions migration
|
||||
if (angular.timeRegions?.length) {
|
||||
let regions: any[] = angular.timeRegions.map((old: GraphTimeRegionConfig, idx: number) => ({
|
||||
name: `T${idx + 1}`,
|
||||
color: old.colorMode !== 'custom' ? old.colorMode : old.fillColor,
|
||||
line: old.line,
|
||||
fill: old.fill,
|
||||
fromDayOfWeek: old.fromDayOfWeek,
|
||||
toDayOfWeek: old.toDayOfWeek,
|
||||
from: old.from,
|
||||
to: old.to,
|
||||
}));
|
||||
|
||||
regions.forEach((region: GraphTimeRegionConfig, idx: number) => {
|
||||
const anno: AnnotationQuery<GrafanaQuery> = {
|
||||
datasource: {
|
||||
type: 'datasource',
|
||||
uid: 'grafana',
|
||||
},
|
||||
enable: true,
|
||||
hide: true, // don't show the toggle at the top of the dashboard
|
||||
filter: {
|
||||
exclude: false,
|
||||
ids: [angular.panel.id],
|
||||
},
|
||||
iconColor: region.fillColor ?? (region as any).color,
|
||||
name: `T${idx + 1}`,
|
||||
target: {
|
||||
queryType: GrafanaQueryType.TimeRegions,
|
||||
refId: 'Anno',
|
||||
timeRegion: {
|
||||
fromDayOfWeek: region.fromDayOfWeek,
|
||||
toDayOfWeek: region.toDayOfWeek,
|
||||
from: region.from,
|
||||
to: region.to,
|
||||
timezone: 'utc', // graph panel was always UTC
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
if (region.fill) {
|
||||
annotations.push(anno);
|
||||
} else if (region.line) {
|
||||
anno.iconColor = region.lineColor ?? 'white';
|
||||
annotations.push(anno);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const tooltipConfig = angular.tooltip;
|
||||
if (tooltipConfig) {
|
||||
if (tooltipConfig.shared !== undefined) {
|
||||
@@ -479,9 +556,18 @@ export function graphToTimeseriesOptions(angular: any): { fieldConfig: FieldConf
|
||||
overrides,
|
||||
},
|
||||
options,
|
||||
annotations,
|
||||
};
|
||||
}
|
||||
|
||||
interface GraphTimeRegionConfig extends TimeRegionConfig {
|
||||
colorMode: string;
|
||||
fill: boolean;
|
||||
fillColor: string;
|
||||
line: boolean;
|
||||
lineColor: string;
|
||||
}
|
||||
|
||||
function getThresholdColor(threshold: AngularThreshold): string {
|
||||
if (threshold.colorMode === 'critical') {
|
||||
return 'red';
|
||||
|
||||
Reference in New Issue
Block a user