Show AC app data visualization in new metrics tab
[portal/ric-dashboard.git] / webapp-frontend / src / app / stats / stats.component.ts
1 /*-
2  * ========================LICENSE_START=================================
3  * O-RAN-SC
4  * %%
5  * Copyright (C) 2019 AT&T Intellectual Property and Nokia
6  * %%
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ========================LICENSE_END===================================
19  */
20 import { Component, OnInit, ViewChildren, QueryList } from '@angular/core';
21 import { BaseChartDirective } from 'ng2-charts/ng2-charts';
22 import { StatsService } from '../services/stats/stats.service';
23 import { HttpClient } from '@angular/common/http';
24 import { map } from 'rxjs/operators';
25 import { DashboardSuccessTransport } from '../interfaces/dashboard.types';
26 import { DomSanitizer, SafeUrl, SafeResourceUrl } from '@angular/platform-browser';
27
28 @Component({
29     selector: 'rd-stats',
30     templateUrl: './stats.component.html',
31     styleUrls: ['./stats.component.scss']
32 })
33 export class StatsComponent implements OnInit {
34
35     @ViewChildren(BaseChartDirective) charts: QueryList<BaseChartDirective>;
36     timeLeft = 60;
37     interval;
38     checked = false;
39     load;
40     delay;
41     metricsUrlAc : SafeResourceUrl;
42
43     public latencyChartColors: Array<any> = [
44         { // blue
45             backgroundColor: 'rgba(197, 239, 247, 0.2)',
46             borderColor: 'lightblue',
47             pointBackgroundColor: 'lightblue',
48             pointBorderColor: '#fff',
49             pointHoverBackgroundColor: '#fff',
50             pointHoverBorderColor: 'rgba(148,159,177,0.8)'
51         }
52     ];
53     public latencyChartOptions = {
54         scaleShowVerticalLines: true,
55         responsive: true,
56         animation: {
57             duration: 800 * 1.5,
58             easing: 'linear'
59         },
60         hover: {
61             animationDuration: 1 // duration of animations when hovering an item
62         },
63         responsiveAnimationDuration: 500,
64         scales: {
65             yAxes: [{
66                 ticks: {
67                     // the data minimum used for determining the ticks is Math.min(dataMin, suggestedMin)
68                     suggestedMin: 0,
69                     // the data maximum used for determining the ticks is Math.max(dataMax, suggestedMax)
70                     //                    suggestedMax: 1000
71                 },
72                 scaleLabel: {
73                     display: true,
74                     labelString: 'msecs'
75                 }
76             }],
77             xAxes: [{
78                 scaleLabel: {
79                     display: true,
80                     labelString: 'time (last 10 seconds)'
81                 }
82             }]
83         },
84     };
85     public latencyChartLabels = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10'];
86     public latencyChartType = 'line';
87     public latencyChartLegend = true;
88     public latencyChartData = [
89         { data: [65, 59, 80, 81, 56, 55, 40, 20, 12, 34], label: 'Latency' },
90     ];
91
92     public loadChartColors: Array<any> = [
93
94         { // green
95             backgroundColor: 'rgba(200, 247, 197, 0.2)',
96             borderColor: 'lightgreen',
97             pointBackgroundColor: 'lightgreen',
98             pointBorderColor: '#fff',
99             pointHoverBackgroundColor: '#fff',
100             pointHoverBorderColor: 'rgba(0,200,0,0.5)'
101         }
102     ];
103     public loadChartOptions = {
104         scaleShowVerticalLines: false,
105         responsive: true,
106         animation: {
107             duration: 800 * 1.5,
108             easing: 'linear'
109         },
110         hover: {
111             animationDuration: 1 // duration of animations when hovering an item
112         },
113         responsiveAnimationDuration: 500,
114         scales: {
115             yAxes: [{
116                 ticks: {
117                     // the data minimum used for determining the ticks is Math.min(dataMin, suggestedMin)
118                     suggestedMin: 0,
119                     // the data maximum used for determining the ticks is Math.max(dataMax, suggestedMax)
120                     //                    suggestedMax: 1000
121                 },
122                 scaleLabel: {
123                     display: true,
124                     labelString: '# of requests'
125                 }
126             }],
127             xAxes: [{
128                 scaleLabel: {
129                     display: true,
130                     labelString: 'time (last 10 seconds)'
131                 }
132             }]
133         },
134     };
135     public loadChartLabels = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10'];
136     public loadChartType = 'line';
137     public loadChartLegend = true;
138     public loadChartData = [
139         { data: [28, 48, 40, 19, 86, 77, 90, 20, 12, 34], label: 'Load' }
140     ];
141
142     public cpuChartColors: Array<any> = [
143
144         { // red
145             backgroundColor: 'rgba(241, 169, 160, 0.2)',
146             borderColor: 'brown',
147             pointBackgroundColor: 'brown',
148             pointBorderColor: '#fff',
149             pointHoverBackgroundColor: '#fff',
150             pointHoverBorderColor: 'rgba(0,200,0,0.5)'
151         }
152     ];
153     public cpuChartOptions = {
154         scaleShowVerticalLines: false,
155         responsive: true,
156         animation: {
157             duration: 800 * 1.5,
158             easing: 'linear'
159         },
160         hover: {
161             animationDuration: 1 // duration of animations when hovering an item
162         },
163         responsiveAnimationDuration: 500,
164         scales: {
165             yAxes: [{
166                 ticks: {
167                     // the data minimum used for determining the ticks is Math.min(dataMin, suggestedMin)
168                     suggestedMin: 0,
169                     // the data maximum used for determining the ticks is Math.max(dataMax, suggestedMax)
170                     //                    suggestedMax: 1000
171                 },
172                 scaleLabel: {
173                     display: true,
174                     labelString: '# of requests'
175                 }
176             }],
177             xAxes: [{
178                 scaleLabel: {
179                     display: true,
180                     labelString: 'time (last 10 seconds)'
181                 }
182             }]
183         },
184     };
185     public cpuChartLabels = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10'];
186     public cpuChartType = 'line';
187     public cpuChartLegend = true;
188     public cpuChartData = [
189         { data: [15, 29, 30, 31, 53, 52, 41, 70, 32, 14], label: 'RICLoad' }
190     ];
191
192     public x = 11;
193     public y = 11;
194     public z = 11;
195     public loop = true;
196
197     public sliderLoadMax = Number(this.service.loadMax) || 0;
198
199     public sliderDelayMax = Number(this.service.delayMax) || 0;
200
201     latencyClickData() {
202         // this.latencyChartData = [{data: [Math.random() * 100, Math.random() * 100, Math.random() * 100,
203         // Math.random() * 100, Math.random() * 100, Math.random() * 100, Math.random() * 100, Math.random() * 100,
204         // Math.random() * 100, Math.random() * 100], label: 'Latency'}];
205         this.charts.forEach((child) => {
206             if (child.datasets[0].label === 'Latency') {
207                 this.latencyChartLabels.shift();
208                 child.datasets[0].data.shift();
209
210                 const latencyData = this.service.getLatencyMetrics();
211                 child.datasets[0].data.push(latencyData);
212                 this.latencyChartLabels.push('' + this.x++);
213             }
214             // once new data is computed and datasets are updated, tell our baseChart the datasets changed
215             child.ngOnChanges({
216                 datasets: {
217                     currentValue: child.datasets,
218                     previousValue: null,
219                     firstChange: true,
220                     isFirstChange: () => true
221                 }
222             });
223         });
224     }
225
226     loadClickData() {
227         if (this.loop) {
228             this.loop = false;
229             this.startLoadTimer();
230         } else {
231             this.loop = true;
232             this.pauseLoadTimer();
233         }
234     }
235
236     loopLoadData(metricsv: any) {
237         this.charts.forEach((child) => {
238             if (child.datasets[0].label === 'Load') {
239                 this.loadChartLabels.shift();
240                 child.datasets[0].data.shift();
241
242                 // const loadData = this.service.getLoad();
243                 // child.datasets[0].data.push(this.service.load);
244                 child.datasets[0].data.push(metricsv['load']);
245                 this.loadChartLabels.push('' + this.x++);
246             }
247             if (child.datasets[0].label === 'Latency') {
248                 this.latencyChartLabels.shift();
249                 child.datasets[0].data.shift();
250
251                 // const loadData = this.service.getLoad();
252                 // child.datasets[0].data.push(this.service.load);
253                 child.datasets[0].data.push(metricsv['latency']);
254                 this.latencyChartLabels.push('' + this.x++);
255             }
256             if (child.datasets[0].label === 'RICLoad') {
257                 this.latencyChartLabels.shift();
258                 child.datasets[0].data.shift();
259
260                 // const loadData = this.service.getLoad();
261                 // child.datasets[0].data.push(this.service.load);
262                 child.datasets[0].data.push(metricsv['ricload']);
263                 this.latencyChartLabels.push('' + this.x++);
264             }
265             // once new data is computed and datasets are updated, tell our baseChart the datasets changed
266             child.ngOnChanges({
267                 datasets: {
268                     currentValue: child.datasets,
269                     previousValue: null,
270                     firstChange: true,
271                     isFirstChange: () => true
272                 }
273             });
274         });
275     }
276
277     cpuClickData() {
278         // this.cpuChartData = [{data: [Math.random() * 100, Math.random() * 100, Math.random() * 100,
279         // Math.random() * 100, Math.random() * 100, Math.random() * 100, Math.random() * 100, Math.random() * 100,
280         // Math.random() * 100, Math.random() * 100], label: 'CPU'}];
281         const cpuData = this.service.getLatencyMetrics();
282         this.newDataPoint([cpuData], this.z++);
283     }
284
285     newDataPoint(dataArr = [100], label) {
286
287         this.cpuChartData.forEach((dataset, index) => {
288             this.cpuChartData[index] = Object.assign({}, this.cpuChartData[index], {
289                 data: [...this.cpuChartData[index].data, dataArr[index]]
290             });
291         });
292
293         this.cpuChartLabels = [...this.cpuChartLabels, label];
294         // console.log(this.cpuChartLabels);
295         // console.log(this.cpuChartData);
296     }
297
298     formatLabel(value: number | null) {
299         if (!value) {
300             return 0;
301         }
302
303         if (value >= 1000) {
304             return Math.round(value / 1000);
305         }
306
307         return value;
308     }
309
310     constructor(private service: StatsService, private httpClient: HttpClient, private sanitize: DomSanitizer) {
311         this.sliderLoadMax = Number(this.service.loadMax) || 0;
312         this.sliderDelayMax = Number(this.service.delayMax) || 0;
313         // console.log('this.sliderLoadMax: ' + this.sliderLoadMax);
314         // console.log('this.sliderDelayMax: ' + this.sliderDelayMax);
315     }
316     ngOnInit() {
317         this.fetchLoad().subscribe(loadv => {
318             // console.log('loadv: ' + loadv);
319             this.checked = loadv;
320         });
321         this.fetchDelay().subscribe(delayv => {
322             // console.log('delayv: ' + delayv);
323             this.delay = delayv;
324         });
325         this.fetchMetrics().subscribe(metricsv => {
326             // console.log('metricsv.load: ' + metricsv['load']);
327         });
328         this.service.getAppMetricsUrl('AC').subscribe((res:DashboardSuccessTransport) => {
329             this.metricsUrlAc = this.sanitize.bypassSecurityTrustResourceUrl(res.data);
330         });
331     }
332
333     startLoadTimer() {
334         this.interval = setInterval(() => {
335             if (this.timeLeft > 0) {
336                 this.timeLeft--;
337                 this.fetchMetrics().subscribe(metricsv => {
338                     // console.log('metricsv.load: ' + metricsv['latency']);
339                     // console.log('metricsv.load: ' + metricsv['load']);
340                     // console.log('metricsv.load: ' + metricsv['ricload']);
341                     this.loopLoadData(metricsv);
342                 });
343
344             } else {
345                 this.timeLeft = 60;
346             }
347         }, 1000);
348     }
349
350     pauseLoadTimer() {
351         clearInterval(this.interval);
352     }
353
354     fetchMetrics() {
355         return this.httpClient.get<any[]>(this.service.hostURL + this.service.metricsPath, this.service.httpOptions).pipe(map(res => {
356             return res;
357         }));
358     }
359
360     fetchDelay() {
361         return this.httpClient.get<any[]>(this.service.hostURL + this.service.delayPath, this.service.httpOptions).pipe(map(res => {
362             const delayv = res['delay'];
363             this.delay = delayv;
364             return this.delay;
365         }));
366     }
367
368     saveDelay() {
369         this.service.putDelay(this.delay);
370     }
371
372     fetchLoad() {
373         return this.httpClient.get<any[]>(this.service.hostURL + this.service.loadPath, this.service.httpOptions).pipe(map(res => {
374             const loadv = res['load'];
375             this.load = loadv;
376             return this.load;
377         }));
378
379     }
380
381     saveLoad() {
382         this.service.putLoad(this.load);
383     }
384
385 }