diff --git a/pkg/new-ui/v1beta1/frontend/src/app/pages/experiment-details/trials-table/trial-details/trial-details.component.html b/pkg/new-ui/v1beta1/frontend/src/app/pages/experiment-details/trials-table/trial-details/trial-details.component.html
index 88baf33ffc0..c9d98a5e648 100644
--- a/pkg/new-ui/v1beta1/frontend/src/app/pages/experiment-details/trials-table/trial-details/trial-details.component.html
+++ b/pkg/new-ui/v1beta1/frontend/src/app/pages/experiment-details/trials-table/trial-details/trial-details.component.html
@@ -50,6 +50,15 @@
+
+
+
+
+
+
diff --git a/pkg/new-ui/v1beta1/frontend/src/app/pages/experiment-details/trials-table/trial-details/trial-details.component.spec.ts b/pkg/new-ui/v1beta1/frontend/src/app/pages/experiment-details/trials-table/trial-details/trial-details.component.spec.ts
index 541e02e8f89..194bc336295 100644
--- a/pkg/new-ui/v1beta1/frontend/src/app/pages/experiment-details/trials-table/trial-details/trial-details.component.spec.ts
+++ b/pkg/new-ui/v1beta1/frontend/src/app/pages/experiment-details/trials-table/trial-details/trial-details.component.spec.ts
@@ -20,6 +20,7 @@ let NamespaceServiceStub: Partial;
KWABackendServiceStub = {
getTrial: () => of([]),
getTrialInfo: () => of(),
+ getTrialLogs: () => of(),
};
NamespaceServiceStub = {
diff --git a/pkg/new-ui/v1beta1/frontend/src/app/pages/experiment-details/trials-table/trial-details/trial-details.component.ts b/pkg/new-ui/v1beta1/frontend/src/app/pages/experiment-details/trials-table/trial-details/trial-details.component.ts
index 827f99befc5..b2412add206 100644
--- a/pkg/new-ui/v1beta1/frontend/src/app/pages/experiment-details/trials-table/trial-details/trial-details.component.ts
+++ b/pkg/new-ui/v1beta1/frontend/src/app/pages/experiment-details/trials-table/trial-details/trial-details.component.ts
@@ -28,6 +28,8 @@ export class TrialDetailsComponent implements OnInit, OnDestroy {
trialDetails: TrialK8s;
experimentName: string;
showTrialGraph: boolean = false;
+ trialLogs: string;
+ logsRequestError: string;
// chart's options
view = [700, 500];
@@ -139,6 +141,17 @@ export class TrialDetailsComponent implements OnInit, OnDestroy {
this.startTrialPolling();
}
});
+
+ this.backendService.getTrialLogs(this.trialName, this.namespace).subscribe(
+ logs => {
+ this.trialLogs = logs;
+ this.logsRequestError = '';
+ },
+ error => {
+ this.trialLogs = null;
+ this.logsRequestError = error;
+ },
+ );
}
private trialStatus(trial: TrialK8s): StatusEnum {
diff --git a/pkg/new-ui/v1beta1/frontend/src/app/pages/experiment-details/trials-table/trial-details/trial-details.module.ts b/pkg/new-ui/v1beta1/frontend/src/app/pages/experiment-details/trials-table/trial-details/trial-details.module.ts
index a32cb7ef323..0c34d5b3889 100644
--- a/pkg/new-ui/v1beta1/frontend/src/app/pages/experiment-details/trials-table/trial-details/trial-details.module.ts
+++ b/pkg/new-ui/v1beta1/frontend/src/app/pages/experiment-details/trials-table/trial-details/trial-details.module.ts
@@ -16,6 +16,7 @@ import {
LoadingSpinnerModule,
PanelModule,
} from 'kubeflow';
+import { TrialLogsModule } from './trial-logs/trial-logs.module';
@NgModule({
declarations: [TrialDetailsComponent],
@@ -34,6 +35,7 @@ import {
PanelModule,
TitleActionsToolbarModule,
TrialYamlModule,
+ TrialLogsModule,
],
exports: [TrialDetailsComponent],
})
diff --git a/pkg/new-ui/v1beta1/frontend/src/app/pages/experiment-details/trials-table/trial-details/trial-logs/trial-logs.component.html b/pkg/new-ui/v1beta1/frontend/src/app/pages/experiment-details/trials-table/trial-details/trial-logs/trial-logs.component.html
new file mode 100644
index 00000000000..a7ac44580f5
--- /dev/null
+++ b/pkg/new-ui/v1beta1/frontend/src/app/pages/experiment-details/trials-table/trial-details/trial-logs/trial-logs.component.html
@@ -0,0 +1,15 @@
+
+
+
+ Error: {{ logsRequestError }}
+
+
+
+
+
+
diff --git a/pkg/new-ui/v1beta1/frontend/src/app/pages/experiment-details/trials-table/trial-details/trial-logs/trial-logs.component.scss b/pkg/new-ui/v1beta1/frontend/src/app/pages/experiment-details/trials-table/trial-details/trial-logs/trial-logs.component.scss
new file mode 100644
index 00000000000..053f94c377f
--- /dev/null
+++ b/pkg/new-ui/v1beta1/frontend/src/app/pages/experiment-details/trials-table/trial-details/trial-logs/trial-logs.component.scss
@@ -0,0 +1,9 @@
+lib-panel {
+ display: block;
+ margin-top: 1rem;
+}
+
+.logs-viewer {
+ margin-bottom: 2rem;
+ margin-top: 1rem;
+}
diff --git a/pkg/new-ui/v1beta1/frontend/src/app/pages/experiment-details/trials-table/trial-details/trial-logs/trial-logs.component.spec.ts b/pkg/new-ui/v1beta1/frontend/src/app/pages/experiment-details/trials-table/trial-details/trial-logs/trial-logs.component.spec.ts
new file mode 100644
index 00000000000..9a018027b10
--- /dev/null
+++ b/pkg/new-ui/v1beta1/frontend/src/app/pages/experiment-details/trials-table/trial-details/trial-logs/trial-logs.component.spec.ts
@@ -0,0 +1,36 @@
+import { CommonModule } from '@angular/common';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import {
+ HeadingSubheadingRowModule,
+ KubeflowModule,
+ LogsViewerModule,
+} from 'kubeflow';
+
+import { TrialLogsComponent } from './trial-logs.component';
+
+describe('TrialLogsComponent', () => {
+ let component: TrialLogsComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [TrialLogsComponent],
+ imports: [
+ CommonModule,
+ KubeflowModule,
+ HeadingSubheadingRowModule,
+ LogsViewerModule,
+ ],
+ }).compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(TrialLogsComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/pkg/new-ui/v1beta1/frontend/src/app/pages/experiment-details/trials-table/trial-details/trial-logs/trial-logs.component.ts b/pkg/new-ui/v1beta1/frontend/src/app/pages/experiment-details/trials-table/trial-details/trial-logs/trial-logs.component.ts
new file mode 100644
index 00000000000..4c02ae69dbf
--- /dev/null
+++ b/pkg/new-ui/v1beta1/frontend/src/app/pages/experiment-details/trials-table/trial-details/trial-logs/trial-logs.component.ts
@@ -0,0 +1,22 @@
+import { Component, Input } from '@angular/core';
+
+@Component({
+ selector: 'app-trial-logs',
+ templateUrl: './trial-logs.component.html',
+ styleUrls: ['./trial-logs.component.scss'],
+})
+export class TrialLogsComponent {
+ public logs: string[];
+
+ @Input() logsRequestError: string;
+
+ @Input()
+ set trialLogs(trialLogs: string) {
+ if (!trialLogs) {
+ return;
+ }
+
+ let arrayOfLogs = trialLogs.split('\n');
+ this.logs = arrayOfLogs;
+ }
+}
diff --git a/pkg/new-ui/v1beta1/frontend/src/app/pages/experiment-details/trials-table/trial-details/trial-logs/trial-logs.module.ts b/pkg/new-ui/v1beta1/frontend/src/app/pages/experiment-details/trials-table/trial-details/trial-logs/trial-logs.module.ts
new file mode 100644
index 00000000000..ac570e04ab2
--- /dev/null
+++ b/pkg/new-ui/v1beta1/frontend/src/app/pages/experiment-details/trials-table/trial-details/trial-logs/trial-logs.module.ts
@@ -0,0 +1,20 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { TrialLogsComponent } from './trial-logs.component';
+import {
+ HeadingSubheadingRowModule,
+ KubeflowModule,
+ LogsViewerModule,
+} from 'kubeflow';
+
+@NgModule({
+ declarations: [TrialLogsComponent],
+ imports: [
+ CommonModule,
+ KubeflowModule,
+ HeadingSubheadingRowModule,
+ LogsViewerModule,
+ ],
+ exports: [TrialLogsComponent],
+})
+export class TrialLogsModule {}
diff --git a/pkg/new-ui/v1beta1/frontend/src/app/services/backend.service.ts b/pkg/new-ui/v1beta1/frontend/src/app/services/backend.service.ts
index 457defc12f2..bd6aab5c352 100644
--- a/pkg/new-ui/v1beta1/frontend/src/app/services/backend.service.ts
+++ b/pkg/new-ui/v1beta1/frontend/src/app/services/backend.service.ts
@@ -102,4 +102,52 @@ export class KWABackendService extends BackendService {
.post(url, { postData: exp })
.pipe(catchError(error => this.parseError(error)));
}
+
+ getTrialLogs(name: string, namespace: string): Observable {
+ const url = `/katib/fetch_trial_logs/?trialName=${name}&namespace=${namespace}`;
+
+ return this.http.get(url).pipe(
+ catchError(error => this.handleError(error, false)),
+ map((resp: any) => {
+ return resp;
+ }),
+ );
+ }
+
+ // ---------------------------Error Handling---------------------------------
+
+ // Override common service's getBackendErrorLog
+ // in order to properly show the message the backend has sent
+ public getBackendErrorLog(error: HttpErrorResponse): string {
+ if (error.error === null) {
+ return error.message;
+ } else {
+ // Show the message the backend has sent
+ return error.error;
+ }
+ }
+
+ // Override common service's getErrorMessage
+ // in order to include the error.status in error message
+ public getErrorMessage(
+ error: HttpErrorResponse | ErrorEvent | string,
+ ): string {
+ if (typeof error === 'string') {
+ return error;
+ }
+
+ if (error instanceof HttpErrorResponse) {
+ if (this.getBackendErrorLog(error) !== undefined) {
+ return `[${error.status}] ${this.getBackendErrorLog(error)}`;
+ }
+
+ return `${error.status}: ${error.message}`;
+ }
+
+ if (error instanceof ErrorEvent) {
+ return error.message;
+ }
+
+ return `Unexpected error encountered`;
+ }
}