| <!-- |
| ~ 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-tabset |
| *ngIf="checkPointStats" |
| [nzSize]="'small'" |
| [nzAnimated]="{ inkBar: true, tabPane: false }" |
| [nzTabBarExtraContent]="extraTemplate" |
| > |
| <nz-tab nzTitle="Overview"> |
| <nz-table |
| class="no-border small" |
| [nzData]="checkPointStats['latest'] ? [''] : []" |
| [nzSize]="'small'" |
| [nzFrontPagination]="false" |
| [nzShowPagination]="false" |
| > |
| <tbody> |
| <ng-container *ngIf="checkPointStats['latest'] && checkPointStats['counts']"> |
| <tr> |
| <td><strong>Checkpoint Counts</strong></td> |
| <td> |
| <span> |
| <strong>Triggered:</strong> |
| {{ checkPointStats['counts']['total'] }} |
| </span> |
| <nz-divider nzType="vertical"></nz-divider> |
| <span> |
| <strong>In Progress:</strong> |
| {{ checkPointStats['counts']['in_progress'] }} |
| </span> |
| <nz-divider nzType="vertical"></nz-divider> |
| <span> |
| <strong>Completed:</strong> |
| {{ checkPointStats['counts']['completed'] }} |
| </span> |
| <nz-divider nzType="vertical"></nz-divider> |
| <span> |
| <strong>Failed:</strong> |
| {{ checkPointStats['counts']['failed'] }} |
| </span> |
| <nz-divider nzType="vertical"></nz-divider> |
| <span> |
| <strong>Restored:</strong> |
| {{ checkPointStats['counts']['restored'] }} |
| </span> |
| </td> |
| </tr> |
| <tr> |
| <td><strong>Latest Completed Checkpoint</strong></td> |
| <td *ngIf="checkPointStats['latest']['completed']"> |
| <span> |
| <strong>ID:</strong> |
| {{ checkPointStats['latest']['completed']['id'] }} |
| </span> |
| <nz-divider nzType="vertical"></nz-divider> |
| <span> |
| <strong>Completion Time:</strong> |
| {{ |
| checkPointStats['latest']['completed']['latest_ack_timestamp'] |
| | date: 'yyyy-MM-dd HH:mm:ss' |
| }} |
| </span> |
| <nz-divider nzType="vertical"></nz-divider> |
| <span> |
| <strong>End to End Duration:</strong> |
| {{ |
| checkPointStats['latest']['completed']['end_to_end_duration'] | humanizeDuration |
| }} |
| </span> |
| <nz-divider nzType="vertical"></nz-divider> |
| <span> |
| <strong>Checkpointed Data Size:</strong> |
| {{ checkPointStats['latest']['completed']['checkpointed_size'] | humanizeBytes }} |
| </span> |
| <nz-divider nzType="vertical"></nz-divider> |
| <span> |
| <strong>Full Checkpoint Data Size:</strong> |
| {{ checkPointStats['latest']['completed']['state_size'] | humanizeBytes }} |
| </span> |
| </td> |
| <td *ngIf="!checkPointStats['latest']['completed']">None</td> |
| </tr> |
| <tr *ngIf="checkPointStats['latest']['completed']"> |
| <td colspan="2" class="collapse-td"> |
| <flink-job-checkpoints-detail |
| [checkPoint]="checkPointStats['latest']['completed']" |
| ></flink-job-checkpoints-detail> |
| </td> |
| </tr> |
| <tr> |
| <td><strong>Latest Failed Checkpoint</strong></td> |
| <td *ngIf="checkPointStats['latest']['failed']"> |
| <span> |
| <strong>ID:</strong> |
| {{ checkPointStats['latest']['failed']['id'] }} |
| </span> |
| <nz-divider nzType="vertical"></nz-divider> |
| <span> |
| <strong>Failure Time:</strong> |
| {{ |
| checkPointStats['latest']['failed']['failure_timestamp'] |
| | date: 'yyyy-MM-dd HH:mm:ss' |
| }} |
| </span> |
| <nz-divider nzType="vertical"></nz-divider> |
| <span> |
| <strong *ngIf="checkPointStats['latest']['failed']['failure_message']"> |
| Cause: |
| </strong> |
| {{ checkPointStats['latest']['failed']['failure_message'] }} |
| </span> |
| <span *ngIf="!checkPointStats['latest']['failed']['failure_message']"> |
| <strong>Cause:</strong> |
| n/a |
| </span> |
| </td> |
| <td *ngIf="!checkPointStats['latest']['failed']">None</td> |
| </tr> |
| <tr *ngIf="checkPointStats['latest']['failed']"> |
| <td colspan="2" class="collapse-td"> |
| <flink-job-checkpoints-detail |
| [checkPoint]="checkPointStats['latest']['failed']" |
| ></flink-job-checkpoints-detail> |
| </td> |
| </tr> |
| <tr> |
| <td><strong>Latest Savepoint</strong></td> |
| <td *ngIf="checkPointStats['latest']['savepoint']"> |
| <span> |
| <strong>ID:</strong> |
| {{ checkPointStats['latest']['savepoint']['id'] }} |
| </span> |
| <nz-divider nzType="vertical"></nz-divider> |
| <span> |
| <strong>Completion Time:</strong> |
| {{ |
| checkPointStats['latest']['savepoint']['latest_ack_timestamp'] |
| | date: 'yyyy-MM-dd HH:mm:ss' |
| }} |
| </span> |
| <nz-divider nzType="vertical"></nz-divider> |
| <span> |
| <strong>Checkpointed Data Size:</strong> |
| {{ checkPointStats['latest']['completed']['checkpointed_size'] | humanizeBytes }} |
| </span> |
| <nz-divider nzType="vertical"></nz-divider> |
| <span> |
| <strong>Full Checkpoint Data Size:</strong> |
| {{ checkPointStats['latest']['savepoint']['state_size'] | humanizeBytes }} |
| </span> |
| <nz-divider nzType="vertical"></nz-divider> |
| <span> |
| <strong>Path:</strong> |
| {{ checkPointStats['latest']['savepoint']['external_path'] }} |
| </span> |
| </td> |
| <td *ngIf="!checkPointStats['latest']['savepoint']">None</td> |
| </tr> |
| <tr *ngIf="checkPointStats['latest']['savepoint']"> |
| <td colspan="2" class="collapse-td"> |
| <flink-job-checkpoints-detail |
| [checkPoint]="checkPointStats['latest']['savepoint']" |
| ></flink-job-checkpoints-detail> |
| </td> |
| </tr> |
| <tr> |
| <td><strong>Latest Restore</strong></td> |
| <td *ngIf="checkPointStats['latest']['restored']"> |
| <span> |
| <strong>ID:</strong> |
| {{ checkPointStats['latest']['restored']['id'] }} |
| </span> |
| <nz-divider nzType="vertical"></nz-divider> |
| <span> |
| <strong>Restore Time:</strong> |
| {{ |
| checkPointStats['latest']['restored']['restore_timestamp'] |
| | date: 'yyyy-MM-dd HH:mm:ss' |
| }} |
| </span> |
| <nz-divider nzType="vertical"></nz-divider> |
| <span *ngIf="checkPointStats['latest']['restored']['is_savepoint']"> |
| <strong>Type:</strong> |
| Savepoint |
| </span> |
| <span *ngIf="!checkPointStats['latest']['restored']['is_savepoint']"> |
| <strong>Type:</strong> |
| Checkpoint |
| </span> |
| <nz-divider nzType="vertical"></nz-divider> |
| <span> |
| <strong *ngIf="checkPointStats['latest']['restored']['external_path']"> |
| Path: |
| </strong> |
| {{ checkPointStats['latest']['restored']['external_path'] }} |
| </span> |
| </td> |
| <td *ngIf="!checkPointStats['latest']['restored']">None</td> |
| </tr> |
| </ng-container> |
| </tbody> |
| </nz-table> |
| </nz-tab> |
| <nz-tab nzTitle="History"> |
| <nz-table |
| class="no-border small" |
| [nzSize]="'small'" |
| [nzData]="checkPointStats['history'] || []" |
| [nzFrontPagination]="false" |
| [nzShowPagination]="false" |
| > |
| <thead> |
| <tr> |
| <th nzWidth="70px"></th> |
| <th><strong>ID</strong></th> |
| <th><strong>Status</strong></th> |
| <th><strong>Acknowledged</strong></th> |
| <th><strong>Trigger Time</strong></th> |
| <th><strong>Latest Acknowledgement</strong></th> |
| <th><strong>End to End Duration</strong></th> |
| <th> |
| <strong> |
| Checkpointed Data Size |
| <i |
| class="header-icon" |
| nz-icon |
| nz-tooltip |
| nzTooltipTitle="The size of data persisted during the sync and async phases of a checkpoint. It's usually smaller than Full checkpoint data size if incremental checkpoints or changelog is enabled." |
| nzType="info-circle" |
| ></i> |
| </strong> |
| </th> |
| <th><strong>Full Checkpoint Data Size</strong></th> |
| <th><strong>Processed (persisted) in-flight data</strong></th> |
| </tr> |
| </thead> |
| <tbody> |
| <ng-container *ngFor="let checkpoint of checkPointStats['history']; trackBy: trackById"> |
| <tr> |
| <td nzShowExpand [(nzExpand)]="checkpoint.expand"></td> |
| <td>{{ checkpoint['id'] }}</td> |
| <td> |
| <flink-checkpoint-badge [state]="checkpoint['status']"> |
| {{ checkpoint['status'] }} |
| <em *ngIf="checkpoint['is_savepoint']">[Savepoint]</em> |
| </flink-checkpoint-badge> |
| </td> |
| |
| <td> |
| {{ checkpoint['num_acknowledged_subtasks'] }}/{{ checkpoint['num_subtasks'] }} |
| <span *ngIf="checkpoint['status'] === 'IN_PROGRESS'"> |
| ({{ |
| checkpoint['num_acknowledged_subtasks'] / checkpoint['num_subtasks'] | percent |
| }}) |
| </span> |
| </td> |
| <td>{{ checkpoint['trigger_timestamp'] | date: 'yyyy-MM-dd HH:mm:ss' }}</td> |
| <td *ngIf="checkpoint['latest_ack_timestamp'] >= 0"> |
| {{ checkpoint['latest_ack_timestamp'] | date: 'yyyy-MM-dd HH:mm:ss' }} |
| </td> |
| <td *ngIf="checkpoint['latest_ack_timestamp'] < 0">n/a</td> |
| <td *ngIf="checkpoint['end_to_end_duration'] >= 0"> |
| {{ checkpoint['end_to_end_duration'] | humanizeDuration }} |
| </td> |
| <td *ngIf="checkpoint['end_to_end_duration'] < 0">n/a</td> |
| <td>{{ checkpoint['checkpointed_size'] | humanizeBytes }}</td> |
| <td>{{ checkpoint['state_size'] | humanizeBytes }}</td> |
| <td> |
| {{ checkpoint['processed_data'] | humanizeBytes }} ({{ |
| checkpoint['persisted_data'] | humanizeBytes |
| }}) |
| </td> |
| </tr> |
| <tr [nzExpand]="checkpoint.expand"> |
| <td colspan="11" *ngIf="checkpoint.expand" class="collapse-td"> |
| <flink-job-checkpoints-detail |
| [checkPoint]="checkpoint" |
| ></flink-job-checkpoints-detail> |
| </td> |
| </tr> |
| </ng-container> |
| </tbody> |
| </nz-table> |
| </nz-tab> |
| <nz-tab nzTitle="Summary"> |
| <nz-table |
| *ngIf="checkPointStats" |
| class="no-border small" |
| [nzData]="checkPointStats && checkPointStats['summary'] ? [''] : []" |
| [nzSize]="'small'" |
| [nzFrontPagination]="false" |
| [nzShowPagination]="false" |
| > |
| <thead> |
| <tr> |
| <th></th> |
| <th><strong>End to End Duration</strong></th> |
| <th> |
| <strong> |
| Checkpointed Data Size |
| <i |
| class="header-icon" |
| nz-icon |
| nz-tooltip |
| nzTooltipTitle="The size of data persisted during the sync and async phases of a checkpoint. It's usually smaller than Full checkpoint data size if incremental checkpoints or changelog is enabled" |
| nzType="info-circle" |
| ></i> |
| </strong> |
| </th> |
| <th><strong>Full Checkpoint Data Size</strong></th> |
| <th><strong>Processed (persisted) in-flight data</strong></th> |
| </tr> |
| </thead> |
| <tbody> |
| <ng-container *ngIf="checkPointStats['summary']"> |
| <tr> |
| <td><strong>Minimum</strong></td> |
| <td> |
| {{ checkPointStats['summary']['end_to_end_duration']['min'] | humanizeDuration }} |
| </td> |
| <td> |
| {{ checkPointStats['summary']['checkpointed_size']['min'] | humanizeBytes }} |
| </td> |
| <td>{{ checkPointStats['summary']['state_size']['min'] | humanizeBytes }}</td> |
| <td> |
| {{ checkPointStats['summary']['processed_data']['min'] | humanizeBytes }} ({{ |
| checkPointStats['summary']['persisted_data']['min'] | humanizeBytes |
| }}) |
| </td> |
| </tr> |
| <tr> |
| <td><strong>Average</strong></td> |
| <td> |
| {{ checkPointStats['summary']['end_to_end_duration']['avg'] | humanizeDuration }} |
| </td> |
| <td> |
| {{ checkPointStats['summary']['checkpointed_size']['avg'] | humanizeBytes }} |
| </td> |
| <td>{{ checkPointStats['summary']['state_size']['avg'] | humanizeBytes }}</td> |
| <td> |
| {{ checkPointStats['summary']['processed_data']['avg'] | humanizeBytes }} ({{ |
| checkPointStats['summary']['persisted_data']['avg'] | humanizeBytes |
| }}) |
| </td> |
| </tr> |
| <tr> |
| <td><strong>Maximum</strong></td> |
| <td> |
| {{ checkPointStats['summary']['end_to_end_duration']['max'] | humanizeDuration }} |
| </td> |
| <td> |
| {{ checkPointStats['summary']['checkpointed_size']['max'] | humanizeBytes }} |
| </td> |
| <td>{{ checkPointStats['summary']['state_size']['max'] | humanizeBytes }}</td> |
| <td> |
| {{ checkPointStats['summary']['processed_data']['max'] | humanizeBytes }} ({{ |
| checkPointStats['summary']['persisted_data']['max'] | humanizeBytes |
| }}) |
| </td> |
| </tr> |
| </ng-container> |
| </tbody> |
| </nz-table> |
| |
| <nz-collapse> |
| <nz-collapse-panel |
| [nzHeader]="'Percentiles'" |
| [nzActive]="moreDetailsPanel.active" |
| [nzDisabled]="moreDetailsPanel.disabled" |
| > |
| <nz-table |
| *ngIf="checkPointStats" |
| class="no-border small" |
| [nzData]="checkPointStats && checkPointStats['summary'] ? [''] : []" |
| [nzSize]="'small'" |
| [nzFrontPagination]="false" |
| [nzShowPagination]="false" |
| > |
| <thead> |
| <tr> |
| <th></th> |
| <th><strong>End to End Duration</strong></th> |
| <th><strong>Checkpointed Data Size</strong></th> |
| <th><strong>Full Checkpoint Data Size</strong></th> |
| <th><strong>Processed (persisted) in-flight data</strong></th> |
| </tr> |
| </thead> |
| <tbody> |
| <ng-container *ngIf="checkPointStats['summary']"> |
| <tr> |
| <td><strong>50% percentile</strong></td> |
| <td> |
| {{ checkPointStats['summary']['end_to_end_duration']['p50'] | humanizeDuration }} |
| </td> |
| <td> |
| {{ checkPointStats['summary']['checkpointed_size']['p50'] | humanizeBytes }} |
| </td> |
| <td>{{ checkPointStats['summary']['state_size']['p50'] | humanizeBytes }}</td> |
| <td> |
| {{ checkPointStats['summary']['processed_data']['p50'] | humanizeBytes }} ({{ |
| checkPointStats['summary']['persisted_data']['p50'] | humanizeBytes |
| }}) |
| </td> |
| </tr> |
| <tr> |
| <td><strong>90% percentile</strong></td> |
| <td> |
| {{ checkPointStats['summary']['end_to_end_duration']['p90'] | humanizeDuration }} |
| </td> |
| <td> |
| {{ checkPointStats['summary']['checkpointed_size']['p90'] | humanizeBytes }} |
| </td> |
| <td>{{ checkPointStats['summary']['state_size']['p90'] | humanizeBytes }}</td> |
| <td> |
| {{ checkPointStats['summary']['processed_data']['p90'] | humanizeBytes }} ({{ |
| checkPointStats['summary']['persisted_data']['p90'] | humanizeBytes |
| }}) |
| </td> |
| </tr> |
| <tr> |
| <td><strong>99% percentile</strong></td> |
| <td> |
| {{ checkPointStats['summary']['end_to_end_duration']['p99'] | humanizeDuration }} |
| </td> |
| <td> |
| {{ checkPointStats['summary']['checkpointed_size']['p99'] | humanizeBytes }} |
| </td> |
| <td>{{ checkPointStats['summary']['state_size']['p99'] | humanizeBytes }}</td> |
| <td> |
| {{ checkPointStats['summary']['processed_data']['p99'] | humanizeBytes }} ({{ |
| checkPointStats['summary']['persisted_data']['p99'] | humanizeBytes |
| }}) |
| </td> |
| </tr> |
| <tr> |
| <td><strong>99.9% percentile</strong></td> |
| <td> |
| {{ checkPointStats['summary']['end_to_end_duration']['p999'] | humanizeDuration }} |
| </td> |
| <td> |
| {{ checkPointStats['summary']['checkpointed_size']['p999'] | humanizeBytes }} |
| </td> |
| <td>{{ checkPointStats['summary']['state_size']['p999'] | humanizeBytes }}</td> |
| <td> |
| {{ checkPointStats['summary']['processed_data']['p999'] | humanizeBytes }} ({{ |
| checkPointStats['summary']['persisted_data']['p999'] | humanizeBytes |
| }}) |
| </td> |
| </tr> |
| </ng-container> |
| </tbody> |
| </nz-table> |
| </nz-collapse-panel> |
| </nz-collapse> |
| </nz-tab> |
| <nz-tab nzTitle="Configuration"> |
| <nz-table |
| class="no-border small" |
| [nzData]="checkPointConfig ? [''] : []" |
| [nzSize]="'small'" |
| [nzFrontPagination]="false" |
| [nzShowPagination]="false" |
| > |
| <thead> |
| <tr> |
| <th><strong>Option</strong></th> |
| <th><strong>Value</strong></th> |
| </tr> |
| </thead> |
| <tbody> |
| <ng-container *ngIf="checkPointConfig"> |
| <tr> |
| <td>Checkpointing Mode</td> |
| <td *ngIf="checkPointConfig['mode'] === 'exactly_once'">Exactly Once</td> |
| <td *ngIf="checkPointConfig['mode'] !== 'exactly_once'">At Least Once</td> |
| </tr> |
| <tr> |
| <td>Checkpoint Storage</td> |
| <td>{{ checkPointConfig['checkpoint_storage'] }}</td> |
| </tr> |
| <tr> |
| <td>State Backend</td> |
| <td>{{ checkPointConfig['state_backend'] }}</td> |
| </tr> |
| <tr> |
| <td>Interval</td> |
| <td *ngIf="checkPointConfig['interval'] === '0x7fffffffffffffff'"> |
| Periodic checkpoints disabled |
| </td> |
| <td *ngIf="checkPointConfig['interval'] !== '0x7fffffffffffffff'"> |
| {{ checkPointConfig['interval'] | humanizeDuration }} |
| </td> |
| </tr> |
| <tr> |
| <td>Timeout</td> |
| <td>{{ checkPointConfig['timeout'] | humanizeDuration }}</td> |
| </tr> |
| <tr> |
| <td>Minimum Pause Between Checkpoints</td> |
| <td>{{ checkPointConfig['min_pause'] | humanizeDuration }}</td> |
| </tr> |
| <tr> |
| <td>Maximum Concurrent Checkpoints</td> |
| <td>{{ checkPointConfig['max_concurrent'] }}</td> |
| </tr> |
| <tr> |
| <td>Unaligned Checkpoints</td> |
| <td>{{ checkPointConfig['unaligned_checkpoints'] ? 'Enabled' : 'Disabled' }}</td> |
| </tr> |
| <tr *ngIf="checkPointConfig['unaligned_checkpoints']"> |
| <td>Aligned checkpoint timeout</td> |
| <td>{{ checkPointConfig['aligned_checkpoint_timeout'] | humanizeDuration }}</td> |
| </tr> |
| <tr *ngIf="checkPointConfig['externalization']"> |
| <td>Persist Checkpoints Externally</td> |
| <td *ngIf="checkPointConfig['externalization']['enabled']"> |
| Enabled |
| <span *ngIf="checkPointConfig['externalization']['delete_on_cancellation']"> |
| (delete on cancellation) |
| </span> |
| <span *ngIf="!checkPointConfig['externalization']['delete_on_cancellation']"> |
| (retain on cancellation) |
| </span> |
| </td> |
| <td *ngIf="!checkPointConfig['externalization']['enabled']">Disabled</td> |
| </tr> |
| <tr> |
| <td>Tolerable Failed Checkpoints</td> |
| <td>{{ checkPointConfig['tolerable_failed_checkpoints'] }}</td> |
| </tr> |
| <tr> |
| <td>Checkpoints With Finished Tasks</td> |
| <td> |
| {{ checkPointConfig['checkpoints_after_tasks_finish'] ? 'Enabled' : 'Disabled' }} |
| </td> |
| </tr> |
| </ng-container> |
| </tbody> |
| </nz-table> |
| </nz-tab> |
| </nz-tabset> |
| |
| <ng-template #extraTemplate> |
| <button nz-button nzType="primary" class="refresh" nzSize="small" (click)="refresh()"> |
| <i nz-icon nzType="sync"></i> |
| Refresh |
| </button> |
| </ng-template> |
| |
| <nz-empty *ngIf="!checkPointStats"></nz-empty> |