Agent Improvements/Fixes (#1284)

* fixed UI bugs and increased jobs history page perf

* cached full error message

* load histories for jobs with errors first

* cr comments
This commit is contained in:
Aditya Bist
2018-05-01 17:42:11 -07:00
committed by GitHub
parent 46fb68214f
commit 6f10f7a21a
4 changed files with 66 additions and 40 deletions

View File

@@ -111,7 +111,7 @@ export class JobHistoryComponent extends Disposable implements OnInit {
} else {
tree.setFocus(element, payload);
tree.setSelection([element], payload);
self.setStepsTree(element);
self.setStepsTree(element);
}
return true;
};
@@ -192,7 +192,8 @@ export class JobHistoryComponent extends Disposable implements OnInit {
private setStepsTree(element: any) {
const self = this;
self.agentJobHistoryInfo = self._treeController.jobHistories.filter(history => history.instanceId === element.instanceID)[0];
self.agentJobHistoryInfo = self._treeController.jobHistories.find(
history => self.formatTime(history.runDate) === self.formatTime(element.runDate));
if (self.agentJobHistoryInfo) {
self.agentJobHistoryInfo.runDate = self.formatTime(self.agentJobHistoryInfo.runDate);
if (self.agentJobHistoryInfo.steps) {
@@ -242,7 +243,7 @@ export class JobHistoryComponent extends Disposable implements OnInit {
private convertToJobHistoryRow(historyInfo: AgentJobHistoryInfo): JobHistoryRow {
let jobHistoryRow = new JobHistoryRow();
jobHistoryRow.runDate = historyInfo.runDate;
jobHistoryRow.runDate = this.formatTime(historyInfo.runDate);
jobHistoryRow.runStatus = AgentJobUtilities.convertToStatusString(historyInfo.runStatus);
jobHistoryRow.instanceID = historyInfo.instanceId;
return jobHistoryRow;

View File

@@ -60,9 +60,11 @@ export class JobHistoryController extends TreeDefaults.DefaultController {
public onKeyDownWrapper(tree: tree.ITree, event: IKeyboardEvent): boolean {
if (event.code === 'ArrowDown' || event.keyCode === 40) {
return super.onDown(tree, event);
super.onDown(tree, event);
return super.onEnter(tree, event);
} else if (event.code === 'ArrowUp' || event.keyCode === 38) {
return super.onUp(tree, event);
super.onUp(tree, event);
return super.onEnter(tree, event);
} else {
event.preventDefault();
event.stopPropagation();

View File

@@ -157,9 +157,7 @@ export class JobsViewComponent implements AfterContentChecked {
let job = self.getJob(args);
self._agentViewComponent.jobId = job.jobId;
self._agentViewComponent.agentJobInfo = job;
setTimeout(() => {
self._agentViewComponent.showHistory = true;
}, 500);
self._agentViewComponent.showHistory = true;
});
if (cached && this._agentViewComponent.refresh !== true) {
this.onJobsAvailable(this._jobCacheObject.jobs);
@@ -290,44 +288,69 @@ export class JobsViewComponent implements AfterContentChecked {
this.rowDetail.applyTemplateNewLineHeight(item, true);
}
private loadJobHistories() {
const self = this;
private loadJobHistories(): void {
if (this.jobs) {
let erroredJobs = 0;
for (let i = 0; i < this.jobs.length; i++) {
let job = this.jobs[i];
let ownerUri: string = this._dashboardService.connectionManagementService.connectionInfo.ownerUri;
this._jobManagementService.getJobHistory(ownerUri, job.jobId).then((result) => {
if (result.jobs) {
self.jobHistories[job.jobId] = result.jobs;
self._jobCacheObject.setJobHistory(job.jobId, result.jobs);
if (self._agentViewComponent.expanded.has(job.jobId)) {
let jobHistory = self._jobCacheObject.getJobHistory(job.jobId)[0];
let item = self.dataView.getItemById(job.jobId + '.error');
let noStepsMessage = nls.localize('jobsView.noSteps', 'No Steps available for this job.');
let errorMessage = jobHistory ? jobHistory.message: noStepsMessage;
item['name'] = nls.localize('jobsView.error', 'Error: ') + errorMessage;
self._agentViewComponent.setExpanded(job.jobId, errorMessage);
self.dataView.updateItem(job.jobId + '.error', item);
}
}
});
}
let ownerUri: string = this._dashboardService.connectionManagementService.connectionInfo.ownerUri;
let separatedJobs = this.separateFailingJobs();
// grab histories of the failing jobs first
// so they can be expanded quicker
let failing = separatedJobs[0];
this.curateJobHistory(failing, ownerUri);
let passing = separatedJobs[1];
this.curateJobHistory(passing, ownerUri);
}
}
private isErrorRow(jobName: string) {
return jobName.includes('Error');
private separateFailingJobs(): sqlops.AgentJobInfo[][] {
let failing = [];
let nonFailing = [];
for (let i = 0; i < this.jobs.length; i++) {
if (this.jobs[i].lastRunOutcome === 0) {
failing.push(this.jobs[i]);
} else {
nonFailing.push(this.jobs[i]);
}
}
return [failing, nonFailing];
}
private isErrorRow(cell: HTMLElement) {
return cell.classList.contains('error-row');
}
private getJob(args: Slick.OnClickEventArgs<any>): sqlops.AgentJobInfo {
let row = args.row;
let jobName = args.grid.getCellNode(row, 1).innerText.trim();
if (this.isErrorRow(jobName)) {
let jobName: string;
let cell = args.grid.getCellNode(row, 1);
if (this.isErrorRow(cell)) {
jobName = args.grid.getCellNode(row-1, 1).innerText.trim();
} else {
jobName = cell.innerText.trim();
}
let job = this.jobs.filter(job => job.name === jobName)[0];
return job;
}
private curateJobHistory(jobs: sqlops.AgentJobInfo[], ownerUri: string) {
const self = this;
for (let i = 0; i < jobs.length; i++) {
let job = jobs[i];
this._jobManagementService.getJobHistory(ownerUri, job.jobId).then((result) => {
if (result && result.jobs) {
self.jobHistories[job.jobId] = result.jobs;
self._jobCacheObject.setJobHistory(job.jobId, result.jobs);
if (self._agentViewComponent.expanded.has(job.jobId)) {
let jobHistory = self._jobCacheObject.getJobHistory(job.jobId)[result.jobs.length-1];
let item = self.dataView.getItemById(job.jobId + '.error');
let noStepsMessage = nls.localize('jobsView.noSteps', 'No Steps available for this job.');
let errorMessage = jobHistory ? jobHistory.message: noStepsMessage;
item['name'] = nls.localize('jobsView.error', 'Error: ') + errorMessage;
self._agentViewComponent.setExpanded(job.jobId, item['name']);
self.dataView.updateItem(job.jobId + '.error', item);
}
}
});
}
}
}

12
src/sql/sqlops.d.ts vendored
View File

@@ -1061,7 +1061,7 @@ declare module 'sqlops' {
}
export interface AgentJobStep {
stepId: number;
stepId: string;
stepName: string;
message: string;
runDate: string;
@@ -1070,20 +1070,20 @@ declare module 'sqlops' {
export interface AgentJobHistoryInfo {
instanceId: number;
sqlMessageId: number;
sqlMessageId: string;
message: string;
stepId: number;
stepId: string;
stepName: string;
sqlSeverity: number;
sqlSeverity: string;
jobId: string;
jobName: string;
runStatus: number;
runDate: string;
runDuration: number;
runDuration: string;
operatorEmailed: string;
operatorNetsent: string;
operatorPaged: string;
retriesAttempted: number;
retriesAttempted: string;
server: string;
steps: AgentJobStep[];
}