src/app/jobs/step-execution-details/step-execution-details.component.ts
Step Execution Details
selector | app-step-execution-details |
styleUrls | styles.scss |
templateUrl | ./step-execution-details.component.html |
Properties |
Methods |
constructor(jobsService: JobsService, route: ActivatedRoute, loggerService: LoggerService, routingStateService: RoutingStateService, notificationService: NotificationService, router: Router)
|
||||||||||||||||||||||||||||
Constructor
Parameters :
|
back |
back()
|
Navigate to the previous page
Returns :
void
|
ngOnInit |
ngOnInit()
|
Init component
Returns :
void
|
refresh |
refresh()
|
Refresh
Returns :
void
|
viewStepExecutionProgress | ||||||||
viewStepExecutionProgress(item: StepExecutionResource)
|
||||||||
Navigates to the step execution progress page.
Parameters :
Returns :
void
|
jobId |
jobId:
|
Type : number
|
Job ID |
stepExecutionDetails$ |
stepExecutionDetails$:
|
Type : Observable<any>
|
Observable Step Execution Informations |
import { Component, OnInit } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { JobsService } from '../jobs.service';
import { StepExecutionResource } from '../model/step-execution-resource.model';
import { Observable, forkJoin } from 'rxjs';
import { mergeMap, map, catchError } from 'rxjs/operators';
import { HttpAppError, AppError } from '../../shared/model/error.model';
import { LoggerService } from '../../shared/services/logger.service';
import { NotificationService } from '../../shared/services/notification.service';
import { RoutingStateService } from '../../shared/services/routing-state.service';
import { EMPTY } from 'rxjs';
/**
* Step Execution Details
*
* @author Glenn Renfro
* @author Gunnar Hillert
* @author Damien Vitrac
*/
@Component({
selector: 'app-step-execution-details',
styleUrls: ['styles.scss'],
templateUrl: './step-execution-details.component.html'
})
export class StepExecutionDetailsComponent implements OnInit {
/**
* Observable Step Execution Informations
*/
stepExecutionDetails$: Observable<any>;
/**
* Job ID
*/
jobId: number;
/**
* Constructor
*
* @param {JobsService} jobsService
* @param {ActivatedRoute} route
* @param {LoggerService} loggerService
* @param {RoutingStateService} routingStateService
* @param {NotificationService} notificationService
* @param {Router} router
*/
constructor(private jobsService: JobsService,
private route: ActivatedRoute,
private loggerService: LoggerService,
private routingStateService: RoutingStateService,
private notificationService: NotificationService,
private router: Router) {
}
/**
* Init component
*/
ngOnInit() {
this.refresh();
}
/**
* Refresh
*/
refresh() {
this.stepExecutionDetails$ = this.route.params
.pipe(mergeMap(
val => forkJoin([
this.jobsService.getJobExecution(val.jobid),
this.jobsService.getStepExecution(val.jobid, val.stepid),
this.jobsService.getStepExecutionProgress(val.jobid, val.stepid)
]).pipe(map((val2) => {
this.jobId = val.jobid;
return val2;
}))
))
.pipe(
map(
val => ({ jobExecution: val[0], stepExecution: val[1], stepExecutionProgress: val[2] })
),
catchError((error) => {
if (HttpAppError.is404(error) || HttpAppError.is400(error)) {
this.routingStateService.back(`/jobs/executions/`);
}
this.loggerService.log('error while loading Step Execution Progress', error);
this.notificationService.error(AppError.is(error) ? error.getMessage() : error);
return EMPTY;
})
);
}
/**
* Navigates to the step execution progress page.
*
* @param {StepExecutionResource} item the id of the StepExecution is used to construct the URI parameters along
* with the JobExecutionId.
*/
viewStepExecutionProgress(item: StepExecutionResource) {
this.router.navigate([`jobs/executions/${item.jobExecutionId}/${item.stepExecution.id}/progress`]);
}
/**
* Navigate to the previous page
*/
back() {
this.routingStateService.back(`jobs/executions/${this.jobId}`);
}
}
<app-page *ngIf="stepExecutionDetails$ | async as stepExecutionDetails; else loading">
<app-page-head>
<app-page-head-back [defaultUrl]="'/jobs/executions/' + jobId"></app-page-head-back>
<app-page-head-title>
Step Execution <strong>{{ stepExecutionDetails.stepExecution.stepExecution.name }}
({{ stepExecutionDetails.stepExecution.stepExecution.id }})</strong>
- Job execution <strong>{{ stepExecutionDetails.jobExecution.name }}</strong>
({{ stepExecutionDetails.jobExecution.jobExecutionId }})
</app-page-head-title>
<app-page-head-actions>
<button id="stats" class="btn btn-primary btn-fa" title="Details"
(click)="viewStepExecutionProgress(stepExecutionDetails.stepExecution)">
<span class="fa fa-info-circle"></span>
More details
</button>
<button id="refresh" class="btn btn-primary btn-fa" (click)="refresh()">
<span class="fa fa-refresh"></span>
Refresh
</button>
</app-page-head-actions>
</app-page-head>
<div *ngIf="stepExecutionDetails.stepExecutionProgress.percentageComplete < 1">
<h4>Step Execution Progress</h4>
<progressbar [animate]="false" max="100"
[value]="stepExecutionDetails.stepExecutionProgress.percentageComplete * 100"
type="success">
<b>{{ stepExecutionDetails.stepExecutionProgress.percentageComplete * 100}}%</b>
</progressbar>
</div>
<div>
<h4>Step Execution</h4>
<div id="nostepexecution" *ngIf="!stepExecutionDetails?.stepExecution.stepExecution">
No Step Execution available.
</div>
<table id="stepExecution" *ngIf="stepExecutionDetails?.stepExecution?.stepExecution" class="table table-hover">
<thead>
<tr>
<th style="width: 250px">Property</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr>
<td>Step Execution Id</td>
<td>{{ stepExecutionDetails.stepExecution.stepExecution.id }}</td>
</tr>
<tr>
<td>Job Execution Id</td>
<td>{{ stepExecutionDetails.stepExecution.jobExecutionId }}</td>
</tr>
<tr>
<td>Step Name</td>
<td>{{ stepExecutionDetails.stepExecution.stepExecution.name }}</td>
</tr>
<tr>
<td>Step Type</td>
<td>{{ stepExecutionDetails.stepExecution.stepType }}</td>
</tr>
<tr>
<td>Status</td>
<td>
<app-job-execution-status
[status]="stepExecutionDetails.stepExecution.stepExecution.status"></app-job-execution-status>
</td>
</tr>
<tr>
<td>Commits</td>
<td>{{ stepExecutionDetails.stepExecution.stepExecution.commitCount }}</td>
</tr>
<tr>
<td>Duration</td>
<td>{{ stepExecutionDetails.stepExecution.stepExecution.startTime | dataflowDuration:
stepExecutionDetails.stepExecution.stepExecution.endTime }}
</td>
</tr>
<tr>
<td>Filter Count</td>
<td>{{ stepExecutionDetails.stepExecution.stepExecution.filterCount }}</td>
</tr>
<tr>
<td>Process Skips</td>
<td>{{ stepExecutionDetails.stepExecution.stepExecution.processSkipCount }}</td>
</tr>
<tr>
<td>Reads</td>
<td>{{ stepExecutionDetails.stepExecution.stepExecution.readCount }}</td>
</tr>
<tr>
<td>Read Skips</td>
<td>{{ stepExecutionDetails.stepExecution.stepExecution.readSkipCount }}</td>
</tr>
<tr>
<td>Rollbacks</td>
<td>{{ stepExecutionDetails.stepExecution.stepExecution.rollbackCount }}</td>
</tr>
<tr>
<td>Skips</td>
<td>{{ stepExecutionDetails.stepExecution.stepExecution.skipCount }}</td>
</tr>
<tr>
<td>Writes</td>
<td>{{ stepExecutionDetails.stepExecution.stepExecution.writeCount }}</td>
</tr>
<tr>
<td>Write Skips</td>
<td>{{ stepExecutionDetails.stepExecution.stepExecution.writeSkipCount }}</td>
</tr>
</tbody>
</table>
</div>
<div *ngIf="stepExecutionDetails?.stepExecution?.stepExecution?.exitMessage">
<h4>Exit Description</h4>
<pre class="exit">{{ stepExecutionDetails?.stepExecution?.stepExecution?.exitMessage || 'N/A' }}</pre>
</div>
<div *ngIf="stepExecutionDetails?.stepExecution?.stepExecution?.executionContext?.values">
<h4>Step Execution Context</h4>
<table id="stepExecutionContext" class="table table-hover">
<thead>
<tr>
<th style="width: 250px">Key</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<ng-template ngFor let-item
[ngForOf]="stepExecutionDetails.stepExecution.stepExecution.executionContext.values | keyvalue">
<tr>
<td>{{ item.key }}</td>
<td>{{ item.value }}</td>
</tr>
</ng-template>
</tbody>
</table>
</div>
</app-page>
<ng-template #loading>
<app-loader></app-loader>
</ng-template>