110 lines
2.2 KiB
Go
110 lines
2.2 KiB
Go
package ingest
|
|
|
|
import (
|
|
"fmt"
|
|
"regexp"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
var rePri = regexp.MustCompile(`^<(\d{1,3})>`)
|
|
|
|
type ParsedSyslog struct {
|
|
Priority int
|
|
Hostname string
|
|
Tag string
|
|
Message string
|
|
RawLine string
|
|
}
|
|
|
|
func parseSyslogPayload(payload []byte) ParsedSyslog {
|
|
line := strings.TrimSpace(string(payload))
|
|
p := ParsedSyslog{RawLine: line, Message: line}
|
|
if line == "" {
|
|
return p
|
|
}
|
|
rest := line
|
|
if m := rePri.FindStringSubmatch(line); len(m) == 2 {
|
|
if pri, err := strconv.Atoi(m[1]); err == nil {
|
|
p.Priority = pri
|
|
}
|
|
rest = line[len(m[0]):]
|
|
}
|
|
rest = strings.TrimSpace(rest)
|
|
fields := strings.SplitN(rest, " ", 6)
|
|
if len(fields) >= 2 && len(fields[0]) == 1 && fields[0][0] >= '1' && fields[0][0] <= '9' {
|
|
if len(fields) >= 4 {
|
|
p.Hostname = fields[2]
|
|
if len(fields) >= 6 {
|
|
p.Message = fields[5]
|
|
} else if len(fields) == 5 {
|
|
p.Message = fields[4]
|
|
}
|
|
}
|
|
return p
|
|
}
|
|
tokens := strings.SplitN(rest, " ", 3)
|
|
if len(tokens) >= 2 {
|
|
if len(tokens) >= 3 && isMonthAbbr(tokens[0]) {
|
|
p.Hostname = tokens[2]
|
|
if idx := strings.Index(rest, ": "); idx > 0 {
|
|
p.Message = strings.TrimSpace(rest[idx+2:])
|
|
}
|
|
} else {
|
|
p.Hostname = tokens[1]
|
|
if len(tokens) >= 3 {
|
|
tagMsg := tokens[2]
|
|
if idx := strings.Index(tagMsg, ": "); idx > 0 {
|
|
p.Tag = tagMsg[:idx]
|
|
p.Message = strings.TrimSpace(tagMsg[idx+2:])
|
|
} else {
|
|
p.Message = tagMsg
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return p
|
|
}
|
|
|
|
func isMonthAbbr(s string) bool {
|
|
if len(s) < 3 {
|
|
return false
|
|
}
|
|
mons := []string{"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}
|
|
for _, m := range mons {
|
|
if strings.HasPrefix(s, m) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func syslogPriorityToSeverity(pri int) string {
|
|
sev := pri % 8
|
|
switch sev {
|
|
case 0, 1, 2:
|
|
return "critical"
|
|
case 3:
|
|
return "major"
|
|
case 4:
|
|
return "warning"
|
|
default:
|
|
return "info"
|
|
}
|
|
}
|
|
|
|
func formatSyslogSummary(p ParsedSyslog) string {
|
|
host := p.Hostname
|
|
if host == "" {
|
|
host = "unknown-host"
|
|
}
|
|
return fmt.Sprintf("%s: %s", host, truncate(p.Message, 512))
|
|
}
|
|
|
|
func truncate(s string, n int) string {
|
|
if len(s) <= n {
|
|
return s
|
|
}
|
|
return s[:n] + "..."
|
|
}
|