mirror of
https://github.com/ARM-software/devlib.git
synced 2025-01-31 02:00:45 +00:00
collector/dmesg: Allow not raising on dmesg output parsing failure
Some drivers emit broken multiline dmesg output (with some Windows-style newline ...) . In order to parse the rest of the content, allow not raising on such input.
This commit is contained in:
parent
d4d9c92ae9
commit
e927e2f2cd
@ -16,6 +16,7 @@
|
|||||||
import re
|
import re
|
||||||
from itertools import takewhile
|
from itertools import takewhile
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
import logging
|
||||||
|
|
||||||
from devlib.collector import (CollectorBase, CollectorOutput,
|
from devlib.collector import (CollectorBase, CollectorOutput,
|
||||||
CollectorOutputEntry)
|
CollectorOutputEntry)
|
||||||
@ -23,6 +24,9 @@ from devlib.exception import TargetStableError
|
|||||||
from devlib.utils.misc import memoized
|
from devlib.utils.misc import memoized
|
||||||
|
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger('dmesg')
|
||||||
|
|
||||||
|
|
||||||
class KernelLogEntry(object):
|
class KernelLogEntry(object):
|
||||||
"""
|
"""
|
||||||
Entry of the kernel ring buffer.
|
Entry of the kernel ring buffer.
|
||||||
@ -112,17 +116,35 @@ class KernelLogEntry(object):
|
|||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_dmesg_output(cls, dmesg_out):
|
def from_dmesg_output(cls, dmesg_out, error=None):
|
||||||
"""
|
"""
|
||||||
Return a generator of :class:`KernelLogEntry` for each line of the
|
Return a generator of :class:`KernelLogEntry` for each line of the
|
||||||
output of dmesg command.
|
output of dmesg command.
|
||||||
|
|
||||||
|
:param error: If ``"raise"`` or ``None``, an exception will be raised
|
||||||
|
if a parsing error occurs. If ``"warn"``, it will be logged at
|
||||||
|
WARNING level. If ``"ignore"``, it will be ignored. If a callable
|
||||||
|
is passed, the exception will be passed to it.
|
||||||
|
:type error: str or None or typing.Callable[[BaseException], None]
|
||||||
|
|
||||||
.. note:: The same restrictions on the dmesg output format as for
|
.. note:: The same restrictions on the dmesg output format as for
|
||||||
:meth:`from_str` apply.
|
:meth:`from_str` apply.
|
||||||
"""
|
"""
|
||||||
for i, line in enumerate(dmesg_out.splitlines()):
|
for i, line in enumerate(dmesg_out.splitlines()):
|
||||||
if line.strip():
|
if line.strip():
|
||||||
yield cls.from_str(line, line_nr=i)
|
try:
|
||||||
|
yield cls.from_str(line, line_nr=i)
|
||||||
|
except Exception as e:
|
||||||
|
if error in (None, 'raise'):
|
||||||
|
raise e
|
||||||
|
elif error == 'warn':
|
||||||
|
_LOGGER.warn(f'error while parsing line "{line!r}": {e}')
|
||||||
|
elif error == 'ignore':
|
||||||
|
pass
|
||||||
|
elif callable(error):
|
||||||
|
error(e)
|
||||||
|
else:
|
||||||
|
raise ValueError(f'Unknown error handling strategy: {error}')
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
facility = self.facility + ': ' if self.facility else ''
|
facility = self.facility + ': ' if self.facility else ''
|
||||||
@ -167,7 +189,7 @@ class DmesgCollector(CollectorBase):
|
|||||||
"debug", # debug-level messages
|
"debug", # debug-level messages
|
||||||
]
|
]
|
||||||
|
|
||||||
def __init__(self, target, level=LOG_LEVELS[-1], facility='kern', empty_buffer=False):
|
def __init__(self, target, level=LOG_LEVELS[-1], facility='kern', empty_buffer=False, parse_error=None):
|
||||||
super(DmesgCollector, self).__init__(target)
|
super(DmesgCollector, self).__init__(target)
|
||||||
|
|
||||||
if not target.is_rooted:
|
if not target.is_rooted:
|
||||||
@ -199,6 +221,7 @@ class DmesgCollector(CollectorBase):
|
|||||||
self._begin_timestamp = None
|
self._begin_timestamp = None
|
||||||
self.empty_buffer = empty_buffer
|
self.empty_buffer = empty_buffer
|
||||||
self._dmesg_out = None
|
self._dmesg_out = None
|
||||||
|
self._parse_error = parse_error
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def dmesg_out(self):
|
def dmesg_out(self):
|
||||||
@ -216,11 +239,15 @@ class DmesgCollector(CollectorBase):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def entries(self):
|
def entries(self):
|
||||||
return self._get_entries(self._dmesg_out, self._begin_timestamp)
|
return self._get_entries(
|
||||||
|
self._dmesg_out,
|
||||||
|
self._begin_timestamp,
|
||||||
|
error=self._parse_error,
|
||||||
|
)
|
||||||
|
|
||||||
@memoized
|
@memoized
|
||||||
def _get_entries(self, dmesg_out, timestamp):
|
def _get_entries(self, dmesg_out, timestamp, error):
|
||||||
entries = KernelLogEntry.from_dmesg_output(dmesg_out)
|
entries = KernelLogEntry.from_dmesg_output(dmesg_out, error=error)
|
||||||
entries = list(entries)
|
entries = list(entries)
|
||||||
if timestamp is None:
|
if timestamp is None:
|
||||||
return entries
|
return entries
|
||||||
|
Loading…
x
Reference in New Issue
Block a user