blob: da71a9e343dff7fac754f580419886e1b445f922 [file] [log] [blame]
BjornMagnussonXA80a92002020-03-19 14:31:06 +01001/*
2# ============LICENSE_START===============================================
3# Copyright (C) 2020 Nordix Foundation. All rights reserved.
4# ========================================================================
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16# ============LICENSE_END=================================================
17#
18*/
19
20// Sim mon server - query the agent and the simulators for counters and other data
21// Presents a web page on localhost:9999/mon
22
23var LOCALHOST="http://127.0.0.1:"
24var MRSTUB_PORT="3905"
25var AGENT_PORT="8081"
26var CR_PORT="8090"
27var http = require('http');
28
29var express = require('express');
30var app = express();
31var fieldSize=32;
32
33
34
35//I am alive
36app.get("/",function(req, res){
37 res.send("ok");
38})
39
40//Get parameter valuue from other server
41function getSimCtr(url, index, cb) {
42 var data = '';
43 http.get(url, (resp) => {
44 // A chunk of data has been recieved.
45 resp.on('data', (chunk) => {
46 data += chunk;
47 });
48
49 // The whole response has been received.
50 resp.on('end', () => {
51 var code=resp.statusCode
52 if (code > 199 && code < 300) {
53 cb(data, index);
54 } else {
55 cb("not found", index);
56 }
57 });
58
59 }).on("error", (err) => {
60 console.log("Error: " + err.message);
61 cb("no response", index);
62 });
63};
64
65
66//Format a comma separated list of data to a html-safe string with fixed fieldsizes
67function formatDataRow(commaList) {
68 var str = "";
69 var tmp=commaList.split(',');
70 for(var i=0;i<tmp.length;i++) {
71 var data=tmp[i];
72 var len = fieldSize-data.length;
73 while(len>0) {
74 data = data+"&nbsp;";
75 len--;
76 }
77 str=str+data+"&nbsp;&nbsp;&nbsp;";
78 }
79 return str;
80}
81
82//Format a comma separated list of ids to a html-safe string with fixed fieldsizes
83function formatIdRow(commaList) {
84 var str = "";
85 var tmp=commaList.split(',');
86 for(var i=0;i<tmp.length;i++) {
87 tmp[i] = tmp[i].trim();
88 var data="&lt"+tmp[i]+"&gt";
89 var len = fieldSize+4-data.length;
90 while(len>0) {
91 data = data+"&nbsp;";
92 len--;
93 }
94 str=str+data+"&nbsp;&nbsp;&nbsp;";
95 }
96 return str;
97}
98
99//Format a list of ids to a html-safe string in compact format
100function formatIdRowCompact(commaList) {
101 if (commaList == undefined) {
102 commaList= "";
103 }
104 var str = "";
105 var tmp=commaList.split(',');
106 for(var i=0;i<tmp.length;i++) {
107 tmp[i] = tmp[i].trim();
108 var data="&lt"+tmp[i]+"&gt";
109 str=str+data+"&nbsp;";
110 }
111 return str;
112}
113
114//Pad a string upto a certain size using a pad string
115function padding(val, fieldSize, pad) {
116 var s=""+val;
117 for(var i=s.length;i<fieldSize;i++) {
118 s=s+pad
119 }
120 return s;
121}
122
123//Status variables, for parameters values fetched from other simulators
124var mr1="", mr2="", mr3="", mr4="", mr5="", mr6="";
125
126//Status variables for agent
127var ag1=""
128var ag2=""
129var ag3=""
130var ag4=""
131
132//Status variables for callback receiver
133var cr1=""
134var cr2=""
135var cr3=""
136
137
138//Container names and ports of the ric simulator
139var simnames=[]
140var simports=[]
141
142//Status variables for each ric simulator
143var simvar1=[]
144var simvar2=[]
145var simvar3=[]
146var simvar4=[]
147
148//Counts the number of get request for the html page
149var getCtr=0
150
151var refreshInterval=2000
152
153function fetchAllMetrics() {
154 setTimeout(() => {
155
156 console.log("Fetching all metics data")
157 if (refreshInterval < 20000) {
158 refreshInterval+=100
159 }
160 if (getCtr%3 == 0) {
161 //Extract the port numbers from the running simulators, for every 3 calls
162 const { exec } = require('child_process');
163 exec('docker ps --filter "name=ricsim" --format "{{.Names}} {{.Ports}}" | sed s/0.0.0.0:// | cut -d \'>\' -f1 | sed \'s/[[-]]*$//\'', (err, stdout, stderr) => {
164
165 var simulators = ""
166 simulators=`${stdout}`.replace(/(\r\n|\n|\r)/gm," ");
167 simulators=simulators.trim();
168 var sims=simulators.split(" ")
169 simnames=[]
170 simports=[]
171 for(i=0;i<sims.length;i=i+2) {
172 simnames[i/2]=sims[i]
173 simports[i/2]=sims[i+1]
174 }
175 });
176 }
177 getCtr=getCtr+1
178
179 //Get metric values from the simulators
180 for(var index=0;index<simnames.length;index++) {
181 getSimCtr(LOCALHOST+simports[index]+"/counter/num_instances", index, function(data, index) {
182 simvar1[index] = data;
183 });
184 getSimCtr(LOCALHOST+simports[index]+"/counter/num_types", index, function(data,index) {
185 simvar2[index] = data;
186 });
187 getSimCtr(LOCALHOST+simports[index]+"/policytypes", index, function(data,index) {
188 data=data.replace(/\[/g,'');
189 data=data.replace(/\]/g,'');
190 data=data.replace(/ /g,'');
191 data=data.replace(/\"/g,'');
192 simvar3[index] = data;
193 });
194 getSimCtr(LOCALHOST+simports[index]+"/counter/interface", index, function(data,index) {
195 simvar4[index] = data;
196 });
197 }
198
199 //MR - get metrics values from the MR stub
200 getSimCtr(LOCALHOST+MRSTUB_PORT+"/counter/requests_submitted", 0, function(data, index) {
201 mr1 = data;
202 });
203 getSimCtr(LOCALHOST+MRSTUB_PORT+"/counter/requests_fetched", 0, function(data, index) {
204 mr2 = data;
205 });
206 getSimCtr(LOCALHOST+MRSTUB_PORT+"/counter/current_requests", 0, function(data, index) {
207 mr3 = data;
208 });
209 getSimCtr(LOCALHOST+MRSTUB_PORT+"/counter/responses_submitted", 0, function(data, index) {
210 mr4 = data;
211 });
212 getSimCtr(LOCALHOST+MRSTUB_PORT+"/counter/responses_fetched", 0, function(data, index) {
213 mr5 = data;
214 });
215 getSimCtr(LOCALHOST+MRSTUB_PORT+"/counter/current_responses", 0, function(data, index) {
216 mr6 = data;
217 });
218
219 //CR - get metrics values from the callbackreceiver
220 getSimCtr(LOCALHOST+CR_PORT+"/counter/received_callbacks", 0, function(data, index) {
221 cr1 = data;
222 });
223 getSimCtr(LOCALHOST+CR_PORT+"/counter/fetched_callbacks", 0, function(data, index) {
224 cr2 = data;
225 });
226 getSimCtr(LOCALHOST+CR_PORT+"/counter/current_messages", 0, function(data, index) {
227 cr3 = data;
228 });
229
230 //Agent - get metrics from the agent
231 getSimCtr(LOCALHOST+AGENT_PORT+"/status", 0, function(data, index) {
232 ag1 = data;
233 });
234 getSimCtr(LOCALHOST+AGENT_PORT+"/services", 0, function(data, index) {
235 ag2="";
236 try {
237 var jd=JSON.parse(data);
238 for(var key in jd) {
239 if (ag2.length > 1) {
240 ag2=ag2+", "
241 }
242 ag2=ag2+(jd[key]["serviceName"]).trim()
243 }
244 }
245 catch (err) {
246 ag2=data
247 }
248 });
249 getSimCtr(LOCALHOST+AGENT_PORT+"/policy_types", 0, function(data, index) {
250 ag3="";
251 try {
252 var jd=JSON.parse(data);
253 for(var key in jd) {
254 if (ag3.length > 0) {
255 ag3=ag3+", "
256 }
257 ag3=ag3+jd[key].trim()
258 }
259 }
260 catch (err) {
261 ag3=""
262 }
263 });
264 getSimCtr(LOCALHOST+AGENT_PORT+"/policy_ids", 0, function(data, index) {
265 ag4=""
266 try {
267 var jd=JSON.parse(data);
268 ag4=""+jd.length
269 }
270 catch (err) {
271 ag4=""
272 }
273 });
274
275
276
277 fetchAllMetrics();
278 }, refreshInterval)
279}
280
281fetchAllMetrics();
282
283setInterval(() => {
284 console.log("Setting interval "+refreshInterval+"ms")
285}, refreshInterval)
286
287app.get("/mon",function(req, res){
288
289
290 refreshInterval=2000
291
292 //Build web page
293 var htmlStr = "<!DOCTYPE html>" +
294 "<html>" +
295 "<head>" +
296 "<meta http-equiv=\"refresh\" content=\"2\">"+ //2 sec auto refresh
297 "<title>Policy Agent and simulator monitor</title>"+
298 "</head>" +
299 "<body>" +
300 "<h3>Policy agent</h3>" +
301 "<font face=\"monospace\">" +
302 "Status:..............................." + formatDataRow(ag1) + "<br>" +
303 "Services:............................." + formatIdRowCompact(ag2) + "<br>" +
304 "Types:................................" + formatIdRowCompact(ag3) + "<br>" +
305 "Number of instances:.................." + formatDataRow(ag4) + "<br>" +
306 "</font>" +
307 "<h3>MR Stub interface</h3>" +
308 "<font face=\"monospace\">"+
309 "Submitted requests:............................" + formatDataRow(mr1) + "<br>" +
310 "Fetched requests:.............................." + formatDataRow(mr2) + "<br>" +
311 "Current requests waiting:......................" + formatDataRow(mr3) + "<br>" +
312 "Submitted responses:..........................." + formatDataRow(mr4) + "<br>" +
313 "Fetched responses.............................." + formatDataRow(mr5) + "<br>" +
314 "Current responses waiting......................" + formatDataRow(mr6) + "<br>" +
315 "</font>"+
316 "<h3>Callback receiver</h3>" +
317 "<font face=\"monospace\">" +
318 "Callbacks received:..................." + formatDataRow(cr1) + "<br>" +
319 "Callbacks fetched:...................." + formatDataRow(cr2) + "<br>" +
320 "Number of waiting callback messages:.." + formatDataRow(cr3) + "<br>" +
321 "</font>" +
322 "<h3>Near-RT RIC Simulators</h3>" +
323 "<font face=\"monospace\">"
324
325 htmlStr=htmlStr+padding("Near-RT RIC Simulator name", 35,"&nbsp;")
326 htmlStr=htmlStr+padding("Types", 10,"&nbsp;")
327 htmlStr=htmlStr+padding("Instances", 10,"&nbsp;")
328 htmlStr=htmlStr+"<br>"+padding("",55,"=")+"<br>"
329
330 for(var simIndex=0;simIndex<simnames.length;simIndex++) {
331 htmlStr=htmlStr+padding(simnames[simIndex]+ " ("+simports[simIndex]+")",35,"&nbsp;");
332 htmlStr=htmlStr+padding(simvar2[simIndex],10,"&nbsp;")
333 htmlStr=htmlStr+padding(simvar1[simIndex],10,"&nbsp;")
334 htmlStr=htmlStr+"<br>";
335 }
336
337 htmlStr=htmlStr+"<br>";
338 htmlStr=htmlStr+padding("Near-RT RIC Simulator name", 35,"&nbsp;")
339 htmlStr=htmlStr+padding("Version", 20,"&nbsp;")
340 htmlStr=htmlStr+padding("Type-IDs", 10,"&nbsp;")+"<br>"
341 htmlStr=htmlStr+padding("",65,"=")+"<br>"
342 for(simIndex=0;simIndex<simnames.length;simIndex++) {
343 htmlStr=htmlStr+padding(simnames[simIndex]+ " ("+simports[simIndex]+")",35,"&nbsp;");
344 htmlStr=htmlStr+padding(simvar4[simIndex],20,"&nbsp;")
345 htmlStr=htmlStr+padding(formatIdRowCompact(simvar3[simIndex]),10,"&nbsp;")
346 htmlStr=htmlStr+"<br>";
347 }
348
349 htmlStr=htmlStr+
350 "</body>" +
351 "</html>";
352 res.send(htmlStr);
353})
354
355var httpServer = http.createServer(app);
356var httpPort=9999;
357httpServer.listen(httpPort);
358console.log("Simulator monitor listening (http) at "+httpPort);
359console.log("Open the web page on localhost:9999/mon to view the statistics page.")