Skip to content

Commit 3251fff

Browse files
committed
merged with latest devDockerv_2
2 parents 2191a39 + dbf493c commit 3251fff

File tree

41 files changed

+2112
-56
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+2112
-56
lines changed

app/charts/GrafanaEventChart.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ interface EventChartProps {
1212
// width: number;
1313
// }
1414

15-
type TimeFrame = '5m' | '15m' | '1h' | '2h' | '1d' | '2d' | '3d';
15+
type TimeFrame = '5m' | '15m' | '30m' | '1h' | '2h' | '1d' | '2d';
1616

1717

1818

@@ -84,11 +84,12 @@ const GrafanaEventChart: React.FC<EventChartProps> = React.memo(props => {
8484
<select name="graphType" id="graphType" onChange={(e) => setTimeFrame(e.target.value as TimeFrame)}>
8585
<option value={'5m'}>5 minutes</option>
8686
<option value={'15m'}>15 minutes</option>
87+
<option value={'30m'}>30 minutes</option>
8788
<option value={'1h'}>1 hour</option>
8889
<option value={'2h'}>2 hours</option>
8990
<option value={'1d'}>1 day</option>
9091
<option value={'2d'}>2 days</option>
91-
<option value={'3d'}>3 days</option>
92+
9293
</select>
9394
</div>
9495
{/* create chart using grafana iframe tag*/}
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
import React, { useEffect, useState, useContext } from 'react';
2+
import { HealthContext } from '../context/HealthContext';
3+
import { QueryContext } from '../context/QueryContext';
4+
import GrafanaEventChart from '../charts/GrafanaEventChart';
5+
import { Button } from '@material-ui/core';
6+
import { useParams } from 'react-router-dom';
7+
8+
interface HealthContainerProps {
9+
sizing: string;
10+
colourGenerator: Function;
11+
category: string;
12+
//currentService: string;
13+
}
14+
15+
interface Params {
16+
service: string;
17+
}
18+
19+
interface DataObject {
20+
[key: string]: {
21+
value: string[],
22+
time: string[],
23+
id: string,
24+
token: string
25+
};
26+
}
27+
interface DockerDataObject {
28+
[key: string]: DataObject
29+
}
30+
31+
const DockerHealthContainer: React.FC<HealthContainerProps> = React.memo(props => {
32+
const { healthData } = useContext(HealthContext);
33+
const { selectedMetrics } = useContext(QueryContext);
34+
const { service } = useParams<keyof Params>() as Params;
35+
const [healthChartsArr, setHealthChartsArr] = useState<JSX.Element[]>([]);
36+
const { sizing, colourGenerator, category } = props;
37+
const [currIndex, setCurrIndex] = useState(0);
38+
const [currChunk, setCurrChunk] = useState<JSX.Element[]>([]);
39+
const chunkSize = 7;
40+
let [isGrafana, setIsGrafana] = useState(false);
41+
/**
42+
* This function filters the selectedMetrics array down to only metrics that match the category of this instance of HealthContainer.
43+
* Once that has finished, it then filters the healthData down to the current category and the filteredMetrics.
44+
*/
45+
46+
function nextChunk() {
47+
const nextChunk = healthChartsArr.slice(currIndex, currIndex + chunkSize);
48+
setCurrChunk(nextChunk);
49+
setCurrIndex(currIndex + chunkSize);
50+
}
51+
function prevChunk() {
52+
const prevChunk = healthChartsArr.slice(currIndex - 2 * chunkSize, currIndex - chunkSize);
53+
setCurrChunk(prevChunk);
54+
setCurrIndex(currIndex - chunkSize);
55+
}
56+
57+
const filterSelectedMetricsAndHealthData = (): DockerDataObject => {
58+
// define a filtered health data object for output
59+
// define an array of filteredMetricNames for later use
60+
const filteredHealthData = {};
61+
const filteredMetricNames: string[] = [];
62+
// iterate over the selectedMetrics from QueryContext
63+
selectedMetrics.forEach(metricObj => {
64+
// due to the way the data is stored, each metricObj has a key of category, and an array of selected metrics as a value
65+
const metricCategory = Object.keys(metricObj)[0];
66+
const metricValuesArray = metricObj[metricCategory];
67+
// if the current metricObj's category matches our instance's current category, iterate through its array of values
68+
if (metricCategory === category) {
69+
metricValuesArray.forEach(metricName => {
70+
filteredMetricNames.push(metricName); // add the metricNames to the filteredMetricNames array
71+
});
72+
}
73+
});
74+
/*
75+
Now that we've defined which of the user's selected metrics belong in this category, iterate over the healthData object
76+
and filter it down to the selected category and metrics.
77+
*/
78+
for (const service in healthData) {
79+
filteredHealthData[service] = {};
80+
const categoryObjects = healthData[service];
81+
for (const categoryName in categoryObjects) {
82+
// if the category in healthData matches the category passed down to this HealthContainer, iterate over the related metrics
83+
if (categoryName === category) {
84+
const metricObjects = categoryObjects[categoryName];
85+
for (const metric in metricObjects) {
86+
// if the metric title matches any element in the filtered metrics array, add the metric serviceName to the filteredHealthData object, then add the metrics for that service
87+
if (filteredMetricNames.includes(metric)) {
88+
filteredHealthData[service][metric] = metricObjects[metric];
89+
}
90+
}
91+
}
92+
}
93+
}
94+
return filteredHealthData;
95+
};
96+
97+
// helper function for geting only the names of the metrics
98+
const getIndex = (str: string, substr: string, ind: number): number => {
99+
let Len = str.length,
100+
i = -1;
101+
while (ind-- && i++ < Len) {
102+
i = str.indexOf(substr, i);
103+
if (i < 0) break;
104+
}
105+
return i;
106+
}
107+
108+
// function to generate charts using the type-sorted data
109+
const generateHealthCharts = (sortedData: DockerDataObject): void => {
110+
//onst chartsArray: JSX.Element[] = [];
111+
const grafanaChartsArray: JSX.Element[] = [];
112+
//let parsedName: string = '';
113+
const keymaker = () => {
114+
return Math.floor(Math.random() * 1000);
115+
};
116+
// iterate over the sortedData and create a chart for each data type and each service of that data
117+
for (const dataType in sortedData) {
118+
const metricObjects = sortedData[service];
119+
for (const metricName in metricObjects) {
120+
// pass down the value of the current data type and service
121+
const chartData = metricObjects[metricName];
122+
const token = chartData.token;
123+
// chartsArray.push(
124+
// <HealthChart
125+
// key={'H' + keymaker()}
126+
// dataType={dataType}
127+
// serviceName={serviceName}
128+
// chartData={chartData}
129+
// categoryName={category}
130+
// sizing={sizing}
131+
// colourGenerator={colourGenerator}
132+
// />
133+
// );
134+
console.log("plotting grafana")
135+
grafanaChartsArray.push(
136+
<GrafanaEventChart metricName={metricName} token={token} />);
137+
138+
}
139+
}
140+
console.log(grafanaChartsArray)
141+
setHealthChartsArr(grafanaChartsArray);
142+
setCurrChunk(grafanaChartsArray.slice(currIndex, currIndex + chunkSize));
143+
setCurrIndex(currIndex + chunkSize);
144+
};
145+
146+
useEffect(() => {
147+
// returns an object containing only the healthData for the current category and the metrics the User selected
148+
const filteredHealthData = filterSelectedMetricsAndHealthData();
149+
// returns an object containing the filtered data sorted by data type
150+
//const typeSortedHealthData = healthDataGroupedByDataType(filteredHealthData);
151+
// invoking generateCharts with the sorted data will update healthChartsArr in state with the list of charts to be rendered
152+
generateHealthCharts(filteredHealthData);
153+
}, [category]);
154+
155+
// JJ-ADDITION
156+
return (
157+
<div>
158+
{/* <div id="grafana" onClick={() => { setIsGrafana(!isGrafana) }}>Grafana</div> */}
159+
{service.includes('kafkametrics') || service.includes('kubernetesmetrics') || service.includes('books') || service.includes('customers') || service.includes('frontend') || service.includes('orders')? currChunk : []}
160+
{healthChartsArr.length > chunkSize && (
161+
<>
162+
<Button id="prevCharts" onClick={prevChunk} variant="contained" color="primary" disabled={currIndex <= chunkSize}>
163+
Prev
164+
</Button>
165+
<Button id="nextCharts" onClick={nextChunk} variant="contained" color="primary" disabled={currIndex >= healthChartsArr.length}>
166+
Next
167+
</Button>
168+
</>
169+
)}
170+
</div>
171+
);
172+
});
173+
174+
export default DockerHealthContainer;

app/containers/EventContainer.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React, { useEffect, useState, useContext } from 'react';
22
import { useParams } from 'react-router-dom';
33
import { EventContext } from '../context/EventContext';
4+
import { HealthContext } from '../context/HealthContext';
45
import { QueryContext } from '../context/QueryContext';
56
import EventChart from '../charts/EventChart';
67
import { Button } from '@material-ui/core';
@@ -160,6 +161,7 @@ const EventContainer: React.FC<EventContainerProps> = React.memo(props => {
160161

161162
<div>
162163
{/* <div id="grafana" onClick={() => { setIsGrafana(!isGrafana) }}>Grafana</div> */}
164+
<button>Inspect</button>
163165
{service.includes('kafkametrics') || service.includes('kubernetesmetrics') ? currChunk : []}
164166
{eventChartsArr.length > chunkSize && (
165167
<>

app/containers/GraphsContainer.tsx

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,11 @@ import HealthContainer from './HealthContainer';
2020
import ModifyMetrics from './ModifyMetricsContainer';
2121
import * as DashboardContext from '../context/DashboardContext';
2222
import lightAndDark from '../components/Styling';
23+
import DockerHealthContainer from './DockerHealthContainer';
2324

2425
import '../stylesheets/GraphsContainer.scss';
26+
import { Link } from 'react-router-dom';
27+
import Inspect from './Inspect';
2528

2629
interface Params {
2730
app: any;
@@ -44,6 +47,7 @@ const GraphsContainer: React.FC = React.memo(props => {
4447
const [chart, setChart] = useState<string>('all');
4548
const [prevRoute, setPrevRoute] = useState<string>('');
4649
const { mode } = useContext(DashboardContext.DashboardContext);
50+
let [inspect, setInspect] = useState<boolean>(false);
4751

4852
useEffect(() => {
4953
const serviceArray = service.split(' ');
@@ -130,7 +134,14 @@ const GraphsContainer: React.FC = React.memo(props => {
130134
if (selectedMetrics) {
131135
selectedMetrics.forEach((element, id) => {
132136
const categoryName = Object.keys(element)[0];
133-
const prefix = categoryName === 'Event' ? 'event_' : 'health_';
137+
let prefix;
138+
if (categoryName === 'Event') {
139+
prefix = 'event_';
140+
} else if (categoryName === 'books' || categoryName === 'customers' || categoryName === 'frontend' || categoryName === 'orders'){
141+
prefix = 'docker_';
142+
} else {
143+
prefix = 'health_';
144+
}
134145
buttonList.push(
135146
<button
136147
id={`${prefix}${categoryName}-button`}
@@ -194,8 +205,21 @@ const GraphsContainer: React.FC = React.memo(props => {
194205
>
195206
Modify Metrics
196207
</button>
208+
{/* <Link className="sidebar-link" to="/Inspect" id="Inspect" >
209+
<SettingsIcon
210+
style={{
211+
WebkitBoxSizing: 'content-box',
212+
boxShadow: 'none',
213+
width: '35px',
214+
height: '35px',
215+
}}
216+
/>
217+
&emsp;Inspect
218+
</Link> */}
219+
<button onClick={() => { setInspect(!inspect) }}>Inspect</button>
197220
</nav>
198221
<Header app={app} service={service} live={live} setLive={setLive} />
222+
{inspect && <Inspect />}
199223
<div className="graphs-container">
200224
{chart === 'communications' ? (
201225
<div className="graphs">
@@ -226,6 +250,12 @@ const GraphsContainer: React.FC = React.memo(props => {
226250
<EventContainer colourGenerator={stringToColour} sizing="solo" />
227251
</>
228252

253+
)}
254+
{chart.startsWith('docker_') && (
255+
<>
256+
<DockerHealthContainer colourGenerator={stringToColour} sizing="solo" category={chart.substring(7)} />
257+
</>
258+
229259
)}
230260
{chart === 'docker' && <DockerChart />}
231261
{chart === 'modifyMetrics' && <ModifyMetrics />}

0 commit comments

Comments
 (0)