Skip to content

Commit 8de1773

Browse files
committed
Add log redirection guide
1 parent 141301d commit 8de1773

File tree

5 files changed

+58
-1
lines changed

5 files changed

+58
-1
lines changed

docs/03_concepts/10_logging.mdx

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ import CodeBlock from '@theme/CodeBlock';
77

88
import LogConfigExample from '!!raw-loader!./code/10_log_config.py';
99
import LoggerUsageExample from '!!raw-loader!./code/10_logger_usage.py';
10+
import RedirectLog from '!!raw-loader!./code/10_redirect_log.py';
11+
import RedirectLogExistingRun from '!!raw-loader!./code/10_redirect_log_existing_run.py';
12+
1013

1114
The Apify SDK is logging useful information through the [`logging`](https://docs.python.org/3/library/logging.html) module from Python's standard library, into the logger with the name `apify`.
1215

@@ -82,3 +85,25 @@ Result:
8285
</pre>
8386

8487
<!-- markdownlint-enable no-inline-html -->
88+
89+
## Redirect logs from other actor runs
90+
In some situations one Actor is going to start one or more other Actors and wait for them to finish and produce some results. In such cases, you might want to redirect the logs and status messages of the started Actors runs back to the parent Actor run, so that you can see the progress of the started Actors in the parent Actor's logs. This guide will show options how to do it.
91+
92+
### Redirecting logs from `Actor.call`
93+
Typical use case for log redirection is to call another Actor using the [`Actor.call`](../../reference/class/Actor#call) method. This method has an optional `logger` argument, which is by default set to `default` literal. This means that the logs of the called Actor will be automatically redirected to the parent Actor's logs with default formating and filtering. If you set `logger` argument to `None`, then no log redirection happens. Third option is to pass your own `Logger` instance with the possibility to define own formater, filter and handler.
94+
95+
<CodeBlock className="language-python">
96+
{RedirectLog}
97+
</CodeBlock>
98+
99+
Each default redirect logger log entry will have specific format. After timestamp, it will contain cyan colored text that will contain the redirect information - the other actor's name and the run ID. The rest of the log message will be printed in the same manner as the parent Actor's logger is configured.
100+
101+
The log redirection can be deep, meaning that if the other actor also starts another actor and is redirecting logs from it, then in the top level actor you can see it as well. See following example screenshot of Apify console when one actor recursively starts itself (there are 2 levels of recursion in the example).
102+
103+
![Console with redirected logs](/img/guides/redirected_logs_example.png 'Example of console with redirected logs from recursively started actor.')
104+
105+
### Redirecting logs from already running Actor run
106+
In some cases you might want to connect to an already running Actor run and redirect its logs to your current Actor run. This can be done using the `ApifyClient` from `apify-client-python` directly.
107+
<CodeBlock className="language-python">
108+
{RedirectLogExistingRun}
109+
</CodeBlock>
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import logging
2+
3+
from apify import Actor
4+
5+
6+
async def main() -> None:
7+
async with Actor:
8+
# Default redirect logger
9+
await Actor.call(actor_id='some_actor_id')
10+
# No redirect logger
11+
await Actor.call(actor_id='some_actor_id', logger=None)
12+
# Custom redirect logger
13+
await Actor.call(
14+
actor_id='some_actor_id', logger=logging.getLogger('custom_logger')
15+
)
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import asyncio
2+
3+
from apify import Actor
4+
5+
6+
async def main() -> None:
7+
async with Actor:
8+
# With context manager
9+
async with await Actor.new_client().run('some_actor_id').get_streamed_log():
10+
await asyncio.sleep(5)
11+
# Logging will stop out of context
12+
13+
# With direct call (lifecycle of logging has to be manually handled)
14+
streamed_log = await Actor.new_client().run('some_id').get_streamed_log()
15+
streamed_log.start()
16+
await asyncio.sleep(5)
17+
await streamed_log.stop()

uv.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
422 KB
Loading

0 commit comments

Comments
 (0)