fix(collector): use word-boundary matching for dmesg severity

dmesgSeverity classified a kernel log line as Critical via plain
strings.Contains, without word boundaries, so common words that merely
contain a keyword as a substring false-positive — "disabled by
default" was flagged Critical because "default" contains "fault"
(de-fault). Found in a support bundle where 140/238 event_logs entries
came back Critical, most of them harmless boot messages (module load
notices, "... is initialized", "disabled by default"), drowning out
genuinely critical entries (Xid, AER, ECC) in the same list.

Switch to the same \b-bounded regexes already used for the capture
patterns above it in this file.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Mikhail Chusavitin
2026-08-24 17:41:28 +03:00
co-authored by Claude Sonnet 5
parent a09201c7ab
commit 56d12b1f3c
2 changed files with 29 additions and 15 deletions
+19 -15
View File
@@ -108,6 +108,23 @@ func matchesAny(s string, patterns []*regexp.Regexp) bool {
return false return false
} }
// dmesgSeverityCriticalPatterns use \b word boundaries, unlike a plain
// strings.Contains check, so common words that merely contain a keyword as a
// substring don't false-positive — e.g. "disabled by default" contains
// "fault" (de-fault), and "undead" would contain "dead".
var dmesgSeverityCriticalPatterns = []*regexp.Regexp{
regexp.MustCompile(`(?i)\bpanic\b`),
regexp.MustCompile(`(?i)\baer\b`),
regexp.MustCompile(`(?i)\buncorrect`),
regexp.MustCompile(`(?i)\bxid\b`),
regexp.MustCompile(`(?i)\bnvrm\b`),
regexp.MustCompile(`(?i)\berror\b`),
regexp.MustCompile(`(?i)\bfault\b`),
regexp.MustCompile(`(?i)\bfail(ed|ure)?\b`),
regexp.MustCompile(`(?i)\bdead\b`),
regexp.MustCompile(`(?i)\bhang\b`),
}
func dmesgSeverity(msg string) string { func dmesgSeverity(msg string) string {
if sev, ok := XidSeverity(msg); ok { if sev, ok := XidSeverity(msg); ok {
if sev == "critical" { if sev == "critical" {
@@ -115,21 +132,8 @@ func dmesgSeverity(msg string) string {
} }
return statusWarning return statusWarning
} }
lower := strings.ToLower(msg) if matchesAny(msg, dmesgSeverityCriticalPatterns) {
switch {
case strings.Contains(lower, "panic") ||
strings.Contains(lower, "aer") ||
strings.Contains(lower, "uncorrect") ||
strings.Contains(lower, "xid") ||
strings.Contains(lower, "nvrm"):
return statusCritical return statusCritical
case strings.Contains(lower, "error") ||
strings.Contains(lower, "fault") ||
strings.Contains(lower, "fail") ||
strings.Contains(lower, "dead") ||
strings.Contains(lower, "hang"):
return statusCritical
default:
return statusWarning
} }
return statusWarning
} }
@@ -33,6 +33,16 @@ func TestDmesgSeverity_xidCodes(t *testing.T) {
msg: "blk_update_request: I/O error, dev sda", msg: "blk_update_request: I/O error, dev sda",
want: statusCritical, want: statusCritical,
}, },
{
name: "disabled by default is not a fault substring match",
msg: "Yama: disabled by default; enable with sysctl kernel.yama.*",
want: statusWarning,
},
{
name: "benign NVRM driver load message still escalates via NVRM keyword",
msg: "NVRM: loading NVIDIA UNIX Open Kernel Module for x86_64 580.159.03",
want: statusCritical,
},
} }
for _, tt := range tests { for _, tt := range tests {