Skip to content

Commit cc0d944

Browse files
committed
Add raw=True
1 parent 753427a commit cc0d944

File tree

2 files changed

+26
-20
lines changed

2 files changed

+26
-20
lines changed

src/apify_client/clients/resource_clients/log.py

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None:
2929
resource_path = kwargs.pop('resource_path', 'logs')
3030
super().__init__(*args, resource_path=resource_path, **kwargs)
3131

32-
def get(self) -> str | None:
32+
def get(self, raw: str = False) -> str | None:
3333
"""Retrieve the log as text.
3434
3535
https://docs.apify.com/api/v2#/reference/logs/log/get-log
@@ -41,7 +41,7 @@ def get(self) -> str | None:
4141
response = self.http_client.call(
4242
url=self.url,
4343
method='GET',
44-
params=self._params(),
44+
params=self._params(raw=raw),
4545
)
4646

4747
return response.text # noqa: TRY300
@@ -51,7 +51,7 @@ def get(self) -> str | None:
5151

5252
return None
5353

54-
def get_as_bytes(self) -> bytes | None:
54+
def get_as_bytes(self, raw: str = False) -> bytes | None:
5555
"""Retrieve the log as raw bytes.
5656
5757
https://docs.apify.com/api/v2#/reference/logs/log/get-log
@@ -63,7 +63,7 @@ def get_as_bytes(self) -> bytes | None:
6363
response = self.http_client.call(
6464
url=self.url,
6565
method='GET',
66-
params=self._params(),
66+
params=self._params(raw=raw),
6767
parse_response=False,
6868
)
6969

@@ -75,7 +75,7 @@ def get_as_bytes(self) -> bytes | None:
7575
return None
7676

7777
@contextmanager
78-
def stream(self) -> Iterator[httpx.Response | None]:
78+
def stream(self, raw: str = False) -> Iterator[httpx.Response | None]:
7979
"""Retrieve the log as a stream.
8080
8181
https://docs.apify.com/api/v2#/reference/logs/log/get-log
@@ -88,7 +88,7 @@ def stream(self) -> Iterator[httpx.Response | None]:
8888
response = self.http_client.call(
8989
url=self.url,
9090
method='GET',
91-
params=self._params(stream=True),
91+
params=self._params(stream=True, raw=raw),
9292
stream=True,
9393
parse_response=False,
9494
)
@@ -110,7 +110,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None:
110110
resource_path = kwargs.pop('resource_path', 'logs')
111111
super().__init__(*args, resource_path=resource_path, **kwargs)
112112

113-
async def get(self) -> str | None:
113+
async def get(self, raw: str = False) -> str | None:
114114
"""Retrieve the log as text.
115115
116116
https://docs.apify.com/api/v2#/reference/logs/log/get-log
@@ -122,7 +122,7 @@ async def get(self) -> str | None:
122122
response = await self.http_client.call(
123123
url=self.url,
124124
method='GET',
125-
params=self._params(),
125+
params=self._params(raw=raw),
126126
)
127127

128128
return response.text # noqa: TRY300
@@ -132,7 +132,7 @@ async def get(self) -> str | None:
132132

133133
return None
134134

135-
async def get_as_bytes(self) -> bytes | None:
135+
async def get_as_bytes(self, raw: str = False) -> bytes | None:
136136
"""Retrieve the log as raw bytes.
137137
138138
https://docs.apify.com/api/v2#/reference/logs/log/get-log
@@ -144,7 +144,7 @@ async def get_as_bytes(self) -> bytes | None:
144144
response = await self.http_client.call(
145145
url=self.url,
146146
method='GET',
147-
params=self._params(),
147+
params=self._params(raw=raw),
148148
parse_response=False,
149149
)
150150

@@ -156,7 +156,7 @@ async def get_as_bytes(self) -> bytes | None:
156156
return None
157157

158158
@asynccontextmanager
159-
async def stream(self) -> AsyncIterator[httpx.Response | None]:
159+
async def stream(self, raw: str = False) -> AsyncIterator[httpx.Response | None]:
160160
"""Retrieve the log as a stream.
161161
162162
https://docs.apify.com/api/v2#/reference/logs/log/get-log
@@ -169,13 +169,13 @@ async def stream(self) -> AsyncIterator[httpx.Response | None]:
169169
response = await self.http_client.call(
170170
url=self.url,
171171
method='GET',
172-
params=self._params(stream=True),
172+
params=self._params(stream=True, raw=raw),
173173
stream=True,
174174
parse_response=False,
175175
)
176176

177177
yield response
178-
except ApifyApiError as exc:
178+
except Exception as exc:
179179
catch_not_found_or_throw(exc)
180180
yield None
181181
finally:
@@ -223,7 +223,7 @@ async def __aexit__(
223223
self._streaming_task = None
224224

225225
async def _stream_log(self, to_logger: logging.Logger) -> None:
226-
async with self._log_client.stream() as log_stream:
226+
async with self._log_client.stream(raw=True) as log_stream:
227227
if not log_stream:
228228
return
229229
async for data in log_stream.aiter_bytes():

tests/unit/test_logging.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@
2424
b'2025-05-13T07:24:14.132Z [apify] INFO multiline \n log',
2525
b'2025-05-13T07:25:14.132Z [apify] WARNING some warning',
2626
b'2025-05-13T07:26:14.132Z [apify] DEBUG c',
27+
b'2025-05-13T0', # Chunked log that got split in the marker, part 1
28+
b'7:26:14.132Z [apify] DEBUG d' # Chunked log that got split in the marker, part 2
29+
b'2025-05-13T07:26:14.132Z [apify] DEB', # Chunked log that got split outside of marker, part 1
30+
b'UG e', # Chunked log that got split outside of marker, part 1
2731
)
2832

2933
_EXPECTED_MESSAGES_AND_LEVELS = (
@@ -33,6 +37,8 @@
3337
('2025-05-13T07:24:14.132Z [apify] INFO multiline \n log', logging.INFO),
3438
('2025-05-13T07:25:14.132Z [apify] WARNING some warning', logging.WARNING),
3539
('2025-05-13T07:26:14.132Z [apify] DEBUG c', logging.DEBUG),
40+
('2025-05-13T07:26:14.132Z [apify] DEBUG d', logging.DEBUG),
41+
('2025-05-13T07:26:14.132Z [apify] DEBUG e', logging.DEBUG),
3642
)
3743

3844

@@ -42,7 +48,7 @@ class AsyncByteStream(httpx._types.AsyncByteStream):
4248
async def __aiter__(self) -> AsyncIterator[bytes]:
4349
for i in _MOCKED_ACTOR_LOGS:
4450
yield i
45-
await asyncio.sleep(0.1)
51+
await asyncio.sleep(0.01)
4652

4753
async def aclose(self) -> None:
4854
pass
@@ -63,7 +69,7 @@ async def aclose(self) -> None:
6369
)
6470

6571
async def actor_runs_side_effect(_: httpx.Request) -> httpx.Response:
66-
await asyncio.sleep(0.5)
72+
await asyncio.sleep(0.1)
6773
return next(actor_runs_responses)
6874

6975
respx.get(url=f'{_MOCKED_API_URL}/v2/actor-runs/{_MOCKED_RUN_ID}').mock(side_effect=actor_runs_side_effect)
@@ -76,7 +82,7 @@ async def actor_runs_side_effect(_: httpx.Request) -> httpx.Response:
7682
return_value=httpx.Response(content=json.dumps({'data': {'id': _MOCKED_RUN_ID}}), status_code=200)
7783
)
7884

79-
respx.get(url=f'{_MOCKED_API_URL}/v2/actor-runs/{_MOCKED_RUN_ID}/log?stream=1').mock(
85+
respx.get(url=f'{_MOCKED_API_URL}/v2/actor-runs/{_MOCKED_RUN_ID}/log?stream=1&raw=1').mock(
8086
return_value=httpx.Response(stream=AsyncByteStream(), status_code=200)
8187
)
8288

@@ -106,7 +112,7 @@ async def test_redirected_logs(
106112
# Do stuff while the log from the other actor is being redirected to the logs.
107113
await asyncio.sleep(1)
108114

109-
assert len(caplog.records) == 6
115+
assert len(caplog.records) == 8
110116
for expected_message_and_level, record in zip(_EXPECTED_MESSAGES_AND_LEVELS, caplog.records):
111117
assert expected_message_and_level[0] == record.message
112118
assert expected_message_and_level[1] == record.levelno
@@ -133,7 +139,7 @@ async def test_actor_call_redirect_logs_to_default_logger(
133139
assert isinstance(logger.handlers[0], logging.StreamHandler)
134140

135141
# Ensure logs are propagated
136-
assert len(caplog.records) == 6
142+
assert len(caplog.records) == 8
137143
for expected_message_and_level, record in zip(_EXPECTED_MESSAGES_AND_LEVELS, caplog.records):
138144
assert expected_message_and_level[0] == record.message
139145
assert expected_message_and_level[1] == record.levelno
@@ -168,7 +174,7 @@ async def test_actor_call_redirect_logs_to_custom_logger(
168174
with caplog.at_level(logging.DEBUG, logger=logger_name):
169175
await run_client.call(logger=logger)
170176

171-
assert len(caplog.records) == 6
177+
assert len(caplog.records) == 8
172178
for expected_message_and_level, record in zip(_EXPECTED_MESSAGES_AND_LEVELS, caplog.records):
173179
assert expected_message_and_level[0] == record.message
174180
assert expected_message_and_level[1] == record.levelno

0 commit comments

Comments
 (0)