blob: 17d3205833e5db32307dac0f98e26fb97698f032 [file] [log] [blame]
BjornMagnussonXA80a92002020-03-19 14:31:06 +01001/*
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
23var LOCALHOST="http://127.0.0.1:"
24var MRSTUB_PORT="3905"
25var AGENT_PORT="8081"
26var CR_PORT="8090"
27var http = require('http');
28
29var express = require('express');
30var app = express();
31var fieldSize=32;
32
BjornMagnussonXAbbd2e9d2020-05-27 21:24:06 +020033var flagstore={}
BjornMagnussonXA80a92002020-03-19 14:31:06 +010034
35//I am alive
36app.get("/",function(req, res){
37 res.send("ok");
38})
39
40//Get parameter valuue from other server
BjornMagnussonXAbbd2e9d2020-05-27 21:24:06 +020041function getSimCtr(url, index, cb) {
BjornMagnussonXA80a92002020-03-19 14:31:06 +010042 var data = '';
BjornMagnussonXAbbd2e9d2020-05-27 21:24:06 +020043
BjornMagnussonXAad047782020-06-08 15:54:11 +020044 //console.log("URL: "+ url + " - ")
BjornMagnussonXA72667f12020-04-24 09:20:18 +020045 try {
BjornMagnussonXAbbd2e9d2020-05-27 21:24:06 +020046 http.get(url, (resp) => {
BjornMagnussonXA72667f12020-04-24 09:20:18 +020047 // A chunk of data has been recieved.
48 resp.on('data', (chunk) => {
49 data += chunk;
50 });
BjornMagnussonXA80a92002020-03-19 14:31:06 +010051
BjornMagnussonXA72667f12020-04-24 09:20:18 +020052 // The whole response has been received.
53 resp.on('end', () => {
54 var code=resp.statusCode
55 if (code > 199 && code < 300) {
56 cb(data, index);
57 } else {
58 cb("not found", index);
59 }
60 });
BjornMagnussonXA80a92002020-03-19 14:31:06 +010061
BjornMagnussonXA72667f12020-04-24 09:20:18 +020062 }).on("error", (err) => {
63 console.log("Error: " + err.message);
64 cb("no response", index);
65 });
66 } catch(err) {
67 cb("no response", index);
68 }
BjornMagnussonXA80a92002020-03-19 14:31:06 +010069};
70
71
72//Format a comma separated list of data to a html-safe string with fixed fieldsizes
73function formatDataRow(commaList) {
74 var str = "";
75 var tmp=commaList.split(',');
76 for(var i=0;i<tmp.length;i++) {
77 var data=tmp[i];
78 var len = fieldSize-data.length;
79 while(len>0) {
80 data = data+"&nbsp;";
81 len--;
82 }
83 str=str+data+"&nbsp;&nbsp;&nbsp;";
84 }
85 return str;
86}
87
88//Format a comma separated list of ids to a html-safe string with fixed fieldsizes
89function formatIdRow(commaList) {
90 var str = "";
91 var tmp=commaList.split(',');
92 for(var i=0;i<tmp.length;i++) {
93 tmp[i] = tmp[i].trim();
94 var data="&lt"+tmp[i]+"&gt";
95 var len = fieldSize+4-data.length;
96 while(len>0) {
97 data = data+"&nbsp;";
98 len--;
99 }
100 str=str+data+"&nbsp;&nbsp;&nbsp;";
101 }
102 return str;
103}
104
105//Format a list of ids to a html-safe string in compact format
106function formatIdRowCompact(commaList) {
107 if (commaList == undefined) {
108 commaList= "";
109 }
110 var str = "";
111 var tmp=commaList.split(',');
112 for(var i=0;i<tmp.length;i++) {
113 tmp[i] = tmp[i].trim();
114 var data="&lt"+tmp[i]+"&gt";
115 str=str+data+"&nbsp;";
116 }
117 return str;
118}
119
120//Pad a string upto a certain size using a pad string
121function padding(val, fieldSize, pad) {
122 var s=""+val;
123 for(var i=s.length;i<fieldSize;i++) {
124 s=s+pad
125 }
126 return s;
127}
128
BjornMagnussonXAbbd2e9d2020-05-27 21:24:06 +0200129//Function to check if the previous call has returned, if so return true, if not return false
130//For preventing multiple calls to slow containers.
131function checkFunctionFlag(flag) {
132 if (flagstore.hasOwnProperty(flag)) {
133 if (flagstore[flag] == 0) {
134 flagstore[flag]=1
135 return true
136 } else if (flagstore[flag] > 10) {
137 //Reset flag after ten attempts
138 console.log("Force release flag "+flag)
139 flagstore[flag]=1
140 return true
141 } else {
142 //Previous call not returned
143 console.log("Flag not available "+flag)
144 flagstore[flag]=flagstore[flag]+1
145 return false
146 }
147 } else {
148 flagstore[flag]=1
149 return true
150 }
151}
152//Clear flag for parameter
153function clearFlag(flag) {
154 flagstore[flag]=0
155}
156
BjornMagnussonXA80a92002020-03-19 14:31:06 +0100157//Status variables, for parameters values fetched from other simulators
158var mr1="", mr2="", mr3="", mr4="", mr5="", mr6="";
159
160//Status variables for agent
161var ag1=""
162var ag2=""
163var ag3=""
164var ag4=""
165
166//Status variables for callback receiver
167var cr1=""
168var cr2=""
169var cr3=""
170
171
172//Container names and ports of the ric simulator
173var simnames=[]
174var simports=[]
175
176//Status variables for each ric simulator
177var simvar1=[]
178var simvar2=[]
179var simvar3=[]
180var simvar4=[]
BjornMagnussonXA72667f12020-04-24 09:20:18 +0200181var simvar5=[]
BjornMagnussonXA80a92002020-03-19 14:31:06 +0100182
183//Counts the number of get request for the html page
184var getCtr=0
185
BjornMagnussonXA72667f12020-04-24 09:20:18 +0200186var refreshInterval=4000
187
BjornMagnussonXAad047782020-06-08 15:54:11 +0200188var ricbasename="ricsim"
189
BjornMagnussonXA80a92002020-03-19 14:31:06 +0100190function fetchAllMetrics() {
191 setTimeout(() => {
192
193 console.log("Fetching all metics data")
194 if (refreshInterval < 20000) {
195 refreshInterval+=100
196 }
197 if (getCtr%3 == 0) {
198 //Extract the port numbers from the running simulators, for every 3 calls
199 const { exec } = require('child_process');
BjornMagnussonXAad047782020-06-08 15:54:11 +0200200 exec('docker ps --filter "name='+ricbasename+'" --format "{{.Names}} {{.Ports}}" | sed s/0.0.0.0:// | cut -d \'>\' -f1 | sed \'s/[[-]]*$//\'', (err, stdout, stderr) => {
BjornMagnussonXA80a92002020-03-19 14:31:06 +0100201
202 var simulators = ""
203 simulators=`${stdout}`.replace(/(\r\n|\n|\r)/gm," ");
204 simulators=simulators.trim();
205 var sims=simulators.split(" ")
206 simnames=[]
207 simports=[]
208 for(i=0;i<sims.length;i=i+2) {
209 simnames[i/2]=sims[i]
210 simports[i/2]=sims[i+1]
211 }
212 });
213 }
214 getCtr=getCtr+1
215
216 //Get metric values from the simulators
217 for(var index=0;index<simnames.length;index++) {
BjornMagnussonXA72667f12020-04-24 09:20:18 +0200218
BjornMagnussonXAbbd2e9d2020-05-27 21:24:06 +0200219 if (checkFunctionFlag("simvar1_"+index)) {
220 getSimCtr(LOCALHOST+simports[index]+"/counter/num_instances", index, function(data, index) {
221 simvar1[index] = data;
222 clearFlag("simvar1_"+index)
223 });
BjornMagnussonXA72667f12020-04-24 09:20:18 +0200224 }
BjornMagnussonXAbbd2e9d2020-05-27 21:24:06 +0200225 if (checkFunctionFlag("simvar2_"+index)) {
226 getSimCtr(LOCALHOST+simports[index]+"/counter/num_types", index, function(data,index) {
227 simvar2[index] = data;
228 clearFlag("simvar2_"+index)
229 });
230 }
231 if (checkFunctionFlag("simvar3_"+index)) {
232 getSimCtr(LOCALHOST+simports[index]+"/policytypes", index, function(data,index) {
233 data=data.replace(/\[/g,'');
234 data=data.replace(/\]/g,'');
235 data=data.replace(/ /g,'');
236 data=data.replace(/\"/g,'');
237 simvar3[index] = data;
238 clearFlag("simvar3_"+index)
239 });
240 }
241 if (checkFunctionFlag("simvar4_"+index)) {
242 getSimCtr(LOCALHOST+simports[index]+"/counter/interface", index, function(data,index) {
243 simvar4[index] = data;
244 clearFlag("simvar4_"+index)
245 });
246 }
247 if (checkFunctionFlag("simvar5_"+index)) {
248 getSimCtr(LOCALHOST+simports[index]+"/counter/remote_hosts", index, function(data,index) {
249 simvar5[index] = data;
250 clearFlag("simvar5_"+index)
251 });
252 }
BjornMagnussonXA80a92002020-03-19 14:31:06 +0100253 }
254
255 //MR - get metrics values from the MR stub
BjornMagnussonXAbbd2e9d2020-05-27 21:24:06 +0200256 if (checkFunctionFlag("mr1")) {
257 getSimCtr(LOCALHOST+MRSTUB_PORT+"/counter/requests_submitted", 0, function(data, index) {
258 mr1 = data;
259 clearFlag("mr1")
260 });
261 }
262 if (checkFunctionFlag("mr2")) {
263 getSimCtr(LOCALHOST+MRSTUB_PORT+"/counter/requests_fetched", 0, function(data, index) {
264 mr2 = data;
265 clearFlag("mr2")
266 });
267 }
268 if (checkFunctionFlag("mr3")) {
269 getSimCtr(LOCALHOST+MRSTUB_PORT+"/counter/current_requests", 0, function(data, index) {
270 mr3 = data;
271 clearFlag("mr3")
272 });
273 }
274 if (checkFunctionFlag("mr4")) {
275 getSimCtr(LOCALHOST+MRSTUB_PORT+"/counter/responses_submitted", 0, function(data, index) {
276 mr4 = data;
277 clearFlag("mr4")
278 });
279 }
280 if (checkFunctionFlag("mr5")) {
281 getSimCtr(LOCALHOST+MRSTUB_PORT+"/counter/responses_fetched", 0, function(data, index) {
282 mr5 = data;
283 clearFlag("mr5")
284 });
285 }
286 if (checkFunctionFlag("mr6")) {
287 getSimCtr(LOCALHOST+MRSTUB_PORT+"/counter/current_responses", 0, function(data, index) {
288 mr6 = data;
289 clearFlag("mr6")
290 });
291 }
BjornMagnussonXA80a92002020-03-19 14:31:06 +0100292
293 //CR - get metrics values from the callbackreceiver
BjornMagnussonXAbbd2e9d2020-05-27 21:24:06 +0200294 if (checkFunctionFlag("cr1")) {
295 getSimCtr(LOCALHOST+CR_PORT+"/counter/received_callbacks", 0, function(data, index) {
296 cr1 = data;
297 clearFlag("cr1")
298 });
299 }
300 if (checkFunctionFlag("cr2")) {
301 getSimCtr(LOCALHOST+CR_PORT+"/counter/fetched_callbacks", 0, function(data, index) {
302 cr2 = data;
303 clearFlag("cr2")
304 });
305 }
306 if (checkFunctionFlag("cr3")) {
307 getSimCtr(LOCALHOST+CR_PORT+"/counter/current_messages", 0, function(data, index) {
308 cr3 = data;
309 clearFlag("cr3")
310 });
311 }
312 //Agent - more get metrics from the agent
313 if (checkFunctionFlag("ag1")) {
314 getSimCtr(LOCALHOST+AGENT_PORT+"/status", 0, function(data, index) {
315 ag1 = data;
316 clearFlag("ag1")
317 });
318 }
319 if (checkFunctionFlag("ag2")) {
320 getSimCtr(LOCALHOST+AGENT_PORT+"/services", 0, function(data, index) {
321 ag2="";
322 try {
323 var jd=JSON.parse(data);
324 for(var key in jd) {
325 if (ag2.length > 1) {
326 ag2=ag2+", "
327 }
328 ag2=ag2+(jd[key]["serviceName"]).trim()
BjornMagnussonXA80a92002020-03-19 14:31:06 +0100329 }
BjornMagnussonXA80a92002020-03-19 14:31:06 +0100330 }
BjornMagnussonXAbbd2e9d2020-05-27 21:24:06 +0200331 catch (err) {
332 ag2=data
333 }
334 clearFlag("ag2")
335 });
336 }
337 if (checkFunctionFlag("ag3")) {
338 getSimCtr(LOCALHOST+AGENT_PORT+"/policy_types", 0, function(data, index) {
339 ag3="";
340 try {
341 var jd=JSON.parse(data);
342 for(var key in jd) {
343 if (ag3.length > 0) {
344 ag3=ag3+", "
345 }
346 ag3=ag3+jd[key].trim()
BjornMagnussonXA80a92002020-03-19 14:31:06 +0100347 }
BjornMagnussonXA80a92002020-03-19 14:31:06 +0100348 }
BjornMagnussonXAbbd2e9d2020-05-27 21:24:06 +0200349 catch (err) {
350 ag3=""
351 }
352 clearFlag("ag3")
353 });
354 }
355 if (checkFunctionFlag("ag4")) {
356 getSimCtr(LOCALHOST+AGENT_PORT+"/policy_ids", 0, function(data, index) {
BjornMagnussonXA80a92002020-03-19 14:31:06 +0100357 ag4=""
BjornMagnussonXAbbd2e9d2020-05-27 21:24:06 +0200358 try {
359 var jd=JSON.parse(data);
360 ag4=""+jd.length
361 }
362 catch (err) {
363 ag4=""
364 }
365 clearFlag("ag4")
366 });
367 }
BjornMagnussonXA80a92002020-03-19 14:31:06 +0100368
369
370 fetchAllMetrics();
371 }, refreshInterval)
372}
373
374fetchAllMetrics();
375
376setInterval(() => {
377 console.log("Setting interval "+refreshInterval+"ms")
378}, refreshInterval)
379
380app.get("/mon",function(req, res){
381
BjornMagnussonXAad047782020-06-08 15:54:11 +0200382 var bn=req.query.basename
383
384 if (bn == undefined) {
385 getCtr=0
386 return res.redirect('/mon?basename=ricsim');
387 } else {
388 ricbasename=bn
389 }
BjornMagnussonXA80a92002020-03-19 14:31:06 +0100390
391 refreshInterval=2000
392
393 //Build web page
394 var htmlStr = "<!DOCTYPE html>" +
395 "<html>" +
396 "<head>" +
397 "<meta http-equiv=\"refresh\" content=\"2\">"+ //2 sec auto refresh
398 "<title>Policy Agent and simulator monitor</title>"+
399 "</head>" +
400 "<body>" +
BjornMagnussonXAad047782020-06-08 15:54:11 +0200401 "<font size=\"-3\" face=\"monospace\">" +
402 "<p>Change basename in url if other ric sim prefix is used</p>" +
403 "</font>" +
BjornMagnussonXA80a92002020-03-19 14:31:06 +0100404 "<h3>Policy agent</h3>" +
405 "<font face=\"monospace\">" +
406 "Status:..............................." + formatDataRow(ag1) + "<br>" +
407 "Services:............................." + formatIdRowCompact(ag2) + "<br>" +
408 "Types:................................" + formatIdRowCompact(ag3) + "<br>" +
409 "Number of instances:.................." + formatDataRow(ag4) + "<br>" +
410 "</font>" +
411 "<h3>MR Stub interface</h3>" +
412 "<font face=\"monospace\">"+
413 "Submitted requests:............................" + formatDataRow(mr1) + "<br>" +
414 "Fetched requests:.............................." + formatDataRow(mr2) + "<br>" +
415 "Current requests waiting:......................" + formatDataRow(mr3) + "<br>" +
416 "Submitted responses:..........................." + formatDataRow(mr4) + "<br>" +
417 "Fetched responses.............................." + formatDataRow(mr5) + "<br>" +
418 "Current responses waiting......................" + formatDataRow(mr6) + "<br>" +
419 "</font>"+
420 "<h3>Callback receiver</h3>" +
421 "<font face=\"monospace\">" +
422 "Callbacks received:..................." + formatDataRow(cr1) + "<br>" +
423 "Callbacks fetched:...................." + formatDataRow(cr2) + "<br>" +
424 "Number of waiting callback messages:.." + formatDataRow(cr3) + "<br>" +
425 "</font>" +
426 "<h3>Near-RT RIC Simulators</h3>" +
427 "<font face=\"monospace\">"
428
429 htmlStr=htmlStr+padding("Near-RT RIC Simulator name", 35,"&nbsp;")
430 htmlStr=htmlStr+padding("Types", 10,"&nbsp;")
BjornMagnussonXA72667f12020-04-24 09:20:18 +0200431 htmlStr=htmlStr+padding("Instances", 10,"&nbsp;")+"<br>"
432 htmlStr=htmlStr+padding("",55,"=")+"<br>"
BjornMagnussonXA80a92002020-03-19 14:31:06 +0100433 for(var simIndex=0;simIndex<simnames.length;simIndex++) {
434 htmlStr=htmlStr+padding(simnames[simIndex]+ " ("+simports[simIndex]+")",35,"&nbsp;");
435 htmlStr=htmlStr+padding(simvar2[simIndex],10,"&nbsp;")
436 htmlStr=htmlStr+padding(simvar1[simIndex],10,"&nbsp;")
437 htmlStr=htmlStr+"<br>";
438 }
439
440 htmlStr=htmlStr+"<br>";
441 htmlStr=htmlStr+padding("Near-RT RIC Simulator name", 35,"&nbsp;")
442 htmlStr=htmlStr+padding("Version", 20,"&nbsp;")
443 htmlStr=htmlStr+padding("Type-IDs", 10,"&nbsp;")+"<br>"
444 htmlStr=htmlStr+padding("",65,"=")+"<br>"
445 for(simIndex=0;simIndex<simnames.length;simIndex++) {
446 htmlStr=htmlStr+padding(simnames[simIndex]+ " ("+simports[simIndex]+")",35,"&nbsp;");
447 htmlStr=htmlStr+padding(simvar4[simIndex],20,"&nbsp;")
448 htmlStr=htmlStr+padding(formatIdRowCompact(simvar3[simIndex]),10,"&nbsp;")
449 htmlStr=htmlStr+"<br>";
450 }
451
BjornMagnussonXA72667f12020-04-24 09:20:18 +0200452 htmlStr=htmlStr+"<br>";
453 htmlStr=htmlStr+padding("Near-RT RIC Simulator name", 35,"&nbsp;")
454 htmlStr=htmlStr+padding("Remote hosts", 50,"&nbsp;")+"<br>"
455 htmlStr=htmlStr+padding("",90,"=")+"<br>"
456 for(simIndex=0;simIndex<simnames.length;simIndex++) {
457 htmlStr=htmlStr+padding(simnames[simIndex]+ " ("+simports[simIndex]+")",35,"&nbsp;");
458 htmlStr=htmlStr+padding(simvar5[simIndex],50,"&nbsp;")
459 htmlStr=htmlStr+"<br>";
460 }
461
BjornMagnussonXA80a92002020-03-19 14:31:06 +0100462 htmlStr=htmlStr+
463 "</body>" +
464 "</html>";
465 res.send(htmlStr);
466})
467
468var httpServer = http.createServer(app);
469var httpPort=9999;
470httpServer.listen(httpPort);
471console.log("Simulator monitor listening (http) at "+httpPort);
472console.log("Open the web page on localhost:9999/mon to view the statistics page.")