You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@submarine.apache.org by pi...@apache.org on 2021/01/19 05:47:31 UTC
[submarine] branch master updated: SUBMARINE-710. Frontend support
for tensorboard
This is an automated email from the ASF dual-hosted git repository.
pingsutw pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/submarine.git
The following commit(s) were added to refs/heads/master by this push:
new a2c1e59 SUBMARINE-710. Frontend support for tensorboard
a2c1e59 is described below
commit a2c1e59d0efb498e42dceaf1264b9ebb93caf76d
Author: Byron <by...@gmail.com>
AuthorDate: Sat Jan 16 23:16:34 2021 +0800
SUBMARINE-710. Frontend support for tensorboard
### What is this PR for?
I created a "tensorboard" button on the experiment page in the workbench.
It will show as loading when
1. the api-client is still fetching the tensorboard meta-data
2. tensorboard pod is not ready
After the fetching succeeds, users can click the button and link to the tensorboard page.
### What type of PR is it?
[Feature]
### Todos
* [ ] - Task
### What is the Jira issue?
https://issues.apache.org/jira/projects/SUBMARINE/issues/SUBMARINE-710
### How should this be tested?
### Screenshots (if appropriate)
![Kapture 2021-01-14 at 20 52 31](https://user-images.githubusercontent.com/24364830/104594689-7a3b4380-56ac-11eb-869d-adf2f102f114.gif)
### Questions:
* Does the licenses files need update? No
* Is there breaking changes for older versions? No
* Does this needs documentation? No
Author: Byron <by...@gmail.com>
Closes #492 from ByronHsu/SUBMARINE-710 and squashes the following commits:
ccaeeb7 [Byron] fix upper case
b52a476 [Byron] revert proxy.conf.js
48c3a86 [Byron] add delete icon
69003d9 [Byron] tensorboard frontend support
---
.../src/app/interfaces/tensorboard-info.ts | 23 ++++++++++++++
.../experiment-home/experiment-home.component.html | 23 +++++++++-----
.../experiment-home/experiment-home.component.ts | 35 ++++++++++++++++++++--
.../src/app/services/experiment.service.ts | 14 +++++++++
4 files changed, 86 insertions(+), 9 deletions(-)
diff --git a/submarine-workbench/workbench-web/src/app/interfaces/tensorboard-info.ts b/submarine-workbench/workbench-web/src/app/interfaces/tensorboard-info.ts
new file mode 100644
index 0000000..12f153a
--- /dev/null
+++ b/submarine-workbench/workbench-web/src/app/interfaces/tensorboard-info.ts
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+export interface TensorboardInfo {
+ available: boolean;
+ url: string;
+}
diff --git a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-home.component.html b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-home.component.html
index 309279a..ff8a468 100644
--- a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-home.component.html
+++ b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-home.component.html
@@ -24,11 +24,18 @@
<label nz-radio-button nzValue="Own">Owned By Me</label>
<label nz-radio-button nzValue="Access">Accessible By Me</label>
</nz-radio-group>
- <nz-input-group
- nzSearch
- style="width: 300px; margin-top: 15px; margin-left: 10px; margin-right: 5px"
- [nzAddOnAfter]="suffixIconButton"
+ <a
+ nz-button
+ nzType="primary"
+ style="margin: 0px 4px 0px 4px"
+ [nzLoading]="isTensorboardLoading"
+ [href]="tensorboardUrl"
>
+ <i nz-icon nzType="area-chart"></i>
+ TensorBoard
+ </a>
+ <br />
+ <nz-input-group nzSearch style="width: 300px; margin: 10px 4px 10px 4px" [nzAddOnAfter]="suffixIconButton">
<input type="text" nz-input placeholder="input search text" />
</nz-input-group>
<ng-template #suffixIconButton>
@@ -39,29 +46,31 @@
nz-button
id="openExperiment"
nzType="primary"
- style="margin-right: 5px; margin-bottom: 15px; margin-top: 15px"
+ style="margin: 10px 4px 10px 4px"
(click)="form.initModal('create')"
>
<i nz-icon nzType="plus"></i>
New Experiment
</button>
+
<button
nz-button
nzType="primary"
- style="margin-bottom: 15px; margin-top: 15px"
+ style="margin: 10px 4px 10px 4px"
nz-popconfirm
nzTitle="Confirm to delete?"
nzCancelText="Cancel"
nzOkText="Ok"
(nzOnConfirm)="deleteExperiments()"
>
+ <i nz-icon nzType="delete"></i>
Delete
</button>
</div>
<submarine-experiment-list
[experimentList]="experimentList"
[checkedList]="checkedList"
- [isLoading]="isLoading"
+ [isLoading]="isListLoading"
(deleteExperiment)="onDeleteExperiment($event, true)"
(initModal)="onInitModal($event)"
[(selectAllChecked)]="selectAllChecked"
diff --git a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-home.component.ts b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-home.component.ts
index 7c656d6..919c5e8 100644
--- a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-home.component.ts
+++ b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-home/experiment-home.component.ts
@@ -22,6 +22,8 @@ import { ExperimentInfo } from '@submarine/interfaces/experiment-info';
import { ExperimentFormService } from '@submarine/services/experiment.form.service';
import { ExperimentService } from '@submarine/services/experiment.service';
import { NzMessageService } from 'ng-zorro-antd';
+import { interval } from 'rxjs';
+import { filter, mergeMap, take, tap, timeout } from 'rxjs/operators';
import { ExperimentFormComponent } from './experiment-form/experiment-form.component';
@Component({
@@ -37,10 +39,14 @@ export class ExperimentHomeComponent implements OnInit {
the modification will be sync to parent.
*/
experimentList: ExperimentInfo[];
- isLoading: boolean = true;
+ isListLoading: boolean = true;
checkedList: boolean[];
selectAllChecked: boolean = false;
+ // tensorboard
+ isTensorboardLoading: boolean = true;
+ tensorboardUrl: string = '';
+
@ViewChild('form', { static: true }) form: ExperimentFormComponent;
constructor(
@@ -55,12 +61,13 @@ export class ExperimentHomeComponent implements OnInit {
});
this.experimentService.emitInfo(null);
+ this.getTensorboardInfo(1000, 50000);
}
fetchExperimentList() {
this.experimentService.fetchExperimentList().subscribe(
(list) => {
- this.isLoading = false;
+ this.isListLoading = false;
this.experimentList = list;
const currentTime = new Date();
this.experimentList.forEach((item) => {
@@ -114,4 +121,28 @@ export class ExperimentHomeComponent implements OnInit {
onInitModal(obj) {
this.form.initModal(obj.initMode, obj.initFormType, obj.id, obj.spec);
}
+
+ getTensorboardInfo(period: number, due: number) {
+ /*
+ It will keep polling every ${period} msec, and stop polling whenever
+ 1. The tensorboard status turns from unavailble to available
+ 2. It takes over ${due} msec
+ */
+
+ interval(period)
+ .pipe(
+ mergeMap(() => this.experimentService.getTensorboardInfo()), // map interval observable to tensorboardInfo observable
+ tap((x) => console.log(x)), // monitoring the process
+ filter((res) => res.available), // only emit the success ones
+ take(1), // if succeed, stop emitting new value from source observable
+ timeout(due) // if timeout, it will throw an error
+ )
+ .subscribe(
+ (res) => {
+ this.isTensorboardLoading = !res.available;
+ this.tensorboardUrl = res.url;
+ },
+ (err) => console.log(err)
+ );
+ }
}
diff --git a/submarine-workbench/workbench-web/src/app/services/experiment.service.ts b/submarine-workbench/workbench-web/src/app/services/experiment.service.ts
index 8672ebd..891b150 100644
--- a/submarine-workbench/workbench-web/src/app/services/experiment.service.ts
+++ b/submarine-workbench/workbench-web/src/app/services/experiment.service.ts
@@ -24,6 +24,7 @@ import { ExperimentInfo } from '@submarine/interfaces/experiment-info';
import { ExperimentSpec } from '@submarine/interfaces/experiment-spec';
import { ExperimentTemplate } from '@submarine/interfaces/experiment-template';
import { ExperimentTemplateSubmit } from '@submarine/interfaces/experiment-template-submit';
+import { TensorboardInfo } from '@submarine/interfaces/tensorboard-info';
import { BaseApiService } from '@submarine/services/base-api.service';
import { of, throwError, Observable, Subject } from 'rxjs';
import { catchError, map, switchMap } from 'rxjs/operators';
@@ -211,6 +212,19 @@ export class ExperimentService {
);
}
+ getTensorboardInfo(): Observable<TensorboardInfo> {
+ const apiUrl = this.baseApi.getRestApi('/v1/experiment/tensorboard');
+ return this.httpClient.get<Rest<TensorboardInfo>>(apiUrl).pipe(
+ switchMap((res) => {
+ if (res.success) {
+ return of(res.result);
+ } else {
+ throw this.baseApi.createRequestError(res.message, res.code, apiUrl, 'get');
+ }
+ })
+ );
+ }
+
durationHandle(secs: number) {
const hr = Math.floor(secs / 3600);
const min = Math.floor((secs - hr * 3600) / 60);
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@submarine.apache.org
For additional commands, e-mail: dev-help@submarine.apache.org