diff --git a/src/app/Analytics/SRE_Analytics/RecommendationComponents/BoxPlot/BoxPlot.tsx b/src/app/Analytics/SRE_Analytics/RecommendationComponents/BoxPlot/BoxPlot.tsx new file mode 100644 index 0000000..26aad3c --- /dev/null +++ b/src/app/Analytics/SRE_Analytics/RecommendationComponents/BoxPlot/BoxPlot.tsx @@ -0,0 +1,136 @@ +import React from 'react'; +import { + Chart, + ChartAxis, + ChartBoxPlot, + ChartCursorFlyout, + ChartCursorTooltip, + ChartLine, + ChartThreshold, + createContainer +} from '@patternfly/react-charts'; +import chart_color_orange_300 from '@patternfly/react-tokens/dist/esm/chart_color_orange_300'; + +interface BoxPlotProps { + data: Array<{ + name: string; + x: string; + y: number[]; + }>; + requestLimitsData: Array<{ + name: string; + x: string; + y: number[]; + }>; + chartTitle: string; + ariaDesc: string; + domain: { y: [number, number] }; + themeColor: string; + legendData: Array<{ name: string }>; +} + +const BoxPlot: React.FC = ({ data, requestLimitsData, chartTitle, ariaDesc, domain, themeColor, legendData }) => { + const baseStyles = { + color: '#f0f0f0', + fontFamily: 'RedHatText, Overpass, overpass, helvetica, arial, sans-serif', + fontSize: '14px' + }; + + const leftColumn = { paddingLeft: '10px', width: '50%' }; + const rightColumn = { paddingRight: '20px', textAlign: 'right', width: '50%' }; + const CursorVoronoiContainer = createContainer('voronoi', 'cursor'); + + const HtmlLegendContent = ({ datum, text, title, x, y, ...rest }) => ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ {title(datum)} +
Max{datum._max}
Median{datum._median}
Min{datum._min}
Q1{datum._q1}
Q3{datum._q3}
+
+
+ ); + + return ( +
+ `${datum.y}`} + labelComponent={ + } + flyoutHeight={145} + flyoutWidth={210} + labelComponent={ datum.x} datum={undefined} text={undefined} x={undefined} y={undefined} />} + /> + } + mouseFollowTooltips + voronoiDimension="x" + voronoiPadding={50} + /> + } + domain={domain} + domainPadding={{ x: [30, 25] }} + legendData={legendData} + legendPosition="bottom" + height={300} + name="chart4" + padding={{ + bottom: 75, + left: 50, + right: 50, + top: 50 + }} + maxDomain={{ y: 9 }} + themeColor={themeColor} + width={600} + > + + + + {/* */} + +
+ ); +}; + +export default BoxPlot; diff --git a/src/app/Analytics/SRE_Analytics/RecommendationComponents/ChartDataPreparation.tsx b/src/app/Analytics/SRE_Analytics/RecommendationComponents/ChartDataPreparation.tsx index d32dab8..552a93f 100644 --- a/src/app/Analytics/SRE_Analytics/RecommendationComponents/ChartDataPreparation.tsx +++ b/src/app/Analytics/SRE_Analytics/RecommendationComponents/ChartDataPreparation.tsx @@ -11,21 +11,7 @@ export function filterDataByTerm(data, givenDay, term) { throw new Error("Invalid term. Use 'short_term', 'medium_term', or 'long_term'."); } - const oneDayInMillis = 24 * 60 * 60 * 1000; - const givenDayMillis = Date.parse(givenDay); - const filteredData = {}; - - for (const key in data) { - if (data.hasOwnProperty(key)) { - const timestampMillis = Date.parse(key); - - if (givenDayMillis - timestampMillis <= oneDayInMillis * numDays && givenDayMillis - timestampMillis >= 0) { - filteredData[key] = data[key]; - } - } - } - - return filteredData; + return filterLastNDayData(data, givenDay, numDays); } export function formatTimestamps(timestampsData) { @@ -41,16 +27,17 @@ export function formatTimestamps(timestampsData) { return formattedData; } + export function formatNumber(input) { if (typeof input === 'number') { - return parseFloat(input.toFixed(3)); + return parseFloat(input.toFixed(3)); // Format the number to 3 decimal places and convert to number } else if (!isNaN(input)) { - return parseFloat(Number(input).toFixed(3)); + return parseFloat(Number(input).toFixed(3)); // Format the number to 3 decimal places and convert to number } return input; } export function addPlusSign(str) { - const number = parseFloat(str); + const number = parseFloat(str); // Try to convert the string to a number if (!isNaN(number) && isFinite(number)) { if (number >= 0) { @@ -58,5 +45,30 @@ export function addPlusSign(str) { } } - return str; + return str; // Return the original string if it's not a non-negative number +} + +export function filterLastNDayData(data, givenDay, numDays) { + const oneDayInMillis = 24 * 60 * 60 * 1000; // Number of milliseconds in a day + const givenDayMillis = Date.parse(givenDay); + const filteredData = {}; + + for (const key in data) { + if (data.hasOwnProperty(key)) { + const timestampMillis = Date.parse(key); + const isGivenTime = + new Date(key).getHours() === new Date(givenDay).getHours() && + new Date(key).getMinutes() === new Date(givenDay).getMinutes(); + + if ( + givenDayMillis - timestampMillis <= oneDayInMillis * numDays && + givenDayMillis - timestampMillis >= 0 && + !isGivenTime + ) { + filteredData[key] = data[key]; + } + } + } + + return filteredData; } diff --git a/src/app/Analytics/SRE_Analytics/RecommendationComponents/CostBoxPlotCharts.tsx b/src/app/Analytics/SRE_Analytics/RecommendationComponents/CostBoxPlotCharts.tsx new file mode 100644 index 0000000..5809150 --- /dev/null +++ b/src/app/Analytics/SRE_Analytics/RecommendationComponents/CostBoxPlotCharts.tsx @@ -0,0 +1,55 @@ +import React, { useState } from 'react'; +import { + Chart, + ChartAxis, + ChartGroup, + ChartLine, + ChartThemeColor, + ChartThreshold, + ChartVoronoiContainer +} from '@patternfly/react-charts'; +import { formatTimestamps, filterDataByTerm, formatNumber } from './ChartDataPreparation'; +import { Card, Grid, GridItem } from '@patternfly/react-core'; +import BoxPlot from './BoxPlot/BoxPlot'; + +import chart_color_blue_300 from '@patternfly/react-tokens/dist/esm/chart_color_blue_300'; + +const CostBoxPlotCharts = (props: { boxPlotData; limitRequestData}) => { + const limit = props.limitRequestData + console.log(limit) + const cpuDataLimit = props.limitRequestData?.limits?.cpu.amount + + return ( + + + + {/* */} + {/* * */} + + ); +}; + +export { CostBoxPlotCharts }; diff --git a/src/app/Analytics/SRE_Analytics/RecommendationComponents/CostDetails.tsx b/src/app/Analytics/SRE_Analytics/RecommendationComponents/CostDetails.tsx index 648bdca..4dde33f 100644 --- a/src/app/Analytics/SRE_Analytics/RecommendationComponents/CostDetails.tsx +++ b/src/app/Analytics/SRE_Analytics/RecommendationComponents/CostDetails.tsx @@ -13,9 +13,12 @@ import { import ReusableCodeBlock from './ReusableCodeBlock'; import { CostHistoricCharts } from './CostHistoricCharts'; import { addPlusSign } from './ChartDataPreparation'; +import BoxPlot from './BoxPlot/BoxPlot'; +import { ChartThreshold } from '@patternfly/react-charts'; +import { CostBoxPlotCharts } from './CostBoxPlotCharts'; -const CostDetails = (props: { recommendedData; currentData; chartData; day; endtime; displayChart }) => { - // console.log(props.recommendedData[0].recommendation_engines); +const CostDetails = (props: { recommendedData; currentData; chartData; day; endtime; displayChart; boxPlotData }) => { + console.log(props.recommendedData); const NumberFormat = (number) => typeof number === 'number' && !isNaN(number) ? (number % 1 !== 0 ? number.toFixed(3) : number) : ''; @@ -25,42 +28,42 @@ const CostDetails = (props: { recommendedData; currentData; chartData; day; endt const current_code = `resources: requests: memory: "${NumberFormat(props.currentData[0]?.requests?.memory?.amount)}${UnitFormat( - props.currentData[0]?.requests?.memory?.format - )}" + props.currentData[0]?.requests?.memory?.format + )}" cpu: "${NumberFormat(props.currentData[0]?.requests?.cpu?.amount)}" limits: memory: "${NumberFormat(props.currentData[0]?.limits?.memory?.amount)}${UnitFormat( - props.currentData[0]?.limits?.memory?.format - )}" + props.currentData[0]?.limits?.memory?.format + )}" cpu: "${NumberFormat(props.currentData[0]?.limits?.cpu?.amount)}"`; const recommended_code = `resources: requests: memory: "${NumberFormat( - props.recommendedData[0]?.recommendation_engines?.cost.config.requests.memory.amount + props.recommendedData[0]?.recommendation_engines?.cost?.config?.requests?.memory?.amount )}${UnitFormat( - props.recommendedData[0]?.recommendation_engines?.cost.config.requests.memory.format - )}" # ${addPlusSign( - NumberFormat(props.recommendedData[0]?.recommendation_engines?.cost.variation.requests.memory.amount) - )}${UnitFormat(props.recommendedData[0]?.recommendation_engines?.cost.variation.requests.memory.format)} + props.recommendedData[0]?.recommendation_engines?.cost?.config?.requests?.memory?.format + )}" # ${addPlusSign( + NumberFormat(props.recommendedData[0]?.recommendation_engines?.cost?.variation?.requests?.memory?.amount) + )}${UnitFormat(props.recommendedData[0]?.recommendation_engines?.cost?.variation?.requests?.memory?.format)} cpu: "${NumberFormat( - props.recommendedData[0]?.recommendation_engines?.cost.config.requests.cpu.amount + props.recommendedData[0]?.recommendation_engines?.cost?.config?.requests?.cpu?.amount )}" # ${addPlusSign( - NumberFormat(props.recommendedData[0]?.recommendation_engines?.cost.variation.requests.cpu.amount) - )} + NumberFormat(props.recommendedData[0]?.recommendation_engines?.cost?.variation?.requests?.cpu?.amount) + )} limits: memory: "${NumberFormat( - props.recommendedData[0]?.recommendation_engines?.cost.config.limits.memory.amount + props.recommendedData[0]?.recommendation_engines?.cost?.config?.limits?.memory?.amount )}${UnitFormat( - props.recommendedData[0]?.recommendation_engines?.cost.config.limits.memory.format - )}" # ${addPlusSign( - NumberFormat(props.recommendedData[0]?.recommendation_engines?.cost.variation.limits.memory.amount) - )}${UnitFormat(props.recommendedData[0]?.recommendation_engines?.cost.variation.limits.memory.format)} + props.recommendedData[0]?.recommendation_engines?.cost?.config?.limits?.memory?.format + )}" # ${addPlusSign( + NumberFormat(props.recommendedData[0]?.recommendation_engines?.cost?.variation?.limits?.memory?.amount) + )}${UnitFormat(props.recommendedData[0]?.recommendation_engines?.cost?.variation?.limits?.memory?.format)} cpu: "${NumberFormat( - props.recommendedData[0]?.recommendation_engines?.cost.config.limits.cpu.amount + props.recommendedData[0]?.recommendation_engines?.cost?.config?.limits?.cpu?.amount )}" # ${addPlusSign( - NumberFormat(props.recommendedData[0]?.recommendation_engines?.cost.variation.limits.cpu.amount) - )}`; + NumberFormat(props.recommendedData[0]?.recommendation_engines?.cost?.variation?.limits?.cpu?.amount) + )}`; return ( @@ -84,6 +87,8 @@ const CostDetails = (props: { recommendedData; currentData; chartData; day; endt + + {props.displayChart && } ); diff --git a/src/app/Analytics/SRE_Analytics/RecommendationComponents/CostHistoricCharts.tsx b/src/app/Analytics/SRE_Analytics/RecommendationComponents/CostHistoricCharts.tsx index cf4433c..236a762 100644 --- a/src/app/Analytics/SRE_Analytics/RecommendationComponents/CostHistoricCharts.tsx +++ b/src/app/Analytics/SRE_Analytics/RecommendationComponents/CostHistoricCharts.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useState } from 'react'; import { Chart, ChartAxis, ChartGroup, ChartLine, ChartVoronoiContainer } from '@patternfly/react-charts'; import { formatTimestamps, filterDataByTerm, formatNumber } from './ChartDataPreparation'; import { Grid, GridItem } from '@patternfly/react-core'; @@ -10,7 +10,7 @@ const CostHistoricCharts = (props: { chartData; day; endtime }) => { const cpuChart = () => { const historicdata = Object.entries(timeStampFormattedData).map(([key, value]) => { const cpuAmount = formatNumber( - (value as any).recommendation_terms[props.day]?.recommendation_engines?.cost?.config.requests.cpu.amount + (value as any).recommendation_terms[props.day]?.recommendation_engines?.cost?.config?.requests?.cpu?.amount ); const displayKey = props.day === 'short_term' ? key.split(' ')[1] : key.split(' ')[0]; return { @@ -22,6 +22,13 @@ const CostHistoricCharts = (props: { chartData; day; endtime }) => { const filteredhistoricdata = historicdata.filter((dataPoint) => typeof dataPoint.y === 'number'); + const uniqueData = filteredhistoricdata.reduce((acc, current) => { + const existing = acc.find(item => item.x === current.x && item.y === current.y); + if (!existing) { + acc.push(current); // If it doesn't exist, then add it + } + return acc; + }, []); return (
{ `${datum.name}: ${datum.y} : ${datum.x}`} constrainToVisibleArea + voronoiDimension="x" /> } legendData={[{ name: 'CPU' }]} @@ -57,7 +65,7 @@ const CostHistoricCharts = (props: { chartData; day; endtime }) => { fontSize: 12, margin: '50px 0', paddingTop: '10px' - } // Add margin to adjust distance + } }} /> { label="cores" tickFormat={(d) => formatNumber(d)} style={{ - axisLabel: { padding: 60 } // Adjust the value to control the padding + axisLabel: { padding: 60 } }} /> - +
@@ -80,7 +88,7 @@ const CostHistoricCharts = (props: { chartData; day; endtime }) => { const memoryChart = () => { const historicdata = Object.entries(timeStampFormattedData).map(([key, value]) => { const memoryAmount = formatNumber( - (value as any).recommendation_terms[props.day]?.recommendation_engines?.cost?.config.requests.memory.amount + (value as any).recommendation_terms[props.day]?.recommendation_engines?.cost?.config?.requests?.memory?.amount ); const displayKey = props.day === 'short_term' ? key.split(' ')[1] : key.split(' ')[0]; return { @@ -101,11 +109,12 @@ const CostHistoricCharts = (props: { chartData; day; endtime }) => { `${datum.name}: ${datum.y} : ${datum.x}`} constrainToVisibleArea + voronoiDimension="x" /> } + legendPosition="right" legendData={[{ name: 'Memory' }]} legendOrientation="vertical" - legendPosition="right" height={250} name="Cost Memory Recommendations" domainPadding={{ y: [30, 25], x: [30, 25] }} diff --git a/src/app/Analytics/SRE_Analytics/RecommendationComponents/PerfDetails.tsx b/src/app/Analytics/SRE_Analytics/RecommendationComponents/PerfDetails.tsx index 6704b6c..244a9b0 100644 --- a/src/app/Analytics/SRE_Analytics/RecommendationComponents/PerfDetails.tsx +++ b/src/app/Analytics/SRE_Analytics/RecommendationComponents/PerfDetails.tsx @@ -14,7 +14,7 @@ import ReusableCodeBlock from './ReusableCodeBlock'; import { PerfHistoricCharts } from './PerfHistoricCharts'; import { addPlusSign } from './ChartDataPreparation'; -const PerfDetails = (props: { recommendedData; currentData; chartData; day; endtime; displayChart }) => { +const PerfDetails = (props: { recommendedData; currentData; chartData; day; endtime; displayChart; boxPlotData }) => { //console.log(props.recommendedData[0]?.recommendation_engines.performance); const NumberFormat = (number) => typeof number === 'number' && !isNaN(number) ? (number % 1 !== 0 ? number.toFixed(3) : number) : ''; @@ -24,42 +24,42 @@ const PerfDetails = (props: { recommendedData; currentData; chartData; day; endt const current_code = `resources: requests: memory: "${NumberFormat(props.currentData[0]?.requests?.memory?.amount)}${UnitFormat( - props.currentData[0]?.requests?.memory?.format - )}" + props.currentData[0]?.requests?.memory?.format + )}" cpu: "${NumberFormat(props.currentData[0]?.requests?.cpu?.amount)}" limits: memory: "${NumberFormat(props.currentData[0]?.limits?.memory?.amount)}${UnitFormat( - props.currentData[0]?.limits?.memory?.format - )}" + props.currentData[0]?.limits?.memory?.format + )}" cpu: "${NumberFormat(props.currentData[0]?.limits?.cpu?.amount)}"`; const recommended_code = `resources: requests: memory: "${NumberFormat( - props.recommendedData[0]?.recommendation_engines?.performance?.config.requests.memory.amount + props.recommendedData[0]?.recommendation_engines?.performance?.config?.requests?.memory?.amount )}${UnitFormat( - props.recommendedData[0]?.recommendation_engines?.performance?.config.requests.memory.format - )}" # ${addPlusSign( - NumberFormat(props.recommendedData[0]?.recommendation_engines?.performance?.variation.requests.memory.amount) - )}${UnitFormat(props.recommendedData[0]?.recommendation_engines?.performance?.variation.requests.memory.format)} + props.recommendedData[0]?.recommendation_engines?.performance?.config?.requests?.memory?.format + )}" # ${addPlusSign( + NumberFormat(props.recommendedData[0]?.recommendation_engines?.performance?.variation?.requests?.memory?.amount) + )}${UnitFormat(props.recommendedData[0]?.recommendation_engines?.performance?.variation?.requests?.memory?.format)} cpu: "${NumberFormat( - props.recommendedData[0]?.recommendation_engines?.performance?.config.requests.cpu.amount + props.recommendedData[0]?.recommendation_engines?.performance?.config?.requests?.cpu?.amount )}" # ${addPlusSign( - NumberFormat(props.recommendedData[0]?.recommendation_engines?.performance?.variation.requests.cpu.amount) - )} + NumberFormat(props.recommendedData[0]?.recommendation_engines?.performance?.variation?.requests?.cpu?.amount) + )} limits: memory: "${NumberFormat( - props.recommendedData[0]?.recommendation_engines?.performance?.config.limits.memory.amount + props.recommendedData[0]?.recommendation_engines?.performance?.config?.limits?.memory?.amount )}${UnitFormat( - props.recommendedData[0]?.recommendation_engines?.performance?.config.limits.memory.format - )}" # ${addPlusSign( - NumberFormat(props.recommendedData[0]?.recommendation_engines?.performance?.variation.limits.memory.amount) - )}${UnitFormat(props.recommendedData[0]?.recommendation_engines?.performance?.variation.limits.memory.format)} + props.recommendedData[0]?.recommendation_engines?.performance?.config?.limits?.memory?.format + )}" # ${addPlusSign( + NumberFormat(props.recommendedData[0]?.recommendation_engines?.performance?.variation?.limits?.memory?.amount) + )}${UnitFormat(props.recommendedData[0]?.recommendation_engines?.performance?.variation?.limits?.memory?.format)} cpu: "${NumberFormat( - props.recommendedData[0]?.recommendation_engines?.performance?.config.limits.cpu.amount + props.recommendedData[0]?.recommendation_engines?.performance?.config?.limits?.cpu?.amount )}" # ${addPlusSign( - NumberFormat(props.recommendedData[0]?.recommendation_engines?.performance?.variation.limits.cpu.amount) - )}`; + NumberFormat(props.recommendedData[0]?.recommendation_engines?.performance?.variation?.limits?.cpu?.amount) + )}`; return ( diff --git a/src/app/Analytics/SRE_Analytics/RecommendationComponents/PerfHistoricCharts.tsx b/src/app/Analytics/SRE_Analytics/RecommendationComponents/PerfHistoricCharts.tsx index ed29af1..01c6492 100644 --- a/src/app/Analytics/SRE_Analytics/RecommendationComponents/PerfHistoricCharts.tsx +++ b/src/app/Analytics/SRE_Analytics/RecommendationComponents/PerfHistoricCharts.tsx @@ -10,7 +10,7 @@ const PerfHistoricCharts = (props: { chartData; day; endtime }) => { const cpuChart = () => { const historicdata = Object.entries(timeStampFormattedData).map(([key, value]) => { const cpuAmount = formatNumber( - (value as any).recommendation_terms[props.day]?.recommendation_engines?.performance?.config.requests.cpu.amount + (value as any).recommendation_terms[props.day]?.recommendation_engines?.performance?.config?.requests?.cpu?.amount ); const displayKey = props.day === 'short_term' ? key.split(' ')[1] : key.split(' ')[0]; return { @@ -80,8 +80,7 @@ const PerfHistoricCharts = (props: { chartData; day; endtime }) => { const memoryChart = () => { const historicdata = Object.entries(timeStampFormattedData).map(([key, value]) => { const memoryAmount = formatNumber( - (value as any).recommendation_terms[props.day]?.recommendation_engines?.performance?.config.requests.memory - .amount + (value as any).recommendation_terms[props.day]?.recommendation_engines?.performance?.config?.requests?.memory?.amount ); const displayKey = props.day === 'short_term' ? key.split(' ')[1] : key.split(' ')[0]; return { diff --git a/src/app/Analytics/SRE_Analytics/RecommendationComponents/TabSection.tsx b/src/app/Analytics/SRE_Analytics/RecommendationComponents/TabSection.tsx index fc9a688..93fa64c 100644 --- a/src/app/Analytics/SRE_Analytics/RecommendationComponents/TabSection.tsx +++ b/src/app/Analytics/SRE_Analytics/RecommendationComponents/TabSection.tsx @@ -3,7 +3,7 @@ import { Tabs, Tab, TabTitleText } from '@patternfly/react-core'; import { CostDetails } from './CostDetails'; import { PerfDetails } from './PerfDetails'; -const TabSection = (props: { recommendedData: any; currentData; chartData; day; endtime; displayChart }) => { +const TabSection = (props: { recommendedData: any; currentData; chartData; day; endtime; displayChart ; boxPlotData}) => { const [activeTabKey, setActiveTabKey] = React.useState(0); const handleTabClick = ( @@ -31,6 +31,7 @@ const TabSection = (props: { recommendedData: any; currentData; chartData; day; day={props.day} endtime={props.endtime} displayChart={props.displayChart} + boxPlotData={props.boxPlotData} /> Performance optimizations}> @@ -41,6 +42,8 @@ const TabSection = (props: { recommendedData: any; currentData; chartData; day; day={props.day} endtime={props.endtime} displayChart={props.displayChart} + boxPlotData={props.boxPlotData} + /> diff --git a/src/app/Analytics/SRE_Analytics/RecommendationTables.tsx b/src/app/Analytics/SRE_Analytics/RecommendationTables.tsx index 8c8bd5a..2c61718 100644 --- a/src/app/Analytics/SRE_Analytics/RecommendationTables.tsx +++ b/src/app/Analytics/SRE_Analytics/RecommendationTables.tsx @@ -12,7 +12,7 @@ import { StackItem } from '@patternfly/react-core'; import React, { useEffect, useState } from 'react'; -import { getRecommendationsURL, getRecommendationsURLWithParams } from '@app/CentralConfig'; +import { getRecommendationsURLWithParams } from '@app/CentralConfig'; import { TabSection } from './RecommendationComponents/TabSection'; import { WorkloadDetails } from './RecommendationComponents/WorkloadDetails'; @@ -29,6 +29,7 @@ const RecommendationTables = (props: { endTimeArray; setEndTimeArray; SREdata; s const [chartDetailsData, setChartDetailsData] = useState([]); const [day, setDay] = useState('short_term'); const [displayChart, setDisplayChart] = useState(true); + const [boxPlotTranslatedData, setBoxPlotTranslatedData] = useState([]); const days = [ { id: '1', value: 'short_term', label: 'Last 1 day', disabled: false }, @@ -36,6 +37,7 @@ const RecommendationTables = (props: { endTimeArray; setEndTimeArray; SREdata; s { id: '3', value: 'long_term', label: 'Last 15 days', disabled: false } ]; + useEffect(() => { if (props.endTimeArray) { setEndtime(props.endTimeArray[0]); @@ -49,8 +51,10 @@ const RecommendationTables = (props: { endTimeArray; setEndTimeArray; SREdata; s const result = await response.json(); const recommended_arr: any = []; const current_arr: any = []; + const boxPlot_arr: any = []; const chartDetailsObject = []; + // current data result[0].kubernetes_objects[0].containers.map((container, index) => { const currentDat = container.recommendations?.data[endtime]?.current; if (currentDat) { @@ -58,13 +62,23 @@ const RecommendationTables = (props: { endTimeArray; setEndTimeArray; SREdata; s } }); + // recommended data result[0].kubernetes_objects[0].containers.map((container, index) => { const recommendationDataNewAPI = container.recommendations.data[endtime]?.recommendation_terms[day]; + // const boxPlotsData = container.recommendations.data[endtime]?.recommendation_terms[day][0]?.plots?.plots_data; if (recommendationDataNewAPI) { recommended_arr.push(recommendationDataNewAPI); } }); + //box plot data + const boxPlotData = + result[0].kubernetes_objects[0].containers[0].recommendations.data[endtime]?.recommendation_terms[day]?.plots + ?.plots_data; + if (boxPlotData) { + boxPlot_arr.push(boxPlotData); + } + // all data before a particular time stamp result[0].kubernetes_objects[0].containers.map((container, index) => { const allRecommData = container.recommendations.data; @@ -95,7 +109,66 @@ const RecommendationTables = (props: { endTimeArray; setEndTimeArray; SREdata; s setCurrentData(current_arr); setRecommendedData(recommended_arr); setChartDetailsData(chartDetailsObject); + // setBoxPlotData(boxPlot_arr); + + const chartData = Object.keys(boxPlot_arr).map((key) => { + if (boxPlot_arr && boxPlot_arr[0]) { + const timestamps = Object.keys(boxPlot_arr[0]); + const cpuDetails = Object.values(boxPlot_arr[0]).map((key) => key.cpuUsage); + + return { + name: 'cpu', + x: timestamps, + y: cpuDetails + }; + } else return 0; + }); + + // console.log(chartData); + const transformedData = + chartData && + chartData.map((containerData) => { + const timestamps = containerData.x; + const yData = containerData.y.map((data) => [data.min, data.q1, data.median, data.q3, data.max]); + + return { + name: 'cpu', + x: timestamps, + y: yData + }; + }); + + // for box plots data points + + if (transformedData && transformedData.length > 0) { + const { name, x, y } = transformedData[0]; + + const translatedData = x.map((time, index) => ({ + name: name, + x: time, + y: y[index] + })); + setBoxPlotTranslatedData(translatedData); + } else { + console.log('currentData is empty or not structured as expected.'); + } + + // for the limits & request line data points + if (transformedData && transformedData.length > 0) { + const { name, x, y } = transformedData[0]; + + const translatedData = x.map((time, index) => ({ + name: name, + x: time, + y: recommended_arr[0]?.recommendation_engines?.cost?.config?.limits?.cpu.amount + })); + console.log(translatedData) + } else { + console.log('currentData is empty or not structured as expected.'); + } + } + }; fetchData(); @@ -108,7 +181,11 @@ const RecommendationTables = (props: { endTimeArray; setEndTimeArray; SREdata; s const onDayChange = (value: string) => { setDay(value); }; - + // if(transdata){ + // const timeStampFormattedData = formatTimestamps(transdata); + // console.log(timeStampFormattedData) + // } + return ( @@ -141,6 +218,7 @@ const RecommendationTables = (props: { endTimeArray; setEndTimeArray; SREdata; s value={endtime} onChange={(_event, value: string) => onChange(value)} aria-label="FormSelect Input" + style={{ width: '300px' }} > {props.endTimeArray && props.endTimeArray.map((option, index) => ( @@ -164,6 +242,7 @@ const RecommendationTables = (props: { endTimeArray; setEndTimeArray; SREdata; s value={day} onChange={(_event, value: string) => onDayChange(value)} aria-label="days dropdown" + style={{ width: '150px' }} > {days.map((selection, index) => ( @@ -181,6 +260,7 @@ const RecommendationTables = (props: { endTimeArray; setEndTimeArray; SREdata; s day={day} endtime={endtime} displayChart={displayChart} + boxPlotData={boxPlotTranslatedData} />