Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Emit Daemon logs for pytest test run #6671

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,8 @@ tests = [
'pympler~=1.0',
'coverage~=7.0',
'sphinx~=7.2.0',
'docutils~=0.20'
'docutils~=0.20',
'watchdog~=6.0'
]
tui = [
'trogon'
Expand Down
56 changes: 54 additions & 2 deletions src/aiida/tools/pytest_fixtures/daemon.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@

from __future__ import annotations

import logging
import pathlib
import typing as t

import pytest

if t.TYPE_CHECKING:
from aiida.engine import Process, ProcessBuilder
from aiida.engine.daemon.client import DaemonClient

Check warning on line 13 in src/aiida/tools/pytest_fixtures/daemon.py

View check run for this annotation

Codecov / codecov/patch

src/aiida/tools/pytest_fixtures/daemon.py#L13

Added line #L13 was not covered by tests
from aiida.orm import ProcessNode


Expand Down Expand Up @@ -47,7 +49,7 @@


@pytest.fixture
def started_daemon_client(daemon_client):
def started_daemon_client(daemon_client: 'DaemonClient'):
"""Ensure that the daemon is running for the test profile and return the associated client.
Usage::
Expand All @@ -60,11 +62,61 @@
daemon_client.start_daemon()
assert daemon_client.is_daemon_running

import threading
import time

from watchdog.events import FileSystemEventHandler
from watchdog.observers import Observer

logger = logging.getLogger('tests.daemon:started_daemon_client')

logger.debug(f'Daemon log file is located at: {daemon_client.daemon_log_file}')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which log level do I have to change to debug to see this message? It tried to run pytest -s --pdb but I don't see this message

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need to run pytest tests --log-cli-level=DEBUG as mentioned in the description of PR.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry 😞 I dont know why I did not see it

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The way to reproduce the write to the daemon log is to run test tests/engine/processes/test_control.py::test_pause_processes -v --log-cli-level=DEBUG -s with print some text in plumpy's Process::pause method. The reason that the print would show things to the REPL where pytest is running since it calls from a rpc call and runs in a daemon worker. The print output will be then written to the daemon log.


# This flag will be used to stop the thread when the fixture is torn down
stop_thread = False

class LogFileEventHandler(FileSystemEventHandler):
def __init__(self, filepath):
self.filepath = filepath
# Keep track of how many bytes have been read so we print only new data
self._pos = 0

def on_modified(self, event):
if event.src_path == self.filepath:
# The file was modified, read from the last known position
with open(self.filepath, 'r') as f:
f.seek(self._pos)
new_output = f.read()
if new_output:
logger.debug(new_output)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe I should not use logger here since the content of the log file is in log format.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we also have other things printed to the terminal in log format. At least the warnings I get are in it

tests/brokers/test_rabbitmq.py 01/07/2025 12:21:45 PM <19376> aiida.broker.rabbitmq: [WARNING] RabbitMQ v3.13.6 is not supported and will cause unexpected problems!

self._pos = f.tell()

def print_log_content(check_interval=0.1):
event_handler = LogFileEventHandler(daemon_client.daemon_log_file)
observer = Observer()
_ = observer.schedule(event_handler, str(pathlib.Path(daemon_client.daemon_log_file)), recursive=False)
observer.start()

try:
while not stop_thread:
time.sleep(check_interval)
finally:
observer.stop()
observer.join()

# Start a background thread to continuously print new log lines
t = threading.Thread(target=print_log_content, daemon=True)
t.start()

yield daemon_client

# After the test finishes, signal the thread to stop and join it
stop_thread = True
t.join(timeout=5)


@pytest.fixture
def stopped_daemon_client(daemon_client):
def stopped_daemon_client(daemon_client: 'DaemonClient'):
"""Ensure that the daemon is not running for the test profile and return the associated client.
Usage::
Expand Down
40 changes: 40 additions & 0 deletions uv.lock

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

Loading