Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
25 changes: 20 additions & 5 deletions taskiq/cli/worker/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,25 @@ def get_receiver_type(args: WorkerArgs) -> type[Receiver]:
return receiver_type


def configure_child_logging(args: WorkerArgs) -> None:
Comment thread
danfimov marked this conversation as resolved.
Outdated
"""
Configure logging in a worker process.

A process started with the ``fork`` start method inherits
the logging configuration of the main process.
Processes started with ``spawn`` or ``forkserver``
(the default on Linux since Python 3.14) begin with
a fresh interpreter, so logging has to be configured again.

:param args: CLI arguments.
"""
if args.configure_logging and get_start_method() != "fork":
logging.basicConfig(
level=args.log_level,
format=args.log_format,
)


def start_listen(args: WorkerArgs) -> None:
"""
This function starts actual listening process.
Expand All @@ -86,11 +105,7 @@ def start_listen(args: WorkerArgs) -> None:
"""
shutdown_event = asyncio.Event()
hardkill_counter = 0
if args.configure_logging and get_start_method() == "spawn":
logging.basicConfig(
level=args.log_level,
format=args.log_format,
)
configure_child_logging(args)

def interrupt_handler(signum: int, _frame: Any) -> None:
"""
Expand Down
49 changes: 49 additions & 0 deletions tests/cli/worker/test_child_logging.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import logging
from unittest.mock import patch

import pytest

from taskiq.cli.worker.args import WorkerArgs
from taskiq.cli.worker.run import configure_child_logging


@pytest.mark.parametrize("start_method", ["spawn", "forkserver"])
def test_logging_is_configured_in_fresh_interpreters(start_method: str) -> None:
Comment thread
danfimov marked this conversation as resolved.
Outdated
"""Spawn and forkserver children don't inherit the parent's logging config."""
args = WorkerArgs.from_cli(
["example:broker", "--log-level", "WARNING", "--log-format", "%(message)s"],
)

with (
patch("taskiq.cli.worker.run.get_start_method", return_value=start_method),
patch("taskiq.cli.worker.run.logging.basicConfig") as basic_config,
):
configure_child_logging(args)

basic_config.assert_called_once_with(level=logging.WARNING, format="%(message)s")


def test_logging_is_inherited_with_fork() -> None:
"""Forked children already have the parent's logging configuration."""
args = WorkerArgs.from_cli(["example:broker"])

with (
patch("taskiq.cli.worker.run.get_start_method", return_value="fork"),
patch("taskiq.cli.worker.run.logging.basicConfig") as basic_config,
):
configure_child_logging(args)

basic_config.assert_not_called()


@pytest.mark.parametrize("start_method", ["spawn", "forkserver"])
def test_no_configure_logging_is_respected(start_method: str) -> None:
args = WorkerArgs.from_cli(["example:broker", "--no-configure-logging"])

with (
patch("taskiq.cli.worker.run.get_start_method", return_value=start_method),
patch("taskiq.cli.worker.run.logging.basicConfig") as basic_config,
):
configure_child_logging(args)

basic_config.assert_not_called()
Loading