<@ULVA73B9P> is there any easy way to config flows...
# ask-marvin
k
@Marvin is there any easy way to config flows to dump some debug info on start? We are working on a python migration and I'd love to get a
python -V
or otherwise in the logs for all flow runs.
m
thought for 117.0 seconds
Yep — the easiest Prefect-native way is an
on_running
flow hook that logs runtime info right when the flow enters Running. Example:
Copy code
python
import sys
import platform
from prefect import flow
from prefect.logging.loggers import flow_run_logger

def log_startup_info(flow, flow_run, state):
    logger = flow_run_logger(flow_run=flow_run, flow=flow)
    <http://logger.info|logger.info>(f"Python: {sys.version}")
    <http://logger.info|logger.info>(f"Platform: {platform.platform()}")
    <http://logger.info|logger.info>(f"Executable: {sys.executable}")

@flow(on_running=[log_startup_info])
def my_flow():
    return "ok"
A shorter version if all you want is the version:
Copy code
python
import sys
from prefect import flow
from prefect.logging.loggers import flow_run_logger

def log_python_version(flow, flow_run, state):
    logger = flow_run_logger(flow_run=flow_run, flow=flow)
    <http://logger.info|logger.info>(f"python -V => {sys.version.split()[0]}")

@flow(on_running=[log_python_version])
def my_flow():
    pass
A few useful notes: - Use
flow_run_logger(...)
inside the hook, not
get_run_logger()
- These logs should show up in the flow run logs in the UI -
on_running
fires before your flow body executes, so it’s a good place for startup diagnostics If you want this on all flows, common patterns are: 1. Add the same hook to each flow 2. Wrap flow creation in a shared helper 3. Use
with_options(on_running=[...])
to apply a hook to an existing flow Example with `with_options`:
Copy code
python
instrumented_flow = my_flow.with_options(on_running=[log_python_version])
If you want, I can also show you a clean pattern to apply this across an entire codebase during your migration. Relevant docs: - Write flows - Logging
k
@Marvin - i'd rather not go update like 100 flows, maybe some kind of change to the docker file, changing the entrypoint to
python -V && $entrypoint
?
m
thought for 131.6 seconds
Yes — if your goal is “all flow runs, no code changes in 100 flows”, doing it at the image / worker infrastructure layer is the better approach. Short answer: your idea is reasonable, but the safest pattern is usually: - put a small wrapper script in the image - make that the image
ENTRYPOINT
- let Prefect continue supplying the run command That way every run logs Python version before the Prefect flow command starts. Example:
Copy code
dockerfile
FROM prefecthq/prefect:3-latest

COPY prefect-entrypoint.sh /opt/prefect-entrypoint.sh
RUN chmod +x /opt/prefect-entrypoint.sh

ENTRYPOINT ["/opt/prefect-entrypoint.sh"]
Copy code
bash
#!/bin/sh
set -e

echo "=== runtime debug ==="
python -V
python -c "import sys; print(sys.executable)"
echo "====================="

exec "$@"
Then Prefect can still launch its normal command, and your wrapper runs first. A few important caveats: 1. Don’t hardcode the full Prefect command unless you have to Prefect workers inject the command they want to run. If you replace that with your own fixed command, you can make upgrades or worker-specific behavior more brittle. So this is better:
Copy code
bash
exec "$@"
than this:
Copy code
bash
python -V && prefect flow-run execute
2. Will it show up in Prefect logs? Usually yes, if the worker is streaming container/process output. That startup
stdout/stderr
should appear at the top of the flow run logs for common worker types like Docker / Kubernetes / process workers. 3. ENTRYPOINT vs CMD If Prefect sets the container command, your image
ENTRYPOINT
still wraps it nicely. That’s why
ENTRYPOINT
is a good place for this. 4. Prefer a script over shell-in-YAML hacks You can wrap commands in a work pool/job template with
sh -c 'python -V && ...'
, but a script in the image is much easier to maintain and debug. If you’re using Kubernetes or Docker workers, this is probably the cleanest global solution. If you want, I can give you the exact pattern for your worker type: - Docker worker - Kubernetes worker - process worker Relevant docs: - Workers - Work pools - Logging