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"
30 var http = require('http');
32 var express = require('express');
33 const { POINT_CONVERSION_HYBRID } = require('constants')
40 app.get("/",function(req, res){
44 //Get parameter value from other server
45 function getSimCtr(url, index, cb) {
49 http.get(url, (resp) => {
50 // A chunk of data has been recieved.
51 resp.on('data', (chunk) => {
55 // The whole response has been received.
56 resp.on('end', () => {
57 var code=resp.statusCode
58 if (code > 199 && code < 300) {
61 cb("not found", index);
65 }).on("error", (err) => {
66 console.log("Error: " + err.message);
67 cb("no response", index);
70 cb("no response", index);
75 //Format a comma separated list of data to a html-safe string with fixed fieldsizes
76 function formatDataRow(commaList) {
78 var tmp=commaList.split(',');
79 for(var i=0;i<tmp.length;i++) {
81 var len = fieldSize-data.length;
86 str=str+data+" ";
91 //Format a comma separated list of ids to a html-safe string with fixed fieldsizes
92 function formatIdRow(commaList) {
94 var tmp=commaList.split(',');
95 for(var i=0;i<tmp.length;i++) {
96 tmp[i] = tmp[i].trim();
97 var data="<"+tmp[i]+">";
98 var len = fieldSize+4-data.length;
100 data = data+" ";
103 str=str+data+" ";
108 //Format a list of ids to a html-safe string in compact format
109 function formatIdRowCompact(commaList) {
110 if (commaList == undefined) {
114 var tmp=commaList.split(',');
115 for(var i=0;i<tmp.length;i++) {
116 tmp[i] = tmp[i].trim();
117 var data="<"+tmp[i]+">";
118 str=str+data+" ";
123 //Pad a string upto a certain size using a pad string
124 function padding(val, size, pad) {
126 for(var i=s.length;i<size;i++) {
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) {
139 } else if (flagstore[flag] > 10) {
140 //Reset flag after ten attempts
141 console.log("Force release flag "+flag)
145 //Previous call not returned
146 console.log("Flag not available "+flag)
147 flagstore[flag]=flagstore[flag]+1
155 //Clear flag for parameter
156 function clearFlag(flag) {
160 //Status variables, for parameters values fetched from other simulators
161 var mr1="", mr2="", mr3="", mr4="", mr5="", mr6="";
163 //Status variables for agent
170 //Status variables for callback receiver
176 //Container names and ports of the ric simulator
180 //Status variables for each ric simulator
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 var ecs_jobs=new Array(0)
195 var ecs_job_status=new Array(0)
197 //Status variables, for parameters values fetched from prodstub
198 var ps2="", ps3="", ps4="", ps_types="-", ps_producers="-";
199 var ps_producer_type_arr=new Array(0)
200 var ps_producer_jobs_arr=new Array(0)
201 var ps_producer_delivery_arr=new Array(0)
206 //Counts the number of get request for the html page
209 var refreshCount_pol=-1
211 var refreshCount_ecs=-1
213 var refreshCount_cr=-1
215 var ricbasename="ricsim"
217 function fetchAllMetrics_pol() {
219 console.log("Fetching policy metrics " + refreshCount_pol)
221 if (refreshCount_pol < 0) {
222 refreshCount_pol = -1
225 refreshCount_pol = refreshCount_pol - 1
230 //Extract the port numbers from the running simulators, for every 3 calls
231 const { exec } = require('child_process');
232 exec('docker ps --filter "name='+ricbasename+'" --format "{{.Names}} {{.Ports}}" | sed s/0.0.0.0:// | cut -d \'>\' -f1 | sed \'s/[[-]]*$//\'', (err, stdout, stderr) => {
235 simulators=`${stdout}`.replace(/(\r\n|\n|\r)/gm," ");
236 simulators=simulators.trim();
237 var sims=simulators.split(" ")
240 for(var i=0;i<sims.length;i=i+2) {
241 simnames[i/2]=sims[i]
242 simports[i/2]=sims[i+1]
248 //Get metric values from the simulators
249 for(var index=0;index<simnames.length;index++) {
251 if (checkFunctionFlag("simvar1_"+index)) {
252 getSimCtr(LOCALHOST+simports[index]+"/counter/num_instances", index, function(data, idx) {
254 clearFlag("simvar1_"+idx)
257 if (checkFunctionFlag("simvar2_"+index)) {
258 getSimCtr(LOCALHOST+simports[index]+"/counter/num_types", index, function(data,idx) {
260 clearFlag("simvar2_"+idx)
263 if (checkFunctionFlag("simvar3_"+index)) {
264 getSimCtr(LOCALHOST+simports[index]+"/policytypes", index, function(data,idx) {
265 data=data.replace(/\[/g,'');
266 data=data.replace(/\]/g,'');
267 data=data.replace(/ /g,'');
268 data=data.replace(/\"/g,'');
270 clearFlag("simvar3_"+idx)
273 if (checkFunctionFlag("simvar4_"+index)) {
274 getSimCtr(LOCALHOST+simports[index]+"/counter/interface", index, function(data,idx) {
276 clearFlag("simvar4_"+idx)
279 if (checkFunctionFlag("simvar5_"+index)) {
280 getSimCtr(LOCALHOST+simports[index]+"/counter/remote_hosts", index, function(data,idx) {
282 clearFlag("simvar5_"+idx)
285 if (checkFunctionFlag("simvar6_"+index)) {
286 getSimCtr(LOCALHOST+simports[index]+"/counter/datadelivery", index, function(data,idx) {
288 clearFlag("simvar6_"+idx)
293 //MR - get metrics values from the MR stub
294 if (checkFunctionFlag("mr1")) {
295 getSimCtr(LOCALHOST+MRSTUB_PORT+"/counter/requests_submitted", 0, function(data, idx) {
300 if (checkFunctionFlag("mr2")) {
301 getSimCtr(LOCALHOST+MRSTUB_PORT+"/counter/requests_fetched", 0, function(data, idx) {
306 if (checkFunctionFlag("mr3")) {
307 getSimCtr(LOCALHOST+MRSTUB_PORT+"/counter/current_requests", 0, function(data, idx) {
312 if (checkFunctionFlag("mr4")) {
313 getSimCtr(LOCALHOST+MRSTUB_PORT+"/counter/responses_submitted", 0, function(data, idx) {
318 if (checkFunctionFlag("mr5")) {
319 getSimCtr(LOCALHOST+MRSTUB_PORT+"/counter/responses_fetched", 0, function(data, idx) {
324 if (checkFunctionFlag("mr6")) {
325 getSimCtr(LOCALHOST+MRSTUB_PORT+"/counter/current_responses", 0, function(data, idx) {
331 //CR - get metrics values from the callbackreceiver
332 if (checkFunctionFlag("cr1")) {
333 getSimCtr(LOCALHOST+CR_PORT+"/counter/received_callbacks", 0, function(data, idx) {
338 if (checkFunctionFlag("cr2")) {
339 getSimCtr(LOCALHOST+CR_PORT+"/counter/fetched_callbacks", 0, function(data, idx) {
344 if (checkFunctionFlag("cr3")) {
345 getSimCtr(LOCALHOST+CR_PORT+"/counter/current_messages", 0, function(data, idx) {
350 //Agent - more get metrics from the agent
351 if (checkFunctionFlag("ag1")) {
352 getSimCtr(LOCALHOST+AGENT_PORT+"/status", 0, function(data, idx) {
357 if (checkFunctionFlag("ag2")) {
358 getSimCtr(LOCALHOST+AGENT_PORT+"/services", 0, function(data, idx) {
361 var jd=JSON.parse(data);
363 if (ag2.length > 1) {
366 ag2=ag2+(jd[key]["serviceName"]).trim()
375 if (checkFunctionFlag("ag3")) {
376 getSimCtr(LOCALHOST+AGENT_PORT+"/policy_types", 0, function(data, idx) {
379 var jd=JSON.parse(data);
381 if (ag3.length > 0) {
384 ag3=ag3+jd[key].trim()
394 if (checkFunctionFlag("ag4")) {
395 getSimCtr(LOCALHOST+AGENT_PORT+"/policy_ids", 0, function(data, idx) {
397 var jd=JSON.parse(data);
407 if (checkFunctionFlag("ag5")) {
408 getSimCtr(LOCALHOST+AGENT_PORT+"/rics", 0, function(data, idx) {
410 var jd=JSON.parse(data);
420 fetchAllMetrics_pol();
425 function fetchAllMetrics_ecs() {
427 console.log("Fetching enrichment metrics - timer:" + refreshCount_ecs)
429 if (refreshCount_ecs < 0) {
430 refreshCount_ecs = -1
433 refreshCount_ecs = refreshCount_ecs - 1
437 if (checkFunctionFlag("ecs_stat")) {
438 getSimCtr(LOCALHOST+ECS_PORT+"/status", 0, function(data, index) {
440 var jd=JSON.parse(data);
442 ecs2=""+jd["no_of_producers"]
443 ecs3=""+jd["no_of_types"]
444 ecs4=""+jd["no_of_jobs"]
447 ecs1="error response"
448 ecs2="error response"
449 ecs3="error response"
450 ecs4="error response"
453 clearFlag("ecs_stat")
455 if (checkFunctionFlag("ecs_types")) {
456 getSimCtr(LOCALHOST+ECS_PORT+"/ei-producer/v1/eitypes", 0, function(data, index) {
457 var tmp_ecs_types="-"
459 var jd=JSON.parse(data);
460 for(var i=0;i<jd.length;i++) {
461 if (tmp_ecs_types.length == 1) {
464 tmp_ecs_types=""+tmp_ecs_types+jd[i]+" "
468 tmp_ecs_types="error response"
470 ecs_types = tmp_ecs_types
472 clearFlag("ecs_types")
474 if (checkFunctionFlag("ecs_producers")) {
475 getSimCtr(LOCALHOST+ECS_PORT+"/ei-producer/v1/eiproducers", 0, function(data, index) {
476 var tmp_ecs_producers="-"
478 var jd=JSON.parse(data);
479 var tmp_ecs_producer_arr=new Array(jd.length)
480 for(var i=0;i<jd.length;i++) {
481 if (tmp_ecs_producers.length == 1) {
484 tmp_ecs_producers=""+tmp_ecs_producers+jd[i]+" "
485 tmp_ecs_producer_arr[i]=jd[i]
487 ecs_producer_arr = tmp_ecs_producer_arr
488 ecs_producers = tmp_ecs_producers
491 ecs_producers="error response"
492 ecs_producer_arr=new Array(0)
495 clearFlag("ecs_producers")
497 if (checkFunctionFlag("ecs_data")) {
499 var tmp_ecs_producer_type_arr = JSON.parse(JSON.stringify(ecs_producer_arr))
500 for(var x=0;x<tmp_ecs_producer_type_arr.length;x++) {
501 getSimCtr(LOCALHOST+ECS_PORT+"/ei-producer/v1/eiproducers/"+tmp_ecs_producer_type_arr[x], x, function(data, idx) {
502 var row=""+tmp_ecs_producer_type_arr[idx]+" : "
504 var jd=JSON.parse(data);
505 var jda=jd["supported_ei_types"]
506 for(var j=0;j<jda.length;j++) {
507 row=""+row+jda[j]["ei_type_identity"]+" "
509 tmp_ecs_producer_type_arr[idx]=row
512 tmp_ecs_producer_type_arr=new Array(0)
516 ecs_producer_type_arr = tmp_ecs_producer_type_arr
518 ecs_producer_type_arr=new Array(0)
521 var tmp_ecs_producer_jobs_arr = JSON.parse(JSON.stringify(ecs_producer_arr))
522 for(x=0;x<tmp_ecs_producer_jobs_arr.length;x++) {
523 getSimCtr(LOCALHOST+ECS_PORT+"/ei-producer/v1/eiproducers/"+tmp_ecs_producer_jobs_arr[x]+"/eijobs", x, function(data, idx) {
524 var row=""+tmp_ecs_producer_jobs_arr[idx]+" : "
526 var jd=JSON.parse(data);
527 for(var j=0;j<jd.length;j++) {
529 row=""+row+jda["ei_job_identity"]+"("+jda["ei_type_identity"]+") "
531 tmp_ecs_producer_jobs_arr[idx]=row
534 tmp_ecs_producer_jobs_arr=new Array(0)
538 ecs_producer_jobs_arr = tmp_ecs_producer_jobs_arr
540 ecs_producer_jobs_arr=new Array(0)
544 var tmp_ecs_producer_status_arr = JSON.parse(JSON.stringify(ecs_producer_arr))
545 for(x=0;x<tmp_ecs_producer_status_arr.length;x++) {
546 getSimCtr(LOCALHOST+ECS_PORT+"/ei-producer/v1/eiproducers/"+tmp_ecs_producer_status_arr[x]+"/status", x, function(data, idx) {
547 var row=""+tmp_ecs_producer_status_arr[idx]+" : "
549 var jd=JSON.parse(data);
550 row=""+row+jd["operational_state"]
551 tmp_ecs_producer_status_arr[idx]=row
554 tmp_ecs_producer_status_arr=new Array(0)
558 ecs_producer_status_arr = tmp_ecs_producer_status_arr
560 ecs_producer_status_arr=new Array(0)
562 clearFlag("ecs_data")
564 if (checkFunctionFlag("ecs_jobs")) {
565 getSimCtr(LOCALHOST+ECS_PORT+"/A1-EI/v1/eijobs", 0, function(data, index) {
567 var jd=JSON.parse(data);
568 var tmpArr=new Array(jd.length)
569 for(var i=0;i<jd.length;i++) {
575 ecs_jobs=new Array(0)
578 clearFlag("ecs_jobs")
580 if (checkFunctionFlag("ecs_job_status")) {
582 var tmp_ecs_job_status= JSON.parse(JSON.stringify(ecs_jobs))
583 for(x=0;x<tmp_ecs_job_status.length;x++) {
584 getSimCtr(LOCALHOST+ECS_PORT+"/A1-EI/v1/eijobs/"+tmp_ecs_job_status[x]+"/status", x, function(data, idx) {
586 var jd=JSON.parse(data);
587 tmp_ecs_job_status[idx]=""+tmp_ecs_job_status[idx]+":"+jd["eiJobStatus"]
590 tmp_ecs_job_status="-"
594 ecs_job_status = tmp_ecs_job_status
598 clearFlag("ecs_job_status")
600 if (checkFunctionFlag("prodstub_stat")) {
601 getSimCtr(LOCALHOST+PRODSTUB_PORT+"/status", x, function(data, idx) {
602 var ctr2_map=new Map()
603 var ctr3_map=new Map()
606 var tmp_ps_producers=""
608 var tmp_ps_producer_type_arr=new Array()
609 var tmp_ps_producer_jobs_arr=new Array()
610 var tmp_ps_producer_delivery_arr=new Array()
615 var jp=JSON.parse(data);
616 for(var prod_name in jp) {
617 ctr2_map.set(prod_name, prod_name)
620 var row=""+prod_name+" : "
621 var rowj=""+prod_name+" : "
622 var rowd=""+prod_name+" : "
623 tmp_ps_producers += prod_name + " "
627 for(var i=0;i<ta.length;i++) {
628 ctr3_map.set(ta[i], ta[i])
631 } else if (ji == "supervision_response") {
633 } else if (ji == "supervision_counter") {
635 } else if (ji == "types") {
641 var job_data=jj[ji]["json"]
642 if (job_data != undefined) {
643 rowj += "("+job_data["ei_type_identity"]+")"
645 rowd += "("+jj[ji]["delivery_attempts"]+")"
648 tmp_ps_producer_type_arr[(ctr2-1)]=row
649 tmp_ps_producer_jobs_arr[(ctr2-1)]=rowj
650 tmp_ps_producer_delivery_arr[(ctr2-1)]=rowd
652 tmp_ps2=""+ctr2_map.size
653 tmp_ps3=""+ctr3_map.size
654 for(const [key, value] of ctr3_map.entries()) {
655 tmp_ps_types += key + " "
659 ps_producers=tmp_ps_producers
660 ps_types=tmp_ps_types
661 ps_producer_type_arr=tmp_ps_producer_type_arr
662 ps_producer_jobs_arr=tmp_ps_producer_jobs_arr
663 ps_producer_delivery_arr=tmp_ps_producer_delivery_arr
669 ps_producers="error response"
670 ps_types="error response"
671 ps_producer_type_arr=new Array()
672 ps_producer_jobs_arr=new Array()
673 ps_producer_delivery_arr=new Array()
679 clearFlag("prodstub_stat")
682 fetchAllMetrics_ecs();
687 function fetchAllMetrics_cr() {
689 console.log("Fetching CR DB - timer:" + refreshCount_ecs)
691 if (refreshCount_cr < 0) {
695 refreshCount_cr = refreshCount_cr - 1
699 if (checkFunctionFlag("cr_stat")) {
700 getSimCtr(LOCALHOST+CR_PORT+"/db", 0, function(data, index) {
702 cr_db=JSON.parse(data);
710 fetchAllMetrics_cr();
715 app.get("/mon3",function(req, res){
717 console.log("Creating CR DB page - timer: " + refreshCount_ecs)
719 if (refreshCount_cr < 0) {
724 var json_str=JSON.stringify(cr_db, null, 1)
725 var htmlStr = "<!DOCTYPE html>" +
728 "<meta http-equiv=\"refresh\" content=\"2\">"+ //2 sec auto refresh
729 "<title>CR DB dump</title>"+
731 "<body style=\"white-space: pre-wrap\">" +
739 app.get("/mon2",function(req, res){
741 console.log("Creating enrichment metrics - timer: " + refreshCount_ecs)
743 if (refreshCount_ecs < 0) {
745 fetchAllMetrics_ecs()
749 var summary=req.query.summary
751 if (summary == undefined) {
752 return res.redirect('/mon2?summary=false');
756 var htmlStr = "<!DOCTYPE html>" +
759 "<meta http-equiv=\"refresh\" content=\"2\">"+ //2 sec auto refresh
760 "<title>Enrichment coordinator service and producer stub</title>"+
763 "<font size=\"-3\" face=\"summary\">"
764 if (summary == "false") {
765 htmlStr=htmlStr+"<p>Set query param '?summary' to true to only show summary statistics.</p>"
767 htmlStr=htmlStr+"<p>Set query param '?summary' to false to only show full statistics</p>"
769 if (ecs_job_status.length > 10) {
770 htmlStr=htmlStr+"<div style=\"color:red\"> Avoid running the server for large number of producers and/or jobs</div>"
772 htmlStr=htmlStr+"</font>" +
773 "<h3>Enrichment Coordinator Service</h3>" +
774 "<font face=\"monospace\">" +
775 "Status:..........." + formatDataRow(ecs1) + "<br>" +
776 "Producers:........" + formatDataRow(ecs2) + "<br>" +
777 "Types:............" + formatDataRow(ecs3) + "<br>" +
778 "Jobs:............." + formatDataRow(ecs4) + "<br>" +
780 if (summary == "false") {
783 "<font face=\"monospace\">" +
784 "Producer ids:....." + formatDataRow(ecs_producers) + "<br>" +
785 "Type ids:........." + formatDataRow(ecs_types) + "<br>" +
787 for(var i=0;i<ecs_producer_type_arr.length;i++) {
788 var tmp=ecs_producer_type_arr[i]
789 if (tmp != undefined) {
790 var s = "Producer types...." + formatDataRow(ecs_producer_type_arr[i]) + "<br>"
794 htmlStr=htmlStr+"<br>";
795 for(i=0;i<ecs_producer_jobs_arr.length;i++) {
796 tmp=ecs_producer_jobs_arr[i]
797 if (tmp != undefined) {
798 s = "Producer jobs....." + formatDataRow(ecs_producer_jobs_arr[i]) + "<br>"
802 htmlStr=htmlStr+"<br>";
803 for(i=0;i<ecs_producer_status_arr.length;i++) {
804 tmp=ecs_producer_status_arr[i]
805 if (tmp != undefined) {
806 s = "Producer status..." + formatDataRow(tmp) + "<br>"
810 htmlStr=htmlStr+"<br>";
811 for(i=0;i<ecs_job_status.length;i++) {
812 tmp=ecs_job_status[i]
814 if (tmp != undefined) {
815 s = padding("Job", 18, ".") + formatDataRow(tmp) + "<br>"
819 htmlStr=htmlStr+"<br>"+"<br>" +
824 "<h3>Producer stub</h3>" +
825 "<font face=\"monospace\">" +
826 "Producers:........" + formatDataRow(ps2) + "<br>" +
827 "Types:............" + formatDataRow(ps3) + "<br>" +
828 "Jobs:............." + formatDataRow(ps4) + "<br>" +
830 if (summary == "false") {
833 "<font face=\"monospace\">" +
834 "Producer ids:....." + formatDataRow(ps_producers) + "<br>" +
835 "Type ids:........." + formatDataRow(ps_types) + "<br>" +
837 for(i=0;i<ps_producer_type_arr.length;i++) {
838 tmp=ps_producer_type_arr[i]
839 if (tmp != undefined) {
840 s = "Producer types...." + formatDataRow(ps_producer_type_arr[i]) + "<br>"
844 htmlStr=htmlStr+"<br>";
845 for(i=0;i<ps_producer_jobs_arr.length;i++) {
846 tmp=ps_producer_jobs_arr[i]
847 if (tmp != undefined) {
848 s = "Producer jobs....." + formatDataRow(ps_producer_jobs_arr[i]) + "<br>"
852 htmlStr=htmlStr+"<br>";
853 for(i=0;i<ps_producer_delivery_arr.length;i++) {
854 tmp=ps_producer_delivery_arr[i]
855 if (tmp != undefined) {
856 s = "Producer delivery." + formatDataRow(ps_producer_delivery_arr[i]) + "<br>"
868 // Monitor for policy management
869 app.get("/mon",function(req, res){
871 console.log("Creating policy metrics page " + refreshCount_pol)
873 if (refreshCount_pol < 0) {
875 fetchAllMetrics_pol()
879 var bn=req.query.basename
881 if (bn == undefined) {
883 return res.redirect('/mon?basename=ricsim');
889 var htmlStr = "<!DOCTYPE html>" +
892 "<meta http-equiv=\"refresh\" content=\"2\">"+ //2 sec auto refresh
893 "<title>Policy Agent and simulator monitor</title>"+
896 "<font size=\"-3\" face=\"monospace\">" +
897 "<p>Change basename in url if other ric sim prefix is used</p>" +
899 "<h3>Policy agent</h3>" +
900 "<font face=\"monospace\">" +
901 "Status:..............................." + formatDataRow(ag1) + "<br>" +
902 "Services:............................." + formatIdRowCompact(ag2) + "<br>" +
903 "Types:................................" + formatIdRowCompact(ag3) + "<br>" +
904 "Number of instances:.................." + formatDataRow(ag4) + "<br>" +
905 "Near-RT RICs:........................." + formatDataRow(ag5) + "<br>" +
907 "<h3>MR Stub interface</h3>" +
908 "<font face=\"monospace\">"+
909 "Submitted requests:............................" + formatDataRow(mr1) + "<br>" +
910 "Fetched requests:.............................." + formatDataRow(mr2) + "<br>" +
911 "Current requests waiting:......................" + formatDataRow(mr3) + "<br>" +
912 "Submitted responses:..........................." + formatDataRow(mr4) + "<br>" +
913 "Fetched responses.............................." + formatDataRow(mr5) + "<br>" +
914 "Current responses waiting......................" + formatDataRow(mr6) + "<br>" +
916 "<h3>Callback receiver</h3>" +
917 "<font face=\"monospace\">" +
918 "Callbacks received:..................." + formatDataRow(cr1) + "<br>" +
919 "Callbacks fetched:...................." + formatDataRow(cr2) + "<br>" +
920 "Number of waiting callback messages:.." + formatDataRow(cr3) + "<br>" +
922 "<h3>Near-RT RIC Simulators</h3>" +
923 "<font face=\"monospace\">"
925 htmlStr=htmlStr+padding("Near-RT RIC Simulator name", 35," ")
926 htmlStr=htmlStr+padding("Types", 10," ")
927 htmlStr=htmlStr+padding("Instances", 12," ")
928 htmlStr=htmlStr+padding("Data delivery", 12," ")+"<br>"
929 htmlStr=htmlStr+padding("",70,"=")+"<br>"
930 for(var simIndex=0;simIndex<simnames.length;simIndex++) {
931 htmlStr=htmlStr+padding(simnames[simIndex]+ " ("+simports[simIndex]+")",35," ");
932 htmlStr=htmlStr+padding(simvar2[simIndex],10," ")
933 htmlStr=htmlStr+padding(simvar1[simIndex],12 ," ")
934 htmlStr=htmlStr+padding(simvar6[simIndex],12," ")
935 htmlStr=htmlStr+"<br>";
938 htmlStr=htmlStr+"<br>";
939 htmlStr=htmlStr+padding("Near-RT RIC Simulator name", 35," ")
940 htmlStr=htmlStr+padding("Version", 20," ")
941 htmlStr=htmlStr+padding("Type-IDs", 10," ")+"<br>"
942 htmlStr=htmlStr+padding("",65,"=")+"<br>"
943 for(simIndex=0;simIndex<simnames.length;simIndex++) {
944 htmlStr=htmlStr+padding(simnames[simIndex]+ " ("+simports[simIndex]+")",35," ");
945 htmlStr=htmlStr+padding(simvar4[simIndex],20," ")
946 htmlStr=htmlStr+padding(formatIdRowCompact(simvar3[simIndex]),10," ")
947 htmlStr=htmlStr+"<br>";
950 htmlStr=htmlStr+"<br>";
951 htmlStr=htmlStr+padding("Near-RT RIC Simulator name", 35," ")
952 htmlStr=htmlStr+padding("Remote hosts", 50," ")+"<br>"
953 htmlStr=htmlStr+padding("",90,"=")+"<br>"
954 for(simIndex=0;simIndex<simnames.length;simIndex++) {
955 htmlStr=htmlStr+padding(simnames[simIndex]+ " ("+simports[simIndex]+")",35," ");
956 htmlStr=htmlStr+padding(simvar5[simIndex],50," ")
957 htmlStr=htmlStr+"<br>";
966 var httpServer = http.createServer(app);
968 httpServer.listen(httpPort);
969 console.log("Simulator monitor listening (http) at "+httpPort);
970 console.log("Open the web page on localhost:9999/mon to view the policy statistics page.")
971 console.log("Open the web page on localhost:9999/mon2 to view the enrichment statistics page.")
972 console.log("Open the web page on localhost:9999/mon3 to view CR DB in json.")