New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
SUBMARINE-442. Support get job's log in submarine-server REST API #263
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a lot for the contribution! @JohnTing Please see my comments below:
getJobLabelSelector(job), null, null, | ||
null, null); | ||
|
||
final V1Pod pod = podList.getItems().get(0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be several containers in the "podList", here it only gets the first one. Is it better that we merge all container's pod with a format? Like this:
{
jobId: job_123,
jobType: tensorflow,
LogContent: [
{podName: tf-ps-0,
podLog: 123123123},
{podName: tf-worker-0,
podLog: 456456456},
...
]
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I will modify it
"false", null, null, | ||
getJobLabelSelector(job), null, null, | ||
null, null); | ||
final V1Pod pod = podList.getItems().get(0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, is it possible that we merge different streams into one? And update the aggregated log stream?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure how to show the mixed stream in the browser ...
Maybe something like this?
[
{"pod1": "log start"},
{"pod1": "1%"},
{"pod2": "log start"},
{"pod1": "2%"},
{"pod2": "1%"},
....
String jobId = "job_1586957273819_0001"; | ||
GetMethod response = httpGet("/api/" + RestConstants.V1 + "/" | ||
+ RestConstants.LOGS + "/" + jobId); | ||
LOG.info(response.toString()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we have some assertions in this test case? Usually, if it could run some job and get the job log would be easy. If we cannot do any assertion here. I suggest we remove this end-to-end unit test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I will add it
// K8s API client for CRD | ||
private CustomObjectsApi api; | ||
|
||
ApiClient client; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ApiClient client; | |
private ApiClient client; |
null, | ||
Boolean.FALSE, | ||
Integer.MAX_VALUE, | ||
40, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should use a constant variable instead of hardcode 40
.
return inputStream; | ||
|
||
} catch (final ApiException e) { | ||
LOG.warn("Error when listing pod for job:" + job.toString(), e.getMessage()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LOG.warn("Error when listing pod for job:" + job.toString(), e.getMessage()); | |
LOG.error("Error when listing pod for job:" + job.toString(), e.getMessage()); |
} catch (final ApiException e) { | ||
LOG.warn("Error when listing pod for job:" + job.toString(), e.getMessage()); | ||
} catch (final IOException e) { | ||
LOG.warn("Error when get pod log stream", e.getMessage()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LOG.warn("Error when get pod log stream", e.getMessage()); | |
LOG.error("Error when get pod log stream", e.getMessage()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @JohnTing for the contribution.
- Considering the new REST is related to job, so we'd better rebase it on
/api/v1/jobs/{id}/logs
. If it accepted theJobLogsRestApi
's content should move intoJobManagerRestApi
. - In the REST controller layer, we'd better use the
JobManager
rather than usesubmitter
directly. - ApiClient would not need to make it to class member, because the
CoreV1Api
's non argument constructor can set the client fromConfiguration
which had set in the client instance stage. - Should add the integration test in
submarine-test/test-k8s
and the unit test should better removed if the UT can't mock the process. - The
JobLogHandler
can be deleted, because it owned to thesubmitter
.
If I understand wrong, please correct me. Thanks again for your contribution!
|
||
package org.apache.submarine.server.api.job; | ||
|
||
// import java.io.InputStream; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need to remove unused import
@tangzhankun, @jiwq, @pingsutw |
Trigger the travis ci again. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@JohnTing Thank you contribution this feature, very cool!
|
||
@GET | ||
@Path("/logs") | ||
public Response listlog(@QueryParam("status") String status) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The hump command method should be used.
Need change to listLog(...
|
||
@GET | ||
@Path("/logs/{id}") | ||
public Response getlog(@PathParam(RestConstants.JOB_ID) String id) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The hump command method should be used.
Need change to getLog(...
// K8s API client for CRD | ||
private CustomObjectsApi api; | ||
|
||
private CoreV1Api COREV1_API; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The hump command method should be used.
Need change to coreApi
@JohnTing You need to add test cases to ensure the correctness of your code. It can also ensure that the code you submit will not be modified by others. |
@JohnTing This branch has conflicts, please rebase this commits. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@JohnTing Thank you contribution this feature.
Will merge if no more comments.
What is this PR for?
Now we have the "jobs" resource in REST which can do CRUD. We also need a "logs" API to get the job's log output. The URI could be "api/v1/logs"
It should accept parameters like "jobid". Initially, the logs could be aggregated logs of all containers.
Streaming is preferred so that the python client can enable a fancy way for the end-user to check logs
What type of PR is it?
Feature
Todos
What is the Jira issue?
https://issues.apache.org/jira/projects/SUBMARINE/issues/SUBMARINE-442
How should this be tested?
Create a job
Visit /api/v1/logs or /api/v1/logs/{jobid} with a browser
Screenshots (if appropriate)
http://127.0.0.1:8080/api/v1/jobs/logs
http://127.0.0.1:8080/api/v1/jobs/logs/job_1587481945001_0001
Questions: