Skip to content

Commit

Permalink
issue #505 option to disable error logs in batch jobs
Browse files Browse the repository at this point in the history
  • Loading branch information
ElienVandermaesenVITO authored and soxofaan committed Jan 7, 2025
1 parent fed61cc commit cf9e4ec
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 11 deletions.
5 changes: 4 additions & 1 deletion openeo/rest/datacube.py
Original file line number Diff line number Diff line change
Expand Up @@ -2477,6 +2477,7 @@ def execute_batch(
job_options: Optional[dict] = None,
validate: Optional[bool] = None,
auto_add_save_result: bool = True,
log_error=True,
# TODO: deprecate `format_options` as keyword arguments
**format_options,
) -> BatchJob:
Expand All @@ -2494,6 +2495,7 @@ def execute_batch(
:param validate: Optional toggle to enable/prevent validation of the process graphs before execution
(overruling the connection's ``auto_validate`` setting).
:param auto_add_save_result: Automatically add a ``save_result`` node to the process graph if there is none yet.
:param log_error: whether to print error logs
.. versionchanged:: 0.32.0
Added ``auto_add_save_result`` option
Expand Down Expand Up @@ -2529,7 +2531,8 @@ def execute_batch(
)
return job.run_synchronous(
outputfile=outputfile,
print=print, max_poll_interval=max_poll_interval, connection_retry_interval=connection_retry_interval
print=print, max_poll_interval=max_poll_interval, connection_retry_interval=connection_retry_interval,
log_error=log_error
)

def create_job(
Expand Down
32 changes: 22 additions & 10 deletions openeo/rest/job.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,19 +236,30 @@ def logs(

def run_synchronous(
self, outputfile: Union[str, Path, None] = None,
print=print, max_poll_interval=60, connection_retry_interval=30
print=print, max_poll_interval=60, connection_retry_interval=30, log_error=True
) -> BatchJob:
"""Start the job, wait for it to finish and download result"""
"""
Start the job, wait for it to finish and download result
:param outputfile: The path of a file to which a result can be written
:param print: print/logging function to show progress/status
:param max_poll_interval: maximum number of seconds to sleep between status polls
:param connection_retry_interval: how long to wait when status poll failed due to connection issue
:param log_error: whether to print error logs
:return:
"""
self.start_and_wait(
print=print, max_poll_interval=max_poll_interval, connection_retry_interval=connection_retry_interval
print=print, max_poll_interval=max_poll_interval, connection_retry_interval=connection_retry_interval,
log_error=log_error
)
# TODO #135 support multi file result sets too?
if outputfile is not None:
self.download_result(outputfile)
return self

def start_and_wait(
self, print=print, max_poll_interval: int = 60, connection_retry_interval: int = 30, soft_error_max=10
self, print=print, max_poll_interval: int = 60, connection_retry_interval: int = 30, soft_error_max=10,
log_error=True
) -> BatchJob:
"""
Start the batch job, poll its status and wait till it finishes (or fails)
Expand All @@ -257,6 +268,7 @@ def start_and_wait(
:param max_poll_interval: maximum number of seconds to sleep between status polls
:param connection_retry_interval: how long to wait when status poll failed due to connection issue
:param soft_error_max: maximum number of soft errors (e.g. temporary connection glitches) to allow
:param log_error: whether to print error logs
:return:
"""
# TODO rename `connection_retry_interval` to something more generic?
Expand Down Expand Up @@ -314,13 +326,13 @@ def soft_error(message: str):
poll_interval = min(1.25 * poll_interval, max_poll_interval)

if status != "finished":
# TODO: allow to disable this printing logs (e.g. in non-interactive contexts)?
# TODO: render logs jupyter-aware in a notebook context?
print(f"Your batch job {self.job_id!r} failed. Error logs:")
print(self.logs(level=logging.ERROR))
print(
f"Full logs can be inspected in an openEO (web) editor or with `connection.job({self.job_id!r}).logs()`."
)
if log_error:
print(f"Your batch job {self.job_id!r} failed. Error logs:")
print(self.logs(level=logging.ERROR))
print(
f"Full logs can be inspected in an openEO (web) editor or with `connection.job({self.job_id!r}).logs()`."
)
raise JobFailedException(
f"Batch job {self.job_id!r} didn't finish successfully. Status: {status} (after {elapsed()}).",
job=self,
Expand Down
51 changes: 51 additions & 0 deletions tests/rest/test_job.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,57 @@ def test_execute_batch_with_error(con100, requests_mock, tmpdir):
"Full logs can be inspected in an openEO (web) editor or with `connection.job('f00ba5').logs()`.",
]

def test_execute_batch_with_error_with_error_logs_disabled(con100, requests_mock, tmpdir):
requests_mock.get(API_URL + "/file_formats", json={"output": {"GTiff": {"gis_data_types": ["raster"]}}})
requests_mock.get(API_URL + "/collections/SENTINEL2", json={"foo": "bar"})
requests_mock.post(API_URL + "/jobs", status_code=201, headers={"OpenEO-Identifier": "f00ba5"})
requests_mock.post(API_URL + "/jobs/f00ba5/results", status_code=202)
requests_mock.get(
API_URL + "/jobs/f00ba5",
[
{"json": {"status": "submitted"}},
{"json": {"status": "queued"}},
{"json": {"status": "running", "progress": 15}},
{"json": {"status": "running", "progress": 80}},
{"json": {"status": "error", "progress": 100}},
],
)
requests_mock.get(
API_URL + "/jobs/f00ba5/logs",
json={
"logs": [
{"id": "12", "level": "info", "message": "starting"},
{"id": "34", "level": "error", "message": "nope"},
]
},
)

path = tmpdir.join("tmp.tiff")
log = []

try:
with fake_time():
con100.load_collection("SENTINEL2").execute_batch(
outputfile=path, out_format="GTIFF",
max_poll_interval=.1, print=log.append, log_error=False
)
pytest.fail("execute_batch should fail")
except JobFailedException as e:
assert e.job.status() == "error"
assert [(l.level, l.message) for l in e.job.logs()] == [
("info", "starting"),
("error", "nope"),
]

assert log == [
"0:00:01 Job 'f00ba5': send 'start'",
"0:00:02 Job 'f00ba5': submitted (progress N/A)",
"0:00:04 Job 'f00ba5': queued (progress N/A)",
"0:00:07 Job 'f00ba5': running (progress 15%)",
"0:00:12 Job 'f00ba5': running (progress 80%)",
"0:00:20 Job 'f00ba5': error (progress 100%)",
]


@pytest.mark.parametrize(["error_response", "expected"], [
(
Expand Down

0 comments on commit cf9e4ec

Please sign in to comment.