mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-17 02:51:36 -05:00
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:
@@ -192,7 +192,8 @@ export class JobHistoryComponent extends Disposable implements OnInit {
|
|||||||
|
|
||||||
private setStepsTree(element: any) {
|
private setStepsTree(element: any) {
|
||||||
const self = this;
|
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) {
|
if (self.agentJobHistoryInfo) {
|
||||||
self.agentJobHistoryInfo.runDate = self.formatTime(self.agentJobHistoryInfo.runDate);
|
self.agentJobHistoryInfo.runDate = self.formatTime(self.agentJobHistoryInfo.runDate);
|
||||||
if (self.agentJobHistoryInfo.steps) {
|
if (self.agentJobHistoryInfo.steps) {
|
||||||
@@ -242,7 +243,7 @@ export class JobHistoryComponent extends Disposable implements OnInit {
|
|||||||
|
|
||||||
private convertToJobHistoryRow(historyInfo: AgentJobHistoryInfo): JobHistoryRow {
|
private convertToJobHistoryRow(historyInfo: AgentJobHistoryInfo): JobHistoryRow {
|
||||||
let jobHistoryRow = new JobHistoryRow();
|
let jobHistoryRow = new JobHistoryRow();
|
||||||
jobHistoryRow.runDate = historyInfo.runDate;
|
jobHistoryRow.runDate = this.formatTime(historyInfo.runDate);
|
||||||
jobHistoryRow.runStatus = AgentJobUtilities.convertToStatusString(historyInfo.runStatus);
|
jobHistoryRow.runStatus = AgentJobUtilities.convertToStatusString(historyInfo.runStatus);
|
||||||
jobHistoryRow.instanceID = historyInfo.instanceId;
|
jobHistoryRow.instanceID = historyInfo.instanceId;
|
||||||
return jobHistoryRow;
|
return jobHistoryRow;
|
||||||
|
|||||||
@@ -60,9 +60,11 @@ export class JobHistoryController extends TreeDefaults.DefaultController {
|
|||||||
|
|
||||||
public onKeyDownWrapper(tree: tree.ITree, event: IKeyboardEvent): boolean {
|
public onKeyDownWrapper(tree: tree.ITree, event: IKeyboardEvent): boolean {
|
||||||
if (event.code === 'ArrowDown' || event.keyCode === 40) {
|
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) {
|
} else if (event.code === 'ArrowUp' || event.keyCode === 38) {
|
||||||
return super.onUp(tree, event);
|
super.onUp(tree, event);
|
||||||
|
return super.onEnter(tree, event);
|
||||||
} else {
|
} else {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
|
|||||||
@@ -157,9 +157,7 @@ export class JobsViewComponent implements AfterContentChecked {
|
|||||||
let job = self.getJob(args);
|
let job = self.getJob(args);
|
||||||
self._agentViewComponent.jobId = job.jobId;
|
self._agentViewComponent.jobId = job.jobId;
|
||||||
self._agentViewComponent.agentJobInfo = job;
|
self._agentViewComponent.agentJobInfo = job;
|
||||||
setTimeout(() => {
|
|
||||||
self._agentViewComponent.showHistory = true;
|
self._agentViewComponent.showHistory = true;
|
||||||
}, 500);
|
|
||||||
});
|
});
|
||||||
if (cached && this._agentViewComponent.refresh !== true) {
|
if (cached && this._agentViewComponent.refresh !== true) {
|
||||||
this.onJobsAvailable(this._jobCacheObject.jobs);
|
this.onJobsAvailable(this._jobCacheObject.jobs);
|
||||||
@@ -290,44 +288,69 @@ export class JobsViewComponent implements AfterContentChecked {
|
|||||||
this.rowDetail.applyTemplateNewLineHeight(item, true);
|
this.rowDetail.applyTemplateNewLineHeight(item, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private loadJobHistories() {
|
private loadJobHistories(): void {
|
||||||
const self = this;
|
|
||||||
if (this.jobs) {
|
if (this.jobs) {
|
||||||
let erroredJobs = 0;
|
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;
|
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 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: 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) => {
|
this._jobManagementService.getJobHistory(ownerUri, job.jobId).then((result) => {
|
||||||
if (result.jobs) {
|
if (result && result.jobs) {
|
||||||
self.jobHistories[job.jobId] = result.jobs;
|
self.jobHistories[job.jobId] = result.jobs;
|
||||||
self._jobCacheObject.setJobHistory(job.jobId, result.jobs);
|
self._jobCacheObject.setJobHistory(job.jobId, result.jobs);
|
||||||
if (self._agentViewComponent.expanded.has(job.jobId)) {
|
if (self._agentViewComponent.expanded.has(job.jobId)) {
|
||||||
let jobHistory = self._jobCacheObject.getJobHistory(job.jobId)[0];
|
let jobHistory = self._jobCacheObject.getJobHistory(job.jobId)[result.jobs.length-1];
|
||||||
let item = self.dataView.getItemById(job.jobId + '.error');
|
let item = self.dataView.getItemById(job.jobId + '.error');
|
||||||
let noStepsMessage = nls.localize('jobsView.noSteps', 'No Steps available for this job.');
|
let noStepsMessage = nls.localize('jobsView.noSteps', 'No Steps available for this job.');
|
||||||
let errorMessage = jobHistory ? jobHistory.message: noStepsMessage;
|
let errorMessage = jobHistory ? jobHistory.message: noStepsMessage;
|
||||||
item['name'] = nls.localize('jobsView.error', 'Error: ') + errorMessage;
|
item['name'] = nls.localize('jobsView.error', 'Error: ') + errorMessage;
|
||||||
self._agentViewComponent.setExpanded(job.jobId, errorMessage);
|
self._agentViewComponent.setExpanded(job.jobId, item['name']);
|
||||||
self.dataView.updateItem(job.jobId + '.error', item);
|
self.dataView.updateItem(job.jobId + '.error', item);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private isErrorRow(jobName: string) {
|
|
||||||
return jobName.includes('Error');
|
|
||||||
}
|
|
||||||
|
|
||||||
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)) {
|
|
||||||
jobName = args.grid.getCellNode(row-1, 1).innerText.trim();
|
|
||||||
}
|
|
||||||
let job = this.jobs.filter(job => job.name === jobName)[0];
|
|
||||||
return job;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
12
src/sql/sqlops.d.ts
vendored
12
src/sql/sqlops.d.ts
vendored
@@ -1061,7 +1061,7 @@ declare module 'sqlops' {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface AgentJobStep {
|
export interface AgentJobStep {
|
||||||
stepId: number;
|
stepId: string;
|
||||||
stepName: string;
|
stepName: string;
|
||||||
message: string;
|
message: string;
|
||||||
runDate: string;
|
runDate: string;
|
||||||
@@ -1070,20 +1070,20 @@ declare module 'sqlops' {
|
|||||||
|
|
||||||
export interface AgentJobHistoryInfo {
|
export interface AgentJobHistoryInfo {
|
||||||
instanceId: number;
|
instanceId: number;
|
||||||
sqlMessageId: number;
|
sqlMessageId: string;
|
||||||
message: string;
|
message: string;
|
||||||
stepId: number;
|
stepId: string;
|
||||||
stepName: string;
|
stepName: string;
|
||||||
sqlSeverity: number;
|
sqlSeverity: string;
|
||||||
jobId: string;
|
jobId: string;
|
||||||
jobName: string;
|
jobName: string;
|
||||||
runStatus: number;
|
runStatus: number;
|
||||||
runDate: string;
|
runDate: string;
|
||||||
runDuration: number;
|
runDuration: string;
|
||||||
operatorEmailed: string;
|
operatorEmailed: string;
|
||||||
operatorNetsent: string;
|
operatorNetsent: string;
|
||||||
operatorPaged: string;
|
operatorPaged: string;
|
||||||
retriesAttempted: number;
|
retriesAttempted: string;
|
||||||
server: string;
|
server: string;
|
||||||
steps: AgentJobStep[];
|
steps: AgentJobStep[];
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user