From 352fc4a4c654465cdf531f3708ef30fe0cd2ed63 Mon Sep 17 00:00:00 2001 From: Petr Heinz Date: Wed, 7 Oct 2026 18:54:36 +0200 Subject: [PATCH 1/2] Match only real MySQL log layouts when detecting the MySQL platform The general-log fallback accepted any " " line, so pods of unrelated apps got platform MySQL. The error log regex now requires one of MySQL's priorities (System, Note, Warning, ERROR) and, when present, a MY-xxxxxx error code, which also lets MySQL 5.7 error lines parse with their priority and message. The general query log regex requires the layout MySQL writes (sql/log.cc File_query_log::write_general): a tab after the timestamp, the padded connection id, one space, the command, and a tab before the optional argument. Also ports the null handling for non-participating regex groups from BetterStackHQ/logtail, so a line without an argument keeps its raw message instead of a null one. Same change as Vector::ParserFactory::MYSQL in BetterStackHQ/logtail. Co-Authored-By: Claude Fable 5.1 --- Chart.yaml | 2 +- values.yaml | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/Chart.yaml b/Chart.yaml index 5d7b02d..f5fe0a0 100644 --- a/Chart.yaml +++ b/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v2 name: betterstack-logs -version: 2.0.0 +version: 2.0.1 dependencies: - name: metrics-server version: 3.12.2 diff --git a/values.yaml b/values.yaml index 4a90bb9..3d4de76 100644 --- a/values.yaml +++ b/values.yaml @@ -156,16 +156,21 @@ vector: del(.postgres) } - .mysql = parse_regex(.message, r'^(?P
\d+-\d+-\d+T\d+:\d+:\d+\.\d+\w+)\s+(?P\d+)\s+\[(?P\S+)\]\s*\[(?P\S+)\]\s*\[(?P\S+)\]\s*(?P.*)') ?? - parse_regex(.message, r'^(?P
\d+-\d+-\d+T\d+:\d+:\d+\.\d+\w+)\s+(?P\d+)\s+(?P[^\t]+)(?:\s+(?P.*))?') ?? + .mysql = parse_regex(.message, r'^(?P
\d+-\d+-\d+T\d+:\d+:\d+\.\d+\w+)\s+(?P\d+)\s+\[(?PSystem|Note|Warning|ERROR)\](?:\s*\[(?PMY-\d+)\]\s*\[(?P\S+)\])?\s*(?P.*)') ?? + parse_regex(.message, r'^(?P
\d+-\d+-\d+T\d+:\d+:\d+\.\d+\w+)\t\s*(?P\d+) (?P[^\t]+)(?:\t\s*(?P\S.*))?') ?? {} if .mysql != {} { + # non-participating optional regex groups parse to null + if is_null(.mysql.message) { del(.mysql.message) } + if is_null(.mysql.error_code) { del(.mysql.error_code) } + if is_null(.mysql.subsystem) { del(.mysql.subsystem) } + .platform = "MySQL" if exists(.mysql.dt) { .dt = del(.mysql.dt) } if exists(.mysql.thread) { .mysql.thread = to_int!(.mysql.thread) } if exists(.mysql.id) { .mysql.id = to_int!(.mysql.id) } - .message = del(.mysql.message) + if exists(.mysql.message) { .message = del(.mysql.message) } # extract message metadata tmp = string!(.message) From abc75a0b17d3776dfdb3923e48de2c8bc33eef2a Mon Sep 17 00:00:00 2001 From: Petr Heinz Date: Thu, 8 Oct 2026 11:49:25 +0200 Subject: [PATCH 2/2] Require MySQL's six-digit timestamps and accept its timezone offsets Both MySQL logs format timestamps with make_iso8601_timestamp: YYYY-MM-DDTHH:MM:SS.ffffff followed by Z, or by +hh:mm/-hh:mm when log_timestamps=SYSTEM. Requiring that shape rejects the common " [ERROR] ..." app line, which the optional error-code group had let through, and makes logs written with log_timestamps=SYSTEM parse, which they never did. Mirrors the same commit in BetterStackHQ/logtail. Co-Authored-By: Claude Fable 5.1 --- values.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/values.yaml b/values.yaml index 3d4de76..ce80618 100644 --- a/values.yaml +++ b/values.yaml @@ -156,8 +156,8 @@ vector: del(.postgres) } - .mysql = parse_regex(.message, r'^(?P
\d+-\d+-\d+T\d+:\d+:\d+\.\d+\w+)\s+(?P\d+)\s+\[(?PSystem|Note|Warning|ERROR)\](?:\s*\[(?PMY-\d+)\]\s*\[(?P\S+)\])?\s*(?P.*)') ?? - parse_regex(.message, r'^(?P
\d+-\d+-\d+T\d+:\d+:\d+\.\d+\w+)\t\s*(?P\d+) (?P[^\t]+)(?:\t\s*(?P\S.*))?') ?? + .mysql = parse_regex(.message, r'^(?P
\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{6}(?:Z|[+-]\d{2}:\d{2}))\s+(?P\d+)\s+\[(?PSystem|Note|Warning|ERROR)\](?:\s*\[(?PMY-\d+)\]\s*\[(?P\S+)\])?\s*(?P.*)') ?? + parse_regex(.message, r'^(?P
\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{6}(?:Z|[+-]\d{2}:\d{2}))\t\s*(?P\d+) (?P[^\t]+)(?:\t\s*(?P\S.*))?') ?? {} if .mysql != {} {