Skip to content

Commit 057b304

Browse files
timlee12xueappRobertoRueMelonitaylrzhang
committed
created ecs graph component w/ rendered graphs
Co-authored-by: Snow X. Bai <[email protected]> Co-authored-by: Roberto Meloni <[email protected]> Co-authored-by: Taylor Zhang <[email protected]>
1 parent 78e9c3f commit 057b304

File tree

5 files changed

+118
-59
lines changed

5 files changed

+118
-59
lines changed
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import React, { useContext, useEffect } from 'react';
2+
import AwsChart from '../charts/AwsChart';
3+
import { AwsContext } from '../context/AwsContext';
4+
5+
const AwsECSClusterGraphs: React.FC = React.memo(props => {
6+
const { awsEcsData, setAwsEcsData } = useContext(AwsContext);
7+
8+
useEffect(() => {
9+
return () => {
10+
setAwsEcsData({})
11+
};
12+
}, [])
13+
14+
const stringToColor = (string: string, recurses = 0) => {
15+
if (recurses > 20) return string;
16+
function hashString(str: string) {
17+
let hash = 0;
18+
for (let i = 0; i < str.length; i++) {
19+
hash = str.charCodeAt(i) + ((hash << 5) - hash);
20+
}
21+
let colour = '#';
22+
for (let i = 0; i < 3; i++) {
23+
const value = (hash >> (i * 8)) & 0xff;
24+
colour += `00${value.toString(16)}`.substring(-2);
25+
}
26+
27+
console.log(colour);
28+
return colour;
29+
}
30+
};
31+
32+
const activeServices = Object.keys(awsEcsData).slice(1).filter(el => awsEcsData[el].CPUUtilization?.value.length > 0)
33+
const serviceGraphs = activeServices.map(service => {
34+
return (
35+
<div className='ecsCharts'>
36+
<div id='service-name'>
37+
<p>Service Name:</p>
38+
<p>{service}</p>
39+
</div>
40+
<AwsChart
41+
className='chart'
42+
renderService='CPU Utilization'
43+
metric='Percent'
44+
timeList={awsEcsData[service]?.CPUUtilization.time}
45+
valueList={awsEcsData[service]?.CPUUtilization.value}
46+
colourGenerator={stringToColor}
47+
/>
48+
<AwsChart
49+
className='chart'
50+
renderService='Memory Utilization'
51+
metric='Percent'
52+
timeList={awsEcsData[service]?.MemoryUtilization.time}
53+
valueList={awsEcsData[service]?.MemoryUtilization.value}
54+
colourGenerator={stringToColor}
55+
/>
56+
</div>
57+
)
58+
});
59+
60+
return (
61+
<div>
62+
{serviceGraphs}
63+
</div>
64+
);
65+
});
66+
67+
export default AwsECSClusterGraphs;

app/components/ClusterTable.tsx

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,15 @@ export interface ClusterTableProps {
4141

4242
const ClusterTable: React.FC<ClusterTableProps> = React.memo(({ region }) => {
4343
const classes = useStyles();
44-
const { awsEcsData } = useContext(AwsContext);
44+
const { awsEcsData, isLoading } = useContext(AwsContext);
4545
// const {clusterName, servicesNum, tasksNum, status} = useContext(DashboardContext);
4646

47+
const activeServices = () => {
48+
const serviceNames = Object.keys(awsEcsData).slice(1);
49+
50+
return serviceNames.filter(el => awsEcsData[el].CPUUtilization?.value.length > 0)
51+
};
52+
4753
return (
4854
<div className="ClusterTable-container">
4955
<TableContainer component={Paper}>
@@ -59,16 +65,16 @@ const ClusterTable: React.FC<ClusterTableProps> = React.memo(({ region }) => {
5965
<TableBody>
6066
<TableCell className={classes.body}>
6167
<div className={classes.column}>
62-
<div>{awsEcsData ? awsEcsData.clusterInfo?.clusterName : 'Loading...'}</div>
68+
<div>{isLoading ? 'Loading...': awsEcsData.clusterInfo?.clusterName}</div>
6369
<div>
6470
<span className="region">{region}</span>
6571
</div>
6672
</div>
6773
</TableCell>
6874
{/* <TableCell className={cluster.status === 'active' ? classes.activeCell : undefined}>testactive</TableCell> */}
69-
<TableCell className={classes.body}>active</TableCell>
70-
<TableCell className={classes.body}>3</TableCell>
71-
<TableCell className={classes.body}>0/3</TableCell>
75+
<TableCell className={classes.body}>{activeServices().length ? 'active' : 'inactive'}</TableCell>
76+
<TableCell className={classes.body}>{isLoading ? 'Loading...' : Object.keys(awsEcsData).length - 1}</TableCell>
77+
<TableCell className={classes.body}>{String(activeServices().length) + '/' + String(Object.keys(awsEcsData).length - 1)}</TableCell>
7278

7379
{/* {clusters.map((cluster: Cluster, index: number) => (
7480
<TableRow key={index}>

app/containers/AWSGraphsContainer.tsx

Lines changed: 20 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,19 @@ import { AwsContext } from '../context/AwsContext';
88
import '../stylesheets/AWSGraphsContainer.scss';
99
import AwsChart from '../charts/AwsChart';
1010
import ClusterTable from '../components/ClusterTable';
11+
import AwsEC2Graphs from '../components/AwsEC2Graphs';
12+
import AwsECSClusterGraphs from '../components/AwsECSClusterGraphs';
13+
import { useLocation } from 'react-router-dom';
1114

1215
const AwsGraphsContainer: React.FC = React.memo(props => {
13-
const { awsData, setAwsData, awsAppInfo, fetchAwsData, fetchAwsEcsData, fetchAwsAppInfo } = useContext(AwsContext);
16+
const { awsData, setAwsData, awsAppInfo, setAwsAppInfo, awsEcsData, setAwsEcsData, fetchAwsData, fetchAwsEcsData, fetchAwsAppInfo } = useContext(AwsContext);
1417
const { app, appIndex, intervalID, setIntervalID } = useContext(ApplicationContext);
1518
const { user } = useContext(DashboardContext);
1619
// const [intervalID, setintervalID] = useState<NodeJS.Timeout | null>(null);
1720
const [awsLive, setAwsLive] = useState<boolean>(false);
18-
const { typeOfService, region } = awsAppInfo;
21+
const { region } = awsAppInfo;
22+
const { state } = useLocation();
23+
const { typeOfService } = state;
1924

2025
useEffect(() => {
2126
if (awsLive) {
@@ -24,17 +29,17 @@ const AwsGraphsContainer: React.FC = React.memo(props => {
2429
setIntervalID(
2530
setInterval(() => {
2631
console.log('intervalId after click live', intervalID);
27-
fetchAwsData(user, appIndex);
2832
fetchAwsAppInfo(user, appIndex);
29-
fetchAwsEcsData(user, appIndex);
33+
34+
typeOfService === 'AWS/EC2' ? fetchAwsData(user, appIndex) : fetchAwsEcsData(user, appIndex);
3035
}, 2000)
3136
)
3237
} else {
3338
console.log('not fetching data')
3439
if(intervalID) clearInterval(intervalID);
35-
fetchAwsData(user, appIndex);
3640
fetchAwsAppInfo(user, appIndex);
37-
fetchAwsEcsData(user, appIndex);
41+
42+
typeOfService === 'AWS/EC2' ? fetchAwsData(user, appIndex) : fetchAwsEcsData(user, appIndex);
3843
}
3944
}, [awsLive]);
4045

@@ -44,6 +49,8 @@ const AwsGraphsContainer: React.FC = React.memo(props => {
4449

4550
if(intervalID) clearInterval(intervalID);
4651
setAwsData({ CPUUtilization: [], NetworkIn: [], NetworkOut: [], DiskReadBytes: [] })
52+
setAwsEcsData({});
53+
setAwsAppInfo({ typeOfService: '', region: '' });
4754
}
4855
}, [])
4956

@@ -84,53 +91,14 @@ const AwsGraphsContainer: React.FC = React.memo(props => {
8491
)}
8592
</button>
8693
</div>
87-
<div className="cluster-table">
88-
{awsAppInfo.typeOfService === 'AWS/ECS' && (
94+
{typeOfService === 'AWS/ECS' ? (
95+
<div className="cluster-table">
8996
<ClusterTable typeOfService={typeOfService} region={region} />
90-
)}
91-
</div>
92-
<div className="charts">
93-
<AwsChart
94-
className='chart'
95-
// key={`Chart${counter}`}
96-
renderService="CPU Utilization"
97-
metric="Percent"
98-
timeList={awsData.CPUUtilization?.map(el => el.time)}
99-
valueList={awsData.CPUUtilization?.map(el => el.value)}
100-
// sizing={props.sizing}
101-
colourGenerator={stringToColor}
102-
/>
103-
<AwsChart
104-
className='chart'
105-
// key={`Chart${counter}`}
106-
renderService="Network In"
107-
metric="Percent"
108-
timeList={awsData.NetworkIn?.map(el => el.time)}
109-
valueList={awsData.NetworkIn?.map(el => el.value)}
110-
// sizing={props.sizing}
111-
colourGenerator={stringToColor}
112-
/>
113-
<AwsChart
114-
className='chart'
115-
// key={`Chart${counter}`}
116-
renderService="Network Out"
117-
metric="Percent"
118-
timeList={awsData.NetworkOut?.map(el => el.time)}
119-
valueList={awsData.NetworkOut?.map(el => el.value)}
120-
// sizing={props.sizing}
121-
colourGenerator={stringToColor}
122-
/>
123-
<AwsChart
124-
className='chart'
125-
// key={`Chart${counter}`}
126-
renderService="DiskReadBytes"
127-
metric="Percent"
128-
timeList={awsData.DiskReadBytes?.map(el => el.time)}
129-
valueList={awsData.DiskReadBytes?.map(el => el.value)}
130-
// sizing={props.sizing}
131-
colourGenerator={stringToColor}
132-
/>
133-
</div>
97+
<AwsECSClusterGraphs />
98+
</div>
99+
) : (
100+
<AwsEC2Graphs />
101+
)}
134102
</div>
135103
);
136104
// }

app/context/AwsContext.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ const AwsContextProvider: React.FC<Props> = React.memo(({ children }) => {
2626
const [awsData, setAwsData] = useState<AwsData>({ CPUUtilization: [], NetworkIn: [], NetworkOut: [], DiskReadBytes: [] })
2727
const [awsEcsData, setAwsEcsData] = useState<any>({});
2828
const [awsAppInfo, setAwsAppInfo] = useState<AwsAppInfo>({ typeOfService: '', region: '' });
29+
const [isLoading, setLoadingState] = useState<boolean>(true);
2930

3031
const fetchAwsData = (username: string, index: number) => {
3132
ipcRenderer.removeAllListeners('ec2MetricsResponse');
@@ -34,25 +35,29 @@ const AwsContextProvider: React.FC<Props> = React.memo(({ children }) => {
3435
ipcRenderer.on('ec2MetricsResponse', (event: Electron.Event, res: any) => {
3536
const data = JSON.parse(res);
3637
console.log('ec2 data fetched from AWS context is: ', data);
37-
38+
3839
setAwsData(data);
40+
setLoadingState(false);
3941
})
4042
};
4143

4244
const fetchAwsEcsData = (username: string, index: number) => {
4345
ipcRenderer.removeAllListeners('ecsMetricsResponse');
46+
setLoadingState(true);
4447

4548
ipcRenderer.send('ecsMetricsRequest', username, index);
4649
ipcRenderer.on('ecsMetricsResponse', (event: Electron.Event, res: any) => {
4750
const data = JSON.parse(res);
4851
console.log('ecs data fetched from AWS context is: ', data);
4952

5053
setAwsEcsData(data);
54+
setLoadingState(false);
5155
});
5256
};
5357

5458
const fetchAwsAppInfo = (username: string, index: number) => {
5559
ipcRenderer.removeAllListeners('awsAppInfoResponse');
60+
setLoadingState(true);
5661

5762
ipcRenderer.send('awsAppInfoRequest', username, index);
5863
ipcRenderer.on('awsAppInfoResponse', (event: Electron.Event, res: any) => {
@@ -65,7 +70,7 @@ const AwsContextProvider: React.FC<Props> = React.memo(({ children }) => {
6570

6671
return (
6772
<AwsContext.Provider
68-
value={{ fetchAwsData, awsData, setAwsData, fetchAwsEcsData, awsEcsData, setAwsEcsData, awsAppInfo, setAwsAppInfo, fetchAwsAppInfo}}
73+
value={{ fetchAwsData, awsData, setAwsData, fetchAwsEcsData, awsEcsData, setAwsEcsData, awsAppInfo, setAwsAppInfo, fetchAwsAppInfo, isLoading}}
6974
>
7075
{children}
7176
</AwsContext.Provider>

app/stylesheets/AWSGraphsContainer.scss

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,19 @@
44
margin-top: 40px;
55
}
66

7+
.ecsCharts {
8+
display: grid;
9+
grid-template-columns: auto auto auto;
10+
padding: 10px;
11+
12+
#service-name {
13+
display: flex;
14+
flex-direction: column;
15+
justify-content: center;
16+
align-items: center;
17+
}
18+
}
19+
720
.charts {
821
display: grid;
922
grid-template-columns: auto auto;

0 commit comments

Comments
 (0)