feat: added logarithmic scale option for panels (#7413)

This commit is contained in:
SagarRajput-7 2025-03-24 18:42:04 +05:30 committed by GitHub
parent 694c185373
commit bc17a10550
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 90 additions and 5 deletions

View File

@ -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);

View File

@ -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,

View File

@ -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<SetStateAction<string>>, 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({
</section>
</section>
)}
{allowLogScale && (
<section className="log-scale">
<Typography.Text className="typography">Y Axis Scale</Typography.Text>
<Select
onChange={(value): void => setIsLogScale(value === LogScale.LOGARITHMIC)}
value={isLogScale ? LogScale.LOGARITHMIC : LogScale.LINEAR}
style={{ width: '100%' }}
className="panel-type-select"
defaultValue={LogScale.LINEAR}
>
<Option value={LogScale.LINEAR}>
<div className="select-option">
<div className="icon">
<LineChart size={16} />
</div>
<Typography.Text className="display">Linear</Typography.Text>
</div>
</Option>
<Option value={LogScale.LOGARITHMIC}>
<div className="select-option">
<div className="icon">
<Spline size={16} />
</div>
<Typography.Text className="display">Logarithmic</Typography.Text>
</div>
</Option>
</Select>
</section>
)}
</section>
{allowCreateAlerts && (
@ -356,6 +396,8 @@ interface RightContainerProps {
setColumnUnits: Dispatch<SetStateAction<ColumnUnit>>;
setSoftMin: Dispatch<SetStateAction<number | null>>;
setSoftMax: Dispatch<SetStateAction<number | null>>;
isLogScale: boolean;
setIsLogScale: Dispatch<SetStateAction<boolean>>;
}
RightContainer.defaultProps = {

View File

@ -170,6 +170,9 @@ function NewWidget({ selectedGraph }: NewWidgetProps): JSX.Element {
const [isFillSpans, setIsFillSpans] = useState<boolean>(
selectedWidget?.fillSpans || false,
);
const [isLogScale, setIsLogScale] = useState<boolean>(
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}

View File

@ -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,
],
);

View File

@ -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 }),
};
};

View File

@ -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,

View File

@ -108,6 +108,7 @@ export interface IBaseWidget {
columnUnits?: ColumnUnit;
selectedLogFields: IField[] | null;
selectedTracesFields: BaseAutocompleteData[] | null;
isLogScale?: boolean;
}
export interface Widgets extends IBaseWidget {
query: Query;