|
@@ -1,35 +1,11 @@
|
|
|
import { Component, OnDestroy, OnInit } from '@angular/core';
|
|
import { Component, OnDestroy, OnInit } from '@angular/core';
|
|
|
import { ActivationEnd, Router } from '@angular/router';
|
|
import { ActivationEnd, Router } from '@angular/router';
|
|
|
-import { ChartData, ChartOptions, TooltipItem } from 'chart.js';
|
|
|
|
|
import { _DeepPartialObject } from 'chart.js/types/utils';
|
|
import { _DeepPartialObject } from 'chart.js/types/utils';
|
|
|
import 'chartjs-adapter-date-fns';
|
|
import 'chartjs-adapter-date-fns';
|
|
|
import { filter, map, Subscription } from 'rxjs';
|
|
import { filter, map, Subscription } from 'rxjs';
|
|
|
|
|
|
|
|
-import { deepCopy } from '../../../../../common/util/object-utils';
|
|
|
|
|
-
|
|
|
|
|
-import { BytePipe } from 'src/app/pipes/byte.pipe';
|
|
|
|
|
import { ServerApiService } from 'src/app/services/server-api.service';
|
|
import { ServerApiService } from 'src/app/services/server-api.service';
|
|
|
|
|
|
|
|
-type ServerDataGraphOptions = ServerDataTypesConfig & {
|
|
|
|
|
- subtypes?: Array<ServerDataGraphOptions>;
|
|
|
|
|
- data?: ChartData<'line', ServerData[], Date>;
|
|
|
|
|
- options: ChartOptions<'line'>;
|
|
|
|
|
- start: Date;
|
|
|
|
|
- end: Date;
|
|
|
|
|
-};
|
|
|
|
|
-type ChartConfigTimeUnit = false | 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | 'week' | 'month' | 'quarter' | 'year' | undefined;
|
|
|
|
|
-
|
|
|
|
|
-const typeDotColors: { [k: string]: string } = {
|
|
|
|
|
- avg: '#cc9a06',
|
|
|
|
|
- peak: '#005299',
|
|
|
|
|
- max: '#941320'
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
-const typeBgColors: { [k: string]: string } = {
|
|
|
|
|
- avg: '#ffe69c',
|
|
|
|
|
- peak: '#cce7ff',
|
|
|
|
|
- max: '#e3a3a9'
|
|
|
|
|
-};
|
|
|
|
|
@Component({
|
|
@Component({
|
|
|
selector: 'app-server-data-page',
|
|
selector: 'app-server-data-page',
|
|
|
templateUrl: './server-data-page.component.html',
|
|
templateUrl: './server-data-page.component.html',
|
|
@@ -39,9 +15,9 @@ export class ServerDataPageComponent implements OnInit, OnDestroy {
|
|
|
private subscriptions: Subscription[] = [];
|
|
private subscriptions: Subscription[] = [];
|
|
|
|
|
|
|
|
public server?: ServerConfig;
|
|
public server?: ServerConfig;
|
|
|
- public types?: ServerDataGraphOptions[];
|
|
|
|
|
|
|
+ public types?: ServerDataTypesConfig[];
|
|
|
|
|
|
|
|
- constructor(private apiService: ServerApiService, router: Router, private bytePipe: BytePipe) {
|
|
|
|
|
|
|
+ constructor(apiService: ServerApiService, router: Router) {
|
|
|
router.events.subscribe({
|
|
router.events.subscribe({
|
|
|
next: event => {
|
|
next: event => {
|
|
|
if (event instanceof ActivationEnd) {
|
|
if (event instanceof ActivationEnd) {
|
|
@@ -52,11 +28,11 @@ export class ServerDataPageComponent implements OnInit, OnDestroy {
|
|
|
this.clearPageModel();
|
|
this.clearPageModel();
|
|
|
}
|
|
}
|
|
|
this.subscriptions.push(
|
|
this.subscriptions.push(
|
|
|
- apiService.serverConfigs$.pipe(map(servers => servers.find(s => s.id === serverID))).subscribe(this.onServerConfig.bind(this)),
|
|
|
|
|
|
|
+ apiService.serverConfigs$.pipe(map(servers => servers.find(s => s.id === serverID))).subscribe(server => (this.server = server)),
|
|
|
apiService.serverDataTypes$
|
|
apiService.serverDataTypes$
|
|
|
.get(serverID)
|
|
.get(serverID)
|
|
|
.pipe(filter(types => !!types))
|
|
.pipe(filter(types => !!types))
|
|
|
- .subscribe(this.onServerDataTypes.bind(this))
|
|
|
|
|
|
|
+ .subscribe(types => (this.types = types))
|
|
|
);
|
|
);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -65,143 +41,6 @@ export class ServerDataPageComponent implements OnInit, OnDestroy {
|
|
|
|
|
|
|
|
ngOnInit(): void {}
|
|
ngOnInit(): void {}
|
|
|
|
|
|
|
|
- onServerConfig(server?: ServerConfig) {
|
|
|
|
|
- this.server = server;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- onServerDataTypes(types: ServerDataTypesConfig[]) {
|
|
|
|
|
- if (this.server) {
|
|
|
|
|
- const end = new Date();
|
|
|
|
|
- const start = new Date(end.getTime() - 1000 * 60 * 60 * 4);
|
|
|
|
|
- this.types = deepCopy(types).map((origType: ServerDataTypeWithData) => {
|
|
|
|
|
- const type = origType as ServerDataGraphOptions;
|
|
|
|
|
- const oldType = this.types?.find(t => type.type === t.type);
|
|
|
|
|
- if (!type.subtypes) {
|
|
|
|
|
- if (oldType && oldType.data) {
|
|
|
|
|
- type.data = oldType.data;
|
|
|
|
|
- return type;
|
|
|
|
|
- }
|
|
|
|
|
- type.start = start;
|
|
|
|
|
- type.end = end;
|
|
|
|
|
- this.updateData(this.server as ServerConfig, type);
|
|
|
|
|
- } else {
|
|
|
|
|
- type.subtypes.forEach((origSub: ServerDataTypeWithData) => {
|
|
|
|
|
- const sub = origSub as ServerDataGraphOptions;
|
|
|
|
|
- if (oldType) {
|
|
|
|
|
- const oldSub = oldType.subtypes?.find(s => sub.type === s.type) as ServerDataGraphOptions;
|
|
|
|
|
- if (oldSub && oldSub.data) {
|
|
|
|
|
- sub.data = oldSub.data;
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- sub.start = start;
|
|
|
|
|
- sub.end = end;
|
|
|
|
|
- this.updateData(this.server as ServerConfig, type, sub);
|
|
|
|
|
- });
|
|
|
|
|
- }
|
|
|
|
|
- return type as ServerDataGraphOptions;
|
|
|
|
|
- });
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- async updateData(server: ServerConfig, type: ServerDataGraphOptions, subType?: ServerDataGraphOptions) {
|
|
|
|
|
- try {
|
|
|
|
|
- const end = subType ? subType.end : type.end;
|
|
|
|
|
- const start = subType ? subType.start : type.start;
|
|
|
|
|
-
|
|
|
|
|
- const diffHrs = (end.getTime() - start.getTime()) / 1000 / 60 / 60;
|
|
|
|
|
- const timeFormat: {
|
|
|
|
|
- tooltipFormat: string;
|
|
|
|
|
- unit: ChartConfigTimeUnit;
|
|
|
|
|
- stepSize: number;
|
|
|
|
|
- } =
|
|
|
|
|
- diffHrs > 24 * 4
|
|
|
|
|
- ? {
|
|
|
|
|
- tooltipFormat: 'yyyy-MM-dd HH:mm',
|
|
|
|
|
- unit: 'day',
|
|
|
|
|
- stepSize: 1
|
|
|
|
|
- }
|
|
|
|
|
- : diffHrs > 24 * 2
|
|
|
|
|
- ? {
|
|
|
|
|
- tooltipFormat: 'yyyy-MM-dd HH:mm',
|
|
|
|
|
- unit: 'hour',
|
|
|
|
|
- stepSize: 6
|
|
|
|
|
- }
|
|
|
|
|
- : diffHrs > 12
|
|
|
|
|
- ? {
|
|
|
|
|
- tooltipFormat: 'HH:mm:ss',
|
|
|
|
|
- unit: 'hour',
|
|
|
|
|
- stepSize: 1
|
|
|
|
|
- }
|
|
|
|
|
- : {
|
|
|
|
|
- tooltipFormat: 'HH:mm:ss',
|
|
|
|
|
- unit: 'minute',
|
|
|
|
|
- stepSize: 30
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- const data = await this.apiService.queryServerData(server.id, `${type.type}${subType ? `:${subType.type}` : ''}`, start, end);
|
|
|
|
|
- const chartData: ChartData<'line', ServerData[], Date> = {
|
|
|
|
|
- labels: data.map(d => d.time),
|
|
|
|
|
- datasets: data.length
|
|
|
|
|
- ? Object.keys(data[0])
|
|
|
|
|
- .filter(k => k !== 'time')
|
|
|
|
|
- .map(key => ({
|
|
|
|
|
- label: key,
|
|
|
|
|
- data,
|
|
|
|
|
- parsing: { yAxisKey: key, xAxisKey: 'time' },
|
|
|
|
|
- fill: key !== 'max',
|
|
|
|
|
- tension: 0.3,
|
|
|
|
|
- backgroundColor: typeBgColors[key],
|
|
|
|
|
- pointBorderColor: typeDotColors[key],
|
|
|
|
|
- borderColor: typeDotColors[key],
|
|
|
|
|
- pointBackgroundColor: typeBgColors[key],
|
|
|
|
|
- pointRadius: key === 'max' ? 0 : undefined,
|
|
|
|
|
- tooltip: {
|
|
|
|
|
- callbacks: {
|
|
|
|
|
- label:
|
|
|
|
|
- type.type !== 'cpu'
|
|
|
|
|
- ? (item: TooltipItem<'line'> & any) => this.bytePipe.transform(item.raw[key])
|
|
|
|
|
- : (item: TooltipItem<'line'> & any) => `${(item.raw[key] as number).toFixed(2)} %`
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }))
|
|
|
|
|
- : []
|
|
|
|
|
- };
|
|
|
|
|
- const options: ChartOptions<'line'> & any = {
|
|
|
|
|
- scales: {
|
|
|
|
|
- xAxis: {
|
|
|
|
|
- display: true,
|
|
|
|
|
- type: 'time',
|
|
|
|
|
- time: {
|
|
|
|
|
- ...timeFormat,
|
|
|
|
|
- displayFormats: {
|
|
|
|
|
- day: 'yyyy-MM-dd',
|
|
|
|
|
- hour: 'yyyy-MM-dd HH:mm',
|
|
|
|
|
- minute: 'HH:mm:ss'
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
- yAxis: {
|
|
|
|
|
- beginAtZero: true,
|
|
|
|
|
- type: 'linear',
|
|
|
|
|
- ticks: {
|
|
|
|
|
- callback: (val: string | number) => (typeof val === 'number' && type.type !== 'cpu' ? this.bytePipe.transform(val) : `${val} %`)
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- };
|
|
|
|
|
- if (subType) {
|
|
|
|
|
- subType.data = chartData;
|
|
|
|
|
- subType.options = options;
|
|
|
|
|
- } else {
|
|
|
|
|
- type.data = chartData;
|
|
|
|
|
- type.options = options;
|
|
|
|
|
- }
|
|
|
|
|
- } catch (err) {
|
|
|
|
|
- console.error(err);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
ngOnDestroy(): void {
|
|
ngOnDestroy(): void {
|
|
|
this.clearSubscriptions();
|
|
this.clearSubscriptions();
|
|
|
}
|
|
}
|