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 e8104e5 SUBMARINE-1171. Experiment artifacts ui
e8104e5 is described below
commit e8104e5935a0b15d7ccbb000650f2bfe90525ba0
Author: jeff-901 <[email protected]>
AuthorDate: Sun Jan 2 21:08:57 2022 +0800
SUBMARINE-1171. Experiment artifacts ui
### What is this PR for?
Add experiment artifacts in experiment info page
### What type of PR is it?
Feature
### Todos
### What is the Jira issue?
https://issues.apache.org/jira/browse/SUBMARINE-1171
### How should this be tested?
### Screenshots (if appropriate)

### Questions:
* Do the license files need updating? No
* Are there breaking changes for older versions? No
* Does this need new documentation? No
Author: jeff-901 <[email protected]>
Signed-off-by: Kevin <[email protected]>
Closes #859 from jeff-901/SUBMARINE-1171 and squashes the following commits:
9728a3a1 [jeff-901] add ui
---
.../submarine/server/rest/ExperimentRestApi.java | 21 ++++++++++++
.../experiment-home/experiment-home.component.html | 11 -------
.../experiment-home/experiment-home.component.ts | 20 ------------
.../artifacts/artifacts.component.html | 22 +++++++++++++
.../artifacts/artifacts.component.scss | 26 +++++++++++++++
.../artifacts/artifacts.component.ts | 37 ++++++++++++++++++++++
.../experiment-info/experiment-info.component.html | 9 ++++++
.../experiment-info/experiment-info.component.ts | 16 ++++++++++
.../workbench/experiment/experiment.module.ts | 2 ++
.../src/app/services/experiment.service.ts | 26 +++++++--------
10 files changed, 146 insertions(+), 44 deletions(-)
diff --git
a/submarine-server/server-core/src/main/java/org/apache/submarine/server/rest/ExperimentRestApi.java
b/submarine-server/server-core/src/main/java/org/apache/submarine/server/rest/ExperimentRestApi.java
index 76331a2..c0a3fba 100644
---
a/submarine-server/server-core/src/main/java/org/apache/submarine/server/rest/ExperimentRestApi.java
+++
b/submarine-server/server-core/src/main/java/org/apache/submarine/server/rest/ExperimentRestApi.java
@@ -49,6 +49,7 @@ import
org.apache.submarine.server.api.experiment.ExperimentLog;
import
org.apache.submarine.server.api.experimenttemplate.ExperimentTemplateSubmit;
import org.apache.submarine.server.api.spec.ExperimentSpec;
import org.apache.submarine.server.response.JsonResponse;
+import org.apache.submarine.server.s3.Client;
/**
* Experiment Service REST API v1
@@ -57,6 +58,7 @@ import org.apache.submarine.server.response.JsonResponse;
@Produces({MediaType.APPLICATION_JSON + "; " + RestConstants.CHARSET_UTF8})
public class ExperimentRestApi {
private ExperimentManager experimentManager =
ExperimentManager.getInstance();
+ private Client minioClient = new Client();
@VisibleForTesting
public void setExperimentManager(ExperimentManager experimentManager) {
@@ -263,6 +265,25 @@ public class ExperimentRestApi {
}
@GET
+ @Path("/artifacts/{id}")
+ @Operation(summary = "List artifact paths by id",
+ tags = {"experiment"},
+ responses = {
+ @ApiResponse(description = "successful operation", content =
@Content(
+ schema = @Schema(implementation = JsonResponse.class))),
+ @ApiResponse(responseCode = "404", description = "Experiment not
found")})
+ public Response getArtifactPaths(@PathParam(RestConstants.ID) String id) {
+ try {
+ List<String> artifactPaths = minioClient.listArtifactByExperimentId(id);
+ return new
JsonResponse.Builder<List<String>>(Response.Status.OK).success(true)
+ .result(artifactPaths).build();
+
+ } catch (SubmarineRuntimeException e) {
+ return parseExperimentServiceException(e);
+ }
+ }
+
+ @GET
@Path("/tensorboard")
@Operation(summary = "Get tensorboard's information",
tags = {"experiment"},
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 9edbce6..3fa8ffb 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
@@ -34,17 +34,6 @@
target="_blank"
nzType="primary"
style="margin: 0px 4px 0px 4px"
- [nzLoading]="isMlflowLoading"
- [href]="mlflowUrl"
- >
- <i nz-icon nzType="radar-chart"></i>
- MLflow UI
- </a>
- <a
- nz-button
- target="_blank"
- nzType="primary"
- style="margin: 0px 4px 0px 4px"
[nzLoading]="isTensorboardLoading"
[href]="tensorboardUrl"
>
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 ce4ec24..e0a0de2 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
@@ -72,7 +72,6 @@ export class ExperimentHomeComponent implements OnInit {
this.experimentService.emitInfo(null);
this.getTensorboardInfo(1000, 50000);
- this.getMlflowInfo(1000, 100000);
this.onSwitchAutoReload();
}
@@ -173,23 +172,4 @@ export class ExperimentHomeComponent implements OnInit {
(err) => console.log(err)
);
}
-
- getMlflowInfo(period: number, due: number) {
- interval(period)
- .pipe(
- mergeMap(() => this.experimentService.getMlflowInfo()),
- retryWhen((error) => error),
- tap((x) => console.log(x)),
- filter((res) => res.available),
- take(1),
- timeout(due)
- )
- .subscribe(
- (res) => {
- this.isMlflowLoading = !res.available;
- this.mlflowUrl = res.url;
- },
- (err) => console.log(err)
- );
- }
}
diff --git
a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-info/artifacts/artifacts.component.html
b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-info/artifacts/artifacts.component.html
new file mode 100644
index 0000000..a083fe3
--- /dev/null
+++
b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-info/artifacts/artifacts.component.html
@@ -0,0 +1,22 @@
+<!--
+ ~ 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.
+ -->
+
+<div id="showArtifactDiv">
+ <p style="white-space: nowrap;" *ngFor="let artifactPath of
artifactPaths;">{{ artifactPath }}</p>
+</div>
diff --git
a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-info/artifacts/artifacts.component.scss
b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-info/artifacts/artifacts.component.scss
new file mode 100644
index 0000000..7cee94d
--- /dev/null
+++
b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-info/artifacts/artifacts.component.scss
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+#showArtifactDiv {
+ background-color: whitesmoke;
+ color: black;
+ padding: 10px;
+ height: 90vh;
+ overflow: auto;
+}
diff --git
a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-info/artifacts/artifacts.component.ts
b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-info/artifacts/artifacts.component.ts
new file mode 100644
index 0000000..12e579b
--- /dev/null
+++
b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-info/artifacts/artifacts.component.ts
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+import { Component, Input, OnInit, SimpleChanges } from '@angular/core';
+
+@Component({
+ selector: 'submarine-artifacts',
+ templateUrl: './artifacts.component.html',
+ styleUrls: ['./artifacts.component.scss']
+})
+export class ArtifactsComponent implements OnInit {
+ @Input() artifactPaths;
+ @Input() experimentID;
+
+ constructor() {}
+
+ ngOnInit() {}
+
+ ngOnChanges(chg: SimpleChanges) {
+ }
+}
diff --git
a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-info/experiment-info.component.html
b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-info/experiment-info.component.html
index 147c833..e91679a 100644
---
a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-info/experiment-info.component.html
+++
b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-info/experiment-info.component.html
@@ -102,6 +102,10 @@
<i nz-icon nzType="desktop" nzTheme="outline"></i>
Outputs
</li>
+ <li nz-menu-item (click)="currentState = 4">
+ <i nz-icon nzType="experiment" nzTheme="outline"></i>
+ Artifacts
+ </li>
</ul>
</nz-sider>
<nz-layout>
@@ -119,6 +123,11 @@
[experimentID]="experimentID"
[podLogArr]="podLogArr"
></submarine-outputs>
+ <submarine-artifacts
+ *ngSwitchCase="4"
+ [artifactPaths]="artifactPaths"
+ [experimentID]="experimentID"
+ ></submarine-artifacts>
</div>
</nz-layout>
</nz-layout>
diff --git
a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-info/experiment-info.component.ts
b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-info/experiment-info.component.ts
index 8e1bf8f..d4b2d73 100644
---
a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-info/experiment-info.component.ts
+++
b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment-info/experiment-info.component.ts
@@ -38,6 +38,7 @@ export class ExperimentInfoComponent implements OnInit {
podLogArr;
paramData;
metricData;
+ artifactPaths;
constructor(
private router: Router,
@@ -78,6 +79,7 @@ export class ExperimentInfoComponent implements OnInit {
);
this.getExperimentPod();
+ this.getExperimentArtifactPaths();
this.experimentService.emitInfo(this.experimentID);
}
@@ -123,6 +125,20 @@ export class ExperimentInfoComponent implements OnInit {
);
}
+ getExperimentArtifactPaths() {
+ this.experimentService
+ .getExperimentArtifactPaths(this.experimentID)
+ .subscribe(
+ (result) => {
+ this.artifactPaths = result;
+ },
+ (err) => {
+ this.nzMessageService.error('Cannot load artifact paths of ' +
this.experimentID);
+ console.log(err);
+ }
+ );
+ }
+
onDeleteExperiment() {
this.experimentService.deleteExperiment(this.experimentID).subscribe(
() => {
diff --git
a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment.module.ts
b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment.module.ts
index d6bd0da..2f3ff4e 100644
---
a/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment.module.ts
+++
b/submarine-workbench/workbench-web/src/app/pages/workbench/experiment/experiment.module.ts
@@ -32,6 +32,7 @@ import { HyperParamsComponent } from
'./experiment-info/hyper-params/hyper-param
import { MetricsComponent } from './experiment-info/metrics/metrics.component';
import { ChartsComponent } from './experiment-info/charts/charts.component';
import { OutputsComponent } from './experiment-info/outputs/outputs.component';
+import { ArtifactsComponent } from
'./experiment-info/artifacts/artifacts.component';
import { ExperimentHomeComponent } from
'./experiment-home/experiment-home.component';
import { ExperimentService } from '@submarine/services/experiment.service';
import { ExperimentFormComponent } from
'./experiment-home/experiment-form/experiment-form.component';
@@ -59,6 +60,7 @@ import { ExperimentCustomizedFormComponent } from
'./experiment-home/experiment-
MetricsComponent,
ChartsComponent,
OutputsComponent,
+ ArtifactsComponent,
ExperimentHomeComponent,
ExperimentFormComponent,
ExperimentPredefinedFormComponent,
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 5916052..56969b9 100644
--- a/submarine-workbench/workbench-web/src/app/services/experiment.service.ts
+++ b/submarine-workbench/workbench-web/src/app/services/experiment.service.ts
@@ -173,6 +173,19 @@ export class ExperimentService {
);
}
+ getExperimentArtifactPaths(id: string): Observable<any> {
+ const apiUrl = this.baseApi.getRestApi('/v1/experiment/artifacts/' + id);
+ return this.httpClient.get<Rest<any>>(apiUrl).pipe(
+ switchMap((res) => {
+ if (res.success) {
+ return of(res.result);
+ } else {
+ throw this.baseApi.createRequestError(res.message, res.code, apiUrl,
'get', id);
+ }
+ })
+ );
+ }
+
fetchExperimentTemplateList(): Observable<ExperimentTemplate[]> {
const apiUrl = this.baseApi.getRestApi('/v1/template');
return this.httpClient.get<Rest<ExperimentTemplate[]>>(apiUrl).pipe(
@@ -265,19 +278,6 @@ export class ExperimentService {
);
}
- getMlflowInfo(): Observable<MlflowInfo> {
- const apiUrl = this.baseApi.getRestApi('/v1/experiment/mlflow');
- return this.httpClient.get<Rest<MlflowInfo>>(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: [email protected]
For additional commands, e-mail: [email protected]