Update to cover new logic. Updatee READMEs and Guides with --debug arg information

This commit is contained in:
Beth Probert 2026-06-17 16:42:25 +01:00
parent b1202723a1
commit cf6fd4ccea
6 changed files with 59 additions and 29 deletions

View file

@ -25,7 +25,7 @@ More information is also available in the [handbook](https://gitlab.com/openflex
## Running directly
The Python package provides a command `ofm-microscope-server` that runs the server. This is what is used by `systemd` to run the service. You will need to provide some command-line arguments, see the output of `--help` for an up to date list. See `/etc/systemd/system/openflexure-microscope-server.service` for the command line used to run the server by default on the Raspberry Pi. In general, you are likely to want to specify a configuration file with `-c`, a host (`--host 0.0.0.0` to serve on all addresses) and a port (`--port 5000`). The `--fallback` option will allow the server to start *even if the hardware specified in the configuration file can't load*. This serves an error page, rather than have the server fail. In the future, it should redirect users to a way to fix their configuration.
The Python package provides a command `ofm-microscope-server` that runs the server. This is what is used by `systemd` to run the service. You will need to provide some command-line arguments, see the output of `--help` for an up to date list. See `/etc/systemd/system/openflexure-microscope-server.service` for the command line used to run the server by default on the Raspberry Pi. In general, you are likely to want to specify a configuration file with `-c`, a host (`--host 0.0.0.0` to serve on all addresses) and a port (`--port 5000`). The `--fallback` option will allow the server to start *even if the hardware specified in the configuration file can't load*. This serves an error page, rather than have the server fail. In the future, it should redirect users to a way to fix their configuration. The `--debug` option spins up both the OpenFlexure Microscope server and the LabThings server in `DEBUG` mode, providing more verbose logging information.
It is also possible to run the server in simulation mode. See Developer guidelines below.

View file

@ -71,6 +71,8 @@ sudo -u openflexure-ws application/openflexure-microscope-server/.venv/bin/openf
```
> Note: If you would like more detailed logging information from both the OpenFlexure Microscope server and the LabThings server, you can add the `--debug` argument to the end of the above command to activate `DEBUG` level logs.
### Running the simulation server on other platforms
To start the simulation server:
@ -81,6 +83,8 @@ To start the simulation server:
`openflexure-microscope-server --fallback -c ./ofm_config_simulation.json`
> Note: If you would like more detailed logging information from both the OpenFlexure Microscope server and the LabThings server, you can add the `--debug` argument to the end of the above command to activate `DEBUG` level logs.
* Open the address displayed in the terminal in any browser.
* To close the simulation server, return to the terminal and press `ctrl + c`.

View file

@ -27,6 +27,8 @@ The simulation server GUI is a copy of the GUI you would find on the hardware wi
This can fail with an error that the chosen port is already in use. In that case, append `--port 8081`
> Note: If you would like more detailed logging information from both the OpenFlexure Microscope server and the LabThings server, you can add the `--debug` argument to the end of the above command to activate `DEBUG` level logs.
---
## Video Walkthrough

View file

@ -73,7 +73,10 @@ def configure_logging(log_folder: str, debug: bool = False) -> None:
except PermissionError as e:
LOGGER.error(f"Cannot create log file at {OFM_LOG_FILE}: {e}")
LOGGER.info("OFM server root logger has been set up at %s level", logging.getLevelName(root_logger.level))
LOGGER.info(
"OFM server root logger has been set up at %s level",
logging.getLevelName(root_logger.level),
)
def retrieve_log() -> PlainTextResponse:

View file

@ -206,3 +206,31 @@ def test_uvicorn_error_only_says_error_on_error(
assert name in log_txt
for name in names_not_in_log:
assert name not in log_txt
@pytest.mark.parametrize(
("debug_flag", "expected_level"),
[
(False, logging.INFO),
(True, logging.DEBUG),
],
)
def test_configure_logging_debug_mode(debug_flag, expected_level):
"""Check that debug flag sets the correct root and handler logging levels."""
# Reset handler at start of test
ofm_logging.OFM_HANDLER = ofm_logging.OFMHandler()
with tmp_logging_dir() as tmpdir:
# Run configuration with the parameterised debug flag
ofm_logging.configure_logging(tmpdir, debug=debug_flag)
root_logger = logging.getLogger()
# Assert the root logger level was set correctly
assert root_logger.level == expected_level
# Assert the custom OFM handler level was synced to the root logger
assert ofm_logging.OFM_HANDLER.level == expected_level
# Cleanup: Remove the OFM_HANDLER from the root logger so it doesn't
# interfere with other tests in the suite.
root_logger.removeHandler(ofm_logging.OFM_HANDLER)

View file

@ -112,42 +112,35 @@ def test_failed_customise(mocker):
def test_debug_mode(mocker):
"""Test that --debug flag triggers lt.logs.configure_thing_logger."""
# Use a side_effect to map the CLI debug arg to the mock server's debug attribute
def mock_from_config(_, debug_flag):
mock_server = mocker.Mock()
mock_server.debug = debug_flag # This will now be correctly True or False
return mock_server
mocker.patch(
# Mock the LabThings server creation so we can inspect its arguments
mock_from_config = mocker.patch(
"openflexure_microscope_server.server.lt.ThingServer.from_config",
side_effect=mock_from_config,
return_value=mocker.Mock(),
)
# Mock customisation dependencies to avoid side effects
mocker.patch.object(ofm_server, "add_v2_endpoints")
mocker.patch.object(ofm_server, "add_static_files")
# Mock logging to avoid side effects and allow checking calls
mocker.patch.object(ofm_server, "configure_logging")
mocker.patch.object(ofm_server, "retrieve_log")
mocker.patch.object(ofm_server, "retrieve_log_from_file")
# Mock uvicorn.run to avoid starting a server
# Mock configure_logging to inspect its arguments and prevent side effects
mock_configure_logging = mocker.patch.object(ofm_server, "configure_logging")
# Mock other dependencies to avoid side effects (file writing, server starting)
mocker.patch.object(ofm_server, "customise_server")
mocker.patch("openflexure_microscope_server.server.uvicorn.run")
# Mock the target function
mock_configure_thing_logger = mocker.patch(
"openflexure_microscope_server.server.lt.logs.configure_thing_logger"
)
# 1. Run with --debug
ofm_server.serve_from_cli(["-c", SIM_CONFIG, "--debug"])
# Verify it was called with DEBUG level
mock_configure_thing_logger.assert_called_once_with(logging.DEBUG)
# Verify configure_logging was called with debug=True (the second argument)
assert mock_configure_logging.call_args.args[1] is True
# Verify ThingServer.from_config was called with debug=True (the second argument)
assert mock_from_config.call_args.args[1] is True
# Reset the mocks for the next run
mock_configure_logging.reset_mock()
mock_from_config.reset_mock()
# 2. Run without --debug
mock_configure_thing_logger.reset_mock()
ofm_server.serve_from_cli(["-c", SIM_CONFIG])
# Verify it was NOT called
mock_configure_thing_logger.assert_not_called()
# Verify configure_logging was called with debug=False
assert mock_configure_logging.call_args.args[1] is False
# Verify ThingServer.from_config was called with debug=False
assert mock_from_config.call_args.args[1] is False