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
9 # http://www.apache.org/licenses/LICENSE-2.0
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=================================================
20 // Sim mon server - query the agent and the simulators for counters and other data
21 // Presents a web page on localhost:9999/mon
23 var LOCALHOST="http://127.0.0.1:"
24 var MRSTUB_PORT="3905"
28 var PRODSTUB_PORT="8092"
31 var http = require('http');
33 var express = require('express');
34 const { POINT_CONVERSION_HYBRID } = require('constants')
41 app.get("/",function(req, res){
45 //Get parameter value from other server
46 function getSimCtr(url, index, cb) {
50 http.get(url, (resp) => {
51 // A chunk of data has been recieved.
52 resp.on('data', (chunk) => {
56 // The whole response has been received.
57 resp.on('end', () => {
58 var code=resp.statusCode
59 if (code > 199 && code < 300) {
62 cb("not found", index);
66 }).on("error", (err) => {
67 console.log("Error: " + err.message);
68 cb("no response", index);
71 cb("no response", index);
76 //Format a comma separated list of data to a html-safe string with fixed fieldsizes
77 function formatDataRow(commaList) {
79 var tmp=commaList.split(',');
80 for(var i=0;i<tmp.length;i++) {
82 var len = fieldSize-data.length;
87 str=str+data+" ";
92 //Format a comma separated list of ids to a html-safe string with fixed fieldsizes
93 function formatIdRow(commaList) {
95 var tmp=commaList.split(',');
96 for(var i=0;i<tmp.length;i++) {
97 tmp[i] = tmp[i].trim();
98 var data="<"+tmp[i]+">";
99 var len = fieldSize+4-data.length;
101 data = data+" ";
104 str=str+data+" ";
109 //Format a list of ids to a html-safe string in compact format
110 function formatIdRowCompact(commaList) {
111 if (commaList == undefined) {
115 var tmp=commaList.split(',');
116 for(var i=0;i<tmp.length;i++) {
117 tmp[i] = tmp[i].trim();
118 var data="<"+tmp[i]+">";
119 str=str+data+" ";
124 //Pad a string upto a certain size using a pad string
125 function padding(val, size, pad) {
127 for(var i=s.length;i<size;i++) {
133 //Function to check if the previous call has returned, if so return true, if not return false
134 //For preventing multiple calls to slow containers.
135 function checkFunctionFlag(flag) {
136 if (flagstore.hasOwnProperty(flag)) {
137 if (flagstore[flag] == 0) {
140 } else if (flagstore[flag] > 10) {
141 //Reset flag after ten attempts
142 console.log("Force release flag "+flag)
146 //Previous call not returned
147 console.log("Flag not available "+flag)
148 flagstore[flag]=flagstore[flag]+1
156 //Clear flag for parameter
157 function clearFlag(flag) {
161 //Status variables, for parameters values fetched from other simulators
162 var mr1="", mr2="", mr3="", mr4="", mr5="", mr6="";
164 //Status variables for agent
171 //Status variables for callback receiver
177 //Container names and ports of the ric simulator
181 //Status variables for each ric simulator
189 //Status variables, for parameters values fetched from ics
190 var ics1="", ics2="", ics3="", ics4="", ics_types="-", ics_producers="-";
191 var ics_producer_arr=new Array(0)
192 var ics_producer_type_arr=new Array(0)
193 var ics_producer_jobs_arr=new Array(0)
194 var ics_producer_status_arr=new Array(0)
195 var ics_jobs=new Array(0)
196 var ics_job_status=new Array(0)
198 //Status variables, for parameters values fetched from prodstub
199 var ps2="", ps3="", ps4="", ps_types="-", ps_producers="-";
200 var ps_producer_type_arr=new Array(0)
201 var ps_producer_jobs_arr=new Array(0)
202 var ps_producer_delivery_arr=new Array(0)
207 //Counts the number of get request for the html page
210 var refreshCount_pol=-1
212 var refreshCount_ics=-1
214 var refreshCount_cr=-1
216 var refreshCount_rc=-1
218 var ricbasename="ricsim"
224 function fetchAllMetrics_pol() {
226 console.log("Fetching policy metrics " + refreshCount_pol)
228 if (refreshCount_pol < 0) {
229 refreshCount_pol = -1
232 refreshCount_pol = refreshCount_pol - 1
237 //Extract the port numbers from the running simulators, for every 3 calls
238 const { exec } = require('child_process');
239 exec('docker ps --filter "name='+ricbasename+'" --filter "network=nonrtric-docker-net" --format "{{.Names}} {{.Ports}}" | sed s/0.0.0.0:// | cut -d \'>\' -f1 | sed \'s/[[-]]*$//\'', (err, stdout, stderr) => {
242 simulators=`${stdout}`.replace(/(\r\n|\n|\r)/gm," ");
243 simulators=simulators.trim();
244 var sims=simulators.split(" ")
247 for(var i=0;i<sims.length;i=i+2) {
248 simnames[i/2]=sims[i]
249 simports[i/2]=sims[i+1]
255 //Get metric values from the simulators
256 for(var index=0;index<simnames.length;index++) {
258 if (checkFunctionFlag("simvar1_"+index)) {
259 getSimCtr(LOCALHOST+simports[index]+"/counter/num_instances", index, function(data, idx) {
261 clearFlag("simvar1_"+idx)
264 if (checkFunctionFlag("simvar2_"+index)) {
265 getSimCtr(LOCALHOST+simports[index]+"/counter/num_types", index, function(data,idx) {
267 clearFlag("simvar2_"+idx)
270 if (checkFunctionFlag("simvar3_"+index)) {
271 getSimCtr(LOCALHOST+simports[index]+"/policytypes", index, function(data,idx) {
272 data=data.replace(/\[/g,'');
273 data=data.replace(/\]/g,'');
274 data=data.replace(/ /g,'');
275 data=data.replace(/\"/g,'');
277 clearFlag("simvar3_"+idx)
280 if (checkFunctionFlag("simvar4_"+index)) {
281 getSimCtr(LOCALHOST+simports[index]+"/counter/interface", index, function(data,idx) {
283 clearFlag("simvar4_"+idx)
286 if (checkFunctionFlag("simvar5_"+index)) {
287 getSimCtr(LOCALHOST+simports[index]+"/counter/remote_hosts", index, function(data,idx) {
289 clearFlag("simvar5_"+idx)
292 if (checkFunctionFlag("simvar6_"+index)) {
293 getSimCtr(LOCALHOST+simports[index]+"/counter/datadelivery", index, function(data,idx) {
295 clearFlag("simvar6_"+idx)
300 //MR - get metrics values from the MR stub
301 if (checkFunctionFlag("mr1")) {
302 getSimCtr(LOCALHOST+MRSTUB_PORT+"/counter/requests_submitted", 0, function(data, idx) {
307 if (checkFunctionFlag("mr2")) {
308 getSimCtr(LOCALHOST+MRSTUB_PORT+"/counter/requests_fetched", 0, function(data, idx) {
313 if (checkFunctionFlag("mr3")) {
314 getSimCtr(LOCALHOST+MRSTUB_PORT+"/counter/current_requests", 0, function(data, idx) {
319 if (checkFunctionFlag("mr4")) {
320 getSimCtr(LOCALHOST+MRSTUB_PORT+"/counter/responses_submitted", 0, function(data, idx) {
325 if (checkFunctionFlag("mr5")) {
326 getSimCtr(LOCALHOST+MRSTUB_PORT+"/counter/responses_fetched", 0, function(data, idx) {
331 if (checkFunctionFlag("mr6")) {
332 getSimCtr(LOCALHOST+MRSTUB_PORT+"/counter/current_responses", 0, function(data, idx) {
338 //CR - get metrics values from the callbackreceiver
339 if (checkFunctionFlag("cr1")) {
340 getSimCtr(LOCALHOST+CR_PORT+"/counter/received_callbacks", 0, function(data, idx) {
345 if (checkFunctionFlag("cr2")) {
346 getSimCtr(LOCALHOST+CR_PORT+"/counter/fetched_callbacks", 0, function(data, idx) {
351 if (checkFunctionFlag("cr3")) {
352 getSimCtr(LOCALHOST+CR_PORT+"/counter/current_messages", 0, function(data, idx) {
357 //Agent - more get metrics from the agent
358 if (checkFunctionFlag("ag1")) {
359 getSimCtr(LOCALHOST+AGENT_PORT+"/status", 0, function(data, idx) {
364 if (checkFunctionFlag("ag2")) {
365 getSimCtr(LOCALHOST+AGENT_PORT+"/services", 0, function(data, idx) {
368 var jd=JSON.parse(data);
370 if (ag2.length > 1) {
373 ag2=ag2+(jd[key]["serviceName"]).trim()
382 if (checkFunctionFlag("ag3")) {
383 getSimCtr(LOCALHOST+AGENT_PORT+"/policy_types", 0, function(data, idx) {
386 var jd=JSON.parse(data);
388 if (ag3.length > 0) {
391 ag3=ag3+jd[key].trim()
401 if (checkFunctionFlag("ag4")) {
402 getSimCtr(LOCALHOST+AGENT_PORT+"/policy_ids", 0, function(data, idx) {
404 var jd=JSON.parse(data);
414 if (checkFunctionFlag("ag5")) {
415 getSimCtr(LOCALHOST+AGENT_PORT+"/rics", 0, function(data, idx) {
417 var jd=JSON.parse(data);
427 fetchAllMetrics_pol();
432 function fetchAllMetrics_ics() {
434 console.log("Fetching information metrics - timer:" + refreshCount_ics)
436 if (refreshCount_ics < 0) {
437 refreshCount_ics = -1
440 refreshCount_ics = refreshCount_ics - 1
444 if (checkFunctionFlag("ics_stat")) {
445 getSimCtr(LOCALHOST+ICS_PORT+"/status", 0, function(data, index) {
447 var jd=JSON.parse(data);
449 ics2=""+jd["no_of_producers"]
450 ics3=""+jd["no_of_types"]
451 ics4=""+jd["no_of_jobs"]
454 ics1="error response"
455 ics2="error response"
456 ics3="error response"
457 ics4="error response"
460 clearFlag("ics_stat")
462 if (checkFunctionFlag("ics_types")) {
463 getSimCtr(LOCALHOST+ICS_PORT+"/ei-producer/v1/eitypes", 0, function(data, index) {
464 var tmp_ics_types="-"
466 var jd=JSON.parse(data);
467 for(var i=0;i<jd.length;i++) {
468 if (tmp_ics_types.length == 1) {
471 tmp_ics_types=""+tmp_ics_types+jd[i]+" "
475 tmp_ics_types="error response"
477 ics_types = tmp_ics_types
479 clearFlag("ics_types")
481 if (checkFunctionFlag("ics_producers")) {
482 getSimCtr(LOCALHOST+ICS_PORT+"/ei-producer/v1/eiproducers", 0, function(data, index) {
483 var tmp_ics_producers="-"
485 var jd=JSON.parse(data);
486 var tmp_ics_producer_arr=new Array(jd.length)
487 for(var i=0;i<jd.length;i++) {
488 if (tmp_ics_producers.length == 1) {
491 tmp_ics_producers=""+tmp_ics_producers+jd[i]+" "
492 tmp_ics_producer_arr[i]=jd[i]
494 ics_producer_arr = tmp_ics_producer_arr
495 ics_producers = tmp_ics_producers
498 ics_producers="error response"
499 ics_producer_arr=new Array(0)
502 clearFlag("ics_producers")
504 if (checkFunctionFlag("ics_data")) {
506 var tmp_ics_producer_type_arr = JSON.parse(JSON.stringify(ics_producer_arr))
507 for(var x=0;x<tmp_ics_producer_type_arr.length;x++) {
508 getSimCtr(LOCALHOST+ICS_PORT+"/ei-producer/v1/eiproducers/"+tmp_ics_producer_type_arr[x], x, function(data, idx) {
509 var row=""+tmp_ics_producer_type_arr[idx]+" : "
511 var jd=JSON.parse(data);
512 var jda=jd["supported_ei_types"]
513 for(var j=0;j<jda.length;j++) {
514 row=""+row+jda[j]+" "
517 tmp_ics_producer_type_arr[idx]=row
520 tmp_ics_producer_type_arr=new Array(0)
524 ics_producer_type_arr = tmp_ics_producer_type_arr
526 ics_producer_type_arr=new Array(0)
529 var tmp_ics_producer_jobs_arr = JSON.parse(JSON.stringify(ics_producer_arr))
530 for(x=0;x<tmp_ics_producer_jobs_arr.length;x++) {
531 getSimCtr(LOCALHOST+ICS_PORT+"/ei-producer/v1/eiproducers/"+tmp_ics_producer_jobs_arr[x]+"/eijobs", x, function(data, idx) {
532 var row=""+tmp_ics_producer_jobs_arr[idx]+" : "
534 var jd=JSON.parse(data);
535 for(var j=0;j<jd.length;j++) {
537 row=""+row+jda["ei_job_identity"]+"("+jda["ei_type_identity"]+") "
539 tmp_ics_producer_jobs_arr[idx]=row
542 tmp_ics_producer_jobs_arr=new Array(0)
546 ics_producer_jobs_arr = tmp_ics_producer_jobs_arr
548 ics_producer_jobs_arr=new Array(0)
552 var tmp_ics_producer_status_arr = JSON.parse(JSON.stringify(ics_producer_arr))
553 for(x=0;x<tmp_ics_producer_status_arr.length;x++) {
554 getSimCtr(LOCALHOST+ICS_PORT+"/ei-producer/v1/eiproducers/"+tmp_ics_producer_status_arr[x]+"/status", x, function(data, idx) {
555 var row=""+tmp_ics_producer_status_arr[idx]+" : "
557 var jd=JSON.parse(data);
558 row=""+row+jd["operational_state"]
559 tmp_ics_producer_status_arr[idx]=row
562 tmp_ics_producer_status_arr=new Array(0)
566 ics_producer_status_arr = tmp_ics_producer_status_arr
568 ics_producer_status_arr=new Array(0)
570 clearFlag("ics_data")
572 if (checkFunctionFlag("ics_jobs")) {
573 getSimCtr(LOCALHOST+ICS_PORT+"/A1-EI/v1/eijobs", 0, function(data, index) {
575 var jd=JSON.parse(data);
576 var tmpArr=new Array(jd.length)
577 for(var i=0;i<jd.length;i++) {
583 ics_jobs=new Array(0)
586 clearFlag("ics_jobs")
588 if (checkFunctionFlag("ics_job_status")) {
590 var tmp_ics_job_status= JSON.parse(JSON.stringify(ics_jobs))
591 for(x=0;x<tmp_ics_job_status.length;x++) {
592 getSimCtr(LOCALHOST+ICS_PORT+"/A1-EI/v1/eijobs/"+tmp_ics_job_status[x]+"/status", x, function(data, idx) {
594 var jd=JSON.parse(data);
595 tmp_ics_job_status[idx]=""+tmp_ics_job_status[idx]+":"+jd["eiJobStatus"]
598 tmp_ics_job_status="-"
602 ics_job_status = tmp_ics_job_status
606 clearFlag("ics_job_status")
608 if (checkFunctionFlag("prodstub_stat")) {
609 getSimCtr(LOCALHOST+PRODSTUB_PORT+"/status", x, function(data, idx) {
610 var ctr2_map=new Map()
611 var ctr3_map=new Map()
614 var tmp_ps_producers=""
616 var tmp_ps_producer_type_arr=new Array()
617 var tmp_ps_producer_jobs_arr=new Array()
618 var tmp_ps_producer_delivery_arr=new Array()
623 var jp=JSON.parse(data);
624 for(var prod_name in jp) {
625 ctr2_map.set(prod_name, prod_name)
628 var row=""+prod_name+" : "
629 var rowj=""+prod_name+" : "
630 var rowd=""+prod_name+" : "
631 tmp_ps_producers += prod_name + " "
635 for(var i=0;i<ta.length;i++) {
636 ctr3_map.set(ta[i], ta[i])
639 } else if (ji == "supervision_response") {
641 } else if (ji == "supervision_counter") {
643 } else if (ji == "types") {
649 var job_data=jj[ji]["json"]
650 if (job_data != undefined) {
651 rowj += "("+job_data["ei_type_identity"]+")"
653 rowd += "("+jj[ji]["delivery_attempts"]+")"
656 tmp_ps_producer_type_arr[(ctr2-1)]=row
657 tmp_ps_producer_jobs_arr[(ctr2-1)]=rowj
658 tmp_ps_producer_delivery_arr[(ctr2-1)]=rowd
660 tmp_ps2=""+ctr2_map.size
661 tmp_ps3=""+ctr3_map.size
662 for(const [key, value] of ctr3_map.entries()) {
663 tmp_ps_types += key + " "
667 ps_producers=tmp_ps_producers
668 ps_types=tmp_ps_types
669 ps_producer_type_arr=tmp_ps_producer_type_arr
670 ps_producer_jobs_arr=tmp_ps_producer_jobs_arr
671 ps_producer_delivery_arr=tmp_ps_producer_delivery_arr
677 ps_producers="error response"
678 ps_types="error response"
679 ps_producer_type_arr=new Array()
680 ps_producer_jobs_arr=new Array()
681 ps_producer_delivery_arr=new Array()
687 clearFlag("prodstub_stat")
690 fetchAllMetrics_ics();
695 function fetchAllMetrics_cr() {
697 console.log("Fetching CR DB - timer:" + refreshCount_ics)
699 if (refreshCount_cr < 0) {
703 refreshCount_cr = refreshCount_cr - 1
707 if (checkFunctionFlag("cr_stat")) {
708 getSimCtr(LOCALHOST+CR_PORT+"/db", 0, function(data, index) {
710 cr_db=JSON.parse(data);
718 fetchAllMetrics_cr();
722 function fetchAllMetrics_rc() {
724 console.log("Fetching RC services - timer:" + refreshCount_ics)
726 if (refreshCount_rc < 0) {
730 refreshCount_rc = refreshCount_rc - 1
734 if (checkFunctionFlag("rc_stat")) {
735 getSimCtr(LOCALHOST+RC_PORT+"/services", 0, function(data, index) {
738 var jd=JSON.parse(data);
739 for(var i=0;i<jd.length;i++) {
740 if (tmp_serv.length > 0) {
741 tmp_serv=tmp_serv+","
743 tmp_serv=tmp_serv+jd[i]["name"]
748 tmp_serv="no_response"
754 fetchAllMetrics_rc();
759 app.get("/mon3",function(req, res){
761 console.log("Creating CR DB page - timer: " + refreshCount_ics)
763 if (refreshCount_cr < 0) {
768 var json_str=JSON.stringify(cr_db, null, 1)
769 var htmlStr = "<!DOCTYPE html>" +
772 "<meta http-equiv=\"refresh\" content=\"2\">"+ //2 sec auto refresh
773 "<title>CR DB dump</title>"+
775 "<body style=\"white-space: pre-wrap\">" +
783 app.get("/mon2",function(req, res){
785 console.log("Creating information metrics - timer: " + refreshCount_ics)
787 if (refreshCount_ics < 0) {
789 fetchAllMetrics_ics()
793 var summary=req.query.summary
795 if (summary == undefined) {
796 return res.redirect('/mon2?summary=false');
800 var htmlStr = "<!DOCTYPE html>" +
803 "<meta http-equiv=\"refresh\" content=\"2\">"+ //2 sec auto refresh
804 "<title>information coordinator service and producer stub</title>"+
807 "<font size=\"-3\" face=\"summary\">"
808 if (summary == "false") {
809 htmlStr=htmlStr+"<p>Set query param '?summary' to true to only show summary statistics.</p>"
811 htmlStr=htmlStr+"<p>Set query param '?summary' to false to only show full statistics</p>"
813 if (ics_job_status.length > 10) {
814 htmlStr=htmlStr+"<div style=\"color:red\"> Avoid running the server for large number of producers and/or jobs</div>"
816 htmlStr=htmlStr+"</font>" +
817 "<h3>Information Coordinator Service</h3>" +
818 "<font face=\"monospace\">" +
819 "Status:..........." + formatDataRow(ics1) + "<br>" +
820 "Producers:........" + formatDataRow(ics2) + "<br>" +
821 "Types:............" + formatDataRow(ics3) + "<br>" +
822 "Jobs:............." + formatDataRow(ics4) + "<br>" +
824 if (summary == "false") {
827 "<font face=\"monospace\">" +
828 "Producer ids:....." + formatDataRow(ics_producers) + "<br>" +
829 "Type ids:........." + formatDataRow(ics_types) + "<br>" +
831 for(var i=0;i<ics_producer_type_arr.length;i++) {
832 var tmp=ics_producer_type_arr[i]
833 if (tmp != undefined) {
834 var s = "Producer types...." + formatDataRow(ics_producer_type_arr[i]) + "<br>"
838 htmlStr=htmlStr+"<br>";
839 for(i=0;i<ics_producer_jobs_arr.length;i++) {
840 tmp=ics_producer_jobs_arr[i]
841 if (tmp != undefined) {
842 s = "Producer jobs....." + formatDataRow(ics_producer_jobs_arr[i]) + "<br>"
846 htmlStr=htmlStr+"<br>";
847 for(i=0;i<ics_producer_status_arr.length;i++) {
848 tmp=ics_producer_status_arr[i]
849 if (tmp != undefined) {
850 s = "Producer status..." + formatDataRow(tmp) + "<br>"
854 htmlStr=htmlStr+"<br>";
855 for(i=0;i<ics_job_status.length;i++) {
856 tmp=ics_job_status[i]
857 if (tmp != undefined) {
858 s = padding("Job", 18, ".") + formatDataRow(tmp) + "<br>"
862 htmlStr=htmlStr+"<br>"+"<br>" +
867 "<h3>Producer stub</h3>" +
868 "<font face=\"monospace\">" +
869 "Producers:........" + formatDataRow(ps2) + "<br>" +
870 "Types:............" + formatDataRow(ps3) + "<br>" +
871 "Jobs:............." + formatDataRow(ps4) + "<br>" +
873 if (summary == "false") {
876 "<font face=\"monospace\">" +
877 "Producer ids:....." + formatDataRow(ps_producers) + "<br>" +
878 "Type ids:........." + formatDataRow(ps_types) + "<br>" +
880 for(i=0;i<ps_producer_type_arr.length;i++) {
881 tmp=ps_producer_type_arr[i]
882 if (tmp != undefined) {
883 s = "Producer types...." + formatDataRow(ps_producer_type_arr[i]) + "<br>"
887 htmlStr=htmlStr+"<br>";
888 for(i=0;i<ps_producer_jobs_arr.length;i++) {
889 tmp=ps_producer_jobs_arr[i]
890 if (tmp != undefined) {
891 s = "Producer jobs....." + formatDataRow(ps_producer_jobs_arr[i]) + "<br>"
895 htmlStr=htmlStr+"<br>";
896 for(i=0;i<ps_producer_delivery_arr.length;i++) {
897 tmp=ps_producer_delivery_arr[i]
898 if (tmp != undefined) {
899 s = "Producer delivery." + formatDataRow(ps_producer_delivery_arr[i]) + "<br>"
911 // Monitor for policy management
912 app.get("/mon",function(req, res){
914 console.log("Creating policy metrics page " + refreshCount_pol)
916 if (refreshCount_pol < 0) {
918 fetchAllMetrics_pol()
922 if (refreshCount_rc < 0) {
928 var bn=req.query.basename
929 pmsprefix=req.query.pmsprefix
931 console.log("PMS"+pmsprefix)
932 if ((bn == undefined) || (pmsprefix == undefined)) {
934 return res.redirect('/mon?basename=ricsim&pmsprefix=/a1-policy/v2');
941 var htmlStr = "<!DOCTYPE html>" +
944 "<meta http-equiv=\"refresh\" content=\"2\">"+ //2 sec auto refresh
945 "<title>Policy Management Service and simulator monitor</title>"+
948 "<font size=\"-3\" face=\"monospace\">" +
949 "<p>Change basename in url if other ric sim prefix is used</p>" +
950 "<p>Change pmsprefix in url if pms with other prefix is used</p>" +
952 "<h3>Policy Management Service</h3>" +
953 "<font face=\"monospace\">" +
954 "Status:..............................." + formatDataRow(ag1) + "<br>" +
955 "Services:............................." + formatIdRowCompact(ag2) + "<br>" +
956 "Types:................................" + formatIdRowCompact(ag3) + "<br>" +
957 "Number of instances:.................." + formatDataRow(ag4) + "<br>" +
958 "Near-RT RICs:........................." + formatDataRow(ag5) + "<br>" +
960 "<h3>MR Stub interface</h3>" +
961 "<font face=\"monospace\">"+
962 "Submitted requests:............................" + formatDataRow(mr1) + "<br>" +
963 "Fetched requests:.............................." + formatDataRow(mr2) + "<br>" +
964 "Current requests waiting:......................" + formatDataRow(mr3) + "<br>" +
965 "Submitted responses:..........................." + formatDataRow(mr4) + "<br>" +
966 "Fetched responses.............................." + formatDataRow(mr5) + "<br>" +
967 "Current responses waiting......................" + formatDataRow(mr6) + "<br>" +
969 "<h3>Callback|Notification receiver</h3>" +
970 "<font face=\"monospace\">" +
971 "Callbacks received:..................." + formatDataRow(cr1) + "<br>" +
972 "Callbacks fetched:...................." + formatDataRow(cr2) + "<br>" +
973 "Number of waiting callback messages:.." + formatDataRow(cr3) + "<br>" +
975 "<h3>R-APP Catalogue</h3>" +
976 "<font face=\"monospace\">" +
977 "Services:............................." + formatIdRowCompact(rc_services) + "<br>" +
979 "<h3>Near-RT RIC | A1 Simulators</h3>" +
980 "<font face=\"monospace\">"
982 htmlStr=htmlStr+padding("Near-RT RIC Simulator name", 35," ")
983 htmlStr=htmlStr+padding("Types", 10," ")
984 htmlStr=htmlStr+padding("Instances", 12," ")
985 htmlStr=htmlStr+padding("Data delivery", 12," ")+"<br>"
986 htmlStr=htmlStr+padding("",70,"=")+"<br>"
987 for(var simIndex=0;simIndex<simnames.length;simIndex++) {
988 htmlStr=htmlStr+padding(simnames[simIndex]+ " ("+simports[simIndex]+")",35," ");
989 htmlStr=htmlStr+padding(simvar2[simIndex],10," ")
990 htmlStr=htmlStr+padding(simvar1[simIndex],12 ," ")
991 htmlStr=htmlStr+padding(simvar6[simIndex],12," ")
992 htmlStr=htmlStr+"<br>";
995 htmlStr=htmlStr+"<br>";
996 htmlStr=htmlStr+padding("Near-RT RIC Simulator name", 35," ")
997 htmlStr=htmlStr+padding("Version", 20," ")
998 htmlStr=htmlStr+padding("Type-IDs", 10," ")+"<br>"
999 htmlStr=htmlStr+padding("",65,"=")+"<br>"
1000 for(simIndex=0;simIndex<simnames.length;simIndex++) {
1001 htmlStr=htmlStr+padding(simnames[simIndex]+ " ("+simports[simIndex]+")",35," ");
1002 htmlStr=htmlStr+padding(simvar4[simIndex],20," ")
1003 htmlStr=htmlStr+padding(formatIdRowCompact(simvar3[simIndex]),10," ")
1004 htmlStr=htmlStr+"<br>";
1007 htmlStr=htmlStr+"<br>";
1008 htmlStr=htmlStr+padding("Near-RT RIC Simulator name", 35," ")
1009 htmlStr=htmlStr+padding("Remote hosts", 50," ")+"<br>"
1010 htmlStr=htmlStr+padding("",90,"=")+"<br>"
1011 for(simIndex=0;simIndex<simnames.length;simIndex++) {
1012 htmlStr=htmlStr+padding(simnames[simIndex]+ " ("+simports[simIndex]+")",35," ");
1013 htmlStr=htmlStr+padding(simvar5[simIndex],50," ")
1014 htmlStr=htmlStr+"<br>";
1023 var httpServer = http.createServer(app);
1025 httpServer.listen(httpPort);
1026 console.log("Simulator monitor listening (http) at "+httpPort);
1027 console.log("Open the web page on localhost:9999/mon to view the policy statistics page.")
1028 console.log("Open the web page on localhost:9999/mon2 to view the information statistics page.")
1029 console.log("Open the web page on localhost:9999/mon3 to view CR DB in json.")