Skip to content

Commit 08274be

Browse files
committed
Merge branch 'chris/fe-health-info' of https://github.com/Chronos2-0/Chronos into chris/fe-health-info
2 parents 9dd6cb4 + a696b8f commit 08274be

5 files changed

Lines changed: 267 additions & 61 deletions

File tree

README.md

Lines changed: 74 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,88 @@
1-
##Chronos Microservice Debugger
2-
Chronos Microservice Debugger consists of an npm package with an optional Electron front end to visualize and monitor your microservices.
1+
# Chronos
2+
Chronos consists of an NPM package to be required into a user’s microservices that intercepts all http and gRPC microservice communications, as well as monitors the health of each microservice over time. This information is written to a user-owned database (PostgreSQL or NoSQL) where it is queried and rendered by the frontend utilizing Node in conjunction with a native, cross-platform Electron desktop application with React components to ensure agreement between the frontend and database.
33

4-
## Install
4+
## Why was Chronos created?
5+
As companies grow larger and begin to scale, they have a tendency to move from a monolithic code architecture and microservices and distributed systems architecture in order to build faster, more maintainable code.
6+
7+
The process of modularizing a code bases and breaking a monolith into individual services can be a daunting task. How do you break apart and re-connect these services? There is often a transitional period where valuable time is spent debugging these connections between services.
8+
9+
Chronos is deigned to meet the needs of companies and developers working to break down their monoliths into distributed systems by combining an NPM package together with an Electron application to monitor and assist in the debugging of their services.
10+
11+
## How to Install Chronos
12+
The Chronos-Microservice-Debugger Express Middleware can be found on npm: https://www.npmjs.com/package/chronos-microservice-debugger
13+
14+
To install the NPM package:
515
```javascript
616
npm install chronos-microservice-debugger
717
```
818

9-
## Usage
19+
The Chronos Electron application is in progress and will soon be availble for public download for all platforms. Please stay tuned.
20+
21+
## How to Use Chronos
1022
There are two main aspects to Chronos-Microservice-Debugger
11-
*Communication Monitor: Listens in on all microservice-microservice and microservice-client communication and monitors the response statuses and messages to ensure communications are making it to the correct destination successfully.
12-
*Health Monitor: The health monitor checks the status of your microservice every second and sends this health information to an optional electron frontend where it is visualized for easier use.
23+
1. Communication Monitor: Listens in on all microservice-microservice and microservice-client communication and monitors the response statuses and messages to ensure communications are making it to the correct destination successfully.
24+
2. Health Monitor: The health monitor checks the status of your microservice every second and sends this health information to an optional electron frontend where it is visualized for easier use.
25+
26+
To use the npm package, there are three required parameters and an optional fourth parameter. You can enter the items as individual strings or as an array containing the three required parameters and one optional parameter.
1327

28+
The parameters are:
29+
1. microserviceName: What do you want to name the current microservice
30+
2. databaseType: We currently support PostgreSQL and Mongo. Enter "mongo" or "sql"
31+
3. databaseURL: Where would you like to store your information? Enter the URL to your database
32+
4. queryFrequency: How often do you want microHealth to monitor the health of your database? It defaults to every second, but you can choose:
33+
* "s" : The default, monitors every second
34+
* "m" : Monitors every minute
35+
* "h" : Monitors every hour
36+
* "d" : Monitors once per day
37+
* "w" : Monitors once per week
1438

39+
String parameter example:
1540
```javascript
16-
app.use('/', chronos-microservice-debugger.microCom('microserviceName', 'databaseType', 'databaseURL'))
17-
chronos-microservice-debugger.microHealth('microserviceName', databaseType, databaseURL))
41+
// How to use chronos-microservice-debugger
42+
app.use('/', chronos-microservice-debgugger.microCom('microserviceName', 'databaseType', 'databaseURL'))
43+
44+
chronos-microservice-debugger.microHealth('microserviceName', 'databaseType', 'databaseURL', 'queryFrequency'))
45+
46+
// Example using string parameters
47+
app.use('/', chronos-microservice-debugger.microCom('books', 'sql', 'thisIsMyURL'))
48+
// Note: microCom does not utilize queryFreq because it logs all communication when an endpoint is hit
49+
50+
chronos-microservice-debugger.microHealth('books', 'sql', 'thisIsMyURL', 'h')
1851
```
19-
Chronos uses a user-owned and provided database to ensure that your private data stays private. We currently support MongoDB and SQL/PostgreSQL databases.
2052

21-
## Things in the Works
22-
*gRPC support
23-
*Ability to determine how often your microservice health is monitored (currently every second)
24-
*'Time Travel' to see how your microservices have changed over time
25-
*Docker health information for containerized microservices
26-
*Implement additional unit testing
53+
Array parameter example:
54+
```javascript
55+
let values = [
56+
'microserviceName',
57+
'databaseType',
58+
'databaseURL',
59+
'queryFrequency'
60+
]
61+
// How to use chronos-micrservice-debugger with an array parameter
62+
app.use('/', chronos-microservice-debgugger.microCom(values)
63+
64+
chronos-microservice-debugger.microHealth(values)
65+
66+
// Example using an array parameter
67+
let values = [
68+
'books',
69+
'mongo',
70+
'thisIsMyNewURL',
71+
'w'
72+
]
2773

28-
## Links
29-
*Chronos Website: http://chronos.ninja
30-
*Gitub Page: https://github.com/oslabs-beta/Chronos
74+
app.use('/', chronos-microservice-debgugger.microCom(values)
75+
// Note: microCom does not utilize queryFreq because it logs all communication when an endpoint is hit
76+
77+
chronos-microservice-debugger.microHealth(values)
78+
79+
```
3180
32-
## Contact Us
33-
For questions, requests, or more information, please contact us at teammicronos@gmail.com
81+
## How to Contribute to Chronos
82+
Chronos hopes to inspire an active community of both users and developers. For questions, comments, suggestions, please contact us at teammicronos@gmail.com or submit a pull request.
3483
84+
## Created By
85+
* Duane McFarlane
86+
* Michelle Herrera
87+
* Mohtasim Chowdhury
88+
* Natalie Umanzor

app/components/Modal.jsx

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import React from 'react';
2+
import RequestTypesChart from '../charts/request-type-chart.jsx';
3+
import ResponseCodesChart from '../charts/response-code-chart.jsx';
4+
import SpeedChart from '../charts/speed-chart.jsx';
5+
import ProcessesChart from '../charts/processes-chart.jsx';
6+
import TemperatureChart from '../charts/temperature-chart.jsx';
7+
import LatencyChart from '../charts/latency-chart.jsx';
8+
import MemoryChart from '../charts/memory-chart.jsx';
9+
10+
const Modal = (props) => {
11+
// Destructuring props to make linter happy
12+
const {
13+
modalChart, service, toggleModalDisplay, chartTitle,
14+
} = props;
15+
// Dictionary used to render proper data chart within Modal component upon rendering
16+
const dict = {
17+
request: <RequestTypesChart service={service} />,
18+
response: <ResponseCodesChart service={service} />,
19+
speed: <SpeedChart service={service} />,
20+
processes: <ProcessesChart service={service} />,
21+
latency: <LatencyChart service={service} />,
22+
temperature: <TemperatureChart service={service} />,
23+
memory: <MemoryChart service={service} />,
24+
};
25+
26+
// event.stopPropogation allows the user to interact with the chart as opposed to a click on the
27+
// chart bubbling out and closing the Modal.
28+
return (
29+
<div id="modalWindow" onClick={() => toggleModalDisplay(!toggleModalDisplay)}>
30+
<div id="modalContent" onClick={(event) => event.stopPropagation()}>
31+
<h3 id="chartTitle">{`${service} - ${chartTitle}`}</h3>
32+
<button id="modalCloseButton" onClick={() => toggleModalDisplay(!toggleModalDisplay)}>&times;</button>
33+
{dict[modalChart]}
34+
</div>
35+
</div>
36+
);
37+
};
38+
39+
export default Modal;

app/components/ServiceDetails.jsx

Lines changed: 66 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,73 @@
1-
import React from 'react';
2-
import RequestTypesChart from '../charts/request-type-chart.jsx';
3-
import ResponseCodesChart from '../charts/response-code-chart.jsx';
4-
import SpeedChart from '../charts/speed-chart.jsx';
5-
import ProcessesChart from '../charts/processes-chart.jsx';
6-
import TemperatureChart from '../charts/temperature-chart.jsx'
7-
import LatencyChart from '../charts/latency-chart.jsx';
8-
import MemoryChart from '../charts/memory-chart.jsx';
1+
/* eslint-disable jsx-a11y/no-noninteractive-element-interactions */
2+
import React, { useState } from 'react';
3+
import Modal from './Modal.jsx';
94

10-
// Renders charts created with health and communication data for a selected database.
5+
// Renders health info detail buttons
116
const ServiceDetails = (props) => {
7+
const { service } = props;
8+
// Hook used to toggle whether or not the Modal component renders
9+
const [modalDisplay, toggleModalDisplay] = useState(false);
10+
// Hook used to set the chart that the Modal displays. The
11+
// modalDisplay state is drilled into the Modal component.
12+
const [modalChart, setModalChart] = useState();
13+
// Hook used to set the Modal Component title. The "alt" attribute
14+
// is grabbed from the onClick event via event.path[0].alt
15+
const [chartTitle, setChartTitle] = useState();
16+
const { currentMicroservice } = props;
17+
18+
// Dictionary used by the healthInfoButtons loop below
19+
const buttonProperties = [
20+
{ id: 'request', alt: 'Request Data', src: 'https://st2.depositphotos.com/3894705/9581/i/950/depositphotos_95816620-stock-photo-round-button-shows-speedometer.jpg' },
21+
{ id: 'response', alt: 'Response Data', src: 'https://st2.depositphotos.com/3894705/9581/i/950/depositphotos_95816620-stock-photo-round-button-shows-speedometer.jpg' },
22+
{ id: 'speed', alt: 'Speed Data', src: 'https://st2.depositphotos.com/3894705/9581/i/950/depositphotos_95816620-stock-photo-round-button-shows-speedometer.jpg' },
23+
{ id: 'processes', alt: 'Processes Data', src: 'https://st2.depositphotos.com/3894705/9581/i/950/depositphotos_95816620-stock-photo-round-button-shows-speedometer.jpg' },
24+
{ id: 'latency', alt: 'Latency Data', src: 'https://st2.depositphotos.com/3894705/9581/i/950/depositphotos_95816620-stock-photo-round-button-shows-speedometer.jpg' },
25+
{ id: 'temperature', alt: 'Temperature Data', src: 'https://st2.depositphotos.com/3894705/9581/i/950/depositphotos_95816620-stock-photo-round-button-shows-speedometer.jpg' },
26+
{ id: 'memory', alt: 'Memory Data', src: 'https://st2.depositphotos.com/3894705/9581/i/950/depositphotos_95816620-stock-photo-round-button-shows-speedometer.jpg' },
27+
];
28+
29+
// Create the Health Info buttons and their associated properties. Each time a button is clicked,
30+
// setChartTitle will grab a title to render in the Modal component, setModalChart will grab the
31+
// correct chart to render, and toggleModalDisplay will actually render the Modal display
32+
const healthInfoButtons = [];
33+
for (let i = 0; i < buttonProperties.length; i += 1) {
34+
healthInfoButtons.push(
35+
<div className="healthChartContainer">
36+
<input
37+
onClick={() => {
38+
setChartTitle(event.path[0].alt);
39+
setModalChart(event.path[0].id);
40+
toggleModalDisplay(!modalDisplay);
41+
}}
42+
service={service}
43+
type="image"
44+
id={buttonProperties[i].id}
45+
src={buttonProperties[i].src}
46+
width="50px"
47+
alt={buttonProperties[i].alt}
48+
/>
49+
</div>,
50+
);
51+
}
52+
53+
1254
return (
13-
<div>
55+
<div id="serviceDetailsContainer">
56+
{modalDisplay ? (
57+
<Modal
58+
chartTitle={chartTitle}
59+
service={service}
60+
modalChart={modalChart}
61+
toggleModalDisplay={toggleModalDisplay}
62+
onClick={() => {
63+
toggleModalDisplay(!modalDisplay);
64+
}}
65+
/>
66+
) : null}
1467
<button className="backButton" type="button" onClick={() => document.location.reload()}>Back</button>
15-
<div>
16-
<h3>Request Types</h3>
17-
<RequestTypesChart service={props.service} />
18-
</div>
19-
<div>
20-
<h3>Response Codes </h3>
21-
<ResponseCodesChart service={props.service} />
22-
</div>
23-
<div>
24-
<h3>Speed Chart</h3>
25-
<SpeedChart service={props.service} />
26-
</div>
27-
<div>
28-
<h3>Processes Chart</h3>
29-
<ProcessesChart service={props.service} />
30-
</div>
31-
<div>
32-
<h3>Latency</h3>
33-
<LatencyChart service={props.service} />
34-
</div>
35-
<div>
36-
<h3>Temperature Chart</h3>
37-
<TemperatureChart service={props.service} />
38-
</div>
39-
<div>
40-
<h3>Memory Chart</h3>
41-
<MemoryChart service={props.service} />
68+
<h3 id="microserviceHealthTitle">Microservice Health</h3>
69+
<div id="healthGrid">
70+
{healthInfoButtons}
4271
</div>
4372
</div>
4473
);

app/components/ServiceOverview.jsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ const ServiceOverview = (props) => {
4545
if (!(element.currentmicroservice in serviceCache)) {
4646
const button = (
4747
<button
48-
className='servicesBtn'
48+
className="servicesBtn"
49+
currentMicroservice={element.currentmicroservice}
4950
type="button"
5051
key={`serviceItem${props.index}${i}`}
5152
onClick={() => {
@@ -73,7 +74,7 @@ const ServiceOverview = (props) => {
7374
if (!(element.currentMicroservice in serviceCache)) {
7475
const button = (
7576
<button
76-
className='servicesBtn'
77+
className="servicesBtn"
7778
type="button"
7879
key={`serviceItem${props.index}${i}`}
7980
onClick={() => {
@@ -105,7 +106,7 @@ const ServiceOverview = (props) => {
105106
return (
106107
<div className="mainContainer">
107108
<div>
108-
<h1 className='overviewTitle'>Microservices Overview</h1>
109+
<h1 className="overviewTitle">Microservices Overview</h1>
109110
</div>
110111
<div />
111112
<div className="servicesList">{serviceList()}</div>

app/index.css

Lines changed: 84 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,9 +207,10 @@ select {
207207

208208
.backButton {
209209
height: 25px;
210+
/* width: 35px; */
210211
background-color: #edd9a3;
211212
transition: 0.2s;
212-
margin-left: 10px;
213+
margin-left: 0px;
213214

214215
}
215216

@@ -223,3 +224,85 @@ form {
223224
font-size: 2vh;
224225
/* margin-top: -4%; */
225226
}
227+
228+
229+
/* healthInfo visualizer css from 2.0 Team */
230+
#serviceDetailsContainer {
231+
display: flex;
232+
flex-direction: column;
233+
align-items: center;
234+
justify-content: center;
235+
}
236+
#healthGrid {
237+
display: grid;
238+
grid-template-columns: 75px 75px 75px;
239+
width: auto;
240+
justify-items: center;
241+
align-items: center;
242+
}
243+
244+
.healthName {
245+
text-align: center;
246+
margin-bottom: 1px;
247+
}
248+
249+
.healthChartContainer {
250+
margin: 10px 10px 10px 10px;
251+
}
252+
253+
.healthChartContainer:hover {
254+
opacity: 0.7;
255+
}
256+
257+
#microserviceHealthInfo {
258+
text-align: center;
259+
margin-top: 25px;
260+
}
261+
262+
#microserviceHealthTitle {
263+
margin-left: 0px;
264+
}
265+
266+
#modalWindow {
267+
position:fixed;
268+
padding:0;
269+
margin:0;
270+
top:0;
271+
left:0;
272+
width: 100%;
273+
height: 100%;
274+
background:rgba(0,0,0,.5);
275+
}
276+
277+
#modalContent {
278+
position: fixed;
279+
top: 50%;
280+
left: 50%;
281+
margin-left: -500px;
282+
margin-top: -380px;
283+
z-index: 1;
284+
width: 1000px;
285+
height: 760px;
286+
background: #333;
287+
opacity: 1 !important;
288+
align-content: center;
289+
290+
}
291+
292+
#chartTitle {
293+
text-align: center;
294+
margin-bottom: 50px;
295+
margin-left: 0px;
296+
}
297+
298+
#modalCloseButton {
299+
position: absolute;
300+
right: 0px;
301+
top: 0px;
302+
background-color: Transparent;
303+
border: none;
304+
color: white;
305+
font-size: 28px;
306+
padding: 0px;
307+
margin-right: 10px;
308+
}

0 commit comments

Comments
 (0)