Skip to content

Commit fec765d

Browse files
authored
Merge pull request #64 from Digipalvelutehdas/feature/dashboard-renders-charts
Code refactoring of Elastic Search
2 parents 9e6f1d6 + dc8d14b commit fec765d

File tree

5 files changed

+176
-147
lines changed

5 files changed

+176
-147
lines changed

core/lib/i18n/en.i18n.json

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -371,14 +371,11 @@
371371
"proxyForm_saveButton_text": "Save",
372372
"proxyItem_editProxy": "Edit",
373373
"proxyItem_removeProxy": "Remove",
374-
"proxyItem_apiUmbrella_proxyType": "Type",
375-
"proxyItem_apiUmbrella_url": "URL",
376-
"proxyItem_apiUmbrella_apiKey": "API Key",
377-
"proxyItem_apiUmbrella_apiToken": "API Token",
378-
"proxyItem_apiUmbrella_elasticsearch": "Elasticsearch",
379-
"proxyItem_emqtt_proxyType": "Type",
380-
"proxyItem_emqtt_url": "URL",
381-
"proxyItem_emqtt_elasticsearch": "Elasticsearch",
374+
"proxyItem_type": "Type",
375+
"proxyItem_url": "URL",
376+
"proxyItem_apiKey": "API Key",
377+
"proxyItem_apiToken": "API Token",
378+
"proxyItem_elasticsearch": "Elasticsearch",
382379
"removeProxy_modalLabel": "Are you sure that you want to remove proxy?",
383380
"removeProxy_modalBody": "proxy backends are connected to this proxy. Removing the proxy will mean that API calls made to any of the connected API backends will break.",
384381
"removeProxy_confirmRemoveProxy": "Yes, remove",

dashboard/client/dashboard.js

Lines changed: 30 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -16,116 +16,49 @@ Template.dashboard.onCreated(function () {
1616
// Keeps ES data for charts
1717
instance.chartData = new ReactiveVar();
1818

19-
instance.getChartData = function (params, proxyId) {
19+
instance.getChartData = function (proxyData, filterParameters) {
2020
return new Promise((resolve, reject) => {
21-
Meteor.call('getElasticSearchData', params, proxyId, (err, res) => {
21+
Meteor.call('getElasticSearchData', proxyData, filterParameters, (err, res) => {
2222
if (err) reject(err);
2323
resolve(res.hits.hits);
2424
});
2525
});
2626
};
2727

28-
instance.getElasticSearchQuery = function () {
29-
// Placeholder for prefixes query
30-
const prefixesQuery = [];
31-
32-
// Get selected backend from query parameter
33-
const backendParameter = FlowRouter.getQueryParam('backend');
34-
35-
// Find proxy backend configuration in DB
36-
const proxyBackend = ProxyBackends.findOne(backendParameter);
37-
38-
// Check existing of fronted prefix
39-
if (proxyBackend && proxyBackend.apiUmbrella && proxyBackend.apiUmbrella.url_matches) {
40-
// Save frontend prefix
41-
const frontendPrefix = proxyBackend.apiUmbrella.url_matches[0].frontend_prefix;
42-
prefixesQuery.push({
43-
wildcard: {
44-
request_path: {
45-
// Add '*' to partially match the url
46-
value: `${frontendPrefix}*`,
47-
},
48-
},
49-
});
50-
}
51-
52-
// Construct parameters for elasticsearch
53-
const params = {
54-
size: 50000,
55-
body: {
56-
query: {
57-
filtered: {
58-
query: {
59-
bool: {
60-
should: [
61-
prefixesQuery,
62-
],
63-
},
64-
},
65-
filter: {
66-
range: {
67-
request_at: { },
68-
},
69-
},
70-
},
71-
},
72-
sort: [
73-
{ request_at: { order: 'desc' } },
74-
],
75-
fields: [
76-
'request_at',
77-
'response_status',
78-
'response_time',
79-
'request_ip_country',
80-
'request_ip',
81-
'request_path',
82-
'user_id',
83-
],
84-
},
85-
};
86-
87-
// Listen for analytics date range changes through URL parameters
88-
const analyticsFrom = FlowRouter.getQueryParam('fromDate');
89-
const analyticsTo = FlowRouter.getQueryParam('toDate');
90-
91-
// Update query parameters for date range, when provided
92-
if (analyticsFrom) {
93-
// Set start date (greater than or equal to) for analytics timeframe
94-
params.body.query.filtered.filter.range.request_at.gte = analyticsFrom;
95-
}
96-
97-
// Update query parameters for date range, when provided
98-
if (analyticsTo) {
99-
// Set end date (less than or equal to) for analytics timeframe
100-
params.body.query.filtered.filter.range.request_at.lte = analyticsTo;
101-
}
102-
103-
return params;
104-
};
105-
10628
instance.autorun(() => {
10729
if (instance.subscriptionsReady()) {
30+
// The main Elastic Search Logic
10831
// Cleanup previous message if one exists
10932
$('.charts-holder>#no-chart-data-placeholder').remove();
11033

111-
// Get elasticsearch query
112-
const params = instance.getElasticSearchQuery();
113-
34+
// Get backend id from query param
11435
const backendParameter = FlowRouter.getQueryParam('backend');
115-
// Find the proxy backend configuration
116-
const proxyBackend = ProxyBackends.findOne(backendParameter);
117-
118-
// If proxy backend exists and has proxy ID
119-
// TODO: Add condition for case "Proxy Admin API" with prefix /api-umbrella/
120-
if (proxyBackend && proxyBackend.proxyId) {
121-
// Provide proxy ID to Elastic Search
122-
instance.getChartData(params, proxyBackend.proxyId)
123-
.then((chartData) => {
124-
// Update reactive variable
125-
instance.chartData.set(chartData);
126-
})
127-
.catch(err => console.error(err));
128-
}
36+
// Get dateTo & dateFrom from query param
37+
const analyticsFrom = FlowRouter.getQueryParam('fromDate');
38+
const analyticsTo = FlowRouter.getQueryParam('toDate');
39+
// Get granularity from query param
40+
const granularity = FlowRouter.getQueryParam('granularity');
41+
42+
// Constructs object of analytics data
43+
const filterParameters = {
44+
analyticsFrom,
45+
analyticsTo,
46+
granularity,
47+
};
48+
49+
// Check of existing needed proxy data
50+
Meteor.call('getProxyData', backendParameter, (error, result) => {
51+
// if it was not error
52+
if (!error) {
53+
// Provide proxy data to elastic search
54+
instance.getChartData(result, filterParameters)
55+
.then((chartData) => {
56+
// Update reactive variable
57+
instance.chartData.set(chartData);
58+
})
59+
.catch(err => console.error(err));
60+
}
61+
});
12962
}
13063
});
13164
});

dashboard/server/methods.js

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { Meteor } from 'meteor/meteor';
2+
// Collection import
3+
import { Proxies } from '/proxies/collection';
4+
import { ProxyBackends } from '/proxy_backends/collection';
5+
6+
Meteor.methods({
7+
getProxyData (proxyBackendId) {
8+
// Get proxy backend configuration
9+
const proxyBackend = ProxyBackends.findOne(proxyBackendId);
10+
11+
if (proxyBackend && proxyBackend.proxyId) {
12+
// Get proxy
13+
const proxy = Proxies.findOne(proxyBackend.proxyId);
14+
15+
const response = {};
16+
17+
// Check existing of proxy, existing of proxy type
18+
if (proxy && proxy.type) {
19+
// save type
20+
response.proxyType = proxy.type;
21+
22+
switch (proxy.type) {
23+
case 'apiUmbrella':
24+
// save fronted prefix
25+
response.frontendPrefix = proxyBackend.apiUmbrella.url_matches[0].frontend_prefix;
26+
// save url
27+
response.elasticSearchUrl = proxy.apiUmbrella.elasticsearch;
28+
break;
29+
case 'emqtt':
30+
// TODO: Add fronted prefix if eMQTT protocol has it
31+
// save url
32+
response.elasticSearchUrl = proxy.emqtt.elasticsearch;
33+
break;
34+
default:
35+
throw new Meteor.Error('Unknown proxy type');
36+
}
37+
38+
// Return proxy data
39+
return response;
40+
}
41+
throw new Meteor.Error('No one proxy was found');
42+
}
43+
throw new Meteor.Error('No one proxy backend configuration was selected');
44+
},
45+
});
46+

elasticsearch/server/methods.js

Lines changed: 87 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,102 @@
11
import { Meteor } from 'meteor/meteor';
22
import ElasticSearch from 'elasticsearch';
3-
// Collection import
4-
import { Proxies } from '/proxies/collection';
5-
63

74
Meteor.methods({
8-
getElasticSearchData (opts, proxyId) {
9-
// Check if user is authorised
10-
if (Meteor.user()) {
11-
const host = Meteor.call('getElasticsearchUrl', proxyId);
12-
13-
// Init ES client
14-
const esClient = new ElasticSearch.Client({ host });
5+
getElasticSearchData (proxyData, filterParameters) {
6+
let params;
157

16-
// Get elasticsearch data and return
17-
return esClient.search(opts).then((res) => {
18-
return res;
19-
}, (err) => {
20-
throw new Meteor.Error(err.message);
21-
});
8+
// Constructs the Elastic Search query object
9+
switch (proxyData.proxyType) {
10+
case 'apiUmbrella':
11+
params = Meteor.call('getElasticQueryUmbrella', proxyData.frontendPrefix, filterParameters);
12+
break;
13+
case 'emqtt':
14+
// TODO: Add fronted prefix parameter if eMQTT protocol has it
15+
params = Meteor.call('getElasticQueryEmqtt');
16+
break;
17+
default:
18+
throw new Meteor.Error('Unknown proxy type');
2219
}
2320

24-
throw new Meteor.Error('User is not authorised.');
21+
// Save the Elastic Search url
22+
const host = proxyData.elasticSearchUrl;
23+
// Init ES client
24+
const esClient = new ElasticSearch.Client({ host });
25+
26+
// Makes the HTTP request
27+
// Get Elastic Search data and return
28+
return esClient.search(params).then((res) => res, (err) => {
29+
// Throw an error
30+
throw new Meteor.Error(err.message);
31+
});
2532
},
26-
elasticsearchIsDefined (proxyId) {
27-
// Get Proxy instance of ID
28-
const proxy = Proxies.findOne(proxyId);
29-
// Check of existing this proxy instance
30-
if (proxy) {
31-
// Get Elastic Search URL
32-
const elasticsearch = proxy.apiUmbrella.elasticsearch;
33+
// Constructs the Elastic Search query object for apiUmbrella
34+
getElasticQueryUmbrella (frontendPrefix, filterParameters) {
35+
// Construct parameters for Elastic Search
36+
// TODO: For case "Proxy Admin API" with prefix /api-umbrella/
37+
// TODO: Values aggregation associated with granularity
38+
const params = {
39+
size: 50000,
40+
body: {
41+
query: {
42+
filtered: {
43+
query: {
44+
bool: {
45+
should: [
46+
{
47+
wildcard: {
48+
request_path: {
49+
// Add '*' to partially match the url
50+
value: `${frontendPrefix}*`,
51+
},
52+
},
53+
},
54+
],
55+
},
56+
},
57+
filter: {
58+
range: {
59+
request_at: {},
60+
},
61+
},
62+
},
63+
},
64+
sort: [
65+
{
66+
request_at: {
67+
order: 'desc',
68+
},
69+
},
70+
],
71+
fields: [
72+
'request_at',
73+
'response_status',
74+
'response_time',
75+
'request_ip_country',
76+
'request_ip',
77+
'request_path',
78+
'user_id',
79+
],
80+
},
81+
};
3382

34-
// Return true or false, depending on whether elasticsearch is defined
35-
return (elasticsearch);
83+
// Update query parameters for date range, when provided
84+
if (filterParameters.analyticsFrom) {
85+
// Set start date (greater than or equal to) for analytics timeframe
86+
params.body.query.filtered.filter.range.request_at.gte = filterParameters.analyticsFrom;
3687
}
3788

38-
return false;
39-
},
40-
getElasticsearchUrl (proxyId) {
41-
// Check existing of Elastci Search URL
42-
if (Meteor.call('elasticsearchIsDefined', proxyId)) {
43-
// Return URL
44-
return Proxies.findOne(proxyId).apiUmbrella.elasticsearch;
89+
// Update query parameters for date range, when provided
90+
if (filterParameters.analyticsTo) {
91+
// Set end date (less than or equal to) for analytics timeframe
92+
params.body.query.filtered.filter.range.request_at.lte = filterParameters.analyticsTo;
4593
}
4694

47-
throw new Meteor.Error('Elasticsearch is not defined');
95+
return params;
96+
},
97+
// TODO: Add the correct query object for eMQTT protocol
98+
getElasticQueryEmqtt () {
99+
// Now it returns some placeholder
100+
return { size: 1000 };
48101
},
49102
});

0 commit comments

Comments
 (0)