Skip to content

Commit 96de726

Browse files
authored
Avoid collecting 80k lines of logs in checkbox collector (bugfix) (#2417)
* Move code to utility function * Test new function lowmem is less than 2Gb * Also collect less logs for lowmem devices Dropping journal lines collected helps first avoiding getting killed by the OOM killer on some platforms with REALLY low ram. Secondly, given that the submission is less compressed, lowers a lot the egress cost of the upload, mitigating the 5xx errors we are getting * Python3.5 is fun * Better docstring and type hint
1 parent 4b95b56 commit 96de726

4 files changed

Lines changed: 40 additions & 7 deletions

File tree

checkbox-ng/plainbox/impl/__init__.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,3 +210,17 @@ def get_plainbox_dir():
210210
Return the root directory of the plainbox package.
211211
"""
212212
return os.path.dirname(getabsfile(plainbox))
213+
214+
215+
def low_memory_device() -> bool:
216+
"""
217+
Returns `True` if the system we are running on has very low RAM installed
218+
219+
This is used to disable or tune down some subsystems to avoid filling
220+
the RAM with Checkbox itself and crashing the system.
221+
"""
222+
mem_bytes = os.sysconf("SC_PAGE_SIZE") * os.sysconf("SC_PHYS_PAGES")
223+
mem_mib = mem_bytes / (1024.0**2)
224+
if mem_mib < 1024 * 2:
225+
return True
226+
return False

checkbox-ng/plainbox/impl/exporter/tar.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import time
3131
from tempfile import SpooledTemporaryFile
3232

33+
from plainbox.impl import low_memory_device
3334
from plainbox.impl.exporter import SessionStateExporterBase
3435
from plainbox.impl.exporter.jinja2 import Jinja2SessionStateExporter
3536
from plainbox.impl.providers import get_providers
@@ -53,14 +54,12 @@ def dump_from_session_manager(self, manager, stream):
5354
5455
"""
5556
preset = None
56-
mem_bytes = os.sysconf("SC_PAGE_SIZE") * os.sysconf("SC_PHYS_PAGES")
57-
mem_mib = mem_bytes / (1024.0**2)
5857
# On systems with less than 1GiB of RAM, create the submission tarball
5958
# without any compression level (i.e preset=0).
6059
# See https://docs.python.org/3/library/lzma.html
6160
# With preset 9 for example, the overhead for an LZMACompressor object
6261
# can be as high as 800 MiB.
63-
if mem_mib < 1200:
62+
if low_memory_device():
6463
preset = 0
6564

6665
job_state_map = manager.default_device_context.state.job_state_map

checkbox-ng/plainbox/impl/session/system_information.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22

33
import abc
44
import json
5+
56
from subprocess import run, PIPE, check_output, STDOUT, CalledProcessError
67

8+
from plainbox.impl import low_memory_device
79
from plainbox import vendor
810
from plainbox.impl.session.storage import WellKnownDirsHelper
911
from checkbox_ng import __version__ as checkbox_version
@@ -296,6 +298,11 @@ def collector_parser(self, collector_output):
296298
return list(map(json.loads, collector_output.splitlines()))
297299

298300
def __init__(self):
301+
to_collect = 80000 # limit the lines to 80k, ~80Mb of memory
302+
if low_memory_device():
303+
# when memory is low, we can't afford to load all that json into
304+
# memory, try to collect a few logs either way
305+
to_collect = 8000
299306
super().__init__(
300307
collection_cmd=[
301308
"journalctl",
@@ -304,7 +311,7 @@ def __init__(self):
304311
"--since",
305312
"-3 days",
306313
"-n",
307-
"80000", # limit the lines to 80k, ~80Mb of memory
314+
str(to_collect),
308315
],
309316
version_cmd=["journalctl", "--version"],
310317
)

checkbox-ng/plainbox/impl/test_init.py

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,11 @@
2323
Test definitions for plainbox.impl module
2424
"""
2525

26-
from unittest import TestCase
2726
import warnings
27+
from unittest import TestCase
28+
from unittest.mock import patch
2829

29-
from plainbox.impl import _get_doc_margin
30-
from plainbox.impl import deprecated
30+
from plainbox.impl import _get_doc_margin, deprecated, low_memory_device
3131

3232

3333
class MiscTests(TestCase):
@@ -113,3 +113,16 @@ def func():
113113
str(boom.exception),
114114
"@deprecated() must be called with a parameter",
115115
)
116+
117+
118+
class LowMemoryDeviceTests(TestCase):
119+
120+
@patch("os.sysconf")
121+
def test_not_lowmem(self, sysconf_mock):
122+
sysconf_mock.side_effect = [4096, 7627054]
123+
self.assertFalse(low_memory_device())
124+
125+
@patch("os.sysconf")
126+
def test_lowmem(self, sysconf_mock):
127+
sysconf_mock.side_effect = [4096, 4]
128+
self.assertTrue(low_memory_device())

0 commit comments

Comments
 (0)