Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Box plots for cpu and cost with api integrations #161

Open
wants to merge 5 commits into
base: mvp_demo
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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<BoxPlotProps> = ({ 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 }) => (
<g>
<foreignObject height="100%" width="100%" x={x+60} y={y-50}>
<table>
<thead>
<tr>
<th colSpan={2} style={{ ...baseStyles, ...leftColumn, fontWeight: 700 }}>
{title(datum)}
</th>
</tr>
</thead>
<tbody>
<tr style={baseStyles}>
<td style={leftColumn}>Max</td>
<td style={rightColumn}>{datum._max}</td>
</tr>
<tr style={baseStyles}>
<td style={leftColumn}>Median</td>
<td style={rightColumn}>{datum._median}</td>
</tr>
<tr style={baseStyles}>
<td style={leftColumn}>Min</td>
<td style={rightColumn}>{datum._min}</td>
</tr>
<tr style={baseStyles}>
<td style={leftColumn}>Q1</td>
<td style={rightColumn}>{datum._q1}</td>
</tr>
<tr style={baseStyles}>
<td style={leftColumn}>Q3</td>
<td style={rightColumn}>{datum._q3}</td>
</tr>
</tbody>
</table>
</foreignObject>
</g>
);

return (
<div style={{ height: '300px', width: '600px' }}>
<Chart
ariaDesc={ariaDesc}
ariaTitle={chartTitle}
containerComponent={
<CursorVoronoiContainer
cursorDimension="x"
labels={({ datum }) => `${datum.y}`}
labelComponent={
<ChartCursorTooltip
flyout={<ChartCursorFlyout />}
flyoutHeight={145}
flyoutWidth={210}
labelComponent={<HtmlLegendContent title={(datum) => 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}
>
<ChartAxis />
<ChartAxis dependentAxis showGrid />
<ChartBoxPlot data={data} />
{/* <ChartLine
data={requestLimitsData}
name="limit"
style={{
data: {
stroke: chart_color_orange_300.var
}
}}
/> */}
</Chart>
</div>
);
};

export default BoxPlot;
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -41,22 +27,48 @@ 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) {
return `+${number}`;
}
}

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;
}
Original file line number Diff line number Diff line change
@@ -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 (
<Card>
<BoxPlot
data={props.boxPlotData}
requestLimitsData={props.limitRequestData}
chartTitle="CPU"
ariaDesc="CPU"
domain={{ y: [0.09, 0.1] }}
themeColor={ChartThemeColor.orange}
legendData={[{ name: 'CPU' }]}
/>

{/* <ChartThreshold
data={props.limitRequestData?.requests?.cpu.amount}
name="request"
style={{
data: {
stroke: chart_color_blue_300.var
}
}}
/> */}
{/* <BoxPlot
data={boxPlotData}
chartTitle="Cat Data Over Years"
ariaDesc="Detailed description for accessibility"
domain={{ y: [0, 12] }}
themeColor={ChartThemeColor.orange}
legendData={[{ name: 'Cats' }]}
/> * */}
</Card>
);
};

export { CostBoxPlotCharts };
Original file line number Diff line number Diff line change
Expand Up @@ -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) : '';
Expand All @@ -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 (
<PageSection variant={PageSectionVariants.light}>
Expand All @@ -84,6 +87,8 @@ const CostDetails = (props: { recommendedData; currentData; chartData; day; endt
</Card>
</GridItem>
</Grid>
<CostBoxPlotCharts boxPlotData={props.boxPlotData} limitRequestData={props.recommendedData[0]?.recommendation_engines?.cost?.config} />

{props.displayChart && <CostHistoricCharts chartData={props.chartData} day={props.day} endtime={props.endtime} />}
</PageSection>
);
Expand Down
Loading