From 81d32a638fa41fa1c1eadc9ee90eb434dfce7345 Mon Sep 17 00:00:00 2001 From: Patryk Hegenberg Date: Thu, 4 Sep 2025 09:31:29 +0200 Subject: [PATCH] feat(service-monitor): add implementation for parsing access-manager logs --- service_monitor.go | 65 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 62 insertions(+), 3 deletions(-) diff --git a/service_monitor.go b/service_monitor.go index 88bef30..f7cc5f5 100644 --- a/service_monitor.go +++ b/service_monitor.go @@ -7,6 +7,7 @@ import ( "fmt" "log/slog" "os/exec" + "regexp" "strconv" "strings" "time" @@ -209,6 +210,8 @@ func (jep *JournalEntryParser) parseServiceSpecific(entry LogEntry) LogEntry { return parseTJMService(entry) case "nginx": return parseNginxService(entry) + case "access-manager": + return parseAMService(entry) default: return entry } @@ -250,7 +253,7 @@ func parseTixstreamService(entry LogEntry) LogEntry { newEntry.Fields["transfer_info"] = strings.Join(info[1:], " ") default: newEntry.Fields["log_type"] = "log_message" - newEntry.Fields["transfer_info"] = info + newEntry.Fields["transfer_info"] = strings.Join(info, " ") } return newEntry @@ -299,6 +302,62 @@ func parseTJMService(entry LogEntry) LogEntry { return newEntry } -func parseNginxService(entry LogEntry) LogEntry { - return entry +var ( + amServicePattern = regexp.MustCompile(`^(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z)\s+(\w+)\s+(\d+)\s+---\s+\[\s*([^\]]*)\]\s+([\w\.]+)\s*:\s*(.*)$`) + nginxAccessPattern = regexp.MustCompile(`^(\S+)\s+\S+\s+(\S+)\s+\[([^\]]+)\]\s+"([^"]+)"\s+(\d+)\s+(\d+|-)\s*(?:"([^"]*)"\s+"([^"]*)")?`) +) + +func parseAMService(entry LogEntry) LogEntry { + newEntry := entry + if newEntry.Fields == nil { + newEntry.Fields = make(map[string]any) + } + + matches := amServicePattern.FindStringSubmatch(strings.TrimSpace(entry.Message)) + if len(matches) != 7 { + return newEntry + } + + newEntry.Fields["timestamp"] = matches[1] + newEntry.Fields["log_level"] = matches[2] + newEntry.Fields["process_id"] = matches[3] + newEntry.Fields["thread_name"] = strings.TrimSpace(matches[4]) + newEntry.Fields["logger_name"] = matches[5] + newEntry.Fields["log_message"] = matches[6] + + return newEntry +} + +func parseNginxService(entry LogEntry) LogEntry { + newEntry := entry + if newEntry.Fields == nil { + newEntry.Fields = make(map[string]any) + } + + matches := nginxAccessPattern.FindStringSubmatch(strings.TrimSpace(entry.Message)) + if len(matches) < 7 { + return newEntry + } + + newEntry.Fields["client_ip"] = matches[1] + newEntry.Fields["remote_user"] = matches[2] + newEntry.Fields["timestamp"] = matches[3] + newEntry.Fields["request"] = matches[4] + newEntry.Fields["status_code"] = matches[5] + newEntry.Fields["bytes_sent"] = matches[6] + + if len(matches) > 7 && matches[7] != "" { + newEntry.Fields["referer"] = matches[7] + } + if len(matches) > 8 && matches[8] != "" { + newEntry.Fields["user_agent"] = matches[8] + } + + if requestParts := strings.Fields(matches[4]); len(requestParts) >= 3 { + newEntry.Fields["http_method"] = requestParts[0] + newEntry.Fields["request_uri"] = requestParts[1] + newEntry.Fields["http_version"] = requestParts[2] + } + + return newEntry }