Skip to content

Commit 9012561

Browse files
committed
Charts now display related data types in a single graph.
Cleaned up healthData to be nested object for consistent data structure.
1 parent e89e238 commit 9012561

File tree

8 files changed

+229
-182
lines changed

8 files changed

+229
-182
lines changed

app/charts/HealthChart.tsx

Lines changed: 63 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,17 @@ import { all, solo as soloStyle } from './sizeSwitch';
55

66
interface HealthChartProps {
77
key: string;
8-
serviceName: string;
9-
// metric: string;
8+
dataType: string;
9+
chartData: object;
1010
categoryName: string;
11-
metrics: any[];
12-
timeList: any[];
13-
// valueList: any;
1411
sizing: string;
1512
colourGenerator: Function;
1613
}
17-
1814
interface SoloStyles {
1915
height: number;
2016
width: number;
2117
}
22-
23-
type plotlyData = {
18+
type PlotlyData = {
2419
name: string;
2520
x: string[];
2621
y: string[];
@@ -30,40 +25,62 @@ type plotlyData = {
3025
};
3126

3227
const HealthChart: React.FC<HealthChartProps> = React.memo(props => {
33-
// 'metrics' is an array of the user-specified metrics as objects => 'metric name': [metric values]
34-
const { serviceName, categoryName, metrics, timeList, sizing, colourGenerator } = props;
28+
const { dataType, chartData, categoryName, sizing, colourGenerator } = props;
3529
const [solo, setSolo] = useState<SoloStyles | null>(null);
36-
const timeArr = timeList.map((el: any) => moment(el).format('kk:mm:ss'));
37-
const reverseTimeArr = timeArr.reverse();
38-
const re = /_/g;
3930

40-
// this array gets populated once generatePlotlyDataObjects is invoked in `createChart`
41-
const plotlyDataObjectArray: plotlyData[] = [];
42-
// generates an array plotly data objects to add to be passed into our plotly chart's data prop
43-
const generatePlotlyDataObjects = (metricsArray, timeArray) => {
44-
console.log('metricsArray: ', metricsArray);
45-
console.log('timeArray: ', timeArray);
46-
// iterate through the metricsArray
47-
// each element is an array of num data (y-axis)
48-
metricsArray.forEach(el => {
49-
const originalMetricName = Object.keys(el)[0];
50-
const prettyMetricName = originalMetricName.replace(re, ' ');
51-
const newColor = colourGenerator(serviceName);
52-
console.log('prettyMetricName ', prettyMetricName);
53-
// plotly's data prop takes an array of objects that each have x, y, type, mode, marker
54-
const dataObject: plotlyData = {
55-
name: prettyMetricName,
56-
x: timeArray,
57-
y: el[originalMetricName],
58-
type: 'scattergl',
59-
mode: 'lines',
60-
marker: {
61-
colors: ['#fc4039', '#4b54ea', '#32b44f', '#3788fc', '#9c27b0', '#febc2c'],
62-
},
63-
};
64-
plotlyDataObjectArray.push(dataObject);
65-
});
66-
console.log('plotlydataObjectarray: ', plotlyDataObjectArray);
31+
// makes time data human-readable, and reverses it so it shows up correctly in the graph
32+
const prettierTimeInReverse = (timeArray: string[]): string[] => {
33+
return timeArray.map((el: any) => moment(el).format('kk:mm:ss')).reverse();
34+
};
35+
36+
// removes underscores from metric names to improve their look in the graph
37+
const prettyMetricName = metricName => {
38+
return metricName.replaceAll('_', ' ');
39+
};
40+
41+
// pulls the current service names to be shown in the graph title from chartData
42+
const serviceNamesAsString = (chartData: object): string => {
43+
let serviceNameString = '';
44+
for (const serviceName in chartData) {
45+
serviceNameString += `${serviceName} | `;
46+
}
47+
return serviceNameString;
48+
};
49+
50+
// generates an array of plotly data objects to be passed into our plotly chart's data prop
51+
const generatePlotlyDataObjects = (chartData: object): object[] => {
52+
const arrayOfPlotlyDataObjects: PlotlyData[] = [];
53+
// iterate through the chartData
54+
for (const serviceName in chartData) {
55+
// define the metrics for this service
56+
const metrics = chartData[serviceName];
57+
// loop through the list of metrics for the current service
58+
for (const metricName of metrics) {
59+
// define the value and time arrays
60+
const dataArray = metrics[metricName].value;
61+
const timeArray = metrics[metricName].time;
62+
// specifically for `Megabyte` types, convert the data of bytes into a value of megabytes before graphing
63+
if (dataType === 'Memory in Megabytes' || 'Cache in Megabytes') {
64+
dataArray.map(value => (value / 1000000).toFixed(2));
65+
}
66+
// create the plotly object
67+
const plotlyDataObject: PlotlyData = {
68+
name: prettyMetricName(metricName),
69+
x: prettierTimeInReverse(timeArray),
70+
y: dataArray,
71+
type: 'scattergl',
72+
mode: 'lines',
73+
marker: {
74+
colors: ['#fc4039', '#4b54ea', '#32b44f', '#3788fc', '#9c27b0', '#febc2c'],
75+
},
76+
};
77+
// push the dataObject into the arrayOfPlotlyDataObjects
78+
arrayOfPlotlyDataObjects.push(plotlyDataObject);
79+
}
80+
}
81+
// return the array of plotlyDataObject
82+
console.log('plotlyObjectArray: ', arrayOfPlotlyDataObjects);
83+
return arrayOfPlotlyDataObjects;
6784
};
6885

6986
setInterval(() => {
@@ -73,15 +90,16 @@ const HealthChart: React.FC<HealthChartProps> = React.memo(props => {
7390
}, 20);
7491

7592
const createChart = () => {
76-
generatePlotlyDataObjects(metrics, reverseTimeArr);
93+
const dataArray = generatePlotlyDataObjects(chartData);
94+
const serviceNames = serviceNamesAsString(chartData);
7795
const sizeSwitch = sizing === 'all' ? all : solo;
7896

7997
return (
8098
<Plot
81-
data={plotlyDataObjectArray}
99+
data={dataArray}
82100
config={{ displayModeBar: true }}
83101
layout={{
84-
title: `${serviceName} | ${categoryName}`,
102+
title: `${serviceNames}| ${categoryName}`,
85103
...sizeSwitch,
86104
font: {
87105
color: '#444d56',
@@ -92,10 +110,7 @@ const HealthChart: React.FC<HealthChartProps> = React.memo(props => {
92110
plot_bgcolor: 'white',
93111
showlegend: true,
94112
legend: {
95-
orientation: 'h',
96-
xanchor: 'center',
97-
x: 0.5,
98-
y: 5,
113+
orientation: 'v',
99114
},
100115
xaxis: {
101116
title: 'Time',
@@ -109,8 +124,7 @@ const HealthChart: React.FC<HealthChartProps> = React.memo(props => {
109124
},
110125
yaxis: {
111126
rangemode: 'nonnegative',
112-
//! change this later :^)
113-
title: 'Value',
127+
title: `${dataType}`,
114128
},
115129
}}
116130
/>

app/components/TransferColumns.tsx

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@ const TransferColumns = React.memo(() => {
3232

3333
const currentMode = mode === 'light' ? lightAndDark.lightModeText : lightAndDark.darkModeText;
3434

35+
console.log('healthMetrics: ', healthMetrics);
36+
console.log('metricsPool: ', metricsPool);
37+
console.log('targetKeys: ', targetKeys);
38+
console.log('eventData: ', eventData);
39+
console.log('eventDataList: ', eventDataList);
40+
3541
useEffect(() => {
3642
if (healthDataObject) {
3743
setHealthMetricsReady(true);
@@ -87,6 +93,7 @@ const TransferColumns = React.memo(() => {
8793
}
8894
}, [service, eventData, healthData]);
8995

96+
// responsible for parsing data and updating state via setMetricsPool
9097
const getMetrics = (type, datalist) => {
9198
let pool: any[] = [];
9299
if (type === 'event') {
@@ -100,25 +107,33 @@ const TransferColumns = React.memo(() => {
100107
pool.push(temp);
101108
});
102109
} else {
103-
datalist.forEach(category => {
104-
const tag: string = Object.keys(category)[0];
105-
const serviceObj: {} = category[tag][0];
106-
const valuesOfServiceObj: any[] = Object.values(serviceObj);
107-
const metricsArr: any[] = valuesOfServiceObj[0];
108-
metricsArr.forEach(element => {
109-
const temp = {};
110-
const metricName: string = Object.keys(element)[0];
111-
const key = tag + ' | ' + metricName;
112-
temp['key'] = key;
113-
temp['title'] = key;
114-
temp['tag'] = tag;
115-
pool.push(temp);
116-
});
117-
});
110+
// iterate throught the healthData object to populate the `Metrics Query` tab with metrics options
111+
// The pool array wants an object with a specific format in order to populate the selection table
112+
for (const service in healthData) {
113+
const categoryObjects = healthData[service];
114+
for (const category in categoryObjects) {
115+
const metricsObjects = categoryObjects[category];
116+
for (const metric in metricsObjects) {
117+
const key = category + ' | ' + metric;
118+
pool.push({
119+
key: key,
120+
title: key,
121+
tag: category,
122+
});
123+
}
124+
}
125+
}
118126
}
119127
return pool;
120128
};
121129

130+
// Justin's alternative to getCharts (b/c getCharts is just saving the user-selected metrics into QueryContext)
131+
// getCharts takes data that already exists in state as an array of strings, and makes it into an array of objects, just to save it to QueryContext state
132+
// the selectedMetrics from QueryContext is used in TransferColumns, EventContainer, GraphsContainer, and HealthContainer
133+
// const saveSelectedMetrics = () => {
134+
// // iterate over the targetKeys array
135+
// }
136+
122137
const getCharts = () => {
123138
const temp: any[] = [];
124139
const categorySet = new Set();
@@ -146,6 +161,7 @@ const TransferColumns = React.memo(() => {
146161
setSelectedMetrics(temp);
147162
};
148163

164+
// makes the column titles for the selection grid
149165
const columns = [
150166
{ field: 'id', headerName: 'ID', width: 100 },
151167
{
@@ -162,8 +178,8 @@ const TransferColumns = React.memo(() => {
162178
},
163179
];
164180

181+
// makes the rows needed for the selection grid
165182
const rows: any[] = [];
166-
167183
metricsPool.forEach((el, index) => {
168184
const row = {};
169185
row['id'] = index;
@@ -172,8 +188,8 @@ const TransferColumns = React.memo(() => {
172188
rows.push(row);
173189
});
174190

191+
// makes the Printed list of 'currently selected rows' on the page using targetKeys array
175192
const selectedRows: any[] = [];
176-
177193
targetKeys.forEach(el => {
178194
selectedRows.push(
179195
<li style={{ marginLeft: '30px', marginTop: '5px', color: currentMode.color }}>{el}</li>

app/containers/GraphsContainer.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ const GraphsContainer: React.FC = React.memo(props => {
9191

9292
return () => {
9393
if (intervalID) clearInterval(intervalID);
94-
setHealthData({ healthDataList: [], healthTimeList: [] });
94+
setHealthData({});
9595
setDockerData({});
9696
setEventData({ eventDataList: [], eventTimeList: [] });
9797
};
@@ -156,9 +156,9 @@ const GraphsContainer: React.FC = React.memo(props => {
156156
};
157157

158158
const HealthAndEventButtons: JSX.Element[] = getHealthAndEventComponents();
159-
console.log('selected metrics: ', {GraphsContainer: selectedMetrics})
160-
console.log('chart: ', { GraphsContainer: chart });
161-
159+
console.log('selected metrics: ', selectedMetrics);
160+
console.log('chart: ', chart);
161+
162162
return (
163163
<>
164164
<nav id="navigationBar">

0 commit comments

Comments
 (0)