From bc17a10550228152e2f8456a0e18ef0c1d084e79 Mon Sep 17 00:00:00 2001 From: SagarRajput-7 <162284829+SagarRajput-7@users.noreply.github.com> Date: Mon, 24 Mar 2025 18:42:04 +0530 Subject: [PATCH] feat: added logarithmic scale option for panels (#7413) --- .../RightContainer/RightContainer.styles.scss | 8 ++++ .../NewWidget/RightContainer/constants.ts | 12 +++++ .../NewWidget/RightContainer/index.tsx | 44 ++++++++++++++++++- frontend/src/container/NewWidget/index.tsx | 11 +++++ .../PanelWrapper/UplotPanelWrapper.tsx | 2 + .../src/lib/uPlotLib/getUplotChartOptions.ts | 5 ++- frontend/src/lib/uPlotLib/utils/getAxes.ts | 12 +++-- frontend/src/types/api/dashboard/getAll.ts | 1 + 8 files changed, 90 insertions(+), 5 deletions(-) diff --git a/frontend/src/container/NewWidget/RightContainer/RightContainer.styles.scss b/frontend/src/container/NewWidget/RightContainer/RightContainer.styles.scss index 55d717926a..8d334c240b 100644 --- a/frontend/src/container/NewWidget/RightContainer/RightContainer.styles.scss +++ b/frontend/src/container/NewWidget/RightContainer/RightContainer.styles.scss @@ -159,6 +159,14 @@ } } + .log-scale { + margin-top: 16px; + display: flex; + justify-content: space-between; + flex-direction: column; + gap: 8px; + } + .panel-time-text { margin-top: 16px; color: var(--bg-vanilla-400); diff --git a/frontend/src/container/NewWidget/RightContainer/constants.ts b/frontend/src/container/NewWidget/RightContainer/constants.ts index 1fad229ed6..cec2f8a600 100644 --- a/frontend/src/container/NewWidget/RightContainer/constants.ts +++ b/frontend/src/container/NewWidget/RightContainer/constants.ts @@ -61,6 +61,18 @@ export const panelTypeVsFillSpan: { [key in PANEL_TYPES]: boolean } = { [PANEL_TYPES.EMPTY_WIDGET]: false, } as const; +export const panelTypeVsLogScale: { [key in PANEL_TYPES]: boolean } = { + [PANEL_TYPES.TIME_SERIES]: true, + [PANEL_TYPES.VALUE]: false, + [PANEL_TYPES.TABLE]: false, + [PANEL_TYPES.LIST]: false, + [PANEL_TYPES.PIE]: false, + [PANEL_TYPES.BAR]: true, + [PANEL_TYPES.HISTOGRAM]: false, + [PANEL_TYPES.TRACE]: false, + [PANEL_TYPES.EMPTY_WIDGET]: false, +} as const; + export const panelTypeVsYAxisUnit: { [key in PANEL_TYPES]: boolean } = { [PANEL_TYPES.TIME_SERIES]: true, [PANEL_TYPES.VALUE]: true, diff --git a/frontend/src/container/NewWidget/RightContainer/index.tsx b/frontend/src/container/NewWidget/RightContainer/index.tsx index d8b2677e60..ee2e024953 100644 --- a/frontend/src/container/NewWidget/RightContainer/index.tsx +++ b/frontend/src/container/NewWidget/RightContainer/index.tsx @@ -10,7 +10,7 @@ import GraphTypes, { } from 'container/NewDashboard/ComponentsSlider/menuItems'; import useCreateAlerts from 'hooks/queryBuilder/useCreateAlerts'; import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder'; -import { ConciergeBell, Plus } from 'lucide-react'; +import { ConciergeBell, LineChart, Plus, Spline } from 'lucide-react'; import { Dispatch, SetStateAction, @@ -27,6 +27,7 @@ import { panelTypeVsColumnUnitPreferences, panelTypeVsCreateAlert, panelTypeVsFillSpan, + panelTypeVsLogScale, panelTypeVsPanelTimePreferences, panelTypeVsSoftMinMax, panelTypeVsStackingChartPreferences, @@ -41,6 +42,12 @@ import YAxisUnitSelector from './YAxisUnitSelector'; const { TextArea } = Input; const { Option } = Select; +enum LogScale { + LINEAR = 'linear', + LOGARITHMIC = 'logarithmic', +} + +// eslint-disable-next-line sonarjs/cognitive-complexity function RightContainer({ description, setDescription, @@ -71,6 +78,8 @@ function RightContainer({ setSoftMin, columnUnits, setColumnUnits, + isLogScale, + setIsLogScale, }: RightContainerProps): JSX.Element { const onChangeHandler = useCallback( (setFunc: Dispatch>, value: string) => { @@ -87,6 +96,7 @@ function RightContainer({ const allowThreshold = panelTypeVsThreshold[selectedGraph]; const allowSoftMinMax = panelTypeVsSoftMinMax[selectedGraph]; const allowFillSpans = panelTypeVsFillSpan[selectedGraph]; + const allowLogScale = panelTypeVsLogScale[selectedGraph]; const allowYAxisUnit = panelTypeVsYAxisUnit[selectedGraph]; const allowCreateAlerts = panelTypeVsCreateAlert[selectedGraph]; const allowBucketConfig = panelTypeVsBucketConfig[selectedGraph]; @@ -293,6 +303,36 @@ function RightContainer({ )} + + {allowLogScale && ( +
+ Y Axis Scale + +
+ )} {allowCreateAlerts && ( @@ -356,6 +396,8 @@ interface RightContainerProps { setColumnUnits: Dispatch>; setSoftMin: Dispatch>; setSoftMax: Dispatch>; + isLogScale: boolean; + setIsLogScale: Dispatch>; } RightContainer.defaultProps = { diff --git a/frontend/src/container/NewWidget/index.tsx b/frontend/src/container/NewWidget/index.tsx index bcae2868bd..4c37252a54 100644 --- a/frontend/src/container/NewWidget/index.tsx +++ b/frontend/src/container/NewWidget/index.tsx @@ -170,6 +170,9 @@ function NewWidget({ selectedGraph }: NewWidgetProps): JSX.Element { const [isFillSpans, setIsFillSpans] = useState( selectedWidget?.fillSpans || false, ); + const [isLogScale, setIsLogScale] = useState( + selectedWidget?.isLogScale || false, + ); const [saveModal, setSaveModal] = useState(false); const [discardModal, setDiscardModal] = useState(false); @@ -234,6 +237,7 @@ function NewWidget({ selectedGraph }: NewWidgetProps): JSX.Element { mergeAllActiveQueries: combineHistogram, selectedLogFields, selectedTracesFields, + isLogScale, }; }); }, [ @@ -255,6 +259,7 @@ function NewWidget({ selectedGraph }: NewWidgetProps): JSX.Element { bucketCount, combineHistogram, stackedBarChart, + isLogScale, ]); const closeModal = (): void => { @@ -369,6 +374,7 @@ function NewWidget({ selectedGraph }: NewWidgetProps): JSX.Element { graphType: getGraphType(selectedGraph || selectedWidget.panelTypes), query: stagedQuery, fillGaps: selectedWidget.fillSpans || false, + isLogScale: selectedWidget.isLogScale || false, formatForWeb: getGraphTypeForFormat(selectedGraph || selectedWidget.panelTypes) === PANEL_TYPES.TABLE, @@ -379,6 +385,7 @@ function NewWidget({ selectedGraph }: NewWidgetProps): JSX.Element { stagedQuery, selectedTime, selectedWidget.fillSpans, + selectedWidget.isLogScale, globalSelectedInterval, ]); @@ -442,6 +449,7 @@ function NewWidget({ selectedGraph }: NewWidgetProps): JSX.Element { softMin: selectedWidget?.softMin || 0, softMax: selectedWidget?.softMax || 0, fillSpans: selectedWidget?.fillSpans, + isLogScale: selectedWidget?.isLogScale || false, bucketWidth: selectedWidget?.bucketWidth || 0, bucketCount: selectedWidget?.bucketCount || 0, mergeAllActiveQueries: selectedWidget?.mergeAllActiveQueries || false, @@ -468,6 +476,7 @@ function NewWidget({ selectedGraph }: NewWidgetProps): JSX.Element { softMin: selectedWidget?.softMin || 0, softMax: selectedWidget?.softMax || 0, fillSpans: selectedWidget?.fillSpans, + isLogScale: selectedWidget?.isLogScale || false, bucketWidth: selectedWidget?.bucketWidth || 0, bucketCount: selectedWidget?.bucketCount || 0, mergeAllActiveQueries: selectedWidget?.mergeAllActiveQueries || false, @@ -730,6 +739,8 @@ function NewWidget({ selectedGraph }: NewWidgetProps): JSX.Element { selectedWidget={selectedWidget} isFillSpans={isFillSpans} setIsFillSpans={setIsFillSpans} + isLogScale={isLogScale} + setIsLogScale={setIsLogScale} softMin={softMin} setSoftMin={setSoftMin} softMax={softMax} diff --git a/frontend/src/container/PanelWrapper/UplotPanelWrapper.tsx b/frontend/src/container/PanelWrapper/UplotPanelWrapper.tsx index 07589af9e9..77b29c7798 100644 --- a/frontend/src/container/PanelWrapper/UplotPanelWrapper.tsx +++ b/frontend/src/container/PanelWrapper/UplotPanelWrapper.tsx @@ -137,6 +137,7 @@ function UplotPanelWrapper({ uPlot.tzDate(new Date(timestamp * 1e3), timezone.value), timezone: timezone.value, customSeries, + isLogScale: widget?.isLogScale, }), [ widget?.id, @@ -161,6 +162,7 @@ function UplotPanelWrapper({ customTooltipElement, timezone.value, customSeries, + widget?.isLogScale, ], ); diff --git a/frontend/src/lib/uPlotLib/getUplotChartOptions.ts b/frontend/src/lib/uPlotLib/getUplotChartOptions.ts index 61e32e9700..f36eac2a9c 100644 --- a/frontend/src/lib/uPlotLib/getUplotChartOptions.ts +++ b/frontend/src/lib/uPlotLib/getUplotChartOptions.ts @@ -58,6 +58,7 @@ export interface GetUPlotChartOptions { tzDate?: (timestamp: number) => Date; timezone?: string; customSeries?: (data: QueryData[]) => uPlot.Series[]; + isLogScale?: boolean; } /** the function converts series A , series B , series C to @@ -164,6 +165,7 @@ export const getUPlotChartOptions = ({ tzDate, timezone, customSeries, + isLogScale, }: GetUPlotChartOptions): uPlot.Options => { const timeScaleProps = getXAxisScale(minTimeScale, maxTimeScale); @@ -220,6 +222,7 @@ export const getUPlotChartOptions = ({ softMax, softMin, }), + distr: isLogScale ? 3 : 1, }, }, plugins: [ @@ -387,6 +390,6 @@ export const getUPlotChartOptions = ({ hiddenGraph, isDarkMode, }), - axes: getAxes({ isDarkMode, yAxisUnit, panelType }), + axes: getAxes({ isDarkMode, yAxisUnit, panelType, isLogScale }), }; }; diff --git a/frontend/src/lib/uPlotLib/utils/getAxes.ts b/frontend/src/lib/uPlotLib/utils/getAxes.ts index 663bccad39..4742ed22b2 100644 --- a/frontend/src/lib/uPlotLib/utils/getAxes.ts +++ b/frontend/src/lib/uPlotLib/utils/getAxes.ts @@ -17,16 +17,19 @@ const getAxes = ({ isDarkMode, yAxisUnit, panelType, + isLogScale, }: { isDarkMode: boolean; yAxisUnit?: string; panelType?: PANEL_TYPES; + isLogScale?: boolean; + // eslint-disable-next-line sonarjs/cognitive-complexity }): any => [ { stroke: isDarkMode ? 'white' : 'black', // Color of the axis line grid: { stroke: getGridColor(isDarkMode), // Color of the grid lines - width: 0.2, // Width of the grid lines, + width: isLogScale ? 0.1 : 0.2, // Width of the grid lines, show: true, }, ticks: { @@ -45,17 +48,20 @@ const getAxes = ({ stroke: isDarkMode ? 'white' : 'black', // Color of the axis line grid: { stroke: getGridColor(isDarkMode), // Color of the grid lines - width: 0.2, // Width of the grid lines + width: isLogScale ? 0.1 : 0.2, // Width of the grid lines }, ticks: { // stroke: isDarkMode ? 'white' : 'black', // Color of the tick lines width: 0.3, // Width of the tick lines show: true, }, + ...(isLogScale ? { space: 20 } : {}), values: (_, t): string[] => t.map((v) => { + if (v === null || v === undefined || Number.isNaN(v)) { + return ''; + } const value = getToolTipValue(v.toString(), yAxisUnit); - return `${value}`; }), gap: 5, diff --git a/frontend/src/types/api/dashboard/getAll.ts b/frontend/src/types/api/dashboard/getAll.ts index 0bf3020d62..8cfd6f7f9a 100644 --- a/frontend/src/types/api/dashboard/getAll.ts +++ b/frontend/src/types/api/dashboard/getAll.ts @@ -108,6 +108,7 @@ export interface IBaseWidget { columnUnits?: ColumnUnit; selectedLogFields: IField[] | null; selectedTracesFields: BaseAutocompleteData[] | null; + isLogScale?: boolean; } export interface Widgets extends IBaseWidget { query: Query;