Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions docs/03_concepts/10_logging.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import CodeBlock from '@theme/CodeBlock';

import LogConfigExample from '!!raw-loader!./code/10_log_config.py';
import LoggerUsageExample from '!!raw-loader!./code/10_logger_usage.py';
import RedirectLog from '!!raw-loader!./code/10_redirect_log.py';
import RedirectLogExistingRun from '!!raw-loader!./code/10_redirect_log_existing_run.py';


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`.

Expand Down Expand Up @@ -82,3 +85,28 @@ Result:
</pre>

<!-- markdownlint-enable no-inline-html -->

## Redirect logs from other actor runs
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' runs in the parent Actor's logs. This guide will show possibilities on how to do it.

### Redirecting logs from `Actor.call`
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 the `default` literal. This means that the logs of the called Actor will be automatically redirected to the parent Actor's logs with default formatting and filtering. If you set the `logger` argument to `None`, then no log redirection happens. The third option is to pass your own `Logger` instance with the possibility to define your own formatter, filter, and handler. Below you can see those three possible ways of log redirection when starting another Actor run through [`Actor.call`](../../reference/class/Actor#call).

<CodeBlock className="language-python">
{RedirectLog}
</CodeBlock>

Each default redirect logger log entry will have a specific format. After the 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.

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 the following example screenshot of the Apify log console when one actor recursively starts itself (there are 2 levels of recursion in the example).

![Console with redirected logs](/img/guides/redirected_logs_example.webp 'Example of console with redirected logs from recursively started actor.')

### Redirecting logs from already running Actor run
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](../../reference/class/Actor#apify_client) and getting the streamed log from a specific Actor run. You can then use it as a context manager, and the log redirection will be active in the context, or you can control the log redirection manually by explicitly calling `start` and `stop` methods.

You can further decide whether you want to redirect just new logs of the ongoing Actor run, or if you also want to redirect historical logs from that Actor's run, so all logs it has produced since it was started. Both options are shown in the example code below.

<CodeBlock className="language-python">
{RedirectLogExistingRun}
</CodeBlock>
15 changes: 15 additions & 0 deletions docs/03_concepts/code/10_redirect_log.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import logging

from apify import Actor


async def main() -> None:
async with Actor:
# Default redirect logger
await Actor.call(actor_id='some_actor_id')
# No redirect logger
await Actor.call(actor_id='some_actor_id', logger=None)
# Custom redirect logger
await Actor.call(
actor_id='some_actor_id', logger=logging.getLogger('custom_logger')
)
24 changes: 24 additions & 0 deletions docs/03_concepts/code/10_redirect_log_existing_run.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import asyncio

from apify import Actor


async def main() -> None:
async with Actor:
# Lifecycle of redirected logs is handled by the context manager.
async with await Actor.apify_client.run('some_actor_id').get_streamed_log(
# Redirect all logs from the start of that run, even the logs from past.
from_start=True
):
await asyncio.sleep(5)
# Logging will stop out of context

# Lifecycle of redirected logs can be handled manually.
streamed_log = await Actor.apify_client.run('some_id').get_streamed_log(
# Do not redirect historical logs from this actor run.
# Redirect only new logs from now on.
from_start=False
)
streamed_log.start()
await asyncio.sleep(5)
await streamed_log.stop()
2 changes: 1 addition & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.