signoz/frontend/src/lib/uPlotLib/getUplotHistogramChartOptions.ts

200 lines
5.1 KiB
TypeScript
Raw Normal View History

feat: add histogram visualisation support (#4858) * refactor: added panel type histogram and basic setup done * feat: histogram for one query * refactor: multiple query support histogram * chore: typecorrection * refactor: done with legend part * refactor: legend change fix * refactor: fix the tooltip value for histogram * refactor: disable drag for histogram * fix: tsc * refactor: handled panel type change in edit mode * refactor: full view done (#4881) Co-authored-by: Rajat-Dabade <rajat@signoz.io> * [Feat]: Full view histogram (#4867) * refactor: added panel type histogram and basic setup done * feat: histogram for one query * refactor: multiple query support histogram * chore: typecorrection * refactor: done with legend part * refactor: legend change fix * refactor: fix the tooltip value for histogram * refactor: disable drag for histogram * fix: tsc * refactor: handled panel type change in edit mode * refactor: full view done --------- Co-authored-by: Rajat-Dabade <rajat@signoz.io> Co-authored-by: Yunus M <myounis.ar@live.com> * feat: histogram customisations (#5133) * feat: added bucket size and bucket width enhancements for histogram * fix: added handling for bucket size bucket count and combine into one series * fix: added bidirectional sync * fix: remove extra props from interfaces * fix: hide legends when merging all queries * fix: minor legend fixes * fix: build issues --------- Co-authored-by: Rajat-Dabade <rajat@signoz.io> Co-authored-by: Yunus M <myounis.ar@live.com> Co-authored-by: Vikrant Gupta <vikrant.thomso@gmail.com>
2024-06-05 07:07:49 +05:30
/* eslint-disable sonarjs/cognitive-complexity */
import { PANEL_TYPES } from 'constants/queryBuilder';
import { themeColors } from 'constants/theme';
import { saveLegendEntriesToLocalStorage } from 'container/GridCardLayout/GridCard/FullView/utils';
import { Dimensions } from 'hooks/useDimensions';
import getLabelName from 'lib/getLabelName';
import { Dispatch, SetStateAction } from 'react';
import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange';
import { Query } from 'types/api/queryBuilder/queryBuilderData';
import { QueryData } from 'types/api/widgets/getQuery';
import uPlot from 'uplot';
import tooltipPlugin from './plugins/tooltipPlugin';
import { drawStyles } from './utils/constants';
import { generateColor } from './utils/generateColor';
import getAxes from './utils/getAxes';
type GetUplotHistogramChartOptionsProps = {
id?: string;
apiResponse?: MetricRangePayloadProps;
histogramData: uPlot.AlignedData;
dimensions: Dimensions;
isDarkMode: boolean;
panelType?: PANEL_TYPES;
onDragSelect?: (startTime: number, endTime: number) => void;
currentQuery?: Query;
graphsVisibilityStates?: boolean[];
setGraphsVisibilityStates?: Dispatch<SetStateAction<boolean[]>>;
mergeAllQueries?: boolean;
};
type GetHistogramSeriesProps = {
apiResponse?: MetricRangePayloadProps;
currentQuery?: Query;
widgetMetaData?: QueryData[];
graphsVisibilityStates?: boolean[];
isMergedSeries?: boolean;
};
const { bars } = uPlot.paths;
const paths = (
u: uPlot,
seriesIdx: number,
idx0: number,
idx1: number,
): uPlot.Series.Paths | null | undefined => {
const renderer = bars && bars({ size: [1], align: -1 });
return renderer && renderer(u, seriesIdx, idx0, idx1);
};
const getHistogramSeries = ({
apiResponse,
currentQuery,
widgetMetaData,
graphsVisibilityStates,
isMergedSeries,
}: GetHistogramSeriesProps): uPlot.Options['series'] => {
const configurations: uPlot.Series[] = [
{ label: 'Timestamp', stroke: 'purple' },
];
const seriesList = apiResponse?.data.result || [];
const newGraphVisibilityStates = graphsVisibilityStates?.slice(1);
for (let i = 0; i < seriesList?.length; i += 1) {
const { metric = {}, queryName = '', legend: lgd } =
(widgetMetaData && widgetMetaData[i]) || {};
const newLegend =
currentQuery?.builder.queryData.find((item) => item.queryName === queryName)
?.legend || '';
const legend = newLegend || lgd || '';
const label = isMergedSeries
? ''
feat: add histogram visualisation support (#4858) * refactor: added panel type histogram and basic setup done * feat: histogram for one query * refactor: multiple query support histogram * chore: typecorrection * refactor: done with legend part * refactor: legend change fix * refactor: fix the tooltip value for histogram * refactor: disable drag for histogram * fix: tsc * refactor: handled panel type change in edit mode * refactor: full view done (#4881) Co-authored-by: Rajat-Dabade <rajat@signoz.io> * [Feat]: Full view histogram (#4867) * refactor: added panel type histogram and basic setup done * feat: histogram for one query * refactor: multiple query support histogram * chore: typecorrection * refactor: done with legend part * refactor: legend change fix * refactor: fix the tooltip value for histogram * refactor: disable drag for histogram * fix: tsc * refactor: handled panel type change in edit mode * refactor: full view done --------- Co-authored-by: Rajat-Dabade <rajat@signoz.io> Co-authored-by: Yunus M <myounis.ar@live.com> * feat: histogram customisations (#5133) * feat: added bucket size and bucket width enhancements for histogram * fix: added handling for bucket size bucket count and combine into one series * fix: added bidirectional sync * fix: remove extra props from interfaces * fix: hide legends when merging all queries * fix: minor legend fixes * fix: build issues --------- Co-authored-by: Rajat-Dabade <rajat@signoz.io> Co-authored-by: Yunus M <myounis.ar@live.com> Co-authored-by: Vikrant Gupta <vikrant.thomso@gmail.com>
2024-06-05 07:07:49 +05:30
: getLabelName(metric, queryName || '', legend);
const color = generateColor(label, themeColors.chartcolors);
const pointSize = seriesList[i].values.length > 1 ? 5 : 10;
const showPoints = !(seriesList[i].values.length > 1);
const seriesObj: uPlot.Series = {
paths,
drawStyle: drawStyles.bars,
lineInterpolation: null,
show: newGraphVisibilityStates ? newGraphVisibilityStates[i] : true,
label,
fill: `${color}40`,
stroke: color,
width: 2,
points: {
size: pointSize,
show: showPoints,
stroke: color,
},
} as uPlot.Series;
configurations.push(seriesObj);
}
return configurations;
};
export const getUplotHistogramChartOptions = ({
id,
dimensions,
isDarkMode,
apiResponse,
currentQuery,
graphsVisibilityStates,
setGraphsVisibilityStates,
mergeAllQueries,
}: GetUplotHistogramChartOptionsProps): uPlot.Options =>
({
id,
width: dimensions.width,
height: dimensions.height - 30,
legend: {
show: !mergeAllQueries,
live: false,
isolate: true,
},
focus: {
alpha: 0.3,
},
padding: [16, 16, 8, 8],
plugins: [
tooltipPlugin({
apiResponse,
isHistogramGraphs: true,
isMergedSeries: mergeAllQueries,
}),
],
scales: {
x: {
time: false,
auto: true,
},
y: {
auto: true,
},
},
cursor: {
drag: {
x: false,
y: false,
setScale: true,
},
},
series: getHistogramSeries({
apiResponse,
widgetMetaData: apiResponse?.data.result,
currentQuery,
graphsVisibilityStates,
isMergedSeries: mergeAllQueries,
}),
hooks: {
ready: [
(self): void => {
const legend = self.root.querySelector('.u-legend');
if (legend) {
const seriesEls = legend.querySelectorAll('.u-series');
const seriesArray = Array.from(seriesEls);
seriesArray.forEach((seriesEl, index) => {
seriesEl.addEventListener('click', () => {
if (graphsVisibilityStates) {
setGraphsVisibilityStates?.((prev) => {
const newGraphVisibilityStates = [...prev];
if (
newGraphVisibilityStates[index + 1] &&
newGraphVisibilityStates.every((value, i) =>
i === index + 1 ? value : !value,
)
) {
newGraphVisibilityStates.fill(true);
} else {
newGraphVisibilityStates.fill(false);
newGraphVisibilityStates[index + 1] = true;
}
saveLegendEntriesToLocalStorage({
options: self,
graphVisibilityState: newGraphVisibilityStates,
name: id || '',
});
return newGraphVisibilityStates;
});
}
});
});
}
},
],
},
axes: getAxes(isDarkMode),
} as uPlot.Options);