Merge "First version of HealtCheck test"
[nonrtric.git] / test / simulator-group / sim-monitor.js
1 /*
2 #  ============LICENSE_START===============================================
3 #  Copyright (C) 2020 Nordix Foundation. All rights reserved.
4 #  ========================================================================
5 #  Licensed under the Apache License, Version 2.0 (the "License");
6 #  you may not use this file except in compliance with the License.
7 #  You may obtain a copy of the License at
8 #
9 #       http://www.apache.org/licenses/LICENSE-2.0
10 #
11 #  Unless required by applicable law or agreed to in writing, software
12 #  distributed under the License is distributed on an "AS IS" BASIS,
13 #  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 #  See the License for the specific language governing permissions and
15 #  limitations under the License.
16 #  ============LICENSE_END=================================================
17 #
18 */
19
20 // Sim mon server - query the agent and the simulators for counters and other data
21 // Presents a web page on localhost:9999/mon
22
23 var LOCALHOST="http://127.0.0.1:"
24 var LOCALHOSTSECURE="https://127.0.0.1:"
25 //This var may switch between LOCALHOST and LOCALHOSTSECURE
26 var SIM_LOCALHOST=LOCALHOST
27 var MRSTUB_PORT="3905"
28 var AGENT_PORT="8081"
29 var CR_PORT="8090"
30 var http = require('http');
31 var https = require('https');
32
33 var express = require('express');
34 var app = express();
35 var fieldSize=32;
36
37
38
39 //I am alive
40 app.get("/",function(req, res){
41         res.send("ok");
42 })
43
44 //Get parameter valuue from other server
45 function getSimCtr(httpx, url, index, cb) {
46     var data = '';
47     var http_type=http
48     if (httpx=="https") {
49         http_type=https
50     }
51     console.log("URL: "+ url + " - " + httpx)
52     try {
53         http_type.get(url, (resp) => {
54             // A chunk of data has been recieved.
55             resp.on('data', (chunk) => {
56                 data += chunk;
57             });
58
59             // The whole response has been received.
60             resp.on('end', () => {
61                 var code=resp.statusCode
62                 if (code > 199 && code < 300) {
63                     cb(data, index);
64                 } else {
65                     cb("not found", index);
66                 }
67             });
68
69         }).on("error", (err) => {
70             console.log("Error: " + err.message);
71             cb("no response", index);
72         });
73     } catch(err) {
74         cb("no response", index);
75     }
76 };
77
78
79 //Format a comma separated list of data to a html-safe string with fixed fieldsizes
80 function formatDataRow(commaList) {
81         var str = "";
82         var tmp=commaList.split(',');
83     for(var i=0;i<tmp.length;i++) {
84         var data=tmp[i];
85         var len = fieldSize-data.length;
86         while(len>0) {
87             data = data+"&nbsp;";
88             len--;
89         }
90         str=str+data+"&nbsp;&nbsp;&nbsp;";
91      }
92         return str;
93 }
94
95 //Format a comma separated list of ids to a html-safe string with fixed fieldsizes
96 function formatIdRow(commaList) {
97         var str = "";
98         var tmp=commaList.split(',');
99     for(var i=0;i<tmp.length;i++) {
100         tmp[i] = tmp[i].trim();
101         var data="&lt"+tmp[i]+"&gt";
102         var len = fieldSize+4-data.length;
103         while(len>0) {
104             data = data+"&nbsp;";
105             len--;
106         }
107         str=str+data+"&nbsp;&nbsp;&nbsp;";
108     }
109         return str;
110 }
111
112 //Format a list of ids to a html-safe string in compact format
113 function formatIdRowCompact(commaList) {
114     if (commaList == undefined) {
115         commaList= "";
116     }
117         var str = "";
118         var tmp=commaList.split(',');
119     for(var i=0;i<tmp.length;i++) {
120         tmp[i] = tmp[i].trim();
121         var data="&lt"+tmp[i]+"&gt";
122         str=str+data+"&nbsp;";
123     }
124         return str;
125 }
126
127 //Pad a string upto a certain size using a pad string
128 function padding(val, fieldSize, pad) {
129         var s=""+val;
130         for(var i=s.length;i<fieldSize;i++) {
131                 s=s+pad
132         }
133         return s;
134 }
135
136 //Status variables, for parameters values fetched from other simulators
137 var mr1="", mr2="", mr3="", mr4="", mr5="", mr6="";
138
139 //Status variables for agent
140 var ag1=""
141 var ag2=""
142 var ag3=""
143 var ag4=""
144
145 //Status variables for callback receiver
146 var cr1=""
147 var cr2=""
148 var cr3=""
149
150
151 //Container names and ports of the ric simulator
152 var simnames=[]
153 var simports=[]
154
155 //Status variables for each ric simulator
156 var simvar1=[]
157 var simvar2=[]
158 var simvar3=[]
159 var simvar4=[]
160 var simvar5=[]
161
162 //Counts the number of get request for the html page
163 var getCtr=0
164
165 var refreshInterval=4000
166
167 //Ignore self signed cert
168 process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = 0;
169
170 var sim_http_type="http"
171
172 function fetchAllMetrics() {
173     setTimeout(() => {
174
175         console.log("Fetching all metics data")
176         if (refreshInterval < 20000) {
177             refreshInterval+=100
178         }
179         if (getCtr%3 == 0) {
180             //Extract the port numbers from the running simulators, for every 3 calls
181             const { exec } = require('child_process');
182             exec('docker ps --filter "name=ricsim" --format "{{.Names}} {{.Ports}}" | sed s/0.0.0.0:// | cut -d \'>\' -f1 | sed \'s/[[-]]*$//\'', (err, stdout, stderr) => {
183
184                 var simulators = ""
185                 simulators=`${stdout}`.replace(/(\r\n|\n|\r)/gm," ");
186                 simulators=simulators.trim();
187                 var sims=simulators.split(" ")
188                 simnames=[]
189                 simports=[]
190                 for(i=0;i<sims.length;i=i+2) {
191                     simnames[i/2]=sims[i]
192                     simports[i/2]=sims[i+1]
193                 }
194             });
195         }
196         getCtr=getCtr+1
197
198         //Get metric values from the simulators
199         for(var index=0;index<simnames.length;index++) {
200             try {
201                 if (index == 0) {
202                     // Check is simulator are running on http or https - no response assumes http
203                     getSimCtr("https",LOCALHOSTSECURE+simports[index]+"/", index, function(data, index) {
204                         if (data=="OK") {
205                             console.log("Found https simulator - assuming all simulators using https" )
206                             sim_http_type="https"
207                             SIM_LOCALHOST=LOCALHOSTSECURE
208                         } else {
209                             console.log("No https simulator found - assuming all simulators using http" )
210                             sim_http_type="http"
211                             SIM_LOCALHOST=LOCALHOST
212                         }
213                     });
214
215                 }
216             } catch(err) {
217                 console.log("No https simulator found - assuming all simulators using http" )
218                 sim_http_type="http"
219                 SIM_LOCALHOST=LOCALHOST
220             }
221             getSimCtr(sim_http_type, SIM_LOCALHOST+simports[index]+"/counter/num_instances", index, function(data, index) {
222                 simvar1[index] = data;
223             });
224             getSimCtr(sim_http_type, SIM_LOCALHOST+simports[index]+"/counter/num_types", index, function(data,index) {
225                 simvar2[index] = data;
226             });
227             getSimCtr(sim_http_type, SIM_LOCALHOST+simports[index]+"/policytypes", index, function(data,index) {
228                 data=data.replace(/\[/g,'');
229                 data=data.replace(/\]/g,'');
230                 data=data.replace(/ /g,'');
231                 data=data.replace(/\"/g,'');
232                 simvar3[index] = data;
233             });
234             getSimCtr(sim_http_type, SIM_LOCALHOST+simports[index]+"/counter/interface", index, function(data,index) {
235                 simvar4[index] = data;
236             });
237             getSimCtr(sim_http_type, SIM_LOCALHOST+simports[index]+"/counter/remote_hosts", index, function(data,index) {
238                 simvar5[index] = data;
239             });
240         }
241
242         //MR - get metrics values from the MR stub
243         getSimCtr("http", LOCALHOST+MRSTUB_PORT+"/counter/requests_submitted", 0, function(data, index) {
244             mr1 = data;
245         });
246         getSimCtr("http", LOCALHOST+MRSTUB_PORT+"/counter/requests_fetched", 0, function(data, index) {
247             mr2 = data;
248         });
249         getSimCtr("http", LOCALHOST+MRSTUB_PORT+"/counter/current_requests", 0, function(data, index) {
250             mr3 = data;
251         });
252         getSimCtr("http", LOCALHOST+MRSTUB_PORT+"/counter/responses_submitted", 0, function(data, index) {
253             mr4 = data;
254         });
255         getSimCtr("http", LOCALHOST+MRSTUB_PORT+"/counter/responses_fetched", 0, function(data, index) {
256             mr5 = data;
257         });
258         getSimCtr("http", LOCALHOST+MRSTUB_PORT+"/counter/current_responses", 0, function(data, index) {
259             mr6 = data;
260         });
261
262         //CR - get metrics values from the callbackreceiver
263         getSimCtr("http", LOCALHOST+CR_PORT+"/counter/received_callbacks", 0, function(data, index) {
264             cr1 = data;
265         });
266         getSimCtr("http", LOCALHOST+CR_PORT+"/counter/fetched_callbacks", 0, function(data, index) {
267             cr2 = data;
268         });
269         getSimCtr("http", LOCALHOST+CR_PORT+"/counter/current_messages", 0, function(data, index) {
270             cr3 = data;
271         });
272
273         //Agent - get metrics from the agent
274         getSimCtr("http", LOCALHOST+AGENT_PORT+"/status", 0, function(data, index) {
275             ag1 = data;
276         });
277         getSimCtr("http", LOCALHOST+AGENT_PORT+"/services", 0, function(data, index) {
278             ag2="";
279             try {
280                 var jd=JSON.parse(data);
281                 for(var key in jd) {
282                     if (ag2.length > 1) {
283                         ag2=ag2+", "
284                     }
285                     ag2=ag2+(jd[key]["serviceName"]).trim()
286                 }
287             }
288             catch (err) {
289                 ag2=data
290             }
291         });
292         getSimCtr("http", LOCALHOST+AGENT_PORT+"/policy_types", 0, function(data, index) {
293             ag3="";
294             try {
295                 var jd=JSON.parse(data);
296                 for(var key in jd) {
297                     if (ag3.length > 0) {
298                         ag3=ag3+", "
299                     }
300                     ag3=ag3+jd[key].trim()
301                 }
302             }
303             catch (err) {
304                 ag3=""
305             }
306         });
307         getSimCtr("http", LOCALHOST+AGENT_PORT+"/policy_ids", 0, function(data, index) {
308             ag4=""
309             try {
310                 var jd=JSON.parse(data);
311                 ag4=""+jd.length
312             }
313             catch (err) {
314                 ag4=""
315             }
316         });
317
318
319
320         fetchAllMetrics();
321     }, refreshInterval)
322 }
323
324 fetchAllMetrics();
325
326 setInterval(() => {
327     console.log("Setting interval "+refreshInterval+"ms")
328 }, refreshInterval)
329
330 app.get("/mon",function(req, res){
331
332
333     refreshInterval=2000
334
335   //Build web page
336         var htmlStr = "<!DOCTYPE html>" +
337           "<html>" +
338           "<head>" +
339             "<meta http-equiv=\"refresh\" content=\"2\">"+  //2 sec auto refresh
340             "<title>Policy Agent and simulator monitor</title>"+
341             "</head>" +
342             "<body>" +
343             "<h3>Policy agent</h3>" +
344             "<font face=\"monospace\">" +
345             "Status:..............................." + formatDataRow(ag1) + "<br>" +
346             "Services:............................." + formatIdRowCompact(ag2) + "<br>" +
347             "Types:................................" + formatIdRowCompact(ag3) + "<br>" +
348             "Number of instances:.................." + formatDataRow(ag4) + "<br>" +
349             "</font>" +
350             "<h3>MR Stub interface</h3>" +
351             "<font face=\"monospace\">"+
352             "Submitted requests:............................" + formatDataRow(mr1) + "<br>" +
353             "Fetched requests:.............................." + formatDataRow(mr2) + "<br>" +
354             "Current requests waiting:......................" + formatDataRow(mr3) + "<br>" +
355             "Submitted responses:..........................." + formatDataRow(mr4) + "<br>" +
356             "Fetched responses.............................." + formatDataRow(mr5) + "<br>" +
357             "Current responses waiting......................" + formatDataRow(mr6) + "<br>" +
358             "</font>"+
359             "<h3>Callback receiver</h3>" +
360             "<font face=\"monospace\">" +
361             "Callbacks received:..................." + formatDataRow(cr1) + "<br>" +
362             "Callbacks fetched:...................." + formatDataRow(cr2) + "<br>" +
363             "Number of waiting callback messages:.." + formatDataRow(cr3) + "<br>" +
364             "</font>" +
365             "<h3>Near-RT RIC Simulators</h3>" +
366             "<font face=\"monospace\">"
367
368             htmlStr=htmlStr+padding("Near-RT RIC Simulator name", 35,"&nbsp;")
369             htmlStr=htmlStr+padding("Types", 10,"&nbsp;")
370             htmlStr=htmlStr+padding("Instances", 10,"&nbsp;")+"<br>"
371             htmlStr=htmlStr+padding("",55,"=")+"<br>"
372             for(var simIndex=0;simIndex<simnames.length;simIndex++) {
373                 htmlStr=htmlStr+padding(simnames[simIndex]+ " ("+simports[simIndex]+")",35,"&nbsp;");
374                 htmlStr=htmlStr+padding(simvar2[simIndex],10,"&nbsp;")
375                 htmlStr=htmlStr+padding(simvar1[simIndex],10,"&nbsp;")
376                 htmlStr=htmlStr+"<br>";
377             }
378
379             htmlStr=htmlStr+"<br>";
380             htmlStr=htmlStr+padding("Near-RT RIC Simulator name", 35,"&nbsp;")
381             htmlStr=htmlStr+padding("Version", 20,"&nbsp;")
382             htmlStr=htmlStr+padding("Type-IDs", 10,"&nbsp;")+"<br>"
383             htmlStr=htmlStr+padding("",65,"=")+"<br>"
384             for(simIndex=0;simIndex<simnames.length;simIndex++) {
385                 htmlStr=htmlStr+padding(simnames[simIndex]+ " ("+simports[simIndex]+")",35,"&nbsp;");
386                 htmlStr=htmlStr+padding(simvar4[simIndex],20,"&nbsp;")
387                 htmlStr=htmlStr+padding(formatIdRowCompact(simvar3[simIndex]),10,"&nbsp;")
388                 htmlStr=htmlStr+"<br>";
389             }
390
391             htmlStr=htmlStr+"<br>";
392             htmlStr=htmlStr+padding("Near-RT RIC Simulator name", 35,"&nbsp;")
393             htmlStr=htmlStr+padding("Remote hosts", 50,"&nbsp;")+"<br>"
394             htmlStr=htmlStr+padding("",90,"=")+"<br>"
395             for(simIndex=0;simIndex<simnames.length;simIndex++) {
396                 htmlStr=htmlStr+padding(simnames[simIndex]+ " ("+simports[simIndex]+")",35,"&nbsp;");
397                 htmlStr=htmlStr+padding(simvar5[simIndex],50,"&nbsp;")
398                 htmlStr=htmlStr+"<br>";
399             }
400
401             htmlStr=htmlStr+
402            "</body>" +
403           "</html>";
404         res.send(htmlStr);
405 })
406
407 var httpServer = http.createServer(app);
408 var httpPort=9999;
409 httpServer.listen(httpPort);
410 console.log("Simulator monitor listening (http) at "+httpPort);
411 console.log("Open the web page on localhost:9999/mon to view the statistics page.")