[web-app] 监控历史图表详情
This commit is contained in:
@@ -1,49 +1,9 @@
|
||||
<nz-card *ngIf="isTable" nzHoverable style="height: auto; margin-left: 14px" [nzBordered]="true" [nzTitle]="monitor_metrics_card_title">
|
||||
<nz-table #smallTable nzSize="small" nzNoResult="No Metrics Data" nzFrontPagination="false" [nzData]="valueRows">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="text-align: center" *ngFor="let field of fields">{{ field.name }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let valueRow of smallTable.data">
|
||||
<td *ngFor="let value of valueRow.values">{{ value.origin }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</nz-table>
|
||||
</nz-card>
|
||||
|
||||
<nz-card *ngIf="!isTable" nzHoverable style="height: auto; margin-left: 14px" [nzBordered]="true" [nzTitle]="monitor_metrics_card_title">
|
||||
<nz-table #smallTable nzSize="small" nzNoResult="No Metrics Data" nzFrontPagination="false" [nzData]="valueRows">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="text-align: center">属性</th>
|
||||
<th style="text-align: center">值</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let field of fields; let i = index">
|
||||
<td>{{ field.name }}</td>
|
||||
<td>{{ rowValues[i].origin + ' ' + (field.unit ? field.unit : '') }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</nz-table>
|
||||
</nz-card>
|
||||
|
||||
<ng-template #monitor_metrics_card_title>
|
||||
<p style="font-size: small; text-align: center; margin-bottom: 3px; color: #0c0c0c">{{ metrics }}</p>
|
||||
<div>
|
||||
<a nz-popover [nzPopoverContent]="'最近采集时间 ' + (time | _date: 'yyyy-MM-dd HH:mm:ss')">
|
||||
<i nz-icon nzType="field-time" nzTheme="outline"></i
|
||||
></a>
|
||||
<i style="font-size: 0.3px; font-weight: normal; color: rgba(84, 83, 83, 0.89)">采集时间:{{ time | _date: 'HH:mm:ss' }}</i>
|
||||
</div>
|
||||
</ng-template>
|
||||
|
||||
<!--<nz-card *ngIf="!isTable" nzHoverable style="height:auto;margin-left: 14px;" [nzBordered]="true"-->
|
||||
<!-- [nzTitle]="monitor_metrics_card_title" >-->
|
||||
<!-- <div *ngFor="let field of fields;let i = index;" nz-row nzGutter="16">-->
|
||||
<!-- <div nz-col nzSpan="10"><p style="text-align: right">{{field.name}}</p></div>-->
|
||||
<!-- <div nz-col nzSpan="14"><p style="text-align: left">{{rowValues[i].origin}}</p></div>-->
|
||||
<!-- </div>-->
|
||||
<!--</nz-card>-->
|
||||
<div
|
||||
echarts
|
||||
[options]="eChartOption"
|
||||
theme="default"
|
||||
[autoResize]="true"
|
||||
[loading]="loading"
|
||||
(chartInit)="onChartInit($event)"
|
||||
style="width: 500px; height: 400px; margin-left: 20px"
|
||||
></div>
|
||||
|
||||
@@ -8,8 +8,9 @@ describe('MonitorDataChartComponent', () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [MonitorDataChartComponent]
|
||||
}).compileComponents();
|
||||
declarations: [ MonitorDataChartComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { EChartsOption } from 'echarts';
|
||||
import { finalize } from 'rxjs/operators';
|
||||
|
||||
import { MonitorService } from '../../../service/monitor.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-monitor-data-chart',
|
||||
templateUrl: './monitor-data-chart.component.html',
|
||||
styleUrls: ['./monitor-data-chart.component.less']
|
||||
styles: []
|
||||
})
|
||||
export class MonitorDataChartComponent implements OnInit {
|
||||
@Input()
|
||||
@@ -14,41 +16,254 @@ export class MonitorDataChartComponent implements OnInit {
|
||||
}
|
||||
set monitorId(monitorId: number) {
|
||||
this._monitorId = monitorId;
|
||||
this.loadData();
|
||||
}
|
||||
private _monitorId!: number;
|
||||
@Input()
|
||||
app!: string;
|
||||
@Input()
|
||||
metrics!: string;
|
||||
|
||||
time!: any;
|
||||
fields!: any[];
|
||||
valueRows!: any[];
|
||||
rowValues!: any[];
|
||||
isTable: boolean = true;
|
||||
|
||||
@Input()
|
||||
metric!: string;
|
||||
@Input()
|
||||
unit!: string;
|
||||
eChartOption!: EChartsOption;
|
||||
lineHistoryTheme!: EChartsOption;
|
||||
loading: boolean = true;
|
||||
echartsInstance!: any;
|
||||
// 查询历史数据时间段 默认最近6小时
|
||||
timePeriod: string = '6h';
|
||||
constructor(private monitorSvc: MonitorService) {}
|
||||
ngOnInit(): void {}
|
||||
|
||||
loadData() {
|
||||
// 读取实时指标数据
|
||||
let metricData$ = this.monitorSvc.getMonitorMetricsData(this.monitorId, this.metrics).subscribe(
|
||||
message => {
|
||||
metricData$.unsubscribe();
|
||||
if (message.code === 0) {
|
||||
this.time = message.data.time;
|
||||
this.fields = message.data.fields;
|
||||
this.valueRows = message.data.valueRows;
|
||||
if (this.valueRows.length == 1) {
|
||||
this.isTable = false;
|
||||
this.rowValues = this.valueRows[0].values;
|
||||
}
|
||||
} else {
|
||||
console.error(message.msg);
|
||||
ngOnInit(): void {
|
||||
this.lineHistoryTheme = {
|
||||
title: {
|
||||
text: `${this.metrics}.${this.metric}`,
|
||||
textStyle: {
|
||||
fontSize: 16,
|
||||
fontFamily: 'monospace',
|
||||
textShadowOffsetX: 10
|
||||
}
|
||||
},
|
||||
error => {
|
||||
metricData$.unsubscribe();
|
||||
toolbox: {
|
||||
show: true,
|
||||
orient: 'vertical',
|
||||
feature: {
|
||||
dataZoom: {
|
||||
yAxisIndex: 'none',
|
||||
title: {
|
||||
zoom: '区域缩放',
|
||||
back: '缩放还原'
|
||||
},
|
||||
emphasis: {
|
||||
iconStyle: {
|
||||
textPosition: 'left'
|
||||
}
|
||||
}
|
||||
},
|
||||
saveAsImage: {
|
||||
title: '保存图片',
|
||||
emphasis: {
|
||||
iconStyle: {
|
||||
textPosition: 'left'
|
||||
}
|
||||
}
|
||||
},
|
||||
myPeriod1h: {
|
||||
show: true,
|
||||
title: '查询近1小时',
|
||||
icon: 'path://M827.871087 196.128913C743.498468 111.756293 631.321596 65.290005 512 65.290005c-119.319549 0-231.499491 46.465265-315.871087 130.837884S65.290005 392.680451 65.290005 512s46.465265 231.499491 130.837884 315.871087 196.551538 130.837884 315.871087 130.837884c119.321596 0 231.499491-46.465265 315.871087-130.837884S958.708971 631.319549 958.708971 512 912.243707 280.500509 827.871087 196.128913zM531.556405 917.246651l0-74.145697c0-11.31572-9.174963-20.491707-20.491707-20.491707-11.316743 0-20.491707 9.174963-20.491707 20.491707l0 74.059739C283.276738 906.322857 116.693746 739.164766 106.755396 531.634176l72.351841 0c11.31572 0 20.491707-9.174963 20.491707-20.491707 0-11.31572-9.174963-20.491707-20.491707-20.491707l-72.273047 0c10.769274-206.737528 177.01253-373.005342 383.740848-383.813502l0 72.346725c0 11.316743 9.174963 20.491707 20.491707 20.491707 11.31572 0 20.491707-9.17394 20.491707-20.491707L531.558451 106.752326c207.593012 9.901511 374.807385 176.539762 385.609405 383.89946l-74.142627 0c-11.316743 0-20.491707 9.174963-20.491707 20.491707 0 11.316743 9.174963 20.491707 20.491707 20.491707l74.220399 0C907.275555 739.78796 739.720422 907.317511 531.556405 917.246651z;M532.098757 503.118726 532.098757 258.240529c0-11.316743-9.174963-20.491707-20.491707-20.491707-11.31572 0-20.491707 9.17394-20.491707 20.491707l0 254.66612c0 7.858992 4.429893 14.677281 10.924817 18.114566L693.447539 722.42757c4.002151 4.000104 9.245572 6.001691 14.490016 6.001691s10.487865-2.001587 14.490016-6.001691c8.002254-8.002254 8.002254-20.977777 0-28.980032L532.098757 503.118726z',
|
||||
emphasis: {
|
||||
iconStyle: {
|
||||
textPosition: 'left'
|
||||
}
|
||||
},
|
||||
onclick: () => {
|
||||
this.loadData('1h');
|
||||
}
|
||||
},
|
||||
myPeriod6h: {
|
||||
show: true,
|
||||
title: '查询近6小时',
|
||||
icon: 'path://M827.871087 196.128913C743.498468 111.756293 631.321596 65.290005 512 65.290005c-119.319549 0-231.499491 46.465265-315.871087 130.837884S65.290005 392.680451 65.290005 512s46.465265 231.499491 130.837884 315.871087 196.551538 130.837884 315.871087 130.837884c119.321596 0 231.499491-46.465265 315.871087-130.837884S958.708971 631.319549 958.708971 512 912.243707 280.500509 827.871087 196.128913zM531.556405 917.246651l0-74.145697c0-11.31572-9.174963-20.491707-20.491707-20.491707-11.316743 0-20.491707 9.174963-20.491707 20.491707l0 74.059739C283.276738 906.322857 116.693746 739.164766 106.755396 531.634176l72.351841 0c11.31572 0 20.491707-9.174963 20.491707-20.491707 0-11.31572-9.174963-20.491707-20.491707-20.491707l-72.273047 0c10.769274-206.737528 177.01253-373.005342 383.740848-383.813502l0 72.346725c0 11.316743 9.174963 20.491707 20.491707 20.491707 11.31572 0 20.491707-9.17394 20.491707-20.491707L531.558451 106.752326c207.593012 9.901511 374.807385 176.539762 385.609405 383.89946l-74.142627 0c-11.316743 0-20.491707 9.174963-20.491707 20.491707 0 11.316743 9.174963 20.491707 20.491707 20.491707l74.220399 0C907.275555 739.78796 739.720422 907.317511 531.556405 917.246651z;M532.098757 503.118726 532.098757 258.240529c0-11.316743-9.174963-20.491707-20.491707-20.491707-11.31572 0-20.491707 9.17394-20.491707 20.491707l0 254.66612c0 7.858992 4.429893 14.677281 10.924817 18.114566L693.447539 722.42757c4.002151 4.000104 9.245572 6.001691 14.490016 6.001691s10.487865-2.001587 14.490016-6.001691c8.002254-8.002254 8.002254-20.977777 0-28.980032L532.098757 503.118726z',
|
||||
emphasis: {
|
||||
iconStyle: {
|
||||
textPosition: 'left'
|
||||
}
|
||||
},
|
||||
onclick: () => {
|
||||
this.loadData('6h');
|
||||
}
|
||||
},
|
||||
myPeriod1d: {
|
||||
show: true,
|
||||
title: '查询近1天',
|
||||
icon: 'path://M827.871087 196.128913C743.498468 111.756293 631.321596 65.290005 512 65.290005c-119.319549 0-231.499491 46.465265-315.871087 130.837884S65.290005 392.680451 65.290005 512s46.465265 231.499491 130.837884 315.871087 196.551538 130.837884 315.871087 130.837884c119.321596 0 231.499491-46.465265 315.871087-130.837884S958.708971 631.319549 958.708971 512 912.243707 280.500509 827.871087 196.128913zM531.556405 917.246651l0-74.145697c0-11.31572-9.174963-20.491707-20.491707-20.491707-11.316743 0-20.491707 9.174963-20.491707 20.491707l0 74.059739C283.276738 906.322857 116.693746 739.164766 106.755396 531.634176l72.351841 0c11.31572 0 20.491707-9.174963 20.491707-20.491707 0-11.31572-9.174963-20.491707-20.491707-20.491707l-72.273047 0c10.769274-206.737528 177.01253-373.005342 383.740848-383.813502l0 72.346725c0 11.316743 9.174963 20.491707 20.491707 20.491707 11.31572 0 20.491707-9.17394 20.491707-20.491707L531.558451 106.752326c207.593012 9.901511 374.807385 176.539762 385.609405 383.89946l-74.142627 0c-11.316743 0-20.491707 9.174963-20.491707 20.491707 0 11.316743 9.174963 20.491707 20.491707 20.491707l74.220399 0C907.275555 739.78796 739.720422 907.317511 531.556405 917.246651z;M532.098757 503.118726 532.098757 258.240529c0-11.316743-9.174963-20.491707-20.491707-20.491707-11.31572 0-20.491707 9.17394-20.491707 20.491707l0 254.66612c0 7.858992 4.429893 14.677281 10.924817 18.114566L693.447539 722.42757c4.002151 4.000104 9.245572 6.001691 14.490016 6.001691s10.487865-2.001587 14.490016-6.001691c8.002254-8.002254 8.002254-20.977777 0-28.980032L532.098757 503.118726z',
|
||||
emphasis: {
|
||||
iconStyle: {
|
||||
textPosition: 'left'
|
||||
}
|
||||
},
|
||||
onclick: () => {
|
||||
this.loadData('1d');
|
||||
}
|
||||
},
|
||||
myPeriod1w: {
|
||||
show: true,
|
||||
title: '查询近1周',
|
||||
icon: 'path://M827.871087 196.128913C743.498468 111.756293 631.321596 65.290005 512 65.290005c-119.319549 0-231.499491 46.465265-315.871087 130.837884S65.290005 392.680451 65.290005 512s46.465265 231.499491 130.837884 315.871087 196.551538 130.837884 315.871087 130.837884c119.321596 0 231.499491-46.465265 315.871087-130.837884S958.708971 631.319549 958.708971 512 912.243707 280.500509 827.871087 196.128913zM531.556405 917.246651l0-74.145697c0-11.31572-9.174963-20.491707-20.491707-20.491707-11.316743 0-20.491707 9.174963-20.491707 20.491707l0 74.059739C283.276738 906.322857 116.693746 739.164766 106.755396 531.634176l72.351841 0c11.31572 0 20.491707-9.174963 20.491707-20.491707 0-11.31572-9.174963-20.491707-20.491707-20.491707l-72.273047 0c10.769274-206.737528 177.01253-373.005342 383.740848-383.813502l0 72.346725c0 11.316743 9.174963 20.491707 20.491707 20.491707 11.31572 0 20.491707-9.17394 20.491707-20.491707L531.558451 106.752326c207.593012 9.901511 374.807385 176.539762 385.609405 383.89946l-74.142627 0c-11.316743 0-20.491707 9.174963-20.491707 20.491707 0 11.316743 9.174963 20.491707 20.491707 20.491707l74.220399 0C907.275555 739.78796 739.720422 907.317511 531.556405 917.246651z;M532.098757 503.118726 532.098757 258.240529c0-11.316743-9.174963-20.491707-20.491707-20.491707-11.31572 0-20.491707 9.17394-20.491707 20.491707l0 254.66612c0 7.858992 4.429893 14.677281 10.924817 18.114566L693.447539 722.42757c4.002151 4.000104 9.245572 6.001691 14.490016 6.001691s10.487865-2.001587 14.490016-6.001691c8.002254-8.002254 8.002254-20.977777 0-28.980032L532.098757 503.118726z',
|
||||
emphasis: {
|
||||
iconStyle: {
|
||||
textPosition: 'left'
|
||||
}
|
||||
},
|
||||
onclick: () => {
|
||||
this.loadData('1w');
|
||||
}
|
||||
},
|
||||
myPeriod4w: {
|
||||
show: true,
|
||||
title: '查询近1月',
|
||||
icon: 'path://M827.871087 196.128913C743.498468 111.756293 631.321596 65.290005 512 65.290005c-119.319549 0-231.499491 46.465265-315.871087 130.837884S65.290005 392.680451 65.290005 512s46.465265 231.499491 130.837884 315.871087 196.551538 130.837884 315.871087 130.837884c119.321596 0 231.499491-46.465265 315.871087-130.837884S958.708971 631.319549 958.708971 512 912.243707 280.500509 827.871087 196.128913zM531.556405 917.246651l0-74.145697c0-11.31572-9.174963-20.491707-20.491707-20.491707-11.316743 0-20.491707 9.174963-20.491707 20.491707l0 74.059739C283.276738 906.322857 116.693746 739.164766 106.755396 531.634176l72.351841 0c11.31572 0 20.491707-9.174963 20.491707-20.491707 0-11.31572-9.174963-20.491707-20.491707-20.491707l-72.273047 0c10.769274-206.737528 177.01253-373.005342 383.740848-383.813502l0 72.346725c0 11.316743 9.174963 20.491707 20.491707 20.491707 11.31572 0 20.491707-9.17394 20.491707-20.491707L531.558451 106.752326c207.593012 9.901511 374.807385 176.539762 385.609405 383.89946l-74.142627 0c-11.316743 0-20.491707 9.174963-20.491707 20.491707 0 11.316743 9.174963 20.491707 20.491707 20.491707l74.220399 0C907.275555 739.78796 739.720422 907.317511 531.556405 917.246651z;M532.098757 503.118726 532.098757 258.240529c0-11.316743-9.174963-20.491707-20.491707-20.491707-11.31572 0-20.491707 9.17394-20.491707 20.491707l0 254.66612c0 7.858992 4.429893 14.677281 10.924817 18.114566L693.447539 722.42757c4.002151 4.000104 9.245572 6.001691 14.490016 6.001691s10.487865-2.001587 14.490016-6.001691c8.002254-8.002254 8.002254-20.977777 0-28.980032L532.098757 503.118726z',
|
||||
emphasis: {
|
||||
iconStyle: {
|
||||
textPosition: 'left'
|
||||
}
|
||||
},
|
||||
onclick: () => {
|
||||
this.loadData('4w');
|
||||
}
|
||||
},
|
||||
myRefresh: {
|
||||
show: true,
|
||||
title: '刷新',
|
||||
icon: 'path://M663.881 339.763l274.021-0.742 0.058-13.271 0.699 0c-0.204-0.48-0.495-0.945-0.699-1.426L938.658 65l-23.776 0.044L914.3 280.41C835.9 151.374 694.321 65 532.342 65c-246.869 0-447 200.132-447 447 0 246.84 200.131 447 447 447 180.343 0 335.657-106.919 406.316-260.75l-33.176 0C836.948 835.027 695.456 929.2 532.342 929.2c-230.048 0-417.2-187.152-417.2-417.2s187.152-417.2 417.2-417.2c158.895 0 297.068 89.487 367.466 220.547l-235.868 0.64L663.881 339.763z',
|
||||
emphasis: {
|
||||
iconStyle: {
|
||||
textPosition: 'left'
|
||||
}
|
||||
},
|
||||
onclick: () => {
|
||||
this.loadData();
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
formatter: function (params: any) {
|
||||
let time: number = params[0].value[0];
|
||||
var date = new Date(time);
|
||||
let seriesName = params[0].seriesName;
|
||||
let month = (date.getMonth() + 1).toString().padStart(2, '0');
|
||||
let day = date.getDate().toString().padStart(2, '0');
|
||||
if (seriesName == null || seriesName == 'NULL') {
|
||||
return `${date.getFullYear()}/${month}/${day} ${date.getHours()}:${date.getMinutes()}:${date.getSeconds()} -- ${
|
||||
params[0].value[1]
|
||||
}`;
|
||||
} else {
|
||||
return `${seriesName} ${date.getFullYear()}/${month}/${day} ${date.getHours()}:${date.getMinutes()}:${date.getSeconds()} -- ${
|
||||
params[0].value[1]
|
||||
}`;
|
||||
}
|
||||
}
|
||||
},
|
||||
xAxis: {
|
||||
type: 'time',
|
||||
splitLine: {
|
||||
show: false
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
boundaryGap: [0, '100%'],
|
||||
splitLine: {
|
||||
show: true
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
if (this.unit != undefined || this.unit != null) {
|
||||
// @ts-ignore
|
||||
this.lineHistoryTheme.title?.subtext = `单位 ${this.unit}`;
|
||||
}
|
||||
this.loadData();
|
||||
}
|
||||
|
||||
loadData(timePeriod?: string) {
|
||||
if (timePeriod != undefined) {
|
||||
this.timePeriod = timePeriod;
|
||||
}
|
||||
// 读取指标历史数据
|
||||
this.loading = true;
|
||||
let metricData$ = this.monitorSvc
|
||||
.getMonitorMetricHistoryData(this.monitorId, this.app, this.metrics, this.metric, this.timePeriod, false)
|
||||
.pipe(
|
||||
finalize(() => {
|
||||
this.loading = false;
|
||||
metricData$.unsubscribe();
|
||||
})
|
||||
)
|
||||
.subscribe(
|
||||
message => {
|
||||
if (message.code === 0 && message.data.values != undefined) {
|
||||
let values: Record<string, any> = message.data.values;
|
||||
let legend: string[] = [];
|
||||
Object.keys(values).forEach(key => {
|
||||
legend.push(key);
|
||||
});
|
||||
if (legend.length > 1) {
|
||||
this.lineHistoryTheme.legend = {
|
||||
orient: 'vertical',
|
||||
data: legend
|
||||
};
|
||||
}
|
||||
Object.keys(values).forEach(key => {
|
||||
let seriesData: Array<{ value: any }> = [];
|
||||
values[key].forEach((item: { time: number; origin: any }) => {
|
||||
seriesData.push({
|
||||
value: [item.time, item.origin]
|
||||
});
|
||||
});
|
||||
this.lineHistoryTheme.series = [];
|
||||
this.lineHistoryTheme.series.push({
|
||||
name: key,
|
||||
type: 'line',
|
||||
smooth: true,
|
||||
showSymbol: false,
|
||||
data: seriesData
|
||||
});
|
||||
this.eChartOption = this.lineHistoryTheme;
|
||||
if (this.echartsInstance != undefined) {
|
||||
this.echartsInstance.setOption(this.eChartOption, {
|
||||
replaceMerge: ['xAxis', 'yAxis', 'series']
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.eChartOption = this.lineHistoryTheme;
|
||||
this.eChartOption.title = {
|
||||
text: `${this.metrics}.${this.metric}` + '\n\n\n' + '暂无数据',
|
||||
textStyle: {
|
||||
fontSize: 16,
|
||||
fontFamily: 'monospace',
|
||||
textShadowOffsetX: 10
|
||||
},
|
||||
left: 'center',
|
||||
top: 'center'
|
||||
};
|
||||
if (this.echartsInstance != undefined) {
|
||||
this.echartsInstance.setOption(this.eChartOption, {
|
||||
replaceMerge: ['title']
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
error => {
|
||||
console.error(error.msg);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
onChartInit(ec: any) {
|
||||
this.echartsInstance = ec;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
<nz-card *ngIf="isTable" nzHoverable style="height: auto; margin-left: 14px" [nzBordered]="true" [nzTitle]="monitor_metrics_card_title">
|
||||
<nz-table #smallTable nzSize="small" nzNoResult="No Metrics Data" nzFrontPagination="false" [nzData]="valueRows">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="text-align: center" *ngFor="let field of fields">{{ field.name }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let valueRow of smallTable.data">
|
||||
<td *ngFor="let value of valueRow.values">{{ value.origin }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</nz-table>
|
||||
</nz-card>
|
||||
|
||||
<nz-card *ngIf="!isTable" nzHoverable style="height: auto; margin-left: 14px" [nzBordered]="true" [nzTitle]="monitor_metrics_card_title">
|
||||
<nz-table #smallTable nzSize="small" nzNoResult="No Metrics Data" nzFrontPagination="false" [nzData]="valueRows">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="text-align: center">属性</th>
|
||||
<th style="text-align: center">值</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let field of fields; let i = index">
|
||||
<td>{{ field.name }}</td>
|
||||
<td>{{ rowValues[i].origin + ' ' + (field.unit ? field.unit : '') }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</nz-table>
|
||||
</nz-card>
|
||||
|
||||
<ng-template #monitor_metrics_card_title>
|
||||
<p style="font-size: small; text-align: center; margin-bottom: 3px; color: #0c0c0c">{{ metrics }}</p>
|
||||
<div>
|
||||
<a nz-popover [nzPopoverContent]="'最近采集时间 ' + (time | _date: 'yyyy-MM-dd HH:mm:ss')">
|
||||
<i nz-icon nzType="field-time" nzTheme="outline"></i
|
||||
></a>
|
||||
<i style="font-size: 0.3px; font-weight: normal; color: rgba(84, 83, 83, 0.89)">采集时间:{{ time | _date: 'HH:mm:ss' }}</i>
|
||||
</div>
|
||||
</ng-template>
|
||||
|
||||
<!--<nz-card *ngIf="!isTable" nzHoverable style="height:auto;margin-left: 14px;" [nzBordered]="true"-->
|
||||
<!-- [nzTitle]="monitor_metrics_card_title" >-->
|
||||
<!-- <div *ngFor="let field of fields;let i = index;" nz-row nzGutter="16">-->
|
||||
<!-- <div nz-col nzSpan="10"><p style="text-align: right">{{field.name}}</p></div>-->
|
||||
<!-- <div nz-col nzSpan="14"><p style="text-align: left">{{rowValues[i].origin}}</p></div>-->
|
||||
<!-- </div>-->
|
||||
<!--</nz-card>-->
|
||||
@@ -0,0 +1,24 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { MonitorDataTableComponent } from './monitor-data-table.component';
|
||||
|
||||
describe('MonitorDataChartComponent', () => {
|
||||
let component: MonitorDataTableComponent;
|
||||
let fixture: ComponentFixture<MonitorDataTableComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [MonitorDataTableComponent]
|
||||
}).compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(MonitorDataTableComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,55 @@
|
||||
import { Component, Input } from '@angular/core';
|
||||
|
||||
import { MonitorService } from '../../../service/monitor.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-monitor-data-table',
|
||||
templateUrl: './monitor-data-table.component.html',
|
||||
styleUrls: ['./monitor-data-table.component.less']
|
||||
})
|
||||
export class MonitorDataTableComponent {
|
||||
@Input()
|
||||
get monitorId(): number {
|
||||
return this._monitorId;
|
||||
}
|
||||
set monitorId(monitorId: number) {
|
||||
this._monitorId = monitorId;
|
||||
// 需将monitorId作为输入参数的最后一个 这样在执行loadData时其它入参才有值
|
||||
this.loadData();
|
||||
}
|
||||
private _monitorId!: number;
|
||||
@Input()
|
||||
metrics!: string;
|
||||
|
||||
time!: any;
|
||||
fields!: any[];
|
||||
valueRows!: any[];
|
||||
rowValues!: any[];
|
||||
isTable: boolean = true;
|
||||
|
||||
constructor(private monitorSvc: MonitorService) {}
|
||||
|
||||
loadData() {
|
||||
// 读取实时指标数据
|
||||
let metricData$ = this.monitorSvc.getMonitorMetricsData(this.monitorId, this.metrics).subscribe(
|
||||
message => {
|
||||
metricData$.unsubscribe();
|
||||
if (message.code === 0) {
|
||||
this.time = message.data.time;
|
||||
this.fields = message.data.fields;
|
||||
this.valueRows = message.data.valueRows;
|
||||
if (this.valueRows.length == 1) {
|
||||
this.isTable = false;
|
||||
this.rowValues = this.valueRows[0].values;
|
||||
}
|
||||
} else {
|
||||
console.error(message.msg);
|
||||
}
|
||||
},
|
||||
error => {
|
||||
console.error(error.msg);
|
||||
metricData$.unsubscribe();
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -103,11 +103,28 @@
|
||||
<nz-tab [nzTitle]="titleTemplate">
|
||||
<ng-template #titleTemplate>
|
||||
<i nz-icon nzType="pic-right" style="margin-left: 10px"></i>
|
||||
监控数据报告详情
|
||||
监控实时数据详情
|
||||
</ng-template>
|
||||
<div style="display: flex; justify-content: flex-start; flex-wrap: wrap">
|
||||
<div *ngFor="let metric of metrics; let i = index">
|
||||
<app-monitor-data-chart [metrics]="metric" [monitorId]="monitorId"></app-monitor-data-chart>
|
||||
<app-monitor-data-table [metrics]="metric" [monitorId]="monitorId"></app-monitor-data-table>
|
||||
</div>
|
||||
</div>
|
||||
</nz-tab>
|
||||
<nz-tab [nzTitle]="title2Template" (nzClick)="initMetricChart()">
|
||||
<ng-template #title2Template>
|
||||
<i nz-icon nzType="pic-right" style="margin-left: 10px"></i>
|
||||
监控历史图表详情
|
||||
</ng-template>
|
||||
<div style="display: flex; justify-content: flex-start; flex-wrap: wrap">
|
||||
<div *ngFor="let item of chartMetrics; let i = index">
|
||||
<app-monitor-data-chart
|
||||
[app]="app"
|
||||
[metrics]="item.metrics"
|
||||
[metric]="item.metric"
|
||||
[unit]="item.unit"
|
||||
[monitorId]="monitorId"
|
||||
></app-monitor-data-chart>
|
||||
</div>
|
||||
</div>
|
||||
</nz-tab>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { ActivatedRoute, ParamMap, Router } from '@angular/router';
|
||||
import { TitleService } from '@delon/theme';
|
||||
import { switchMap } from 'rxjs/operators';
|
||||
import { ActivatedRoute, ParamMap } from '@angular/router';
|
||||
import { finalize, switchMap } from 'rxjs/operators';
|
||||
|
||||
import { Monitor } from '../../../pojo/Monitor';
|
||||
import { Param } from '../../../pojo/Param';
|
||||
import { AppDefineService } from '../../../service/app-define.service';
|
||||
import { MonitorService } from '../../../service/monitor.service';
|
||||
|
||||
@Component({
|
||||
@@ -13,14 +13,15 @@ import { MonitorService } from '../../../service/monitor.service';
|
||||
styleUrls: ['./monitor-detail.component.less']
|
||||
})
|
||||
export class MonitorDetailComponent implements OnInit {
|
||||
constructor(private monitorSvc: MonitorService, private route: ActivatedRoute, private router: Router, private titleSvc: TitleService) {}
|
||||
constructor(private monitorSvc: MonitorService, private route: ActivatedRoute, private appDefineSvc: AppDefineService) {}
|
||||
isSpinning: boolean = false;
|
||||
monitorId!: number;
|
||||
app: string | undefined;
|
||||
monitor: Monitor | undefined;
|
||||
app!: string;
|
||||
monitor!: Monitor;
|
||||
options: any;
|
||||
port: number | undefined;
|
||||
metrics!: string[];
|
||||
chartMetrics: any[] = [];
|
||||
|
||||
ngOnInit(): void {
|
||||
this.route.paramMap
|
||||
@@ -53,6 +54,45 @@ export class MonitorDetailComponent implements OnInit {
|
||||
},
|
||||
error => {
|
||||
this.isSpinning = false;
|
||||
console.error(error.msg);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
initMetricChart() {
|
||||
// 查询过滤出此监控下可计算聚合的数字指标
|
||||
const define$ = this.appDefineSvc
|
||||
.getAppDefine(this.app)
|
||||
.pipe(
|
||||
finalize(() => {
|
||||
define$.unsubscribe();
|
||||
})
|
||||
)
|
||||
.subscribe(
|
||||
message => {
|
||||
if (message.code === 0 && message.data != undefined) {
|
||||
this.chartMetrics = [];
|
||||
let metrics = message.data.metrics;
|
||||
metrics.forEach((metric: { name: any; fields: any }) => {
|
||||
let fields = metric.fields;
|
||||
if (fields != undefined) {
|
||||
fields.forEach((field: { type: number; field: any; unit: any }) => {
|
||||
if (field.type == 0) {
|
||||
this.chartMetrics.push({
|
||||
metrics: metric.name,
|
||||
metric: field.field,
|
||||
unit: field.unit
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.warn(message.msg);
|
||||
}
|
||||
},
|
||||
error => {
|
||||
console.error(error.msg);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import { NzTagModule } from 'ng-zorro-antd/tag';
|
||||
import { NgxEchartsModule } from 'ngx-echarts';
|
||||
|
||||
import { MonitorDataChartComponent } from './monitor-data-chart/monitor-data-chart.component';
|
||||
import { MonitorDataTableComponent } from './monitor-data-table/monitor-data-table.component';
|
||||
import { MonitorDetailComponent } from './monitor-detail/monitor-detail.component';
|
||||
import { MonitorEditComponent } from './monitor-edit/monitor-edit.component';
|
||||
import { MonitorListComponent } from './monitor-list/monitor-list.component';
|
||||
@@ -21,6 +22,7 @@ const COMPONENTS: Array<Type<void>> = [
|
||||
MonitorEditComponent,
|
||||
MonitorListComponent,
|
||||
MonitorDetailComponent,
|
||||
MonitorDataTableComponent,
|
||||
MonitorDataChartComponent
|
||||
];
|
||||
|
||||
|
||||
@@ -21,6 +21,13 @@ export class AppDefineService {
|
||||
return this.http.get<Message<ParamDefine[]>>(paramDefineUri);
|
||||
}
|
||||
|
||||
public getAppDefine(app: string | undefined | null): Observable<Message<any>> {
|
||||
if (app === null || app === undefined) {
|
||||
console.log('getAppDefine app can not null');
|
||||
}
|
||||
return this.http.get<Message<any>>(`/apps/${app}/define`);
|
||||
}
|
||||
|
||||
public getAppHierarchy(): Observable<Message<any>> {
|
||||
let httpParams = new HttpParams().append('lang', 'zh-CN');
|
||||
const options = { params: httpParams };
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
const Authorization = 'Authorization';
|
||||
const refreshToken = 'refresh-token';
|
||||
const AuthorizationConst = 'Authorization';
|
||||
const RefreshTokenConst = 'refresh-token';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
@@ -19,23 +19,23 @@ export class LocalStorageService {
|
||||
}
|
||||
|
||||
public getAuthorizationToken(): string | null {
|
||||
return this.getData(Authorization);
|
||||
return this.getData(AuthorizationConst);
|
||||
}
|
||||
|
||||
public getRefreshToken(): string | null {
|
||||
return this.getData(refreshToken);
|
||||
return this.getData(RefreshTokenConst);
|
||||
}
|
||||
|
||||
public storageRefreshToken(token: string) {
|
||||
return this.putData(refreshToken, token);
|
||||
return this.putData(RefreshTokenConst, token);
|
||||
}
|
||||
|
||||
public storageAuthorizationToken(token: string) {
|
||||
return this.putData(Authorization, token);
|
||||
return this.putData(AuthorizationConst, token);
|
||||
}
|
||||
|
||||
public hasAuthorizationToken() {
|
||||
return localStorage.getItem(Authorization) != null;
|
||||
return localStorage.getItem(AuthorizationConst) != null;
|
||||
}
|
||||
|
||||
public clear() {
|
||||
|
||||
@@ -107,6 +107,24 @@ export class MonitorService {
|
||||
return this.http.get<Message<any>>(`/monitor/${monitorId}/metrics/${metrics}`);
|
||||
}
|
||||
|
||||
public getMonitorMetricHistoryData(
|
||||
monitorId: number,
|
||||
app: string,
|
||||
metrics: string,
|
||||
metric: string,
|
||||
history: string,
|
||||
interval: boolean
|
||||
): Observable<Message<any>> {
|
||||
let metricFull = `${app}.${metrics}.${metric}`;
|
||||
let httpParams = new HttpParams();
|
||||
httpParams = httpParams.appendAll({
|
||||
history: history,
|
||||
interval: interval
|
||||
});
|
||||
const options = { params: httpParams };
|
||||
return this.http.get<Message<any>>(`/monitor/${monitorId}/metric/${metricFull}`, options);
|
||||
}
|
||||
|
||||
public getAppsMonitorSummary(): Observable<Message<any>> {
|
||||
return this.http.get<Message<any>>(summary_uri);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user