Adapted test scripts to changes in PMS 2.0
[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 MRSTUB_PORT="3905"
25 var AGENT_PORT="8081"
26 var CR_PORT="8090"
27 var ECS_PORT="8083"
28 var PRODSTUB_PORT="8092"
29
30 var http = require('http');
31
32 var express = require('express');
33 const { POINT_CONVERSION_HYBRID } = require('constants')
34 var app = express();
35 var fieldSize=32;
36
37 var flagstore={}
38
39 //I am alive
40 app.get("/",function(req, res){
41         res.send("ok");
42 })
43
44 //Get parameter value from other server
45 function getSimCtr(url, index, cb) {
46     var data = '';
47
48     try {
49         http.get(url, (resp) => {
50             // A chunk of data has been recieved.
51             resp.on('data', (chunk) => {
52                 data += chunk;
53             });
54
55             // The whole response has been received.
56             resp.on('end', () => {
57                 var code=resp.statusCode
58                 if (code > 199 && code < 300) {
59                     cb(data, index);
60                 } else {
61                     cb("not found", index);
62                 }
63             });
64
65         }).on("error", (err) => {
66             console.log("Error: " + err.message);
67             cb("no response", index);
68         });
69     } catch(err) {
70         cb("no response", index);
71     }
72 };
73
74
75 //Format a comma separated list of data to a html-safe string with fixed fieldsizes
76 function formatDataRow(commaList) {
77         var str = "";
78         var tmp=commaList.split(',');
79     for(var i=0;i<tmp.length;i++) {
80         var data=tmp[i];
81         var len = fieldSize-data.length;
82         while(len>0) {
83             data = data+"&nbsp;";
84             len--;
85         }
86         str=str+data+"&nbsp;&nbsp;&nbsp;";
87      }
88         return str;
89 }
90
91 //Format a comma separated list of ids to a html-safe string with fixed fieldsizes
92 function formatIdRow(commaList) {
93         var str = "";
94         var tmp=commaList.split(',');
95     for(var i=0;i<tmp.length;i++) {
96         tmp[i] = tmp[i].trim();
97         var data="&lt"+tmp[i]+"&gt";
98         var len = fieldSize+4-data.length;
99         while(len>0) {
100             data = data+"&nbsp;";
101             len--;
102         }
103         str=str+data+"&nbsp;&nbsp;&nbsp;";
104     }
105         return str;
106 }
107
108 //Format a list of ids to a html-safe string in compact format
109 function formatIdRowCompact(commaList) {
110     if (commaList == undefined) {
111         commaList= "";
112     }
113         var str = "";
114         var tmp=commaList.split(',');
115     for(var i=0;i<tmp.length;i++) {
116         tmp[i] = tmp[i].trim();
117         var data="&lt"+tmp[i]+"&gt";
118         str=str+data+"&nbsp;";
119     }
120         return str;
121 }
122
123 //Pad a string upto a certain size using a pad string
124 function padding(val, fieldSize, pad) {
125         var s=""+val;
126         for(var i=s.length;i<fieldSize;i++) {
127                 s=s+pad
128         }
129         return s;
130 }
131
132 //Function to check if the previous call has returned, if so return true, if not return false
133 //For preventing multiple calls to slow containers.
134 function checkFunctionFlag(flag) {
135     if (flagstore.hasOwnProperty(flag)) {
136         if (flagstore[flag] == 0) {
137             flagstore[flag]=1
138             return true
139         } else if (flagstore[flag] > 10) {
140             //Reset flag after ten attempts
141             console.log("Force release flag "+flag)
142             flagstore[flag]=1
143             return true
144         } else {
145             //Previous call not returned
146             console.log("Flag not available "+flag)
147             flagstore[flag]=flagstore[flag]+1
148             return false
149         }
150     } else {
151         flagstore[flag]=1
152         return true
153     }
154 }
155 //Clear flag for parameter
156 function clearFlag(flag) {
157     flagstore[flag]=0
158 }
159
160 //Status variables, for parameters values fetched from other simulators
161 var mr1="", mr2="", mr3="", mr4="", mr5="", mr6="";
162
163 //Status variables for agent
164 var ag1=""
165 var ag2=""
166 var ag3=""
167 var ag4=""
168 var ag5=""
169
170 //Status variables for callback receiver
171 var cr1=""
172 var cr2=""
173 var cr3=""
174
175
176 //Container names and ports of the ric simulator
177 var simnames=[]
178 var simports=[]
179
180 //Status variables for each ric simulator
181 var simvar1=[]
182 var simvar2=[]
183 var simvar3=[]
184 var simvar4=[]
185 var simvar5=[]
186 var simvar6=[]
187
188 //Status variables, for parameters values fetched from ecs
189 var ecs1="", ecs2="", ecs3="", ecs4="", ecs_types="-", ecs_producers="-";
190 var ecs_producer_arr=new Array(0)
191 var ecs_producer_type_arr=new Array(0)
192 var ecs_producer_jobs_arr=new Array(0)
193 var ecs_producer_status_arr=new Array(0)
194
195 //Status variables, for parameters values fetched from prodstub
196 var ps2="", ps3="", ps4="", ps_types="-", ps_producers="-";
197 var ps_producer_type_arr=new Array(0)
198 var ps_producer_jobs_arr=new Array(0)
199 var ps_producer_delivery_arr=new Array(0)
200
201 //Full CR DB
202 var cr_db={}
203
204 //Counts the number of get request for the html page
205 var getCtr=0
206
207 var refreshCount_pol=-1
208
209 var refreshCount_ecs=-1
210
211 var refreshCount_cr=-1
212
213 var ricbasename="ricsim"
214
215 function fetchAllMetrics_pol() {
216
217     console.log("Fetching policy metrics " + refreshCount_pol)
218
219     if (refreshCount_pol < 0) {
220         refreshCount_pol = -1
221         return
222     } else {
223         refreshCount_pol = refreshCount_pol - 1
224     }
225     setTimeout(() => {
226
227         if (getCtr%3 == 0) {
228             //Extract the port numbers from the running simulators, for every 3 calls
229             const { exec } = require('child_process');
230             exec('docker ps --filter "name='+ricbasename+'" --format "{{.Names}} {{.Ports}}" | sed s/0.0.0.0:// | cut -d \'>\' -f1 | sed \'s/[[-]]*$//\'', (err, stdout, stderr) => {
231
232                 var simulators = ""
233                 simulators=`${stdout}`.replace(/(\r\n|\n|\r)/gm," ");
234                 simulators=simulators.trim();
235                 var sims=simulators.split(" ")
236                 simnames=[]
237                 simports=[]
238                 for(i=0;i<sims.length;i=i+2) {
239                     simnames[i/2]=sims[i]
240                     simports[i/2]=sims[i+1]
241                 }
242             });
243         }
244         getCtr=getCtr+1
245
246         //Get metric values from the simulators
247         for(var index=0;index<simnames.length;index++) {
248
249             if (checkFunctionFlag("simvar1_"+index)) {
250                 getSimCtr(LOCALHOST+simports[index]+"/counter/num_instances", index, function(data, index) {
251                     simvar1[index] = data;
252                     clearFlag("simvar1_"+index)
253                 });
254             }
255             if (checkFunctionFlag("simvar2_"+index)) {
256                 getSimCtr(LOCALHOST+simports[index]+"/counter/num_types", index, function(data,index) {
257                     simvar2[index] = data;
258                     clearFlag("simvar2_"+index)
259                 });
260             }
261             if (checkFunctionFlag("simvar3_"+index)) {
262                 getSimCtr(LOCALHOST+simports[index]+"/policytypes", index, function(data,index) {
263                     data=data.replace(/\[/g,'');
264                     data=data.replace(/\]/g,'');
265                     data=data.replace(/ /g,'');
266                     data=data.replace(/\"/g,'');
267                     simvar3[index] = data;
268                     clearFlag("simvar3_"+index)
269                 });
270             }
271             if (checkFunctionFlag("simvar4_"+index)) {
272                 getSimCtr(LOCALHOST+simports[index]+"/counter/interface", index, function(data,index) {
273                     simvar4[index] = data;
274                     clearFlag("simvar4_"+index)
275                 });
276             }
277             if (checkFunctionFlag("simvar5_"+index)) {
278                 getSimCtr(LOCALHOST+simports[index]+"/counter/remote_hosts", index, function(data,index) {
279                     simvar5[index] = data;
280                     clearFlag("simvar5_"+index)
281                 });
282             }
283             if (checkFunctionFlag("simvar6_"+index)) {
284                 getSimCtr(LOCALHOST+simports[index]+"/counter/datadelivery", index, function(data,index) {
285                     simvar6[index] = data;
286                     clearFlag("simvar6_"+index)
287                 });
288             }
289         }
290
291         //MR - get metrics values from the MR stub
292         if (checkFunctionFlag("mr1")) {
293             getSimCtr(LOCALHOST+MRSTUB_PORT+"/counter/requests_submitted", 0, function(data, index) {
294                 mr1 = data;
295                 clearFlag("mr1")
296             });
297         }
298         if (checkFunctionFlag("mr2")) {
299             getSimCtr(LOCALHOST+MRSTUB_PORT+"/counter/requests_fetched", 0, function(data, index) {
300                 mr2 = data;
301                 clearFlag("mr2")
302             });
303         }
304         if (checkFunctionFlag("mr3")) {
305             getSimCtr(LOCALHOST+MRSTUB_PORT+"/counter/current_requests", 0, function(data, index) {
306                 mr3 = data;
307                 clearFlag("mr3")
308             });
309         }
310         if (checkFunctionFlag("mr4")) {
311             getSimCtr(LOCALHOST+MRSTUB_PORT+"/counter/responses_submitted", 0, function(data, index) {
312                 mr4 = data;
313                 clearFlag("mr4")
314             });
315         }
316         if (checkFunctionFlag("mr5")) {
317             getSimCtr(LOCALHOST+MRSTUB_PORT+"/counter/responses_fetched", 0, function(data, index) {
318                 mr5 = data;
319                 clearFlag("mr5")
320             });
321         }
322         if (checkFunctionFlag("mr6")) {
323             getSimCtr(LOCALHOST+MRSTUB_PORT+"/counter/current_responses", 0, function(data, index) {
324                 mr6 = data;
325                 clearFlag("mr6")
326             });
327         }
328
329         //CR - get metrics values from the callbackreceiver
330         if (checkFunctionFlag("cr1")) {
331             getSimCtr(LOCALHOST+CR_PORT+"/counter/received_callbacks", 0, function(data, index) {
332                 cr1 = data;
333                 clearFlag("cr1")
334             });
335         }
336         if (checkFunctionFlag("cr2")) {
337             getSimCtr(LOCALHOST+CR_PORT+"/counter/fetched_callbacks", 0, function(data, index) {
338                 cr2 = data;
339                 clearFlag("cr2")
340             });
341         }
342         if (checkFunctionFlag("cr3")) {
343             getSimCtr(LOCALHOST+CR_PORT+"/counter/current_messages", 0, function(data, index) {
344                 cr3 = data;
345                 clearFlag("cr3")
346             });
347         }
348         //Agent - more get metrics from the agent
349         if (checkFunctionFlag("ag1")) {
350             getSimCtr(LOCALHOST+AGENT_PORT+"/status", 0, function(data, index) {
351                 ag1 = data;
352                 clearFlag("ag1")
353             });
354         }
355         if (checkFunctionFlag("ag2")) {
356             getSimCtr(LOCALHOST+AGENT_PORT+"/services", 0, function(data, index) {
357                 ag2="";
358                 try {
359                     var jd=JSON.parse(data);
360                     for(var key in jd) {
361                         if (ag2.length > 1) {
362                             ag2=ag2+", "
363                         }
364                         ag2=ag2+(jd[key]["serviceName"]).trim()
365                     }
366                 }
367                 catch (err) {
368                     ag2=data
369                 }
370                 clearFlag("ag2")
371             });
372         }
373         if (checkFunctionFlag("ag3")) {
374             getSimCtr(LOCALHOST+AGENT_PORT+"/policy_types", 0, function(data, index) {
375                 ag3="";
376                 try {
377                     var jd=JSON.parse(data);
378                     for(var key in jd) {
379                         if (ag3.length > 0) {
380                             ag3=ag3+", "
381                         }
382                         ag3=ag3+jd[key].trim()
383                     }
384                 }
385                 catch (err) {
386                     ag3=""
387                 }
388                 clearFlag("ag3")
389             });
390         }
391
392         if (checkFunctionFlag("ag4")) {
393             getSimCtr(LOCALHOST+AGENT_PORT+"/policy_ids", 0, function(data, index) {
394                 try {
395                     var jd=JSON.parse(data);
396                     ag4=""+jd.length
397                 }
398                 catch (err) {
399                     ag4=""
400                 }
401                 clearFlag("ag4")
402             });
403         }
404
405         if (checkFunctionFlag("ag5")) {
406             getSimCtr(LOCALHOST+AGENT_PORT+"/rics", 0, function(data, index) {
407                 try {
408                     var jd=JSON.parse(data);
409                     ag5=""+jd.length
410                 }
411                 catch (err) {
412                     ag5=""
413                 }
414                 clearFlag("ag5")
415             });
416         }
417
418         fetchAllMetrics_pol();
419
420     }, 500)
421 }
422
423 function fetchAllMetrics_ecs() {
424
425     console.log("Fetching enrichment metrics - timer:" + refreshCount_ecs)
426
427     if (refreshCount_ecs < 0) {
428         refreshCount_ecs = -1
429         return
430     } else {
431         refreshCount_ecs = refreshCount_ecs - 1
432     }
433     setTimeout(() => {
434
435         if (checkFunctionFlag("ecs_stat")) {
436             getSimCtr(LOCALHOST+ECS_PORT+"/status", 0, function(data, index) {
437                 ecs1=""
438                 ecs2=""
439                 ecs3=""
440                 ecs4=""
441                 try {
442                     var jd=JSON.parse(data);
443                     ecs1=jd["status"]
444                     ecs2=""+jd["no_of_producers"]
445                     ecs3=""+jd["no_of_types"]
446                     ecs4=""+jd["no_of_jobs"]
447                 }
448                 catch (err) {
449                     ecs1="error response"
450                     ecs2="error response"
451                     ecs3="error response"
452                     ecs4="error response"
453                 }
454             });
455
456             getSimCtr(LOCALHOST+ECS_PORT+"/ei-producer/v1/eitypes", 0, function(data, index) {
457                 ecs_types="-"
458                 try {
459                     var jd=JSON.parse(data);
460                     for(var i=0;i<jd.length;i++) {
461                         if (ecs_types.length == 1) {
462                             ecs_types=""
463                         }
464                         ecs_types=""+ecs_types+jd[i]+" "
465                     }
466                 }
467                 catch (err) {
468                     ecs_types="error response"
469                 }
470             });
471
472             getSimCtr(LOCALHOST+ECS_PORT+"/ei-producer/v1/eiproducers", 0, function(data, index) {
473                 ecs_producers="-"
474                 try {
475                     var jd=JSON.parse(data);
476                     var tmp_ecs_producer_arr=new Array(jd.length)
477                     for(var i=0;i<jd.length;i++) {
478                         if (ecs_producers.length == 1) {
479                             ecs_producers=""
480                         }
481                         ecs_producers=""+ecs_producers+jd[i]+" "
482                         tmp_ecs_producer_arr[i]=jd[i]
483                     }
484                     ecs_producer_arr = tmp_ecs_producer_arr
485                 }
486                 catch (err) {
487                     ecs_producers="error response"
488                     ecs_producer_arr=new Array(0)
489                 }
490             });
491
492             ecs_producer_type_arr = JSON.parse(JSON.stringify(ecs_producer_arr))
493             for(var x=0;x<ecs_producer_type_arr.length;x++) {
494                 getSimCtr(LOCALHOST+ECS_PORT+"/ei-producer/v1/eiproducers/"+ecs_producer_type_arr[x], x, function(data, x) {
495                     var row=""+ecs_producer_type_arr[x]+" : "
496                     try {
497                         var jd=JSON.parse(data);
498                         var jda=jd["supported_ei_types"]
499                         for(var j=0;j<jda.length;j++) {
500                             row=""+row+jda[j]["ei_type_identity"]+" "
501                         }
502                         ecs_producer_type_arr[x]=row
503                     }
504                     catch (err) {
505                         ecs_producer_type_arr=new Array(0)
506                     }
507                 });
508             }
509
510             ecs_producer_jobs_arr = JSON.parse(JSON.stringify(ecs_producer_arr))
511             for(var x=0;x<ecs_producer_jobs_arr.length;x++) {
512                 getSimCtr(LOCALHOST+ECS_PORT+"/ei-producer/v1/eiproducers/"+ecs_producer_jobs_arr[x]+"/eijobs", x, function(data, x) {
513                     var row=""+ecs_producer_jobs_arr[x]+" : "
514                     try {
515                         var jd=JSON.parse(data);
516                         for(var j=0;j<jd.length;j++) {
517                             var jda=jd[j]
518                             row=""+row+jda["ei_job_identity"]+"("+jda["ei_type_identity"]+") "
519                         }
520                         ecs_producer_jobs_arr[x]=row
521                     }
522                     catch (err) {
523                         ecs_producer_jobs_arr=new Array(0)
524                     }
525                 });
526             }
527
528             ecs_producer_status_arr = JSON.parse(JSON.stringify(ecs_producer_arr))
529             for(var x=0;x<ecs_producer_status_arr.length;x++) {
530                 getSimCtr(LOCALHOST+ECS_PORT+"/ei-producer/v1/eiproducers/"+ecs_producer_status_arr[x]+"/status", x, function(data, x) {
531                     var row=""+ecs_producer_status_arr[x]+" : "
532                     try {
533                         var jd=JSON.parse(data);
534                         row=""+row+jd["operational_state"]
535                         ecs_producer_status_arr[x]=row
536                     }
537                     catch (err) {
538                         ecs_producer_status_arr=new Array(0)
539                     }
540                 });
541             }
542             clearFlag("ecs_stat")
543         }
544         if (checkFunctionFlag("prodstub_stat")) {
545             getSimCtr(LOCALHOST+PRODSTUB_PORT+"/status", x, function(data, x) {
546                 var ctr2_map=new Map()
547                 var ctr3_map=new Map()
548                 var ctr2=0
549                 var ctr4=0
550                 ps_producers=""
551                 ps_types=""
552                 ps_producer_type_arr=new Array()
553                 ps_producer_jobs_arr=new Array()
554                 ps_producer_delivery_arr=new Array()
555                 ps2=""
556                 ps3=""
557                 ps4=""
558                 try {
559                     var jp=JSON.parse(data);
560                     for(var prod_name in jp) {
561                         ctr2_map.set(prod_name, prod_name)
562                         ctr2 += 1
563                         var jj=jp[prod_name]
564                         var row=""+prod_name+" : "
565                         var rowj=""+prod_name+" : "
566                         var rowd=""+prod_name+" : "
567                         ps_producers += prod_name + " "
568                         for(var ji in jj) {
569                             if (ji == "types") {
570                                 var ta=jj[ji]
571                                 for(var i=0;i<ta.length;i++) {
572                                     ctr3_map.set(ta[i], ta[i])
573                                     row += " "+ta[i]
574                                 }
575                             } else if (ji == "supervision_response") {
576                             } else if (ji == "supervision_counter") {
577                             } else if (ji == "types") {
578                             } else {
579                                 ctr4 += 1
580                                 rowj += " "+ji
581                                 rowd += " "+ji
582                                 var job_data=jj[ji]["json"]
583                                 if (job_data != undefined) {
584                                     rowj += "("+job_data["ei_type_identity"]+")"
585                                 }
586                                 rowd += "("+jj[ji]["delivery_attempts"]+")"
587                             }
588                         }
589                         ps_producer_type_arr[(ctr2-1)]=row
590                         ps_producer_jobs_arr[(ctr2-1)]=rowj
591                         ps_producer_delivery_arr[(ctr2-1)]=rowd
592                     }
593                     ps2=""+ctr2_map.size
594                     ps3=""+ctr3_map.size
595                     for(const [key, value] of ctr3_map.entries()) {
596                         ps_types += key + " "
597                     }
598                     ps4=""+ctr4
599                 }
600                 catch (err) {
601                     console.error(err);
602                     ps_producers="error response"
603                     ps_types="error response"
604                     ps_producer_type_arr=new Array()
605                     ps_producer_jobs_arr=new Array()
606                     ps_producer_delivery_arr=new Array()
607                     ps2="error response"
608                     ps3="error response"
609                     ps4="error response"
610                 }
611             });
612             clearFlag("prodstub_stat")
613         }
614
615         fetchAllMetrics_ecs();
616
617     }, 500)
618 }
619
620 function fetchAllMetrics_cr() {
621
622     console.log("Fetching CR DB - timer:" + refreshCount_ecs)
623
624     if (refreshCount_cr < 0) {
625         refreshCount_cr = -1
626         return
627     } else {
628         refreshCount_cr = refreshCount_cr - 1
629     }
630     setTimeout(() => {
631
632         if (checkFunctionFlag("cr_stat")) {
633             getSimCtr(LOCALHOST+CR_PORT+"/db", 0, function(data, index) {
634                 ecs4=""
635                 try {
636                     cr_db=JSON.parse(data);
637                 }
638                 catch (err) {
639                     cr_db={}
640                 }
641             });
642             clearFlag("cr_stat")
643         }
644         fetchAllMetrics_cr();
645     }, 500)
646 }
647
648 // Monitor for CR db
649 app.get("/mon3",function(req, res){
650
651     console.log("Creating CR DB page - timer: " + refreshCount_ecs)
652
653     if (refreshCount_cr < 0) {
654         refreshCount_cr=5
655         fetchAllMetrics_cr()
656     }
657     refreshCount_cr=5
658     var json_str=JSON.stringify(cr_db, null, 1)
659     var htmlStr = "<!DOCTYPE html>" +
660     "<html>" +
661     "<head>" +
662       "<meta http-equiv=\"refresh\" content=\"2\">"+  //2 sec auto refresh
663       "<title>CR DB dump</title>"+
664       "</head>" +
665       "<body style=\"white-space: pre-wrap\">" +
666       json_str +
667       "</body>" +
668       "</html>";
669     res.send(htmlStr);
670 })
671
672 // Monitor for ECS
673 app.get("/mon2",function(req, res){
674
675     console.log("Creating enrichment metrics - timer: " + refreshCount_ecs)
676
677     if (refreshCount_ecs < 0) {
678         refreshCount_ecs=5
679         fetchAllMetrics_ecs()
680     }
681     refreshCount_ecs=5
682
683     var summary=req.query.summary
684
685     if (summary == undefined) {
686         return res.redirect('/mon2?summary=false');
687     }
688
689   //Build web page
690         var htmlStr = "<!DOCTYPE html>" +
691           "<html>" +
692           "<head>" +
693             "<meta http-equiv=\"refresh\" content=\"2\">"+  //2 sec auto refresh
694             "<title>Enrichment coordinator service and producer stub</title>"+
695             "</head>" +
696             "<body>" +
697             "<font size=\"-3\" face=\"summary\">"
698             if (summary == "false") {
699                 htmlStr=htmlStr+"<p>Set query param '?summary' to true to only show summary statistics</p>"
700             } else {
701                 htmlStr=htmlStr+"<p>Set query param '?summary' to false to only show full statistics</p>"
702             }
703             htmlStr=htmlStr+"</font>" +
704             "<h3>Enrichment Coordinator Service</h3>" +
705             "<font face=\"monospace\">" +
706             "Status:..........." + formatDataRow(ecs1) + "<br>" +
707             "Producers:........" + formatDataRow(ecs2) + "<br>" +
708             "Types:............" + formatDataRow(ecs3) + "<br>" +
709             "Jobs:............." + formatDataRow(ecs4) + "<br>" +
710             "</font>"
711             if (summary == "false") {
712                 htmlStr=htmlStr+
713                 "<h4>Details</h4>" +
714                 "<font face=\"monospace\">" +
715                 "Producer ids:....." + formatDataRow(ecs_producers) + "<br>" +
716                 "Type ids:........." + formatDataRow(ecs_types) + "<br>" +
717                 "<br>";
718                 for(var i=0;i<ecs_producer_type_arr.length;i++) {
719                     var tmp=ecs_producer_type_arr[i]
720                     if (tmp != undefined) {
721                         var s = "Producer types...." + formatDataRow(ecs_producer_type_arr[i]) + "<br>"
722                         htmlStr=htmlStr+s
723                     }
724                 }
725                 htmlStr=htmlStr+"<br>";
726                 for(var i=0;i<ecs_producer_jobs_arr.length;i++) {
727                     var tmp=ecs_producer_jobs_arr[i]
728                     if (tmp != undefined) {
729                         var s = "Producer jobs....." + formatDataRow(ecs_producer_jobs_arr[i]) + "<br>"
730                         htmlStr=htmlStr+s
731                     }
732                 }
733                 htmlStr=htmlStr+"<br>";
734                 for(var i=0;i<ecs_producer_status_arr.length;i++) {
735                     var tmp=ecs_producer_status_arr[i]
736                     if (tmp != undefined) {
737                         var s = "Producer status..." + formatDataRow(ecs_producer_status_arr[i]) + "<br>"
738                         htmlStr=htmlStr+s
739                     }
740                 }
741                 htmlStr=htmlStr+"<br>"+"<br>" +
742                 "</font>"
743             }
744             htmlStr=htmlStr+
745             "<h3>Producer stub</h3>" +
746             "<font face=\"monospace\">" +
747             "Producers:........" + formatDataRow(ps2) + "<br>" +
748             "Types:............" + formatDataRow(ps3) + "<br>" +
749             "Jobs:............." + formatDataRow(ps4) + "<br>" +
750             "</font>"
751             if (summary == "false") {
752                 htmlStr=htmlStr+
753                 "<h4>Details</h4>" +
754                 "<font face=\"monospace\">" +
755                 "Producer ids:....." + formatDataRow(ps_producers) + "<br>" +
756                 "Type ids:........." + formatDataRow(ps_types) + "<br>" +
757                 "<br>";
758                 for(var i=0;i<ps_producer_type_arr.length;i++) {
759                     var tmp=ps_producer_type_arr[i]
760                     if (tmp != undefined) {
761                         var s = "Producer types...." + formatDataRow(ps_producer_type_arr[i]) + "<br>"
762                         htmlStr=htmlStr+s
763                     }
764                 }
765                 htmlStr=htmlStr+"<br>";
766                 for(var i=0;i<ps_producer_jobs_arr.length;i++) {
767                     var tmp=ps_producer_jobs_arr[i]
768                     if (tmp != undefined) {
769                         var s = "Producer jobs....." + formatDataRow(ps_producer_jobs_arr[i]) + "<br>"
770                         htmlStr=htmlStr+s
771                     }
772                 }
773                 htmlStr=htmlStr+"<br>";
774                 for(var i=0;i<ps_producer_delivery_arr.length;i++) {
775                     var tmp=ps_producer_delivery_arr[i]
776                     if (tmp != undefined) {
777                         var s = "Producer delivery." + formatDataRow(ps_producer_delivery_arr[i]) + "<br>"
778                         htmlStr=htmlStr+s
779                     }
780                 }
781             }
782             htmlStr=htmlStr+
783             "</font>" +
784            "</body>" +
785           "</html>";
786         res.send(htmlStr);
787 })
788
789 // Monitor for policy management
790 app.get("/mon",function(req, res){
791
792     console.log("Creating policy metrics page " + refreshCount_pol)
793
794     if (refreshCount_pol < 0) {
795         refreshCount_pol=5
796         fetchAllMetrics_pol()
797     }
798     refreshCount_pol=5
799
800     var bn=req.query.basename
801
802     if (bn == undefined) {
803         getCtr=0
804         return res.redirect('/mon?basename=ricsim');
805     } else {
806         ricbasename=bn
807     }
808
809     //Build web page
810         var htmlStr = "<!DOCTYPE html>" +
811           "<html>" +
812           "<head>" +
813             "<meta http-equiv=\"refresh\" content=\"2\">"+  //2 sec auto refresh
814             "<title>Policy Agent and simulator monitor</title>"+
815             "</head>" +
816             "<body>" +
817             "<font size=\"-3\" face=\"monospace\">" +
818             "<p>Change basename in url if other ric sim prefix is used</p>" +
819             "</font>" +
820             "<h3>Policy agent</h3>" +
821             "<font face=\"monospace\">" +
822             "Status:..............................." + formatDataRow(ag1) + "<br>" +
823             "Services:............................." + formatIdRowCompact(ag2) + "<br>" +
824             "Types:................................" + formatIdRowCompact(ag3) + "<br>" +
825             "Number of instances:.................." + formatDataRow(ag4) + "<br>" +
826             "Near-RT RICs:........................." + formatDataRow(ag5) + "<br>" +
827             "</font>" +
828             "<h3>MR Stub interface</h3>" +
829             "<font face=\"monospace\">"+
830             "Submitted requests:............................" + formatDataRow(mr1) + "<br>" +
831             "Fetched requests:.............................." + formatDataRow(mr2) + "<br>" +
832             "Current requests waiting:......................" + formatDataRow(mr3) + "<br>" +
833             "Submitted responses:..........................." + formatDataRow(mr4) + "<br>" +
834             "Fetched responses.............................." + formatDataRow(mr5) + "<br>" +
835             "Current responses waiting......................" + formatDataRow(mr6) + "<br>" +
836             "</font>"+
837             "<h3>Callback receiver</h3>" +
838             "<font face=\"monospace\">" +
839             "Callbacks received:..................." + formatDataRow(cr1) + "<br>" +
840             "Callbacks fetched:...................." + formatDataRow(cr2) + "<br>" +
841             "Number of waiting callback messages:.." + formatDataRow(cr3) + "<br>" +
842             "</font>" +
843             "<h3>Near-RT RIC Simulators</h3>" +
844             "<font face=\"monospace\">"
845
846             htmlStr=htmlStr+padding("Near-RT RIC Simulator name", 35,"&nbsp;")
847             htmlStr=htmlStr+padding("Types", 10,"&nbsp;")
848             htmlStr=htmlStr+padding("Instances", 12,"&nbsp;")
849             htmlStr=htmlStr+padding("Data delivery", 12,"&nbsp;")+"<br>"
850             htmlStr=htmlStr+padding("",70,"=")+"<br>"
851             for(var simIndex=0;simIndex<simnames.length;simIndex++) {
852                 htmlStr=htmlStr+padding(simnames[simIndex]+ " ("+simports[simIndex]+")",35,"&nbsp;");
853                 htmlStr=htmlStr+padding(simvar2[simIndex],10,"&nbsp;")
854                 htmlStr=htmlStr+padding(simvar1[simIndex],12    ,"&nbsp;")
855                 htmlStr=htmlStr+padding(simvar6[simIndex],12,"&nbsp;")
856                 htmlStr=htmlStr+"<br>";
857             }
858
859             htmlStr=htmlStr+"<br>";
860             htmlStr=htmlStr+padding("Near-RT RIC Simulator name", 35,"&nbsp;")
861             htmlStr=htmlStr+padding("Version", 20,"&nbsp;")
862             htmlStr=htmlStr+padding("Type-IDs", 10,"&nbsp;")+"<br>"
863             htmlStr=htmlStr+padding("",65,"=")+"<br>"
864             for(simIndex=0;simIndex<simnames.length;simIndex++) {
865                 htmlStr=htmlStr+padding(simnames[simIndex]+ " ("+simports[simIndex]+")",35,"&nbsp;");
866                 htmlStr=htmlStr+padding(simvar4[simIndex],20,"&nbsp;")
867                 htmlStr=htmlStr+padding(formatIdRowCompact(simvar3[simIndex]),10,"&nbsp;")
868                 htmlStr=htmlStr+"<br>";
869             }
870
871             htmlStr=htmlStr+"<br>";
872             htmlStr=htmlStr+padding("Near-RT RIC Simulator name", 35,"&nbsp;")
873             htmlStr=htmlStr+padding("Remote hosts", 50,"&nbsp;")+"<br>"
874             htmlStr=htmlStr+padding("",90,"=")+"<br>"
875             for(simIndex=0;simIndex<simnames.length;simIndex++) {
876                 htmlStr=htmlStr+padding(simnames[simIndex]+ " ("+simports[simIndex]+")",35,"&nbsp;");
877                 htmlStr=htmlStr+padding(simvar5[simIndex],50,"&nbsp;")
878                 htmlStr=htmlStr+"<br>";
879             }
880
881             htmlStr=htmlStr+
882            "</body>" +
883           "</html>";
884         res.send(htmlStr);
885 })
886
887 var httpServer = http.createServer(app);
888 var httpPort=9999;
889 httpServer.listen(httpPort);
890 console.log("Simulator monitor listening (http) at "+httpPort);
891 console.log("Open the web page on localhost:9999/mon to view the policy statistics page.")
892 console.log("Open the web page on localhost:9999/mon2 to view the enrichment statistics page.")
893 console.log("Open the web page on localhost:9999/mon3 to view CR DB in json.")