Skip to content

Commit 4c8f243

Browse files
douglas-raillard-armmarcbonnici
authored andcommitted
trace: dmesg: Allow using old util-linux binary
Old util-linux binaries don't support --force-prefix. Multi-line entry parsing will break on these, but at least we can collect the log. Also decode the raw priority, so only the facility is not decoded in case busybox or old util-linux is used.
1 parent a8b6e56 commit 4c8f243

File tree

1 file changed

+38
-28
lines changed

1 file changed

+38
-28
lines changed

devlib/trace/dmesg.py

+38-28
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ class KernelLogEntry(object):
3939
"""
4040

4141
_TIMESTAMP_MSG_REGEX = re.compile(r'\[(.*?)\] (.*)')
42+
_RAW_LEVEL_REGEX = re.compile(r'<([0-9]+)>(.*)')
43+
_PRETTY_LEVEL_REGEX = re.compile(r'\s*([a-z]+)\s*:([a-z]+)\s*:\s*(.*)')
4244

4345
def __init__(self, facility, level, timestamp, msg):
4446
self.facility = facility
@@ -52,50 +54,57 @@ def from_str(cls, line):
5254
Parses a "dmesg --decode" output line, formatted as following:
5355
kern :err : [3618282.310743] nouveau 0000:01:00.0: systemd-logind[988]: nv50cal_space: -16
5456
55-
Or the more basic output:
56-
[3618282.310743] nouveau 0000:01:00.0: systemd-logind[988]: nv50cal_space: -16
57+
Or the more basic output given by "dmesg -r":
58+
<3>[3618282.310743] nouveau 0000:01:00.0: systemd-logind[988]: nv50cal_space: -16
5759
5860
"""
5961

60-
def parse_timestamp_msg(line):
61-
match = cls._TIMESTAMP_MSG_REGEX.match(line.strip())
62+
def parse_raw_level(line):
63+
match = cls._RAW_LEVEL_REGEX.match(line)
6264
if not match:
6365
raise ValueError('dmesg entry format not recognized: {}'.format(line))
66+
level, remainder = match.groups()
67+
levels = DmesgCollector.LOG_LEVELS
68+
# BusyBox dmesg can output numbers that need to wrap around
69+
level = levels[int(level) % len(levels)]
70+
return level, remainder
71+
72+
def parse_pretty_level(line):
73+
match = cls._PRETTY_LEVEL_REGEX.match(line)
74+
facility, level, remainder = match.groups()
75+
return facility, level, remainder
76+
77+
def parse_timestamp_msg(line):
78+
match = cls._TIMESTAMP_MSG_REGEX.match(line)
6479
timestamp, msg = match.groups()
80+
timestamp = timedelta(seconds=float(timestamp.strip()))
6581
return timestamp, msg
6682

67-
# If we can parse the timestamp directly, that is a basic line
83+
line = line.strip()
84+
85+
# If we can parse the raw prio directly, that is a basic line
6886
try:
69-
timestamp, msg = parse_timestamp_msg(line)
70-
except ValueError:
71-
facility, level, remainder = line.split(':', 2)
72-
timestamp, msg = parse_timestamp_msg(remainder)
73-
facility = facility.strip()
74-
level = level.strip()
75-
else:
87+
level, remainder = parse_raw_level(line)
7688
facility = None
77-
level = None
89+
except ValueError:
90+
facility, level, remainder = parse_pretty_level(line)
91+
92+
timestamp, msg = parse_timestamp_msg(remainder)
7893

7994
return cls(
8095
facility=facility,
8196
level=level,
82-
timestamp=timedelta(seconds=float(timestamp.strip())),
97+
timestamp=timestamp,
8398
msg=msg.strip(),
8499
)
85100

86101
def __str__(self):
87-
if self.facility and self.level:
88-
prefix = '{facility}:{level}:'.format(
89-
facility=self.facility,
90-
level=self.level,
91-
)
92-
else:
93-
prefix = ''
94-
95-
return '{prefix}[{timestamp}] {msg}'.format(
102+
facility = self.facility + ': ' if self.facility else ''
103+
return '{facility}{level}: [{timestamp}] {msg}'.format(
104+
facility=facility,
105+
level=self.level,
96106
timestamp=self.timestamp.total_seconds(),
97107
msg=self.msg,
98-
prefix=prefix,
99108
)
100109

101110

@@ -136,11 +145,12 @@ def __init__(self, target, level=LOG_LEVELS[-1], facility='kern'):
136145
))
137146
self.level = level
138147

139-
# Check if dmesg is the BusyBox one, or the one from util-linux.
148+
# Check if dmesg is the BusyBox one, or the one from util-linux in a
149+
# recent version.
140150
# Note: BusyBox dmesg does not support -h, but will still print the
141151
# help with an exit code of 1
142-
self.basic_dmesg = 'BusyBox' in self.target.execute('dmesg -h',
143-
check_exit_code=False)
152+
self.basic_dmesg = '--force-prefix' not in \
153+
self.target.execute('dmesg -h', check_exit_code=False)
144154
self.facility = facility
145155
self.reset()
146156

@@ -173,7 +183,7 @@ def stop(self):
173183
))
174184
levels_list.append(self.level)
175185
if self.basic_dmesg:
176-
cmd = 'dmesg'
186+
cmd = 'dmesg -r'
177187
else:
178188
cmd = 'dmesg --facility={facility} --force-prefix --decode --level={levels}'.format(
179189
levels=','.join(levels_list),

0 commit comments

Comments
 (0)