diff --git a/supervisor/api/host.py b/supervisor/api/host.py index 50bfa9190..f6f99aac0 100644 --- a/supervisor/api/host.py +++ b/supervisor/api/host.py @@ -61,7 +61,7 @@ _LOGGER: logging.Logger = logging.getLogger(__name__) IDENTIFIER = "identifier" BOOTID = "bootid" -DEFAULT_RANGE = 100 +DEFAULT_LINES = 100 SCHEMA_OPTIONS = vol.Schema({vol.Optional(ATTR_HOSTNAME): str}) @@ -226,13 +226,24 @@ class APIHost(CoreSysAttributes): log_formatter = LogFormatter.VERBOSE if "lines" in request.query: - lines = request.query.get("lines", DEFAULT_RANGE) + lines = request.query.get("lines", DEFAULT_LINES) + try: + lines = int(lines) + except ValueError: + # If the user passed a non-integer value, just use the default instead of error. + lines = DEFAULT_LINES + finally: + # We can't use the entries= Range header syntax to refer to the last 1 line, + # and passing 1 to the calculation below would return the 1st line of the logs + # instead. Since this is really an edge case that doesn't matter much, we'll just + # return 2 lines at minimum. + lines = max(2, lines) # entries=cursor[[:num_skip]:num_entries] - range_header = f"entries=:-{lines}:" + range_header = f"entries=:-{lines-1}:{lines}" elif RANGE in request.headers: range_header = request.headers.get(RANGE) else: - range_header = f"entries=:-{DEFAULT_RANGE}:" + range_header = f"entries=:-{DEFAULT_LINES-1}:{DEFAULT_LINES}" async with self.sys_host.logs.journald_logs( params=params, range_header=range_header, accept=LogFormat.JOURNAL diff --git a/tests/api/__init__.py b/tests/api/__init__.py index 1b712021a..50b8d859a 100644 --- a/tests/api/__init__.py +++ b/tests/api/__init__.py @@ -6,7 +6,7 @@ from aiohttp.test_utils import TestClient from supervisor.host.const import LogFormat -DEFAULT_LOG_RANGE = "entries=:-100:" +DEFAULT_LOG_RANGE = "entries=:-99:100" async def common_test_api_advanced_logs( diff --git a/tests/api/test_host.py b/tests/api/test_host.py index 9c5d29016..b2312fae8 100644 --- a/tests/api/test_host.py +++ b/tests/api/test_host.py @@ -14,7 +14,7 @@ from supervisor.host.control import SystemControl from tests.dbus_service_mocks.base import DBusServiceMock from tests.dbus_service_mocks.systemd import Systemd as SystemdService -DEFAULT_RANGE = "entries=:-100:" +DEFAULT_RANGE = "entries=:-99:100" # pylint: disable=protected-access @@ -249,7 +249,7 @@ async def test_advaced_logs_query_parameters( await api_client.get("/host/logs?lines=53") journald_logs.assert_called_once_with( params={"SYSLOG_IDENTIFIER": coresys.host.logs.default_identifiers}, - range_header="entries=:-53:", + range_header="entries=:-52:53", accept=LogFormat.JOURNAL, ) @@ -277,7 +277,7 @@ async def test_advaced_logs_query_parameters( ) journald_logs.assert_called_once_with( params={"SYSLOG_IDENTIFIER": coresys.host.logs.default_identifiers}, - range_header="entries=:-53:", + range_header="entries=:-52:53", accept=LogFormat.JOURNAL, ) journal_logs_reader.assert_called_with(ANY, LogFormatter.VERBOSE)