Add support for journalctl output
The lines in the "Mem-Info:" block start with spaces instead of date / time / hostname. As a result, removing the needless columns no longer works correctly. Suggested-by: Mikko Rantalainen <mikko.rantalainen@gmail.com>
This commit is contained in:
parent
7038cced1f
commit
a7e1e4cc64
@ -897,6 +897,7 @@ window.onerror = function (msg, url, lineNo, columnNo, error) {
|
||||
<li>Add support for manually triggered OOM (suggested by Mikko Rantalainen)</li>
|
||||
<li>Add support for systems w/o swap (suggested by Mikko Rantalainen)</li>
|
||||
<li>Add support for newer kernels (suggested by Mikko Rantalainen)</li>
|
||||
<li>Add support for journalctl output (suggested by Mikko Rantalainen)</li>
|
||||
<li>...</li>
|
||||
</ol>
|
||||
|
||||
|
@ -525,6 +525,7 @@ class OOMEntity:
|
||||
oom_lines = self._remove_non_oom_lines(oom_lines)
|
||||
oom_lines = self._remove_kernel_colon(oom_lines)
|
||||
cols_to_strip = self._number_of_columns_to_strip(oom_lines[self._get_CPU_index(oom_lines)])
|
||||
oom_lines = self._journalctl_add_leading_columns_to_meminfo(oom_lines, cols_to_strip)
|
||||
oom_lines = self._strip_needless_columns(oom_lines, cols_to_strip)
|
||||
oom_lines = self._rsyslog_unescape_lf(oom_lines)
|
||||
|
||||
@ -536,6 +537,34 @@ class OOMEntity:
|
||||
else:
|
||||
self.state = OOMEntityState.started
|
||||
|
||||
def _journalctl_add_leading_columns_to_meminfo(self, oom_lines, cols_to_add):
|
||||
"""
|
||||
Add leading columns to handle line breaks in journalctl output correctly.
|
||||
|
||||
The output of the "Mem-Info:" block contains line breaks. journalctl breaks these lines accordingly, but
|
||||
inserts at the beginning spaces instead of date and time. As a result, removing the needless columns no longer
|
||||
works correctly.
|
||||
|
||||
This function adds columns back in the affected rows so that the removal works cleanly over all rows.
|
||||
|
||||
@see: _rsyslog_unescape_lf()
|
||||
"""
|
||||
pattern = r'^\s+ (active_file|unevictable|slab_reclaimable|mapped|free):.+$'
|
||||
rec = re.compile(pattern)
|
||||
|
||||
add_cols = ""
|
||||
for i in range(cols_to_add):
|
||||
add_cols += "Col{} ".format(i)
|
||||
|
||||
expanded_lines = []
|
||||
for line in oom_lines:
|
||||
match = rec.search(line)
|
||||
if match:
|
||||
line = "{} {}".format(add_cols, line.strip())
|
||||
expanded_lines.append(line)
|
||||
|
||||
return expanded_lines
|
||||
|
||||
def _get_CPU_index(self, lines):
|
||||
"""
|
||||
Return the index of the first line with "CPU: "
|
||||
@ -605,12 +634,17 @@ class OOMEntity:
|
||||
|
||||
def _rsyslog_unescape_lf(self, oom_lines):
|
||||
"""
|
||||
Rsyslog replaces line breaks with their octal representation #012.
|
||||
Split lines at '#012' (octal representation of LF).
|
||||
|
||||
The output of the "Mem-Info:" block contains line breaks. Rsyslog replaces these line breaks with their octal
|
||||
representation #012. This breaks the removal of needless columns as well as the detection of the OOM values.
|
||||
|
||||
Splitting the lines (again) solves this issue.
|
||||
|
||||
This feature can be controlled inside the rsyslog configuration with the directives
|
||||
$EscapeControlCharactersOnReceive, $Escape8BitCharactersOnReceive and $ControlCharactersEscapePrefix.
|
||||
|
||||
The replacement is only in second line (active_anon:....) of the Mem-Info block.
|
||||
@see: _journalctl_add_leading_columns_to_meminfo()
|
||||
"""
|
||||
lines = []
|
||||
|
||||
|
31
test.py
31
test.py
@ -304,6 +304,37 @@ Killed process 6576 (java) total-vm:33914892kB, anon-rss:20629004kB, file-rss:0k
|
||||
self.assertEqual(self.get_error_text(), "ERROR: Failed to extract kernel version from OOM text")
|
||||
self.click_reset()
|
||||
|
||||
def test_035_leading_journalctl_input(self):
|
||||
"""Test loading input from journalctl """
|
||||
# prepare example
|
||||
example_lines = OOMAnalyser.OOMDisplay.example_rhel7.split('\n')
|
||||
res = []
|
||||
|
||||
# unescape #012 - see OOMAnalyser.OOMEntity._rsyslog_unescape_lf()
|
||||
for line in example_lines:
|
||||
if '#012' in line:
|
||||
res.extend(line.split('#012'))
|
||||
else:
|
||||
res.append(line)
|
||||
example_lines = res
|
||||
res = []
|
||||
|
||||
# add date/time prefix except for "Mem-Info:" block
|
||||
pattern = r'^ (active_file|unevictable|slab_reclaimable|mapped|free):.+$'
|
||||
rec = re.compile(pattern)
|
||||
for line in example_lines:
|
||||
match = rec.search(line)
|
||||
if match:
|
||||
line = " {}".format(line)
|
||||
else:
|
||||
line = "Apr 01 14:13:32 mysrv <kern.warning> kernel: {}".format(line)
|
||||
res.append(line)
|
||||
example = "\n".join(res)
|
||||
|
||||
self.analyse_oom(example)
|
||||
self.check_results_rhel7()
|
||||
self.click_reset()
|
||||
|
||||
def test_040_trigger_proc_space(self):
|
||||
"""Test trigger process name contains a space"""
|
||||
example = OOMAnalyser.OOMDisplay.example_rhel7
|
||||
|
Loading…
Reference in New Issue
Block a user