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 ecs
190 var ecs1="", ecs2="", ecs3="", ecs4="", ecs_types="-", ecs_producers="-";
191 var ecs_producer_arr=new Array(0)
192 var ecs_producer_type_arr=new Array(0)
193 var ecs_producer_jobs_arr=new Array(0)
194 var ecs_producer_status_arr=new Array(0)
195 var ecs_jobs=new Array(0)
196 var ecs_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_ecs=-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+'" --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_ecs() {
434 console.log("Fetching enrichment metrics - timer:" + refreshCount_ecs)
436 if (refreshCount_ecs < 0) {
437 refreshCount_ecs = -1
440 refreshCount_ecs = refreshCount_ecs - 1
444 if (checkFunctionFlag("ecs_stat")) {
445 getSimCtr(LOCALHOST+ECS_PORT+"/status", 0, function(data, index) {
447 var jd=JSON.parse(data);
449 ecs2=""+jd["no_of_producers"]
450 ecs3=""+jd["no_of_types"]
451 ecs4=""+jd["no_of_jobs"]
454 ecs1="error response"
455 ecs2="error response"
456 ecs3="error response"
457 ecs4="error response"
460 clearFlag("ecs_stat")
462 if (checkFunctionFlag("ecs_types")) {
463 getSimCtr(LOCALHOST+ECS_PORT+"/ei-producer/v1/eitypes", 0, function(data, index) {
464 var tmp_ecs_types="-"
466 var jd=JSON.parse(data);
467 for(var i=0;i<jd.length;i++) {
468 if (tmp_ecs_types.length == 1) {
471 tmp_ecs_types=""+tmp_ecs_types+jd[i]+" "
475 tmp_ecs_types="error response"
477 ecs_types = tmp_ecs_types
479 clearFlag("ecs_types")
481 if (checkFunctionFlag("ecs_producers")) {
482 getSimCtr(LOCALHOST+ECS_PORT+"/ei-producer/v1/eiproducers", 0, function(data, index) {
483 var tmp_ecs_producers="-"
485 var jd=JSON.parse(data);
486 var tmp_ecs_producer_arr=new Array(jd.length)
487 for(var i=0;i<jd.length;i++) {
488 if (tmp_ecs_producers.length == 1) {
491 tmp_ecs_producers=""+tmp_ecs_producers+jd[i]+" "
492 tmp_ecs_producer_arr[i]=jd[i]
494 ecs_producer_arr = tmp_ecs_producer_arr
495 ecs_producers = tmp_ecs_producers
498 ecs_producers="error response"
499 ecs_producer_arr=new Array(0)
502 clearFlag("ecs_producers")
504 if (checkFunctionFlag("ecs_data")) {
506 var tmp_ecs_producer_type_arr = JSON.parse(JSON.stringify(ecs_producer_arr))
507 for(var x=0;x<tmp_ecs_producer_type_arr.length;x++) {
508 getSimCtr(LOCALHOST+ECS_PORT+"/ei-producer/v1/eiproducers/"+tmp_ecs_producer_type_arr[x], x, function(data, idx) {
509 var row=""+tmp_ecs_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]["ei_type_identity"]+" "
516 tmp_ecs_producer_type_arr[idx]=row
519 tmp_ecs_producer_type_arr=new Array(0)
523 ecs_producer_type_arr = tmp_ecs_producer_type_arr
525 ecs_producer_type_arr=new Array(0)
528 var tmp_ecs_producer_jobs_arr = JSON.parse(JSON.stringify(ecs_producer_arr))
529 for(x=0;x<tmp_ecs_producer_jobs_arr.length;x++) {
530 getSimCtr(LOCALHOST+ECS_PORT+"/ei-producer/v1/eiproducers/"+tmp_ecs_producer_jobs_arr[x]+"/eijobs", x, function(data, idx) {
531 var row=""+tmp_ecs_producer_jobs_arr[idx]+" : "
533 var jd=JSON.parse(data);
534 for(var j=0;j<jd.length;j++) {
536 row=""+row+jda["ei_job_identity"]+"("+jda["ei_type_identity"]+") "
538 tmp_ecs_producer_jobs_arr[idx]=row
541 tmp_ecs_producer_jobs_arr=new Array(0)
545 ecs_producer_jobs_arr = tmp_ecs_producer_jobs_arr
547 ecs_producer_jobs_arr=new Array(0)
551 var tmp_ecs_producer_status_arr = JSON.parse(JSON.stringify(ecs_producer_arr))
552 for(x=0;x<tmp_ecs_producer_status_arr.length;x++) {
553 getSimCtr(LOCALHOST+ECS_PORT+"/ei-producer/v1/eiproducers/"+tmp_ecs_producer_status_arr[x]+"/status", x, function(data, idx) {
554 var row=""+tmp_ecs_producer_status_arr[idx]+" : "
556 var jd=JSON.parse(data);
557 row=""+row+jd["operational_state"]
558 tmp_ecs_producer_status_arr[idx]=row
561 tmp_ecs_producer_status_arr=new Array(0)
565 ecs_producer_status_arr = tmp_ecs_producer_status_arr
567 ecs_producer_status_arr=new Array(0)
569 clearFlag("ecs_data")
571 if (checkFunctionFlag("ecs_jobs")) {
572 getSimCtr(LOCALHOST+ECS_PORT+"/A1-EI/v1/eijobs", 0, function(data, index) {
574 var jd=JSON.parse(data);
575 var tmpArr=new Array(jd.length)
576 for(var i=0;i<jd.length;i++) {
582 ecs_jobs=new Array(0)
585 clearFlag("ecs_jobs")
587 if (checkFunctionFlag("ecs_job_status")) {
589 var tmp_ecs_job_status= JSON.parse(JSON.stringify(ecs_jobs))
590 for(x=0;x<tmp_ecs_job_status.length;x++) {
591 getSimCtr(LOCALHOST+ECS_PORT+"/A1-EI/v1/eijobs/"+tmp_ecs_job_status[x]+"/status", x, function(data, idx) {
593 var jd=JSON.parse(data);
594 tmp_ecs_job_status[idx]=""+tmp_ecs_job_status[idx]+":"+jd["eiJobStatus"]
597 tmp_ecs_job_status="-"
601 ecs_job_status = tmp_ecs_job_status
605 clearFlag("ecs_job_status")
607 if (checkFunctionFlag("prodstub_stat")) {
608 getSimCtr(LOCALHOST+PRODSTUB_PORT+"/status", x, function(data, idx) {
609 var ctr2_map=new Map()
610 var ctr3_map=new Map()
613 var tmp_ps_producers=""
615 var tmp_ps_producer_type_arr=new Array()
616 var tmp_ps_producer_jobs_arr=new Array()
617 var tmp_ps_producer_delivery_arr=new Array()
622 var jp=JSON.parse(data);
623 for(var prod_name in jp) {
624 ctr2_map.set(prod_name, prod_name)
627 var row=""+prod_name+" : "
628 var rowj=""+prod_name+" : "
629 var rowd=""+prod_name+" : "
630 tmp_ps_producers += prod_name + " "
634 for(var i=0;i<ta.length;i++) {
635 ctr3_map.set(ta[i], ta[i])
638 } else if (ji == "supervision_response") {
640 } else if (ji == "supervision_counter") {
642 } else if (ji == "types") {
648 var job_data=jj[ji]["json"]
649 if (job_data != undefined) {
650 rowj += "("+job_data["ei_type_identity"]+")"
652 rowd += "("+jj[ji]["delivery_attempts"]+")"
655 tmp_ps_producer_type_arr[(ctr2-1)]=row
656 tmp_ps_producer_jobs_arr[(ctr2-1)]=rowj
657 tmp_ps_producer_delivery_arr[(ctr2-1)]=rowd
659 tmp_ps2=""+ctr2_map.size
660 tmp_ps3=""+ctr3_map.size
661 for(const [key, value] of ctr3_map.entries()) {
662 tmp_ps_types += key + " "
666 ps_producers=tmp_ps_producers
667 ps_types=tmp_ps_types
668 ps_producer_type_arr=tmp_ps_producer_type_arr
669 ps_producer_jobs_arr=tmp_ps_producer_jobs_arr
670 ps_producer_delivery_arr=tmp_ps_producer_delivery_arr
676 ps_producers="error response"
677 ps_types="error response"
678 ps_producer_type_arr=new Array()
679 ps_producer_jobs_arr=new Array()
680 ps_producer_delivery_arr=new Array()
686 clearFlag("prodstub_stat")
689 fetchAllMetrics_ecs();
694 function fetchAllMetrics_cr() {
696 console.log("Fetching CR DB - timer:" + refreshCount_ecs)
698 if (refreshCount_cr < 0) {
702 refreshCount_cr = refreshCount_cr - 1
706 if (checkFunctionFlag("cr_stat")) {
707 getSimCtr(LOCALHOST+CR_PORT+"/db", 0, function(data, index) {
709 cr_db=JSON.parse(data);
717 fetchAllMetrics_cr();
721 function fetchAllMetrics_rc() {
723 console.log("Fetching RC services - timer:" + refreshCount_ecs)
725 if (refreshCount_rc < 0) {
729 refreshCount_rc = refreshCount_rc - 1
733 if (checkFunctionFlag("rc_stat")) {
734 getSimCtr(LOCALHOST+RC_PORT+"/services", 0, function(data, index) {
737 var jd=JSON.parse(data);
738 for(var i=0;i<jd.length;i++) {
739 if (tmp_serv.length > 0) {
740 tmp_serv=tmp_serv+","
742 tmp_serv=tmp_serv+jd[i]["name"]
747 tmp_serv="no_response"
753 fetchAllMetrics_rc();
758 app.get("/mon3",function(req, res){
760 console.log("Creating CR DB page - timer: " + refreshCount_ecs)
762 if (refreshCount_cr < 0) {
767 var json_str=JSON.stringify(cr_db, null, 1)
768 var htmlStr = "<!DOCTYPE html>" +
771 "<meta http-equiv=\"refresh\" content=\"2\">"+ //2 sec auto refresh
772 "<title>CR DB dump</title>"+
774 "<body style=\"white-space: pre-wrap\">" +
782 app.get("/mon2",function(req, res){
784 console.log("Creating enrichment metrics - timer: " + refreshCount_ecs)
786 if (refreshCount_ecs < 0) {
788 fetchAllMetrics_ecs()
792 var summary=req.query.summary
794 if (summary == undefined) {
795 return res.redirect('/mon2?summary=false');
799 var htmlStr = "<!DOCTYPE html>" +
802 "<meta http-equiv=\"refresh\" content=\"2\">"+ //2 sec auto refresh
803 "<title>Enrichment coordinator service and producer stub</title>"+
806 "<font size=\"-3\" face=\"summary\">"
807 if (summary == "false") {
808 htmlStr=htmlStr+"<p>Set query param '?summary' to true to only show summary statistics.</p>"
810 htmlStr=htmlStr+"<p>Set query param '?summary' to false to only show full statistics</p>"
812 if (ecs_job_status.length > 10) {
813 htmlStr=htmlStr+"<div style=\"color:red\"> Avoid running the server for large number of producers and/or jobs</div>"
815 htmlStr=htmlStr+"</font>" +
816 "<h3>Enrichment Coordinator Service</h3>" +
817 "<font face=\"monospace\">" +
818 "Status:..........." + formatDataRow(ecs1) + "<br>" +
819 "Producers:........" + formatDataRow(ecs2) + "<br>" +
820 "Types:............" + formatDataRow(ecs3) + "<br>" +
821 "Jobs:............." + formatDataRow(ecs4) + "<br>" +
823 if (summary == "false") {
826 "<font face=\"monospace\">" +
827 "Producer ids:....." + formatDataRow(ecs_producers) + "<br>" +
828 "Type ids:........." + formatDataRow(ecs_types) + "<br>" +
830 for(var i=0;i<ecs_producer_type_arr.length;i++) {
831 var tmp=ecs_producer_type_arr[i]
832 if (tmp != undefined) {
833 var s = "Producer types...." + formatDataRow(ecs_producer_type_arr[i]) + "<br>"
837 htmlStr=htmlStr+"<br>";
838 for(i=0;i<ecs_producer_jobs_arr.length;i++) {
839 tmp=ecs_producer_jobs_arr[i]
840 if (tmp != undefined) {
841 s = "Producer jobs....." + formatDataRow(ecs_producer_jobs_arr[i]) + "<br>"
845 htmlStr=htmlStr+"<br>";
846 for(i=0;i<ecs_producer_status_arr.length;i++) {
847 tmp=ecs_producer_status_arr[i]
848 if (tmp != undefined) {
849 s = "Producer status..." + formatDataRow(tmp) + "<br>"
853 htmlStr=htmlStr+"<br>";
854 for(i=0;i<ecs_job_status.length;i++) {
855 tmp=ecs_job_status[i]
856 if (tmp != undefined) {
857 s = padding("Job", 18, ".") + formatDataRow(tmp) + "<br>"
861 htmlStr=htmlStr+"<br>"+"<br>" +
866 "<h3>Producer stub</h3>" +
867 "<font face=\"monospace\">" +
868 "Producers:........" + formatDataRow(ps2) + "<br>" +
869 "Types:............" + formatDataRow(ps3) + "<br>" +
870 "Jobs:............." + formatDataRow(ps4) + "<br>" +
872 if (summary == "false") {
875 "<font face=\"monospace\">" +
876 "Producer ids:....." + formatDataRow(ps_producers) + "<br>" +
877 "Type ids:........." + formatDataRow(ps_types) + "<br>" +
879 for(i=0;i<ps_producer_type_arr.length;i++) {
880 tmp=ps_producer_type_arr[i]
881 if (tmp != undefined) {
882 s = "Producer types...." + formatDataRow(ps_producer_type_arr[i]) + "<br>"
886 htmlStr=htmlStr+"<br>";
887 for(i=0;i<ps_producer_jobs_arr.length;i++) {
888 tmp=ps_producer_jobs_arr[i]
889 if (tmp != undefined) {
890 s = "Producer jobs....." + formatDataRow(ps_producer_jobs_arr[i]) + "<br>"
894 htmlStr=htmlStr+"<br>";
895 for(i=0;i<ps_producer_delivery_arr.length;i++) {
896 tmp=ps_producer_delivery_arr[i]
897 if (tmp != undefined) {
898 s = "Producer delivery." + formatDataRow(ps_producer_delivery_arr[i]) + "<br>"
910 // Monitor for policy management
911 app.get("/mon",function(req, res){
913 console.log("Creating policy metrics page " + refreshCount_pol)
915 if (refreshCount_pol < 0) {
917 fetchAllMetrics_pol()
921 if (refreshCount_rc < 0) {
927 var bn=req.query.basename
928 pmsprefix=req.query.pmsprefix
930 console.log("PMS"+pmsprefix)
931 if ((bn == undefined) || (pmsprefix == undefined)) {
933 return res.redirect('/mon?basename=ricsim&pmsprefix=/a1-policy/v2');
940 var htmlStr = "<!DOCTYPE html>" +
943 "<meta http-equiv=\"refresh\" content=\"2\">"+ //2 sec auto refresh
944 "<title>Policy Management Service and simulator monitor</title>"+
947 "<font size=\"-3\" face=\"monospace\">" +
948 "<p>Change basename in url if other ric sim prefix is used</p>" +
949 "<p>Change pmsprefix in url if pms with other prefix is used</p>" +
951 "<h3>Policy Management Service</h3>" +
952 "<font face=\"monospace\">" +
953 "Status:..............................." + formatDataRow(ag1) + "<br>" +
954 "Services:............................." + formatIdRowCompact(ag2) + "<br>" +
955 "Types:................................" + formatIdRowCompact(ag3) + "<br>" +
956 "Number of instances:.................." + formatDataRow(ag4) + "<br>" +
957 "Near-RT RICs:........................." + formatDataRow(ag5) + "<br>" +
959 "<h3>MR Stub interface</h3>" +
960 "<font face=\"monospace\">"+
961 "Submitted requests:............................" + formatDataRow(mr1) + "<br>" +
962 "Fetched requests:.............................." + formatDataRow(mr2) + "<br>" +
963 "Current requests waiting:......................" + formatDataRow(mr3) + "<br>" +
964 "Submitted responses:..........................." + formatDataRow(mr4) + "<br>" +
965 "Fetched responses.............................." + formatDataRow(mr5) + "<br>" +
966 "Current responses waiting......................" + formatDataRow(mr6) + "<br>" +
968 "<h3>Callback|Notification receiver</h3>" +
969 "<font face=\"monospace\">" +
970 "Callbacks received:..................." + formatDataRow(cr1) + "<br>" +
971 "Callbacks fetched:...................." + formatDataRow(cr2) + "<br>" +
972 "Number of waiting callback messages:.." + formatDataRow(cr3) + "<br>" +
974 "<h3>R-APP Catalogue</h3>" +
975 "<font face=\"monospace\">" +
976 "Services:............................." + formatIdRowCompact(rc_services) + "<br>" +
978 "<h3>Near-RT RIC | A1 Simulators</h3>" +
979 "<font face=\"monospace\">"
981 htmlStr=htmlStr+padding("Near-RT RIC Simulator name", 35," ")
982 htmlStr=htmlStr+padding("Types", 10," ")
983 htmlStr=htmlStr+padding("Instances", 12," ")
984 htmlStr=htmlStr+padding("Data delivery", 12," ")+"<br>"
985 htmlStr=htmlStr+padding("",70,"=")+"<br>"
986 for(var simIndex=0;simIndex<simnames.length;simIndex++) {
987 htmlStr=htmlStr+padding(simnames[simIndex]+ " ("+simports[simIndex]+")",35," ");
988 htmlStr=htmlStr+padding(simvar2[simIndex],10," ")
989 htmlStr=htmlStr+padding(simvar1[simIndex],12 ," ")
990 htmlStr=htmlStr+padding(simvar6[simIndex],12," ")
991 htmlStr=htmlStr+"<br>";
994 htmlStr=htmlStr+"<br>";
995 htmlStr=htmlStr+padding("Near-RT RIC Simulator name", 35," ")
996 htmlStr=htmlStr+padding("Version", 20," ")
997 htmlStr=htmlStr+padding("Type-IDs", 10," ")+"<br>"
998 htmlStr=htmlStr+padding("",65,"=")+"<br>"
999 for(simIndex=0;simIndex<simnames.length;simIndex++) {
1000 htmlStr=htmlStr+padding(simnames[simIndex]+ " ("+simports[simIndex]+")",35," ");
1001 htmlStr=htmlStr+padding(simvar4[simIndex],20," ")
1002 htmlStr=htmlStr+padding(formatIdRowCompact(simvar3[simIndex]),10," ")
1003 htmlStr=htmlStr+"<br>";
1006 htmlStr=htmlStr+"<br>";
1007 htmlStr=htmlStr+padding("Near-RT RIC Simulator name", 35," ")
1008 htmlStr=htmlStr+padding("Remote hosts", 50," ")+"<br>"
1009 htmlStr=htmlStr+padding("",90,"=")+"<br>"
1010 for(simIndex=0;simIndex<simnames.length;simIndex++) {
1011 htmlStr=htmlStr+padding(simnames[simIndex]+ " ("+simports[simIndex]+")",35," ");
1012 htmlStr=htmlStr+padding(simvar5[simIndex],50," ")
1013 htmlStr=htmlStr+"<br>";
1022 var httpServer = http.createServer(app);
1024 httpServer.listen(httpPort);
1025 console.log("Simulator monitor listening (http) at "+httpPort);
1026 console.log("Open the web page on localhost:9999/mon to view the policy statistics page.")
1027 console.log("Open the web page on localhost:9999/mon2 to view the enrichment statistics page.")
1028 console.log("Open the web page on localhost:9999/mon3 to view CR DB in json.")