@@ -39,6 +39,8 @@ class KernelLogEntry(object):
39
39
"""
40
40
41
41
_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*(.*)' )
42
44
43
45
def __init__ (self , facility , level , timestamp , msg ):
44
46
self .facility = facility
@@ -52,50 +54,57 @@ def from_str(cls, line):
52
54
Parses a "dmesg --decode" output line, formatted as following:
53
55
kern :err : [3618282.310743] nouveau 0000:01:00.0: systemd-logind[988]: nv50cal_space: -16
54
56
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
57
59
58
60
"""
59
61
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 )
62
64
if not match :
63
65
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 )
64
79
timestamp , msg = match .groups ()
80
+ timestamp = timedelta (seconds = float (timestamp .strip ()))
65
81
return timestamp , msg
66
82
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
68
86
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 )
76
88
facility = None
77
- level = None
89
+ except ValueError :
90
+ facility , level , remainder = parse_pretty_level (line )
91
+
92
+ timestamp , msg = parse_timestamp_msg (remainder )
78
93
79
94
return cls (
80
95
facility = facility ,
81
96
level = level ,
82
- timestamp = timedelta ( seconds = float ( timestamp . strip ())) ,
97
+ timestamp = timestamp ,
83
98
msg = msg .strip (),
84
99
)
85
100
86
101
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 ,
96
106
timestamp = self .timestamp .total_seconds (),
97
107
msg = self .msg ,
98
- prefix = prefix ,
99
108
)
100
109
101
110
@@ -136,11 +145,12 @@ def __init__(self, target, level=LOG_LEVELS[-1], facility='kern'):
136
145
))
137
146
self .level = level
138
147
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.
140
150
# Note: BusyBox dmesg does not support -h, but will still print the
141
151
# 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 )
144
154
self .facility = facility
145
155
self .reset ()
146
156
@@ -173,7 +183,7 @@ def stop(self):
173
183
))
174
184
levels_list .append (self .level )
175
185
if self .basic_dmesg :
176
- cmd = 'dmesg'
186
+ cmd = 'dmesg -r '
177
187
else :
178
188
cmd = 'dmesg --facility={facility} --force-prefix --decode --level={levels}' .format (
179
189
levels = ',' .join (levels_list ),
0 commit comments