mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-18 02:25:55 +08:00
fix: update logic for handling data for uplot charts (#4131)
* fix: update logic for handling data for uplot charts * fix: hide tooltip if no tooltip values present * fix: remove console log
This commit is contained in:
parent
b616dca52d
commit
3e29161fea
@ -107,48 +107,8 @@ function RightContainer({
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* <TextContainer>
|
|
||||||
<Typography>Stacked Graphs :</Typography>
|
|
||||||
<Switch
|
|
||||||
checked={stacked}
|
|
||||||
onChange={(): void => {
|
|
||||||
setStacked((value) => !value);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</TextContainer> */}
|
|
||||||
|
|
||||||
{/* <Title light={'true'}>Fill Opacity: </Title> */}
|
|
||||||
|
|
||||||
{/* <Slider
|
|
||||||
value={parseInt(opacity, 10)}
|
|
||||||
marks={{
|
|
||||||
0: '0',
|
|
||||||
33: '33',
|
|
||||||
66: '66',
|
|
||||||
100: '100',
|
|
||||||
}}
|
|
||||||
onChange={(number): void => onChangeHandler(setOpacity, number.toString())}
|
|
||||||
step={1}
|
|
||||||
/> */}
|
|
||||||
|
|
||||||
{/* <Title light={'true'}>Null/Zero values: </Title>
|
|
||||||
|
|
||||||
<NullButtonContainer>
|
|
||||||
{nullValueButtons.map((button) => (
|
|
||||||
<Button
|
|
||||||
type={button.check === selectedNullZeroValue ? 'primary' : 'default'}
|
|
||||||
key={button.name}
|
|
||||||
onClick={(): void =>
|
|
||||||
onChangeHandler(setSelectedNullZeroValue, button.check)
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{button.name}
|
|
||||||
</Button>
|
|
||||||
))}
|
|
||||||
</NullButtonContainer> */}
|
|
||||||
|
|
||||||
<Space style={{ marginTop: 10 }} direction="vertical">
|
<Space style={{ marginTop: 10 }} direction="vertical">
|
||||||
<Typography>Fill span gaps</Typography>
|
<Typography>Fill gaps</Typography>
|
||||||
|
|
||||||
<Switch
|
<Switch
|
||||||
checked={isFillSpans}
|
checked={isFillSpans}
|
||||||
|
@ -29,6 +29,8 @@ const generateTooltipContent = (
|
|||||||
): HTMLElement => {
|
): HTMLElement => {
|
||||||
const container = document.createElement('div');
|
const container = document.createElement('div');
|
||||||
container.classList.add('tooltip-container');
|
container.classList.add('tooltip-container');
|
||||||
|
const overlay = document.getElementById('overlay');
|
||||||
|
let tooltipCount = 0;
|
||||||
|
|
||||||
let tooltipTitle = '';
|
let tooltipTitle = '';
|
||||||
const formattedData: Record<string, UplotTooltipDataProps> = {};
|
const formattedData: Record<string, UplotTooltipDataProps> = {};
|
||||||
@ -49,28 +51,40 @@ const generateTooltipContent = (
|
|||||||
const { metric = {}, queryName = '', legend = '' } =
|
const { metric = {}, queryName = '', legend = '' } =
|
||||||
seriesList[index - 1] || {};
|
seriesList[index - 1] || {};
|
||||||
|
|
||||||
|
const value = data[index][idx];
|
||||||
const label = getLabelName(metric, queryName || '', legend || '');
|
const label = getLabelName(metric, queryName || '', legend || '');
|
||||||
|
|
||||||
const value = data[index][idx] || 0;
|
if (value) {
|
||||||
const tooltipValue = getToolTipValue(value, yAxisUnit);
|
const tooltipValue = getToolTipValue(value, yAxisUnit);
|
||||||
|
|
||||||
const dataObj = {
|
const dataObj = {
|
||||||
show: item.show || false,
|
show: item.show || false,
|
||||||
color: colors[(index - 1) % colors.length],
|
color: colors[(index - 1) % colors.length],
|
||||||
label,
|
label,
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
focus: item?._focus || false,
|
focus: item?._focus || false,
|
||||||
value,
|
value,
|
||||||
tooltipValue,
|
tooltipValue,
|
||||||
textContent: `${label} : ${tooltipValue}`,
|
textContent: `${label} : ${tooltipValue}`,
|
||||||
};
|
};
|
||||||
|
|
||||||
formattedData[label] = dataObj;
|
tooltipCount += 1;
|
||||||
|
formattedData[label] = dataObj;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Show tooltip only if atleast only series has a value at the hovered timestamp
|
||||||
|
if (tooltipCount <= 0) {
|
||||||
|
if (overlay && overlay.style.display === 'block') {
|
||||||
|
overlay.style.display = 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
|
||||||
const sortedData: Record<
|
const sortedData: Record<
|
||||||
string,
|
string,
|
||||||
UplotTooltipDataProps
|
UplotTooltipDataProps
|
||||||
@ -116,8 +130,6 @@ const generateTooltipContent = (
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const overlay = document.getElementById('overlay');
|
|
||||||
|
|
||||||
if (overlay && overlay.style.display === 'none') {
|
if (overlay && overlay.style.display === 'none') {
|
||||||
overlay.style.display = 'block';
|
overlay.style.display = 'block';
|
||||||
}
|
}
|
||||||
|
@ -1,44 +1,65 @@
|
|||||||
import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange';
|
import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange';
|
||||||
|
import { QueryData } from 'types/api/widgets/getQuery';
|
||||||
|
|
||||||
// eslint-disable-next-line sonarjs/cognitive-complexity
|
function getXAxisTimestamps(seriesList: QueryData[]): number[] {
|
||||||
function fillMissingTimestamps(
|
const timestamps = new Set();
|
||||||
sortedTimestamps: number[],
|
|
||||||
subsetArray: any[],
|
|
||||||
fillSpans: boolean | undefined,
|
|
||||||
): any[] {
|
|
||||||
const filledArray = [];
|
|
||||||
|
|
||||||
let subsetIndex = 0;
|
seriesList.forEach((series: { values: [number, string][] }) => {
|
||||||
// eslint-disable-next-line no-restricted-syntax
|
series.values.forEach((value) => {
|
||||||
for (const timestamp of sortedTimestamps) {
|
timestamps.add(value[0]);
|
||||||
if (
|
});
|
||||||
subsetIndex < subsetArray.length &&
|
});
|
||||||
timestamp === subsetArray[subsetIndex][0]
|
|
||||||
) {
|
|
||||||
// Timestamp is present in subsetArray
|
|
||||||
const seriesPointData = subsetArray[subsetIndex];
|
|
||||||
|
|
||||||
if (
|
const timestampsArr: number[] | unknown[] = Array.from(timestamps) || [];
|
||||||
seriesPointData &&
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
Array.isArray(seriesPointData) &&
|
// @ts-ignore
|
||||||
seriesPointData.length > 0 &&
|
return timestampsArr.sort((a, b) => a - b);
|
||||||
seriesPointData[1] !== 'NaN'
|
}
|
||||||
) {
|
|
||||||
filledArray.push(subsetArray[subsetIndex]);
|
|
||||||
} else {
|
|
||||||
const value = fillSpans ? 0 : null;
|
|
||||||
filledArray.push([seriesPointData[0], value]);
|
|
||||||
}
|
|
||||||
|
|
||||||
subsetIndex += 1;
|
function fillMissingXAxisTimestamps(
|
||||||
} else {
|
timestampArr: number[],
|
||||||
// Timestamp is missing in subsetArray, fill with [timestamp, 0]
|
data: any[],
|
||||||
|
fillSpans: boolean,
|
||||||
|
): any {
|
||||||
|
// Generate a set of all timestamps in the range
|
||||||
|
const allTimestampsSet = new Set(timestampArr);
|
||||||
|
const processedData = JSON.parse(JSON.stringify(data));
|
||||||
|
|
||||||
|
// Fill missing timestamps with null values
|
||||||
|
processedData.forEach((entry: { values: (number | null)[][] }) => {
|
||||||
|
const existingTimestamps = new Set(entry.values.map((value) => value[0]));
|
||||||
|
|
||||||
|
const missingTimestamps = Array.from(allTimestampsSet).filter(
|
||||||
|
(timestamp) => !existingTimestamps.has(timestamp),
|
||||||
|
);
|
||||||
|
|
||||||
|
missingTimestamps.forEach((timestamp) => {
|
||||||
const value = fillSpans ? 0 : null;
|
const value = fillSpans ? 0 : null;
|
||||||
filledArray.push([timestamp, value]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return filledArray;
|
entry.values.push([timestamp, value]);
|
||||||
|
});
|
||||||
|
|
||||||
|
entry.values.forEach((v) => {
|
||||||
|
if (Number.isNaN(v[1])) {
|
||||||
|
const replaceValue = fillSpans ? 0 : null;
|
||||||
|
// eslint-disable-next-line no-param-reassign
|
||||||
|
v[1] = replaceValue;
|
||||||
|
} else if (v[1] !== null) {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-ignore
|
||||||
|
// eslint-disable-next-line no-param-reassign
|
||||||
|
v[1] = parseFloat(v[1]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-ignore
|
||||||
|
entry.values.sort((a, b) => a[0] - b[0]);
|
||||||
|
});
|
||||||
|
|
||||||
|
return processedData.map((entry: { values: [number, string][] }) =>
|
||||||
|
entry.values.map((value) => value[1]),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getUPlotChartData = (
|
export const getUPlotChartData = (
|
||||||
@ -46,43 +67,12 @@ export const getUPlotChartData = (
|
|||||||
fillSpans?: boolean,
|
fillSpans?: boolean,
|
||||||
): any[] => {
|
): any[] => {
|
||||||
const seriesList = apiResponse?.data?.result || [];
|
const seriesList = apiResponse?.data?.result || [];
|
||||||
const uPlotData = [];
|
const timestampArr = getXAxisTimestamps(seriesList);
|
||||||
|
const yAxisValuesArr = fillMissingXAxisTimestamps(
|
||||||
// this helps us identify the series with the max number of values and helps define the x axis - timestamps
|
timestampArr,
|
||||||
const xSeries = seriesList.reduce(
|
seriesList,
|
||||||
(maxObj, currentObj) =>
|
fillSpans || false,
|
||||||
currentObj.values.length > maxObj.values.length ? currentObj : maxObj,
|
|
||||||
seriesList[0],
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// sort seriesList
|
return [timestampArr, ...yAxisValuesArr];
|
||||||
for (let index = 0; index < seriesList.length; index += 1) {
|
|
||||||
seriesList[index]?.values?.sort((a, b) => a[0] - b[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
const timestampArr = xSeries?.values?.map((v) => v[0]);
|
|
||||||
|
|
||||||
// timestamp
|
|
||||||
uPlotData.push(timestampArr);
|
|
||||||
|
|
||||||
// for each series, push the values
|
|
||||||
seriesList.forEach((series) => {
|
|
||||||
const updatedSeries = fillMissingTimestamps(
|
|
||||||
timestampArr,
|
|
||||||
series?.values || [],
|
|
||||||
fillSpans,
|
|
||||||
);
|
|
||||||
|
|
||||||
const seriesData =
|
|
||||||
updatedSeries?.map((v) => {
|
|
||||||
if (v[1] === null) {
|
|
||||||
return v[1];
|
|
||||||
}
|
|
||||||
return parseFloat(v[1]);
|
|
||||||
}) || [];
|
|
||||||
|
|
||||||
uPlotData.push(seriesData);
|
|
||||||
});
|
|
||||||
|
|
||||||
return uPlotData;
|
|
||||||
};
|
};
|
||||||
|
@ -42,6 +42,11 @@ body {
|
|||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.u-off {
|
||||||
|
text-decoration: line-through;
|
||||||
|
text-decoration-thickness: 3px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user