This is an automated email from the ASF dual-hosted git repository.
xtsong pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/flink.git
The following commit(s) were added to refs/heads/master by this push:
new 35e557afe9e [FLINK-28315][runtime-web] introduce aggregate stats in
tables of the subtasks and taskmanagers
35e557afe9e is described below
commit 35e557afe9e8392b1b1ebb115f0c7134504b584d
Author: yangjunhan <[email protected]>
AuthorDate: Wed Jul 13 09:51:43 2022 +0800
[FLINK-28315][runtime-web] introduce aggregate stats in tables of the
subtasks and taskmanagers
This closes #20260
---
.../src/app/interfaces/job-vertex-task-manager.ts | 55 ------
.../web-dashboard/src/app/interfaces/job-vertex.ts | 106 +++++++++++
.../web-dashboard/src/app/interfaces/public-api.ts | 3 +-
.../modules/completed-job/completed-job.module.ts | 18 --
.../app/pages/job/overview/job-overview.config.ts | 3 +
.../app/pages/job/overview/job-overview.module.ts | 4 +-
.../job-overview-drawer-subtasks.component.html | 181 ++++++++++--------
.../job-overview-drawer-subtasks.component.less | 21 +++
.../job-overview-drawer-subtasks.component.ts | 59 +++---
.../subtasks-table-action.component.ts | 6 +-
.../taskmanagers-table-action.component.html | 31 ++-
.../taskmanagers-table-action.component.less | 5 +
.../taskmanagers-table-action.component.ts | 10 +-
.../web-dashboard/src/app/services/job.service.ts | 12 +-
.../table-aggregated-metrics.component.html | 207 +++++++++++++++++++++
.../table-aggregated-metrics.component.less} | 30 ++-
.../table-aggregated-metrics.component.ts} | 19 +-
.../duration-badge/duration-badge.component.html} | 32 +---
.../duration-badge/duration-badge.component.less} | 23 +--
.../duration-badge/duration-badge.component.ts} | 28 +--
.../src/app/share/pipes/humanize-bytes.pipe.ts | 2 +-
.../web-dashboard/src/app/share/share.module.ts | 10 +-
22 files changed, 587 insertions(+), 278 deletions(-)
diff --git
a/flink-runtime-web/web-dashboard/src/app/interfaces/job-vertex-task-manager.ts
b/flink-runtime-web/web-dashboard/src/app/interfaces/job-vertex-task-manager.ts
deleted file mode 100644
index 804037b2943..00000000000
---
a/flink-runtime-web/web-dashboard/src/app/interfaces/job-vertex-task-manager.ts
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-export interface JobVertexTaskManager {
- id: string;
- name: string;
- now: number;
- taskmanagers: VertexTaskManagerDetail[];
-}
-
-export interface VertexTaskManagerDetail {
- host: string;
- status: string;
- 'start-time': number;
- 'end-time': number;
- duration: number;
- metrics: {
- 'read-bytes': number;
- 'read-bytes-complete': boolean;
- 'write-bytes': number;
- 'write-bytes-complete': boolean;
- 'read-records': number;
- 'read-records-complete': boolean;
- 'write-records': number;
- 'write-records-complete': boolean;
- };
- 'status-counts': {
- CANCELED: number;
- CANCELING: number;
- CREATED: number;
- DEPLOYING: number;
- FAILED: number;
- FINISHED: number;
- RECONCILING: number;
- RUNNING: number;
- SCHEDULED: number;
- INITIALIZING: number;
- };
- 'taskmanager-id': string;
-}
diff --git a/flink-runtime-web/web-dashboard/src/app/interfaces/job-vertex.ts
b/flink-runtime-web/web-dashboard/src/app/interfaces/job-vertex.ts
new file mode 100644
index 00000000000..f4b635fa9dc
--- /dev/null
+++ b/flink-runtime-web/web-dashboard/src/app/interfaces/job-vertex.ts
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+interface JobVertexMetricFlags {
+ 'read-bytes-complete': boolean;
+ 'read-records-complete': boolean;
+ 'write-bytes-complete': boolean;
+ 'write-records-complete': boolean;
+}
+
+export interface JobVertexMetricStatistics<T> {
+ 'read-bytes': T;
+ 'read-records': T;
+ 'write-bytes': T;
+ 'write-records': T;
+ 'accumulated-backpressured-time': T;
+ 'accumulated-busy-time': T;
+ 'accumulated-idle-time': T;
+}
+
+export interface AggregatedStatistics {
+ min: number;
+ max: number;
+ avg: number;
+ sum: number;
+ median: number;
+ p25: number;
+ p75: number;
+ p95: number;
+}
+
+export interface JobVertexStatusDuration<T> {
+ CREATED: T;
+ INITIALIZING: T;
+ RUNNING: T;
+ SCHEDULED: T;
+ DEPLOYING: T;
+}
+
+export interface JobVertexAggregated {
+ metrics: JobVertexMetricStatistics<AggregatedStatistics>;
+ 'status-duration': JobVertexStatusDuration<AggregatedStatistics>;
+}
+
+export interface JobVertexSubTask {
+ attempt: number;
+ duration: number;
+ 'end-time': number;
+ host: string;
+ start_time: number;
+ status: string;
+ subtask: number;
+ metrics: JobVertexMetricStatistics<number> & JobVertexMetricFlags;
+ 'taskmanager-id': string;
+ 'status-duration': JobVertexStatusDuration<number>;
+}
+
+export interface JobVertexSubTaskDetail {
+ subtasks: JobVertexSubTask[];
+ aggregated: JobVertexAggregated;
+}
+
+export interface JobVertexTaskManager {
+ id: string;
+ name: string;
+ now: number;
+ taskmanagers: VertexTaskManagerDetail[];
+}
+
+export interface VertexTaskManagerDetail {
+ duration: number;
+ host: string;
+ status: string;
+ 'start-time': number;
+ 'end-time': number;
+ 'taskmanager-id': string;
+ metrics: JobVertexMetricStatistics<number> & JobVertexMetricFlags;
+ 'status-counts': {
+ CANCELED: number;
+ CANCELING: number;
+ CREATED: number;
+ DEPLOYING: number;
+ FAILED: number;
+ FINISHED: number;
+ RECONCILING: number;
+ RUNNING: number;
+ SCHEDULED: number;
+ INITIALIZING: number;
+ };
+ aggregated: JobVertexAggregated;
+}
diff --git a/flink-runtime-web/web-dashboard/src/app/interfaces/public-api.ts
b/flink-runtime-web/web-dashboard/src/app/interfaces/public-api.ts
index 202c93fa219..46aa79f35b5 100644
--- a/flink-runtime-web/web-dashboard/src/app/interfaces/public-api.ts
+++ b/flink-runtime-web/web-dashboard/src/app/interfaces/public-api.ts
@@ -23,9 +23,8 @@ export * from './job-detail';
export * from './job-exception';
export * from './job-timeline';
export * from './job-config';
-export * from './job-vertex-task-manager';
+export * from './job-vertex';
export * from './job-checkpoint';
-export * from './job-subtask';
export * from './job-backpressure';
export * from './job-flamegraph';
export * from './plan';
diff --git
a/flink-runtime-web/web-dashboard/src/app/pages/job/modules/completed-job/completed-job.module.ts
b/flink-runtime-web/web-dashboard/src/app/pages/job/modules/completed-job/completed-job.module.ts
index 688e0862de8..bbd4687e457 100644
---
a/flink-runtime-web/web-dashboard/src/app/pages/job/modules/completed-job/completed-job.module.ts
+++
b/flink-runtime-web/web-dashboard/src/app/pages/job/modules/completed-job/completed-job.module.ts
@@ -21,10 +21,6 @@ import { NgModule } from '@angular/core';
import { JOB_MODULE_CONFIG, JOB_MODULE_DEFAULT_CONFIG, JobModuleConfig } from
'@flink-runtime-web/pages/job/job.config';
import { CompletedJobRoutingModule } from
'@flink-runtime-web/pages/job/modules/completed-job/completed-job-routing.module';
-import {
- JOB_OVERVIEW_MODULE_CONFIG,
- JobOverviewModuleConfig
-} from '@flink-runtime-web/pages/job/overview/job-overview.config';
import { StatusService } from '@flink-runtime-web/services';
import { ShareModule } from '@flink-runtime-web/share/share.module';
import { NzAlertModule } from 'ng-zorro-antd/alert';
@@ -37,16 +33,6 @@ import { NzTableModule } from 'ng-zorro-antd/table';
import { ClusterConfigComponent } from
'./cluster-config/cluster-config.component';
-const OVERRIDE_JOB_OVERVIEW_MODULE_CONFIG_FACTORY = ():
JobOverviewModuleConfig => {
- return {
- routerTabs: [
- { title: 'Detail', path: 'detail' },
- { title: 'SubTasks', path: 'subtasks' },
- { title: 'TaskManagers', path: 'taskmanagers' }
- ]
- };
-};
-
const OVERRIDE_JOB_MODULE_CONFIG_FACTORY = (statusService: StatusService):
JobModuleConfig => {
const isHistoryServer = statusService.configuration.features['web-history'];
return {
@@ -78,10 +64,6 @@ const OVERRIDE_JOB_MODULE_CONFIG_FACTORY = (statusService:
StatusService): JobMo
NzPipesModule
],
providers: [
- {
- provide: JOB_OVERVIEW_MODULE_CONFIG,
- useFactory: OVERRIDE_JOB_OVERVIEW_MODULE_CONFIG_FACTORY
- },
{
provide: JOB_MODULE_CONFIG,
useFactory: OVERRIDE_JOB_MODULE_CONFIG_FACTORY,
diff --git
a/flink-runtime-web/web-dashboard/src/app/pages/job/overview/job-overview.config.ts
b/flink-runtime-web/web-dashboard/src/app/pages/job/overview/job-overview.config.ts
index aadd61455fd..73d50f3fa13 100644
---
a/flink-runtime-web/web-dashboard/src/app/pages/job/overview/job-overview.config.ts
+++
b/flink-runtime-web/web-dashboard/src/app/pages/job/overview/job-overview.config.ts
@@ -22,12 +22,14 @@ import { ModuleConfig } from
'@flink-runtime-web/core/module-config';
import { SubtasksTableActionComponent } from
'@flink-runtime-web/pages/job/overview/subtasks/table-action/subtasks-table-action.component';
import { TaskmanagersTableActionComponent } from
'@flink-runtime-web/pages/job/overview/taskmanagers/table-action/taskmanagers-table-action.component';
import { BackpressureBadgeComponent } from
'@flink-runtime-web/share/customize/backpressure-badge/backpressure-badge.component';
+import { DurationBadgeComponent } from
'@flink-runtime-web/share/customize/duration-badge/duration-badge.component';
import { JobBadgeComponent } from
'@flink-runtime-web/share/customize/job-badge/job-badge.component';
import { TaskBadgeComponent } from
'@flink-runtime-web/share/customize/task-badge/task-badge.component';
type customComponentKeys =
| 'taskManagerActionComponent'
| 'subtaskActionComponent'
+ | 'durationBadgeComponent'
| 'stateBadgeComponent'
| 'taskCountBadgeComponent'
| 'backpressureBadgeComponent';
@@ -51,6 +53,7 @@ export const JOB_OVERVIEW_MODULE_DEFAULT_CONFIG:
Required<JobOverviewModuleConfi
customComponents: {
taskManagerActionComponent: TaskmanagersTableActionComponent,
subtaskActionComponent: SubtasksTableActionComponent,
+ durationBadgeComponent: DurationBadgeComponent,
stateBadgeComponent: JobBadgeComponent,
taskCountBadgeComponent: TaskBadgeComponent,
backpressureBadgeComponent: BackpressureBadgeComponent
diff --git
a/flink-runtime-web/web-dashboard/src/app/pages/job/overview/job-overview.module.ts
b/flink-runtime-web/web-dashboard/src/app/pages/job/overview/job-overview.module.ts
index 08d1e4eac25..6957cd98441 100644
---
a/flink-runtime-web/web-dashboard/src/app/pages/job/overview/job-overview.module.ts
+++
b/flink-runtime-web/web-dashboard/src/app/pages/job/overview/job-overview.module.ts
@@ -26,6 +26,7 @@ import { NzDividerModule } from 'ng-zorro-antd/divider';
import { NzDropDownModule } from 'ng-zorro-antd/dropdown';
import { NzFormModule } from 'ng-zorro-antd/form';
import { NzIconModule } from 'ng-zorro-antd/icon';
+import { NzModalModule } from 'ng-zorro-antd/modal';
import { NzRadioModule } from 'ng-zorro-antd/radio';
import { NzSelectModule } from 'ng-zorro-antd/select';
import { NzSpinModule } from 'ng-zorro-antd/spin';
@@ -62,7 +63,8 @@ import { JobOverviewDrawerWatermarksComponent } from
'./watermarks/job-overview-
NzSelectModule,
NzDividerModule,
NzTabsModule,
- NzDropDownModule
+ NzDropDownModule,
+ NzModalModule
],
declarations: [
JobOverviewComponent,
diff --git
a/flink-runtime-web/web-dashboard/src/app/pages/job/overview/subtasks/job-overview-drawer-subtasks.component.html
b/flink-runtime-web/web-dashboard/src/app/pages/job/overview/subtasks/job-overview-drawer-subtasks.component.html
index 9dc5cabf439..861b9a17ad7 100644
---
a/flink-runtime-web/web-dashboard/src/app/pages/job/overview/subtasks/job-overview-drawer-subtasks.component.html
+++
b/flink-runtime-web/web-dashboard/src/app/pages/job/overview/subtasks/job-overview-drawer-subtasks.component.html
@@ -15,84 +15,113 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-
-<nz-table
- nzSize="small"
- [nzLoading]="isLoading"
- [nzData]="listOfTask"
- [nzScroll]="{ x: '1530px', y: 'calc( 100% - 36px )' }"
- [nzFrontPagination]="false"
- [nzShowPagination]="false"
- [nzVirtualItemSize]="virtualItemSize"
- [nzVirtualMinBufferPx]="300"
- [nzVirtualMaxBufferPx]="300"
- [nzVirtualForTrackBy]="trackBySubtask"
->
- <thead>
- <tr>
- <th nzWidth="80px" nzLeft>ID</th>
- <th [nzSortFn]="sortReadBytesFn" nzWidth="140px">Bytes Received</th>
- <th [nzSortFn]="sortReadRecordsFn" nzWidth="150px">Records Received</th>
- <th [nzSortFn]="sortWriteBytesFn" nzWidth="120px">Bytes Sent</th>
- <th [nzSortFn]="sortWriteRecordsFn" nzWidth="120px">Records Sent</th>
- <th [nzSortFn]="sortAttemptFn" nzWidth="100px">Attempt</th>
- <th [nzSortFn]="sortHostFn" nzWidth="200px">Host</th>
- <th [nzSortFn]="sortStartTimeFn" nzWidth="150px">Start Time</th>
- <th [nzSortFn]="sortDurationFn" nzWidth="150px">Duration</th>
- <th [nzSortFn]="sortEndTimeFn" nzWidth="150px">End Time</th>
- <th [nzSortFn]="sortStatusFn" nzWidth="120px" nzRight>Status</th>
- <th nzWidth="50px" nzRight>More</th>
- </tr>
- </thead>
- <tbody>
- <ng-template nz-virtual-scroll let-data>
- <ng-container *ngIf="narrowLogData(data) as subtask">
+<nz-tabset [nzTabBarGutter]="16" [nzSize]="'small'">
+ <nz-tab nzTitle="Aggregated Metrics">
+ <flink-table-aggregated-metrics
+ [isLoading]="isLoading"
+ [aggregated]="aggregated"
+ ></flink-table-aggregated-metrics>
+ </nz-tab>
+ <nz-tab nzTitle="Subtask Metrics">
+ <nz-table
+ nzSize="small"
+ [nzLoading]="isLoading"
+ [nzData]="listOfTask"
+ [nzScroll]="{ x: '2170px', y: 'calc(100% - 36px)' }"
+ [nzFrontPagination]="false"
+ [nzShowPagination]="false"
+ [nzVirtualItemSize]="virtualItemSize"
+ [nzVirtualMinBufferPx]="300"
+ [nzVirtualMaxBufferPx]="300"
+ [nzVirtualForTrackBy]="trackBySubtask"
+ >
+ <thead>
<tr>
- <td nzLeft>
- {{ subtask['subtask'] }}
- </td>
- <td>
- <span *ngIf="subtask['metrics']['read-bytes-complete']; else
loadingTemplate">
- {{ subtask['metrics']['read-bytes'] | humanizeBytes }}
- </span>
- </td>
- <td>
- <span *ngIf="subtask['metrics']['read-records-complete']; else
loadingTemplate">
- {{ subtask['metrics']['read-records'] | number: '1.0-0' }}
- </span>
- </td>
- <td>
- <span *ngIf="subtask['metrics']['write-bytes-complete']; else
loadingTemplate">
- {{ subtask['metrics']['write-bytes'] | humanizeBytes }}
- </span>
- </td>
- <td>
- <span *ngIf="subtask['metrics']['write-records-complete']; else
loadingTemplate">
- {{ subtask['metrics']['write-records'] | number: '1.0-0' }}
- </span>
- </td>
- <td>{{ subtask.attempt + 1 }}</td>
- <td>{{ subtask.host }}</td>
- <td>{{ subtask['start_time'] | humanizeDate: 'yyyy-MM-dd HH:mm:ss'
}}</td>
- <td>{{ subtask.duration | humanizeDuration }}</td>
- <td>{{ subtask['end-time'] | humanizeDate: 'yyyy-MM-dd HH:mm:ss'
}}</td>
- <td nzRight>
- <flink-dynamic-host
- [data]="{ state: subtask['status'] }"
- [component]="stateBadgeComponent"
- ></flink-dynamic-host>
- </td>
- <td nzRight>
- <flink-dynamic-host
- [data]="{ subtask }"
- [component]="actionComponent"
- ></flink-dynamic-host>
- </td>
+ <th nzWidth="80px" nzLeft>ID</th>
+ <th [nzSortFn]="sortReadBytesFn" nzWidth="140px">Bytes Received</th>
+ <th [nzSortFn]="sortReadRecordsFn" nzWidth="150px">Records
Received</th>
+ <th [nzSortFn]="sortWriteBytesFn" nzWidth="120px">Bytes Sent</th>
+ <th [nzSortFn]="sortWriteRecordsFn" nzWidth="120px">Records Sent</th>
+ <th [nzSortFn]="sortAttemptFn" nzWidth="100px">Attempt</th>
+ <th [nzSortFn]="sortHostFn" nzWidth="200px">Host</th>
+ <th [nzSortFn]="sortStartTimeFn" nzWidth="150px">Start Time</th>
+ <th [nzSortFn]="sortDurationFn" nzWidth="150px">Duration</th>
+ <th [nzSortFn]="sortEndTimeFn" nzWidth="150px">End Time</th>
+ <th nzWidth="320px">Accumulated Time (Backpressured/Idle/Busy)</th>
+ <th nzWidth="320px">Status Durations</th>
+ <th [nzSortFn]="sortStatusFn" nzWidth="120px" nzRight>Status</th>
+ <th nzWidth="50px" nzRight>More</th>
</tr>
- </ng-container>
- </ng-template>
- </tbody>
-</nz-table>
+ </thead>
+ <tbody>
+ <ng-template nz-virtual-scroll let-data>
+ <ng-container *ngIf="narrowLogData(data) as subtask">
+ <tr>
+ <td nzLeft>
+ {{ subtask['subtask'] }}
+ </td>
+ <td>
+ <span *ngIf="subtask['metrics']['read-bytes-complete']; else
loadingTemplate">
+ {{ subtask['metrics']['read-bytes'] | humanizeBytes }}
+ </span>
+ </td>
+ <td>
+ <span *ngIf="subtask['metrics']['read-records-complete']; else
loadingTemplate">
+ {{ subtask['metrics']['read-records'] | number: '1.0-0' }}
+ </span>
+ </td>
+ <td>
+ <span *ngIf="subtask['metrics']['write-bytes-complete']; else
loadingTemplate">
+ {{ subtask['metrics']['write-bytes'] | humanizeBytes }}
+ </span>
+ </td>
+ <td>
+ <span *ngIf="subtask['metrics']['write-records-complete'];
else loadingTemplate">
+ {{ subtask['metrics']['write-records'] | number: '1.0-0' }}
+ </span>
+ </td>
+ <td>{{ subtask.attempt + 1 }}</td>
+ <td>{{ subtask.host }}</td>
+ <td>{{ subtask['start_time'] | humanizeDate: 'yyyy-MM-dd
HH:mm:ss' }}</td>
+ <td>{{ subtask.duration | humanizeDuration }}</td>
+ <td>{{ subtask['end-time'] | humanizeDate: 'yyyy-MM-dd HH:mm:ss'
}}</td>
+ <td>
+ {{ subtask['metrics']['accumulated-backpressured-time'] |
humanizeDuration }}
+ /
+ {{ subtask['metrics']['accumulated-idle-time'] |
humanizeDuration }}
+ /
+ {{ subtask['metrics']['accumulated-busy-time'] |
humanizeDuration }}
+ </td>
+ <td>
+ <ng-container *ngIf="!subtask['status-duration']; else
badges">-</ng-container>
+ <ng-template #badges>
+ <flink-dynamic-host
+ *ngFor="let duration of
convertStatusDuration(subtask['status-duration'])"
+ [data]="{ state: duration.key, duration: duration.value }"
+ [component]="durationBadgeComponent"
+ ></flink-dynamic-host>
+ </ng-template>
+ </td>
+ <td nzRight>
+ <flink-dynamic-host
+ [data]="{ state: subtask['status'] }"
+ [component]="stateBadgeComponent"
+ ></flink-dynamic-host>
+ </td>
+ <td nzRight>
+ <flink-dynamic-host
+ [data]="{ subtask }"
+ [component]="actionComponent"
+ ></flink-dynamic-host>
+ </td>
+ </tr>
+ </ng-container>
+ </ng-template>
+ </tbody>
+ </nz-table>
+ </nz-tab>
+</nz-tabset>
+
<ng-template #loadingTemplate>
<i nz-icon nzType="loading"></i>
</ng-template>
diff --git
a/flink-runtime-web/web-dashboard/src/app/pages/job/overview/subtasks/job-overview-drawer-subtasks.component.less
b/flink-runtime-web/web-dashboard/src/app/pages/job/overview/subtasks/job-overview-drawer-subtasks.component.less
index 00e8cda7c6c..d17ec2fae0a 100644
---
a/flink-runtime-web/web-dashboard/src/app/pages/job/overview/subtasks/job-overview-drawer-subtasks.component.less
+++
b/flink-runtime-web/web-dashboard/src/app/pages/job/overview/subtasks/job-overview-drawer-subtasks.component.less
@@ -22,11 +22,32 @@
width: 100%;
height: 100%;
+ nz-tabset {
+ height: 100%;
+ }
+
::ng-deep {
.ant-table-cell {
font-size: @font-size-sm;
}
+ .ant-tabs-content {
+ height: 100%;
+
+ .ant-tabs-tabpane {
+ height: 100%;
+ }
+ }
+
+ .ant-tabs-nav {
+ margin-bottom: 0;
+ }
+
+ .ant-tabs-small > .ant-tabs-nav .ant-tabs-tab {
+ margin: 0 0 0 @margin-md;
+ font-size: @font-size-sm;
+ }
+
::-webkit-scrollbar {
display: none;
}
diff --git
a/flink-runtime-web/web-dashboard/src/app/pages/job/overview/subtasks/job-overview-drawer-subtasks.component.ts
b/flink-runtime-web/web-dashboard/src/app/pages/job/overview/subtasks/job-overview-drawer-subtasks.component.ts
index bedba3c8cf8..21d4db49aaa 100644
---
a/flink-runtime-web/web-dashboard/src/app/pages/job/overview/subtasks/job-overview-drawer-subtasks.component.ts
+++
b/flink-runtime-web/web-dashboard/src/app/pages/job/overview/subtasks/job-overview-drawer-subtasks.component.ts
@@ -20,7 +20,7 @@ import { ChangeDetectionStrategy, ChangeDetectorRef,
Component, Inject, OnDestro
import { of, Subject } from 'rxjs';
import { catchError, mergeMap, takeUntil } from 'rxjs/operators';
-import { JobSubTask } from '@flink-runtime-web/interfaces';
+import { JobVertexAggregated, JobVertexStatusDuration, JobVertexSubTask } from
'@flink-runtime-web/interfaces';
import {
JOB_OVERVIEW_MODULE_CONFIG,
JOB_OVERVIEW_MODULE_DEFAULT_CONFIG,
@@ -32,7 +32,7 @@ import { NzTableSortFn } from
'ng-zorro-antd/table/src/table.types';
import { JobLocalService } from '../../job-local.service';
-function createSortFn(selector: (item: JobSubTask) => number | string):
NzTableSortFn<JobSubTask> {
+function createSortFn(selector: (item: JobVertexSubTask) => number | string):
NzTableSortFn<JobVertexSubTask> {
return (pre, next) => (selector(pre) > selector(next) ? 1 : -1);
}
@@ -43,25 +43,27 @@ function createSortFn(selector: (item: JobSubTask) =>
number | string): NzTableS
changeDetection: ChangeDetectionStrategy.OnPush
})
export class JobOverviewDrawerSubtasksComponent implements OnInit, OnDestroy {
- public readonly trackBySubtask = (_: number, node: JobSubTask): number =>
node.subtask;
+ readonly trackBySubtask = (_: number, node: JobVertexSubTask): number =>
node.subtask;
- public readonly sortReadBytesFn = createSortFn(item =>
item.metrics?.['read-bytes']);
- public readonly sortReadRecordsFn = createSortFn(item =>
item.metrics?.['read-records']);
- public readonly sortWriteBytesFn = createSortFn(item =>
item.metrics?.['write-bytes']);
- public readonly sortWriteRecordsFn = createSortFn(item =>
item.metrics?.['write-records']);
- public readonly sortAttemptFn = createSortFn(item => item.attempt);
- public readonly sortHostFn = createSortFn(item => item.host);
- public readonly sortStartTimeFn = createSortFn(item => item['start_time']);
- public readonly sortDurationFn = createSortFn(item => item.duration);
- public readonly sortEndTimeFn = createSortFn(item => item['end-time']);
- public readonly sortStatusFn = createSortFn(item => item.status);
+ readonly sortReadBytesFn = createSortFn(item =>
item.metrics?.['read-bytes']);
+ readonly sortReadRecordsFn = createSortFn(item =>
item.metrics?.['read-records']);
+ readonly sortWriteBytesFn = createSortFn(item =>
item.metrics?.['write-bytes']);
+ readonly sortWriteRecordsFn = createSortFn(item =>
item.metrics?.['write-records']);
+ readonly sortAttemptFn = createSortFn(item => item.attempt);
+ readonly sortHostFn = createSortFn(item => item.host);
+ readonly sortStartTimeFn = createSortFn(item => item['start_time']);
+ readonly sortDurationFn = createSortFn(item => item.duration);
+ readonly sortEndTimeFn = createSortFn(item => item['end-time']);
+ readonly sortStatusFn = createSortFn(item => item.status);
- public listOfTask: JobSubTask[] = [];
- public isLoading = true;
- public virtualItemSize = 36;
- public actionComponent: Type<unknown>;
- public stateBadgeComponent: Type<unknown>;
- public readonly narrowLogData = typeDefinition<JobSubTask>();
+ listOfTask: JobVertexSubTask[] = [];
+ aggregated?: JobVertexAggregated;
+ isLoading = true;
+ virtualItemSize = 36;
+ actionComponent: Type<unknown>;
+ durationBadgeComponent: Type<unknown>;
+ stateBadgeComponent: Type<unknown>;
+ readonly narrowLogData = typeDefinition<JobVertexSubTask>();
private readonly destroy$ = new Subject<void>();
@@ -74,29 +76,40 @@ export class JobOverviewDrawerSubtasksComponent implements
OnInit, OnDestroy {
this.actionComponent =
moduleConfig.customComponents?.subtaskActionComponent ||
JOB_OVERVIEW_MODULE_DEFAULT_CONFIG.customComponents.subtaskActionComponent;
+ this.durationBadgeComponent =
+ moduleConfig.customComponents?.durationBadgeComponent ||
+
JOB_OVERVIEW_MODULE_DEFAULT_CONFIG.customComponents.durationBadgeComponent;
this.stateBadgeComponent =
moduleConfig.customComponents?.stateBadgeComponent ||
JOB_OVERVIEW_MODULE_DEFAULT_CONFIG.customComponents.stateBadgeComponent;
}
- public ngOnInit(): void {
+ ngOnInit(): void {
this.jobLocalService
.jobWithVertexChanges()
.pipe(
mergeMap(data =>
- this.jobService.loadSubTasks(data.job.jid,
data.vertex!.id).pipe(catchError(() => of([] as JobSubTask[])))
+ this.jobService.loadSubTasks(data.job.jid,
data.vertex!.id).pipe(catchError(() => of(undefined)))
),
takeUntil(this.destroy$)
)
.subscribe(data => {
- this.listOfTask = data;
+ this.listOfTask = data?.subtasks || [];
+ this.aggregated = data?.aggregated;
this.isLoading = false;
this.cdr.markForCheck();
});
}
- public ngOnDestroy(): void {
+ ngOnDestroy(): void {
this.destroy$.next();
this.destroy$.complete();
}
+
+ convertStatusDuration(duration: JobVertexStatusDuration<number>): Array<{
key: string; value: number }> {
+ return Object.keys(duration || {}).map(key => ({
+ key,
+ value: duration[key as keyof JobVertexStatusDuration<number>]
+ }));
+ }
}
diff --git
a/flink-runtime-web/web-dashboard/src/app/pages/job/overview/subtasks/table-action/subtasks-table-action.component.ts
b/flink-runtime-web/web-dashboard/src/app/pages/job/overview/subtasks/table-action/subtasks-table-action.component.ts
index 4db3407ed0a..069687b25c0 100644
---
a/flink-runtime-web/web-dashboard/src/app/pages/job/overview/subtasks/table-action/subtasks-table-action.component.ts
+++
b/flink-runtime-web/web-dashboard/src/app/pages/job/overview/subtasks/table-action/subtasks-table-action.component.ts
@@ -18,10 +18,10 @@
import { Component, ChangeDetectionStrategy, Input } from '@angular/core';
-import { JobSubTask } from '@flink-runtime-web/interfaces';
+import { JobVertexSubTask } from '@flink-runtime-web/interfaces';
export interface JobOverviewSubtasksTableAction {
- subtask?: JobSubTask;
+ subtask?: JobVertexSubTask;
}
@Component({
@@ -31,5 +31,5 @@ export interface JobOverviewSubtasksTableAction {
changeDetection: ChangeDetectionStrategy.OnPush
})
export class SubtasksTableActionComponent implements
JobOverviewSubtasksTableAction {
- @Input() subtask?: JobSubTask;
+ @Input() subtask?: JobVertexSubTask;
}
diff --git
a/flink-runtime-web/web-dashboard/src/app/pages/job/overview/taskmanagers/table-action/taskmanagers-table-action.component.html
b/flink-runtime-web/web-dashboard/src/app/pages/job/overview/taskmanagers/table-action/taskmanagers-table-action.component.html
index f2c24eb4072..66b93bc6efb 100644
---
a/flink-runtime-web/web-dashboard/src/app/pages/job/overview/taskmanagers/table-action/taskmanagers-table-action.component.html
+++
b/flink-runtime-web/web-dashboard/src/app/pages/job/overview/taskmanagers/table-action/taskmanagers-table-action.component.html
@@ -16,16 +16,7 @@
~ limitations under the License.
-->
-<span
- *ngIf="
- !taskManager ||
- !taskManager['taskmanager-id'] ||
- taskManager['taskmanager-id'] === '(unassigned)';
- else hrefTpl
- "
->
- -
-</span>
+<span *ngIf="!taskManager; else hrefTpl">-</span>
<ng-template #hrefTpl>
<a nz-dropdown nzPlacement="bottomRight" [nzDropdownMenu]="menu">
<i nz-icon nzType="ellipsis" nzTheme="outline"></i>
@@ -33,6 +24,26 @@
<nz-dropdown-menu #menu="nzDropdownMenu">
<ul nz-menu>
<li nz-menu-item>
+ <a (click)="setModalVisible(true)">View Aggregated Metrics</a>
+ <nz-modal
+ [nzTitle]="taskManager['taskmanager-id']"
+ [(nzVisible)]="visible"
+ [nzFooter]="null"
+ [nzStyle]="{ top: '40px' }"
+ [nzWidth]="900"
+ (nzOnCancel)="setModalVisible(false)"
+ >
+ <ng-container *nzModalContent>
+ <flink-table-aggregated-metrics
+ [aggregated]="taskManager.aggregated"
+ ></flink-table-aggregated-metrics>
+ </ng-container>
+ </nz-modal>
+ </li>
+ <li
+ nz-menu-item
+ *ngIf="taskManager['taskmanager-id'] && taskManager['taskmanager-id']
!== '(unassigned)'"
+ >
<a
[routerLink]="['/task-manager', taskManager['taskmanager-id'],
'logs']"
[queryParamsHandling]="'preserve'"
diff --git
a/flink-runtime-web/web-dashboard/src/app/pages/job/overview/taskmanagers/table-action/taskmanagers-table-action.component.less
b/flink-runtime-web/web-dashboard/src/app/pages/job/overview/taskmanagers/table-action/taskmanagers-table-action.component.less
index 2379ddac12c..c1887ad4f71 100644
---
a/flink-runtime-web/web-dashboard/src/app/pages/job/overview/taskmanagers/table-action/taskmanagers-table-action.component.less
+++
b/flink-runtime-web/web-dashboard/src/app/pages/job/overview/taskmanagers/table-action/taskmanagers-table-action.component.less
@@ -15,3 +15,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+@import "theme";
+
+:host {
+ display: block;
+}
diff --git
a/flink-runtime-web/web-dashboard/src/app/pages/job/overview/taskmanagers/table-action/taskmanagers-table-action.component.ts
b/flink-runtime-web/web-dashboard/src/app/pages/job/overview/taskmanagers/table-action/taskmanagers-table-action.component.ts
index e004b7f6a1e..c807b3778ce 100644
---
a/flink-runtime-web/web-dashboard/src/app/pages/job/overview/taskmanagers/table-action/taskmanagers-table-action.component.ts
+++
b/flink-runtime-web/web-dashboard/src/app/pages/job/overview/taskmanagers/table-action/taskmanagers-table-action.component.ts
@@ -16,7 +16,7 @@
* limitations under the License.
*/
-import { Component, ChangeDetectionStrategy, Input } from '@angular/core';
+import { Component, ChangeDetectionStrategy, Input, ChangeDetectorRef } from
'@angular/core';
import { VertexTaskManagerDetail } from '@flink-runtime-web/interfaces';
@@ -32,4 +32,12 @@ export interface JobOverviewTaskManagersTableAction {
})
export class TaskmanagersTableActionComponent implements
JobOverviewTaskManagersTableAction {
@Input() taskManager?: VertexTaskManagerDetail;
+ visible = false;
+
+ constructor(private cdr: ChangeDetectorRef) {}
+
+ setModalVisible(visible: boolean): void {
+ this.visible = visible;
+ this.cdr.markForCheck();
+ }
}
diff --git a/flink-runtime-web/web-dashboard/src/app/services/job.service.ts
b/flink-runtime-web/web-dashboard/src/app/services/job.service.ts
index 0a460e78602..e8266198b85 100644
--- a/flink-runtime-web/web-dashboard/src/app/services/job.service.ts
+++ b/flink-runtime-web/web-dashboard/src/app/services/job.service.ts
@@ -35,14 +35,14 @@ import {
JobFlameGraph,
JobOverview,
JobsItem,
- JobSubTask,
JobSubTaskTime,
JobVertexTaskManager,
NodesItemCorrect,
SubTaskAccumulators,
TaskStatus,
UserAccumulators,
- VerticesLink
+ VerticesLink,
+ JobVertexSubTaskDetail
} from '@flink-runtime-web/interfaces';
import { ConfigService } from './config.service';
@@ -122,10 +122,10 @@ export class JobService {
);
}
- public loadSubTasks(jobId: string, vertexId: string):
Observable<JobSubTask[]> {
- return this.httpClient
- .get<{ subtasks: JobSubTask[]
}>(`${this.configService.BASE_URL}/jobs/${jobId}/vertices/${vertexId}`)
- .pipe(map(data => (data && data.subtasks) || []));
+ public loadSubTasks(jobId: string, vertexId: string):
Observable<JobVertexSubTaskDetail> {
+ return this.httpClient.get<JobVertexSubTaskDetail>(
+ `${this.configService.BASE_URL}/jobs/${jobId}/vertices/${vertexId}`
+ );
}
public loadSubTaskTimes(jobId: string, vertexId: string):
Observable<JobSubTaskTime> {
diff --git
a/flink-runtime-web/web-dashboard/src/app/share/common/table-aggregated-metrics/table-aggregated-metrics.component.html
b/flink-runtime-web/web-dashboard/src/app/share/common/table-aggregated-metrics/table-aggregated-metrics.component.html
new file mode 100644
index 00000000000..5b2964ad4f6
--- /dev/null
+++
b/flink-runtime-web/web-dashboard/src/app/share/common/table-aggregated-metrics/table-aggregated-metrics.component.html
@@ -0,0 +1,207 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<nz-table
+ class="small"
+ nzTemplateMode
+ nzSize="small"
+ [nzLoading]="isLoading"
+ [nzScroll]="{ x: '1180px', y: 'calc(100% - 36px)' }"
+ [nzFrontPagination]="false"
+ [nzShowPagination]="false"
+>
+ <thead>
+ <tr>
+ <th nzWidth="220px" nzLeft>Metric</th>
+ <th nzWidth="120px">Min</th>
+ <th nzWidth="120px">Max</th>
+ <th nzWidth="120px">Avg</th>
+ <th nzWidth="120px">Sum</th>
+ <th nzWidth="120px">Median</th>
+ <th nzWidth="120px">25th Percentile</th>
+ <th nzWidth="120px">75th Percentile</th>
+ <th nzWidth="120px">95th Percentile</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td nzLeft>INITIALIZING Duration</td>
+ <td>{{ aggregated?.['status-duration'].INITIALIZING.min |
humanizeDuration }}</td>
+ <td>{{ aggregated?.['status-duration'].INITIALIZING.max |
humanizeDuration }}</td>
+ <td>{{ aggregated?.['status-duration'].INITIALIZING.avg |
humanizeDuration }}</td>
+ <td>{{ aggregated?.['status-duration'].INITIALIZING.sum |
humanizeDuration }}</td>
+ <td>{{ aggregated?.['status-duration'].INITIALIZING.median |
humanizeDuration }}</td>
+ <td>{{ aggregated?.['status-duration'].INITIALIZING.p25 |
humanizeDuration }}</td>
+ <td>{{ aggregated?.['status-duration'].INITIALIZING.p75 |
humanizeDuration }}</td>
+ <td>{{ aggregated?.['status-duration'].INITIALIZING.p95 |
humanizeDuration }}</td>
+ </tr>
+ <tr>
+ <td nzLeft>CREATED Duration</td>
+ <td>{{ aggregated?.['status-duration'].CREATED.min | humanizeDuration
}}</td>
+ <td>{{ aggregated?.['status-duration'].CREATED.max | humanizeDuration
}}</td>
+ <td>{{ aggregated?.['status-duration'].CREATED.avg | humanizeDuration
}}</td>
+ <td>{{ aggregated?.['status-duration'].CREATED.sum | humanizeDuration
}}</td>
+ <td>{{ aggregated?.['status-duration'].CREATED.median | humanizeDuration
}}</td>
+ <td>{{ aggregated?.['status-duration'].CREATED.p25 | humanizeDuration
}}</td>
+ <td>{{ aggregated?.['status-duration'].CREATED.p75 | humanizeDuration
}}</td>
+ <td>{{ aggregated?.['status-duration'].CREATED.p95 | humanizeDuration
}}</td>
+ </tr>
+ <tr>
+ <td nzLeft>SCHEDULED Duration</td>
+ <td>{{ aggregated?.['status-duration'].SCHEDULED.min | humanizeDuration
}}</td>
+ <td>{{ aggregated?.['status-duration'].SCHEDULED.max | humanizeDuration
}}</td>
+ <td>{{ aggregated?.['status-duration'].SCHEDULED.avg | humanizeDuration
}}</td>
+ <td>{{ aggregated?.['status-duration'].SCHEDULED.sum | humanizeDuration
}}</td>
+ <td>{{ aggregated?.['status-duration'].SCHEDULED.median |
humanizeDuration }}</td>
+ <td>{{ aggregated?.['status-duration'].SCHEDULED.p25 | humanizeDuration
}}</td>
+ <td>{{ aggregated?.['status-duration'].SCHEDULED.p75 | humanizeDuration
}}</td>
+ <td>{{ aggregated?.['status-duration'].SCHEDULED.p95 | humanizeDuration
}}</td>
+ </tr>
+ <tr>
+ <td nzLeft>RUNNING Duration</td>
+ <td>{{ aggregated?.['status-duration'].RUNNING.min | humanizeDuration
}}</td>
+ <td>{{ aggregated?.['status-duration'].RUNNING.max | humanizeDuration
}}</td>
+ <td>{{ aggregated?.['status-duration'].RUNNING.avg | humanizeDuration
}}</td>
+ <td>{{ aggregated?.['status-duration'].RUNNING.sum | humanizeDuration
}}</td>
+ <td>{{ aggregated?.['status-duration'].RUNNING.median | humanizeDuration
}}</td>
+ <td>{{ aggregated?.['status-duration'].RUNNING.p25 | humanizeDuration
}}</td>
+ <td>{{ aggregated?.['status-duration'].RUNNING.p75 | humanizeDuration
}}</td>
+ <td>{{ aggregated?.['status-duration'].RUNNING.p95 | humanizeDuration
}}</td>
+ </tr>
+ <tr>
+ <td nzLeft>DEPLOYING Duration</td>
+ <td>
+ {{ aggregated?.['status-duration'].DEPLOYING.min | humanizeDuration }}
+ </td>
+ <td>
+ {{ aggregated?.['status-duration'].DEPLOYING.max | humanizeDuration }}
+ </td>
+ <td>
+ {{ aggregated?.['status-duration'].DEPLOYING.avg | humanizeDuration }}
+ </td>
+ <td>
+ {{ aggregated?.['status-duration'].DEPLOYING.sum | humanizeDuration }}
+ </td>
+ <td>
+ {{ aggregated?.['status-duration'].DEPLOYING.median | humanizeDuration
}}
+ </td>
+ <td>
+ {{ aggregated?.['status-duration'].DEPLOYING.p25 | humanizeDuration }}
+ </td>
+ <td>
+ {{ aggregated?.['status-duration'].DEPLOYING.p75 | humanizeDuration }}
+ </td>
+ <td>
+ {{ aggregated?.['status-duration'].DEPLOYING.p95 | humanizeDuration }}
+ </td>
+ </tr>
+ <tr>
+ <td nzLeft>Read Records</td>
+ <td>{{ (aggregated?.metrics['read-records'].min | number: '1.0-0') ||
'-' }}</td>
+ <td>{{ (aggregated?.metrics['read-records'].max | number: '1.0-0') ||
'-' }}</td>
+ <td>{{ (aggregated?.metrics['read-records'].avg | number: '1.0-0') ||
'-' }}</td>
+ <td>{{ (aggregated?.metrics['read-records'].sum | number: '1.0-0') ||
'-' }}</td>
+ <td>{{ (aggregated?.metrics['read-records'].median | number: '1.0-0') ||
'-' }}</td>
+ <td>{{ (aggregated?.metrics['read-records'].p25 | number: '1.0-0') ||
'-' }}</td>
+ <td>{{ (aggregated?.metrics['read-records'].p75 | number: '1.0-0') ||
'-' }}</td>
+ <td>{{ (aggregated?.metrics['read-records'].p95 | number: '1.0-0') ||
'-' }}</td>
+ </tr>
+ <tr>
+ <td nzLeft>Write Records</td>
+ <td>{{ (aggregated?.metrics['write-records'].min | number: '1.0-0') ||
'-' }}</td>
+ <td>{{ (aggregated?.metrics['write-records'].max | number: '1.0-0') ||
'-' }}</td>
+ <td>{{ (aggregated?.metrics['write-records'].avg | number: '1.0-0') ||
'-' }}</td>
+ <td>{{ (aggregated?.metrics['write-records'].sum | number: '1.0-0') ||
'-' }}</td>
+ <td>{{ (aggregated?.metrics['write-records'].median | number: '1.0-0')
|| '-' }}</td>
+ <td>{{ (aggregated?.metrics['write-records'].p25 | number: '1.0-0') ||
'-' }}</td>
+ <td>{{ (aggregated?.metrics['write-records'].p75 | number: '1.0-0') ||
'-' }}</td>
+ <td>{{ (aggregated?.metrics['write-records'].p95 | number: '1.0-0') ||
'-' }}</td>
+ </tr>
+ <tr>
+ <td nzLeft>Read Bytes</td>
+ <td>{{ aggregated?.metrics['read-bytes'].min | humanizeBytes }}</td>
+ <td>{{ aggregated?.metrics['read-bytes'].max | humanizeBytes }}</td>
+ <td>{{ aggregated?.metrics['read-bytes'].avg | humanizeBytes }}</td>
+ <td>{{ aggregated?.metrics['read-bytes'].sum | humanizeBytes }}</td>
+ <td>{{ aggregated?.metrics['read-bytes'].median | humanizeBytes }}</td>
+ <td>{{ aggregated?.metrics['read-bytes'].p25 | humanizeBytes }}</td>
+ <td>{{ aggregated?.metrics['read-bytes'].p75 | humanizeBytes }}</td>
+ <td>{{ aggregated?.metrics['read-bytes'].p95 | humanizeBytes }}</td>
+ </tr>
+ <tr>
+ <td nzLeft>Write Bytes</td>
+ <td>{{ aggregated?.metrics['write-bytes'].min | humanizeBytes }}</td>
+ <td>{{ aggregated?.metrics['write-bytes'].max | humanizeBytes }}</td>
+ <td>{{ aggregated?.metrics['write-bytes'].avg | humanizeBytes }}</td>
+ <td>{{ aggregated?.metrics['write-bytes'].sum | humanizeBytes }}</td>
+ <td>{{ aggregated?.metrics['write-bytes'].median | humanizeBytes }}</td>
+ <td>{{ aggregated?.metrics['write-bytes'].p25 | humanizeBytes }}</td>
+ <td>{{ aggregated?.metrics['write-bytes'].p75 | humanizeBytes }}</td>
+ <td>{{ aggregated?.metrics['write-bytes'].p95 | humanizeBytes }}</td>
+ </tr>
+ <tr>
+ <td nzLeft>Accumulated Backpressured Time</td>
+ <td>
+ {{ aggregated?.metrics['accumulated-backpressured-time'].min |
humanizeDuration }}
+ </td>
+ <td>
+ {{ aggregated?.metrics['accumulated-backpressured-time'].max |
humanizeDuration }}
+ </td>
+ <td>
+ {{ aggregated?.metrics['accumulated-backpressured-time'].avg |
humanizeDuration }}
+ </td>
+ <td>
+ {{ aggregated?.metrics['accumulated-backpressured-time'].sum |
humanizeDuration }}
+ </td>
+ <td>
+ {{ aggregated?.metrics['accumulated-backpressured-time'].median |
humanizeDuration }}
+ </td>
+ <td>
+ {{ aggregated?.metrics['accumulated-backpressured-time'].p25 |
humanizeDuration }}
+ </td>
+ <td>
+ {{ aggregated?.metrics['accumulated-backpressured-time'].p75 |
humanizeDuration }}
+ </td>
+ <td>
+ {{ aggregated?.metrics['accumulated-backpressured-time'].p95 |
humanizeDuration }}
+ </td>
+ </tr>
+ <tr>
+ <td nzLeft>Accumulated Idle Time</td>
+ <td>{{ aggregated?.metrics['accumulated-idle-time'].min |
humanizeDuration }}</td>
+ <td>{{ aggregated?.metrics['accumulated-idle-time'].max |
humanizeDuration }}</td>
+ <td>{{ aggregated?.metrics['accumulated-idle-time'].avg |
humanizeDuration }}</td>
+ <td>{{ aggregated?.metrics['accumulated-idle-time'].sum |
humanizeDuration }}</td>
+ <td>{{ aggregated?.metrics['accumulated-idle-time'].median |
humanizeDuration }}</td>
+ <td>{{ aggregated?.metrics['accumulated-idle-time'].p25 |
humanizeDuration }}</td>
+ <td>{{ aggregated?.metrics['accumulated-idle-time'].p75 |
humanizeDuration }}</td>
+ <td>{{ aggregated?.metrics['accumulated-idle-time'].p95 |
humanizeDuration }}</td>
+ </tr>
+ <tr>
+ <td nzLeft>Accumulated Busy Time</td>
+ <td>{{ aggregated?.metrics['accumulated-busy-time'].min |
humanizeDuration }}</td>
+ <td>{{ aggregated?.metrics['accumulated-busy-time'].max |
humanizeDuration }}</td>
+ <td>{{ aggregated?.metrics['accumulated-busy-time'].avg |
humanizeDuration }}</td>
+ <td>{{ aggregated?.metrics['accumulated-busy-time'].sum |
humanizeDuration }}</td>
+ <td>{{ aggregated?.metrics['accumulated-busy-time'].median |
humanizeDuration }}</td>
+ <td>{{ aggregated?.metrics['accumulated-busy-time'].p25 |
humanizeDuration }}</td>
+ <td>{{ aggregated?.metrics['accumulated-busy-time'].p75 |
humanizeDuration }}</td>
+ <td>{{ aggregated?.metrics['accumulated-busy-time'].p95 |
humanizeDuration }}</td>
+ </tr>
+ </tbody>
+</nz-table>
diff --git a/flink-runtime-web/web-dashboard/src/app/interfaces/job-subtask.ts
b/flink-runtime-web/web-dashboard/src/app/share/common/table-aggregated-metrics/table-aggregated-metrics.component.less
similarity index 63%
rename from flink-runtime-web/web-dashboard/src/app/interfaces/job-subtask.ts
rename to
flink-runtime-web/web-dashboard/src/app/share/common/table-aggregated-metrics/table-aggregated-metrics.component.less
index 1c8e0fcc514..08aa17292af 100644
--- a/flink-runtime-web/web-dashboard/src/app/interfaces/job-subtask.ts
+++
b/flink-runtime-web/web-dashboard/src/app/share/common/table-aggregated-metrics/table-aggregated-metrics.component.less
@@ -15,24 +15,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+@import "theme";
-export interface JobSubTask {
- attempt: number;
- duration: number;
- 'end-time': number;
- host: string;
- start_time: number;
- status: string;
- subtask: number;
- metrics: {
- 'read-bytes': number;
- 'read-bytes-complete': boolean;
- 'read-records': number;
- 'read-records-complete': boolean;
- 'write-bytes': number;
- 'write-bytes-complete': boolean;
- 'write-records': number;
- 'write-records-complete': boolean;
- };
- 'taskmanager-id': string;
+:host {
+ display: block;
+ height: 100%;
+
+ nz-table,
+ nz-spin,
+ .ant-spin-container,
+ .ant-table {
+ height: 100%;
+ }
}
diff --git
a/flink-runtime-web/web-dashboard/src/app/pages/job/overview/subtasks/table-action/subtasks-table-action.component.ts
b/flink-runtime-web/web-dashboard/src/app/share/common/table-aggregated-metrics/table-aggregated-metrics.component.ts
similarity index 70%
copy from
flink-runtime-web/web-dashboard/src/app/pages/job/overview/subtasks/table-action/subtasks-table-action.component.ts
copy to
flink-runtime-web/web-dashboard/src/app/share/common/table-aggregated-metrics/table-aggregated-metrics.component.ts
index 4db3407ed0a..1b61eef5490 100644
---
a/flink-runtime-web/web-dashboard/src/app/pages/job/overview/subtasks/table-action/subtasks-table-action.component.ts
+++
b/flink-runtime-web/web-dashboard/src/app/share/common/table-aggregated-metrics/table-aggregated-metrics.component.ts
@@ -18,18 +18,17 @@
import { Component, ChangeDetectionStrategy, Input } from '@angular/core';
-import { JobSubTask } from '@flink-runtime-web/interfaces';
-
-export interface JobOverviewSubtasksTableAction {
- subtask?: JobSubTask;
-}
+import { JobVertexAggregated } from '@flink-runtime-web/interfaces';
@Component({
- selector: 'flink-table-actions',
- templateUrl: './subtasks-table-action.component.html',
- styleUrls: ['./subtasks-table-action.component.less'],
+ selector: 'flink-table-aggregated-metrics',
+ templateUrl: './table-aggregated-metrics.component.html',
+ styleUrls: ['./table-aggregated-metrics.component.less'],
changeDetection: ChangeDetectionStrategy.OnPush
})
-export class SubtasksTableActionComponent implements
JobOverviewSubtasksTableAction {
- @Input() subtask?: JobSubTask;
+export class TableAggregatedMetricsComponent {
+ @Input() isLoading = false;
+ @Input() aggregated?: JobVertexAggregated;
+
+ constructor() {}
}
diff --git
a/flink-runtime-web/web-dashboard/src/app/pages/job/overview/taskmanagers/table-action/taskmanagers-table-action.component.html
b/flink-runtime-web/web-dashboard/src/app/share/customize/duration-badge/duration-badge.component.html
similarity index 56%
copy from
flink-runtime-web/web-dashboard/src/app/pages/job/overview/taskmanagers/table-action/taskmanagers-table-action.component.html
copy to
flink-runtime-web/web-dashboard/src/app/share/customize/duration-badge/duration-badge.component.html
index f2c24eb4072..1ec91e59253 100644
---
a/flink-runtime-web/web-dashboard/src/app/pages/job/overview/taskmanagers/table-action/taskmanagers-table-action.component.html
+++
b/flink-runtime-web/web-dashboard/src/app/share/customize/duration-badge/duration-badge.component.html
@@ -15,32 +15,10 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-
-<span
- *ngIf="
- !taskManager ||
- !taskManager['taskmanager-id'] ||
- taskManager['taskmanager-id'] === '(unassigned)';
- else hrefTpl
- "
->
- -
+<span nz-tooltip [nzTooltipTitle]="tooltip">
+ {{ duration | humanizeDuration }}
</span>
-<ng-template #hrefTpl>
- <a nz-dropdown nzPlacement="bottomRight" [nzDropdownMenu]="menu">
- <i nz-icon nzType="ellipsis" nzTheme="outline"></i>
- </a>
- <nz-dropdown-menu #menu="nzDropdownMenu">
- <ul nz-menu>
- <li nz-menu-item>
- <a
- [routerLink]="['/task-manager', taskManager['taskmanager-id'],
'logs']"
- [queryParamsHandling]="'preserve'"
- target="_blank"
- >
- View Taskmanager Log
- </a>
- </li>
- </ul>
- </nz-dropdown-menu>
+
+<ng-template #tooltip>
+ <span>{{ state }}: {{ duration | humanizeDuration }}</span>
</ng-template>
diff --git
a/flink-runtime-web/web-dashboard/src/app/pages/task-manager/task-manager-local.service.ts
b/flink-runtime-web/web-dashboard/src/app/share/customize/duration-badge/duration-badge.component.less
similarity index 60%
rename from
flink-runtime-web/web-dashboard/src/app/pages/task-manager/task-manager-local.service.ts
rename to
flink-runtime-web/web-dashboard/src/app/share/customize/duration-badge/duration-badge.component.less
index 458bc3602fe..c2d8a536f6a 100644
---
a/flink-runtime-web/web-dashboard/src/app/pages/task-manager/task-manager-local.service.ts
+++
b/flink-runtime-web/web-dashboard/src/app/share/customize/duration-badge/duration-badge.component.less
@@ -16,20 +16,17 @@
* limitations under the License.
*/
-import { Injectable } from '@angular/core';
-import { Observable, ReplaySubject } from 'rxjs';
+@import "theme";
-import { TaskManagerDetail } from '@flink-runtime-web/interfaces';
+:host {
+ display: inline-block;
+ margin: 0 1px;
-@Injectable()
-export class TaskManagerLocalService {
- private readonly taskManagerDetail$ = new
ReplaySubject<TaskManagerDetail>(1);
-
- public taskManagerDetailChanges(): Observable<TaskManagerDetail> {
- return this.taskManagerDetail$.asObservable();
- }
-
- public setTaskManagerDetail(detail: TaskManagerDetail): void {
- this.taskManagerDetail$.next(detail);
+ span {
+ padding: 1px @padding-xss;
+ color: @text-color-inverse;
+ font-weight: 500;
+ text-align: center;
+ cursor: default;
}
}
diff --git
a/flink-runtime-web/web-dashboard/src/app/pages/job/overview/subtasks/table-action/subtasks-table-action.component.ts
b/flink-runtime-web/web-dashboard/src/app/share/customize/duration-badge/duration-badge.component.ts
similarity index 60%
copy from
flink-runtime-web/web-dashboard/src/app/pages/job/overview/subtasks/table-action/subtasks-table-action.component.ts
copy to
flink-runtime-web/web-dashboard/src/app/share/customize/duration-badge/duration-badge.component.ts
index 4db3407ed0a..d35568caefc 100644
---
a/flink-runtime-web/web-dashboard/src/app/pages/job/overview/subtasks/table-action/subtasks-table-action.component.ts
+++
b/flink-runtime-web/web-dashboard/src/app/share/customize/duration-badge/duration-badge.component.ts
@@ -18,18 +18,24 @@
import { Component, ChangeDetectionStrategy, Input } from '@angular/core';
-import { JobSubTask } from '@flink-runtime-web/interfaces';
-
-export interface JobOverviewSubtasksTableAction {
- subtask?: JobSubTask;
-}
+import { ColorKey, ConfigService } from '@flink-runtime-web/services';
@Component({
- selector: 'flink-table-actions',
- templateUrl: './subtasks-table-action.component.html',
- styleUrls: ['./subtasks-table-action.component.less'],
- changeDetection: ChangeDetectionStrategy.OnPush
+ selector: 'flink-duration-badge',
+ templateUrl: './duration-badge.component.html',
+ styleUrls: ['./duration-badge.component.less'],
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ host: {
+ '[style.backgroundColor]': 'backgroundColor'
+ }
})
-export class SubtasksTableActionComponent implements
JobOverviewSubtasksTableAction {
- @Input() subtask?: JobSubTask;
+export class DurationBadgeComponent {
+ @Input() public state: string;
+ @Input() public duration: number;
+
+ constructor(private readonly configService: ConfigService) {}
+
+ get backgroundColor(): string {
+ return this.configService.COLOR_MAP[this.state as ColorKey];
+ }
}
diff --git
a/flink-runtime-web/web-dashboard/src/app/share/pipes/humanize-bytes.pipe.ts
b/flink-runtime-web/web-dashboard/src/app/share/pipes/humanize-bytes.pipe.ts
index cbaf6222630..da91323b328 100644
--- a/flink-runtime-web/web-dashboard/src/app/share/pipes/humanize-bytes.pipe.ts
+++ b/flink-runtime-web/web-dashboard/src/app/share/pipes/humanize-bytes.pipe.ts
@@ -26,7 +26,7 @@ import { isNil } from '@flink-runtime-web/utils';
export class HumanizeBytesPipe implements PipeTransform {
public transform(value: number): string {
if (isNil(value) || isNaN(value) || value < 0) {
- return '–';
+ return '-';
}
const units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB'];
diff --git a/flink-runtime-web/web-dashboard/src/app/share/share.module.ts
b/flink-runtime-web/web-dashboard/src/app/share/share.module.ts
index 17288e4f9df..dfcf5f36954 100644
--- a/flink-runtime-web/web-dashboard/src/app/share/share.module.ts
+++ b/flink-runtime-web/web-dashboard/src/app/share/share.module.ts
@@ -28,6 +28,7 @@ import { FileReadDirective } from
'@flink-runtime-web/share/common/file-read/fil
import { NavigationComponent } from
'@flink-runtime-web/share/common/navigation/navigation.component';
import { ResizeComponent } from
'@flink-runtime-web/share/common/resize/resize.component';
import { JobStatusComponent } from
'@flink-runtime-web/share/common/status/job-status.component';
+import { TableAggregatedMetricsComponent } from
'@flink-runtime-web/share/common/table-aggregated-metrics/table-aggregated-metrics.component';
import { BackpressureBadgeComponent } from
'@flink-runtime-web/share/customize/backpressure-badge/backpressure-badge.component';
import { CheckpointBadgeComponent } from
'@flink-runtime-web/share/customize/checkpoint-badge/checkpoint-badge.component';
import { JobBadgeComponent } from
'@flink-runtime-web/share/customize/job-badge/job-badge.component';
@@ -49,6 +50,7 @@ import { NzToolTipModule } from 'ng-zorro-antd/tooltip';
import { ConfigurationCardsComponent } from
'./common/configuration-cards/configuration-cards.component';
import { TableDisplayComponent } from
'./common/configuration-cards/table-display/table-display.component';
+import { DurationBadgeComponent } from
'./customize/duration-badge/duration-badge.component';
import { FlameGraphComponent } from
'./customize/flame-graph/flame-graph.component';
@NgModule({
@@ -85,7 +87,9 @@ import { FlameGraphComponent } from
'./customize/flame-graph/flame-graph.compone
FlameGraphComponent,
JobStatusComponent,
TableDisplayComponent,
- ConfigurationCardsComponent
+ ConfigurationCardsComponent,
+ TableAggregatedMetricsComponent,
+ DurationBadgeComponent
],
exports: [
JobListComponent,
@@ -105,7 +109,9 @@ import { FlameGraphComponent } from
'./customize/flame-graph/flame-graph.compone
FlameGraphComponent,
JobStatusComponent,
TableDisplayComponent,
- ConfigurationCardsComponent
+ ConfigurationCardsComponent,
+ TableAggregatedMetricsComponent,
+ DurationBadgeComponent
]
})
export class ShareModule {}