Skip to content

Commit d7e24a3

Browse files
committed
Merge branch 'devDocker_v2' into Edwin/CI-CD
2 parents 5219e47 + fcb2850 commit d7e24a3

Some content is hidden

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

74 files changed

+6087
-586
lines changed

app/context/helpers.ts

Lines changed: 30 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -36,61 +36,49 @@ interface HealthDataObject {
3636
[key: string]: MetricObject[]
3737
}
3838

39-
// Transforms health data into a nested object based on service name
4039
export function healthTransformer(healthData: HealthDataObject[]) {
4140
// make an object for storing different services' metrics data
42-
const serviceMetricsObject = {}; //books:..., customers:..., orders:..., frontend:...
41+
const serviceMetricsObject = {};
4342
// loop through the services in the healthData array
44-
healthData.forEach(serviceObj => { //books
43+
healthData.forEach(serviceObj => {
4544
// grab the key string from the current service object
46-
const serviceName = Object.keys(serviceObj)[0]; //books-containerinfos
47-
// add the serviceName as a key on the serviceMetricsObject and assign it an empty object
48-
serviceMetricsObject[serviceName] = {}; //add key service Name to object
49-
const serviceElements = serviceObj[serviceName]; //array of metric objects IN heatlhdataObj @ serviceName
45+
const serviceName = Object.keys(serviceObj)[0];
46+
const serviceElements = serviceObj[serviceName];
5047
console.log('serviceElements: ', serviceElements);
48+
// add the serviceName as a key on the serviceMetricsObject and assign it an empty object
49+
serviceMetricsObject[serviceName] = {};
5150
// loop through the elements of the current service
52-
serviceElements.forEach((dataObject: any) => { //--v12 --make it an object typscript?
53-
console.log('raw dataOBJ LN 53', dataObject);
54-
// !containerName exist, generate a key for that object that matches the category value of the current dataObject
55-
let containerName = dataObject.containername;
56-
if (!serviceMetricsObject[serviceName][containerName]) {
57-
serviceMetricsObject[serviceName][containerName] = {};
58-
console.log('line 58 if category ', [containerName])
51+
serviceElements.forEach(dataObject => {
52+
// if it doesn't exist, generate a key for that object that matches the category value of the current dataObject
53+
if (!serviceMetricsObject[serviceName][dataObject.category]) {
54+
serviceMetricsObject[serviceName][dataObject.category] = {};
5955
}
60-
61-
for (let metric in dataObject) { //loop the data object for metric names and values
62-
// in containerName nested object, assign a key using the current dataObject's metric value and assign its value an empty object
63-
if (!serviceMetricsObject[serviceName][containerName][metric]) {
64-
serviceMetricsObject[serviceName][containerName][metric] = {};
65-
console.log('line 60 if metric ', metric)
66-
}
67-
// if the 'value' key doesn't exist in the previous object assign a key of 'value' with the value of an array that includes the value of value
68-
if (!serviceMetricsObject[serviceName][containerName][metric].value) {
69-
serviceMetricsObject[serviceName][containerName][metric].value = [dataObject[metric]];
70-
console.log('line 65 if value ', dataObject[metric])
71-
} else { // if it does exist, push the value of the current dataObject's time key onto the array
72-
serviceMetricsObject[serviceName][containerName][metric].value.push(
73-
dataObject[metric]
74-
);
75-
console.log('line 68 else value ', dataObject[metric])
76-
}
77-
// in that same object, if the key 'time' doesn't exist yet, assign a key of 'time' with the value as an array that includes the time value
78-
if (!serviceMetricsObject[serviceName][containerName][metric].time) {
79-
serviceMetricsObject[serviceName][containerName][metric].time = [dataObject.time];
80-
console.log('line 75 if time ', [dataObject.time])
81-
} else { // if it does exist aready, push the current time value into the time array
82-
serviceMetricsObject[serviceName][containerName][metric].time.push(
83-
dataObject.time
84-
);
85-
console.log('line 78 else time ', [dataObject.time])
86-
}
87-
console.log('serviceMetricsOBJ LN83: ', serviceMetricsObject)
56+
// in that nested object, assign a key using the current dataObject's metric value and assign its value an empty object
57+
if (!serviceMetricsObject[serviceName][dataObject.category][dataObject.metric]) {
58+
serviceMetricsObject[serviceName][dataObject.category][dataObject.metric] = {};
59+
}
60+
// if the 'value' key doesn't exist in the previous object assign a key of 'value' with the value of an array that includes the value of value
61+
if (!serviceMetricsObject[serviceName][dataObject.category][dataObject.metric].value) {
62+
serviceMetricsObject[serviceName][dataObject.category][dataObject.metric].value = [dataObject.value];
63+
} else { // if it does exist, push the value of the current dataObject's time key onto the array
64+
serviceMetricsObject[serviceName][dataObject.category][dataObject.metric].value.push(
65+
dataObject.value
66+
);
67+
}
68+
// in that same object, if the key 'time' doesn't exist yet, assign a key of 'time' with the value as an array that includes the time value
69+
if (!serviceMetricsObject[serviceName][dataObject.category][dataObject.metric].time) {
70+
serviceMetricsObject[serviceName][dataObject.category][dataObject.metric].time = [dataObject.time];
71+
} else { // if it does exist aready, push the current time value into the time array
72+
serviceMetricsObject[serviceName][dataObject.category][dataObject.metric].time.push(
73+
dataObject.time
74+
);
8875
}
8976
});
9077
})
9178
return serviceMetricsObject;
9279
};
9380

81+
9482
export function eventTransformer(eventData: MetricObject[]) {
9583
// make an object for storing the metrics data
9684
const eventMetricsObject = {};

app/modals/EnvModal.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ const EnvModal: React.FC<EnvModalProps> = React.memo(
2727
<Typography>Cloud-Based</Typography>
2828
</button>
2929
<button
30-
className="env-button"
30+
className="env-button2"
3131
onClick={() => {
3232
setOpen(false);
3333
setAddModalOpen(true);

app/stylesheets/EnvModal.scss

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,21 @@
1919
}
2020
}
2121

22+
.env-button2 {
23+
background-color: transparent;
24+
border: 0;
25+
outline: none;
26+
white-space: nowrap;
27+
margin: 10px;
28+
// padding: 0px;
29+
color: $gblue !important;
30+
box-shadow: $boxshadow;
31+
padding: 2rem;
32+
&:hover {
33+
background-color: $lightpurple;
34+
}
35+
}
36+
2237
p {
2338
padding: 0 !important;
2439
}

chronos_npm_package/chronos.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,20 @@ class Chronos {
138138
}
139139
}
140140

141+
async docker () {
142+
await utilities.testMetricsQuery(this.config);
143+
if (this.config.database.type === 'MongoDB') {
144+
mongo.connect(this.config);
145+
mongo.serverQuery(this.config);
146+
// return mongo.modifyMetrics(this.config);
147+
} else if (this.config.database.type === 'PostgreSQL') {
148+
postgres.connect(this.config);
149+
postgres.serverQuery(this.config);
150+
} else {
151+
throw new Error('The only allowed database types are MongoDB and PostgreSQL');
152+
}
153+
}
154+
141155
ServerWrapper(server, proto, methods) {
142156
/**
143157
* Wraps the gRPC server object to automatically write logs to provided DB

chronos_npm_package/controllers/mongo.js

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -169,12 +169,14 @@ mongo.serverQuery = async config => {
169169
await mongo.setQueryOnInterval(config);
170170
};
171171

172-
mongo.saveService = async config => {
172+
mongo.saveService = config => {
173173
let microservice;
174174
if (config.mode === 'kafka') {
175175
microservice = 'kafkametrics';
176176
} else if (config.mode === 'kubernetes') {
177177
microservice = 'kubernetesmetrics';
178+
} else if (config.mode === 'docker') {
179+
microservice = `${config.containerName}`;
178180
} else {
179181
throw new Error('Unrecongnized mode');
180182
}
@@ -205,6 +207,11 @@ mongo.setQueryOnInterval = async config => {
205207
} else if (config.mode === 'kubernetes') {
206208
model = KubernetesModel;
207209
metricsQuery = await utilities.promMetricsQuery;
210+
} else if (config.mode === 'docker') {
211+
model = ContainerInfoFunc(`${config.containerName}`);
212+
//console.log('setQueryOnInterval line 212 dockerModel:', ContainerInfoFunc(`${config.containerName}`));
213+
metricsQuery = utilities.promMetricsQuery;
214+
//console.log('setQueryOnInterval line 214 metricsQuery:', metricsQuery);
208215
} else {
209216
throw new Error('Unrecognized mode');
210217
}
@@ -227,26 +234,28 @@ mongo.setQueryOnInterval = async config => {
227234
// //currentMetricNames[metric] = true;
228235
// }
229236
// }
237+
///////
230238
length = await mongo.addMetrics(parsedArray, config.mode, currentMetricNames, model);
231239
}
232-
// const documents = [];
233-
// for (const metric of parsedArray) {
234-
// /**
235-
// * This will check if the current metric in the parsed array
236-
// * evaluates to true within the currentMetricNames object
237-
// * which is updated by the user when they select/deselect metrics on the electron app
238-
// * helping to avoid overloading the db with unnecessary data.
239-
// */
240-
241-
// if (currentMetricNames[metric.metric]) documents.push(model(metric));
242-
// }
243-
// await model.insertMany(parsedArray, err => {
244-
// if (err) {
245-
// console.error(err)
246-
// } else {
247-
// console.log(`${config.mode} metrics recorded in MongoDB`)
248-
// }
249-
// });
240+
const documents = [];
241+
for (const metric of parsedArray) {
242+
/**
243+
* This will check if the current metric in the parsed array
244+
* evaluates to true within the currentMetricNames object
245+
* which is updated by the user when they select/deselect metrics on the electron app
246+
* helping to avoid overloading the db with unnecessary data.
247+
*/
248+
249+
if (currentMetricNames[metric.metric]) documents.push(model(metric));
250+
}
251+
await model.insertMany(parsedArray, err => {
252+
if (err) {
253+
console.error(err)
254+
} else {
255+
console.log(`${config.mode} metrics recorded in MongoDB`)
256+
}
257+
});
258+
250259
let allMetrics = await model.find({});
251260
console.log('allMetrics.length: ', allMetrics.length);
252261
console.log("🟡 🟡 🟡 🟡 🟡 🟡 🟡 🟡 🟡 🟡 🟡 🟡 🟡 🟡 🟡 🟡 🟡 start creating dashboards 🟡 🟡 🟡 🟡 🟡 🟡 🟡 🟡 🟡 🟡 🟡 🟡 🟡 🟡 🟡 🟡 🟡")

chronos_npm_package/controllers/utilities.js

Lines changed: 31 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,11 @@ const helpers = {
5555
);
5656
}
5757

58-
const modeTypes = ['kafka', 'kubernetes', 'microservices'];
58+
const modeTypes = ['kafka', 'kubernetes', 'microservices', 'docker'];
5959

6060
if (!mode || !modeTypes.includes(mode)) {
6161
throw new Error(
62-
'You must input a mode into your chronos.config file. The mode may either be "kubernetes", "kafka", or "microservice"'
62+
'You must input a mode into your chronos.config file. The mode may either be "kubernetes", "kafka", "microservice", or "docker"'
6363
);
6464
}
6565

@@ -69,7 +69,7 @@ const helpers = {
6969
);
7070
}
7171

72-
if (mode === 'kubernetes') {
72+
if (mode === 'kubernetes' || mode === 'docker') {
7373
if (
7474
!promService ||
7575
typeof promService !== 'string' ||
@@ -139,7 +139,7 @@ const helpers = {
139139
getMetricsURI: config => {
140140
if (config.mode === 'kafka') {
141141
return config.jmxuri;
142-
} else if (config.mode === 'kubernetes') {
142+
} else if (config.mode === 'kubernetes' || config.mode === 'docker') {
143143
return `http://${config.promService}:${config.promPort}/api/v1/query?query=`;
144144
} else {
145145
throw new Error('Unrecognized mode');
@@ -153,14 +153,14 @@ const helpers = {
153153
*/
154154
testMetricsQuery: async config => {
155155
let URI = helpers.getMetricsURI(config);
156-
if (config.mode === 'kubernetes') URI += 'up';
156+
URI += 'up';
157157
try {
158158
const response = await axios.get(URI);
159-
if (response.status !== 200) console.error('Invalid response from metrics server:', URI);
159+
if (response.status !== 200) console.error('Invalid response from metrics server:', URI, response.status, response.data);
160160
else console.log('Successful initial response from metrics server:', URI);
161161
return response;
162162
} catch (error) {
163-
console.log(error);
163+
console.error(error);
164164
throw new Error('Unable to query metrics server: ' + URI);
165165
}
166166
},
@@ -226,38 +226,30 @@ const helpers = {
226226
*/
227227
promMetricsQuery: async config => {
228228
const URI = helpers.getMetricsURI(config);
229-
const query = URI + encodeURIComponent('{__name__=~".+",container=""}');
230-
try {
231-
const response = await axios.get(query);
232-
//console.log("response is: ", response);
233-
return helpers.parseProm(response.data.data.result);
234-
} catch (error) {
235-
return console.error(config.mode, '|', 'Error fetching from URI:', URI, '\n', error);
229+
let query;
230+
if (config.mode === 'docker') {
231+
query = URI + encodeURIComponent(`{__name__=~".+",name="${config.containerName}"}`);
232+
} else {
233+
query = URI + encodeURIComponent('{__name__=~".+",container=""}');
236234
}
237-
},
238-
239-
promMetrics: async config => {
240-
const URI = `http://${config.promService}:${config.promPort}/api/v1/query?query=`;
241-
const query = URI + encodeURIComponent('{__name__=~".+",container=""}');
242235
try {
243236
const response = await axios.get(query);
244-
//console.log("response is: ", response);
245-
return response.data.data.result;
237+
//console.log('promMetricsQuery line 236:', response.data.data.result);
238+
return helpers.parseProm(config, response.data.data.result);
246239
} catch (error) {
247-
return console.error('Error fetching from URI:', URI, '\n', error);
240+
return console.error(config.mode, '|', 'Error fetching from URI:', URI, '\n', error);
248241
}
249242
},
250243

251-
252244
/**
253245
* Parses response from Prometheus request and returns object with
254246
* @param {*} data
255247
* @returns bject with the gathered metric, value, time gathered, and category of event
256248
*/
257-
parseProm: data => {
249+
parseProm: (config, data) => {
258250
const res = [];
259251
const time = Date.now();
260-
const category = 'Event';
252+
const category = config.mode === 'docker' ? `${config.containerName}`: 'Event';
261253

262254
/**
263255
* Opportunity for improvement: Prometheus may query metrics that have the same job + instance + metric
@@ -272,10 +264,18 @@ const helpers = {
272264
const names = new Set();
273265

274266
for (const info of data) {
275-
if (!info.metric.job) continue;
276-
// Set the base name using the job, IP, and metric __name__
277-
let wholeName = info.metric.job + '/' + info.metric.instance + '/' + info.metric['__name__'];
278-
let name = wholeName.replace(/.*\/.*\//g, '');
267+
let wholeName;
268+
let name;
269+
if (config.mode === 'docker'){
270+
if (!info.metric.name) continue;
271+
wholeName = info.metric['__name__'];
272+
name = wholeName.replace(/.*\/.*\//g, '');
273+
} else {
274+
if (!info.metric.job) continue;
275+
// Set the base name using the job, IP, and metric __name__
276+
wholeName = info.metric.job + '/' + info.metric.instance + '/' + info.metric['__name__'];
277+
name = wholeName.replace(/.*\/.*\//g, '');
278+
}
279279
if (names.has(name)) continue;
280280
else {
281281
names.add(name);
@@ -303,6 +303,8 @@ const helpers = {
303303
return res;
304304
},
305305

306+
307+
306308
createGrafanaDashboard: async (
307309
metric,
308310
datasource,

0 commit comments

Comments
 (0)