Skip to content

Commit ceadf34

Browse files
author
Matthew Fisher
committed
ref(logger): leave incoming messages unparsed
1 parent 2cdf3ee commit ceadf34

7 files changed

Lines changed: 32 additions & 207 deletions

File tree

logger/syslog/filehandler.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ type FileHandler struct {
1919

2020
// NewFileHandler accepts all arguments expected by NewBaseHandler plus
2121
// filename which is the path to the log file.
22-
func NewFileHandler(filename string, qlen int, filter func(*Message) bool,
22+
func NewFileHandler(filename string, qlen int, filter func(SyslogMessage) bool,
2323
ft bool) *FileHandler {
2424

2525
h := &FileHandler{
@@ -61,7 +61,7 @@ func (h *FileHandler) mainLoop() {
6161
}
6262
}
6363

64-
func (h *FileHandler) saveMessage(m *Message) {
64+
func (h *FileHandler) saveMessage(m SyslogMessage) {
6565
var err error
6666
if h.f == nil {
6767
h.f, err = os.OpenFile(
@@ -90,6 +90,6 @@ func (h *FileHandler) checkErr(err error) bool {
9090
}
9191

9292
// Handle queues and dispatches a message. See BaseHandler.Handle
93-
func (h *FileHandler) Handle(m *Message) *Message {
93+
func (h *FileHandler) Handle(m SyslogMessage) SyslogMessage {
9494
return h.bh.Handle(m)
9595
}

logger/syslog/filehandler_test.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package syslog
22

33
import (
44
"testing"
5-
"time"
65
)
76

87
type TestLogger struct{}
@@ -12,24 +11,24 @@ func (tl TestLogger) Printf(format string, v ...interface{}) {}
1211
func (tl TestLogger) Println(...interface{}) {}
1312

1413
func TestNewFileHandler(t *testing.T) {
15-
fh := NewFileHandler("", 1, func(m *Message) bool { return true }, true)
14+
fh := NewFileHandler("", 1, func(m SyslogMessage) bool { return true }, true)
1615
if fh == nil {
1716
t.Errorf("expected filehandler, got nil")
1817
}
1918
}
2019

2120
func TestSetLogger(t *testing.T) {
2221
tl := TestLogger{}
23-
fh := NewFileHandler("", 1, func(m *Message) bool { return true }, true)
22+
fh := NewFileHandler("", 1, func(m SyslogMessage) bool { return true }, true)
2423
fh.SetLogger(tl)
2524
if fh.l != tl {
2625
t.Errorf("expected the logger to be set")
2726
}
2827
}
2928

3029
func TestHandle(t *testing.T) {
31-
fh := NewFileHandler("/tmp/test", 1, func(m *Message) bool { return true }, true)
32-
handle := fh.Handle(&Message{time.Now(), nil, 0, 0, time.Now(), "localhost", "test", "message", "", ""})
30+
fh := NewFileHandler("/tmp/test", 1, func(m SyslogMessage) bool { return true }, true)
31+
handle := fh.Handle(&Message{"localhost test message"})
3332
if handle == nil {
3433
t.Errorf("expected a handle, got nil")
3534
}

logger/syslog/handler.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,26 +5,26 @@ type Handler interface {
55
// Handle should return Message (maybe modified) for future processing by
66
// other handlers or return nil. If Handle is called with nil message it
77
// should complete all remaining work and properly shutdown before return.
8-
Handle(*Message) *Message
8+
Handle(SyslogMessage) SyslogMessage
99
}
1010

1111
// BaseHandler is designed to simplify the creation of real handlers. It
1212
// implements Handler interface using nonblocking queuing of messages and
1313
// simple message filtering.
1414
type BaseHandler struct {
15-
queue chan *Message
15+
queue chan SyslogMessage
1616
end chan struct{}
17-
filter func(*Message) bool
17+
filter func(SyslogMessage) bool
1818
ft bool
1919
}
2020

2121
// NewBaseHandler creates BaseHandler using a specified filter. If filter is nil
2222
// or if it returns true messages are passed to BaseHandler internal queue
2323
// (of qlen length). If filter returns false or ft is true messages are returned
2424
// to server for future processing by other handlers.
25-
func NewBaseHandler(qlen int, filter func(*Message) bool, ft bool) *BaseHandler {
25+
func NewBaseHandler(qlen int, filter func(SyslogMessage) bool, ft bool) *BaseHandler {
2626
return &BaseHandler{
27-
queue: make(chan *Message, qlen),
27+
queue: make(chan SyslogMessage, qlen),
2828
end: make(chan struct{}),
2929
filter: filter,
3030
ft: ft,
@@ -34,7 +34,7 @@ func NewBaseHandler(qlen int, filter func(*Message) bool, ft bool) *BaseHandler
3434
// Handle inserts m in an internal queue. It immediately returns even if
3535
// queue is full. If m == nil it closes queue and waits for End method call
3636
// before return.
37-
func (h *BaseHandler) Handle(m *Message) *Message {
37+
func (h *BaseHandler) Handle(m SyslogMessage) SyslogMessage {
3838
if m == nil {
3939
close(h.queue) // signal that there is no more messages for processing
4040
<-h.end // wait for handler shutdown
@@ -58,7 +58,7 @@ func (h *BaseHandler) Handle(m *Message) *Message {
5858
// Get returns first message from internal queue. It waits for message if queue
5959
// is empty. It returns nil if there is no more messages to process and handler
6060
// should shutdown.
61-
func (h *BaseHandler) Get() *Message {
61+
func (h *BaseHandler) Get() SyslogMessage {
6262
m, ok := <-h.queue
6363
if ok {
6464
return m
@@ -70,7 +70,7 @@ func (h *BaseHandler) Get() *Message {
7070
// it directly, especially if your handler needs to select from multiple channels
7171
// or have to work without blocking. You need to check if this channel is closed by
7272
// sender and properly shutdown in this case.
73-
func (h *BaseHandler) Queue() <-chan *Message {
73+
func (h *BaseHandler) Queue() <-chan SyslogMessage {
7474
return h.queue
7575
}
7676

logger/syslog/message.go

Lines changed: 7 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,16 @@
11
package syslog
22

3-
import (
4-
"fmt"
5-
"net"
6-
"time"
7-
)
3+
import "fmt"
84

9-
// Message defines an RFC 3164 syslog message.
10-
type Message struct {
11-
Time time.Time // time the message was logged
12-
Source net.Addr // source address of the log message
13-
Facility // facility tag (see type Facility)
14-
Severity // severity tag (see type Severity)
15-
Timestamp time.Time // optional
16-
Hostname string // optional
17-
Tag string // message tag as defined in RFC 3164
18-
Content string // message content as defined in RFC 3164
19-
Tag1 string // alternate message tag (white rune as separator)
20-
Content1 string // alternate message content (white rune as separator)
5+
type SyslogMessage interface {
6+
fmt.Stringer
217
}
228

23-
// NetSrc only network part of Source as string (IP for UDP or Name for UDS)
24-
func (m *Message) NetSrc() string {
25-
switch a := m.Source.(type) {
26-
case *net.UDPAddr:
27-
return a.IP.String()
28-
case *net.UnixAddr:
29-
return a.Name
30-
case *net.TCPAddr:
31-
return a.IP.String()
32-
}
33-
// Unknown type
34-
return m.Source.String()
9+
// Message defines a syslog message.
10+
type Message struct {
11+
Msg string
3512
}
3613

37-
// String returns the Message in a string format. This satisfies the fmt.Stringer
38-
// interface.
3914
func (m *Message) String() string {
40-
timeLayout := "2006-01-02 15:04:05"
41-
return fmt.Sprintf(
42-
"%s %s %s%s",
43-
m.Time.Format(timeLayout),
44-
m.Hostname,
45-
m.Tag,
46-
m.Content,
47-
)
15+
return m.Msg
4816
}

logger/syslog/message_test.go

Lines changed: 0 additions & 80 deletions
This file was deleted.

logger/syslog/server.go

Lines changed: 4 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,10 @@
33
package syslog
44

55
import (
6-
"bytes"
76
"log"
87
"net"
98
"os"
10-
"strconv"
119
"strings"
12-
"time"
1310
"unicode"
1411
)
1512

@@ -90,7 +87,7 @@ func isNulCrLf(r rune) bool {
9087
return r == 0 || r == '\r' || r == '\n'
9188
}
9289

93-
func (s *Server) passToHandlers(m *Message) {
90+
func (s *Server) passToHandlers(m SyslogMessage) {
9491
for _, h := range s.handlers {
9592
m = h.Handle(m)
9693
if m == nil {
@@ -103,72 +100,14 @@ func (s *Server) receiver(c net.PacketConn) {
103100
//q := (chan<- Message)(s.q)
104101
buf := make([]byte, 1024)
105102
for {
106-
n, addr, err := c.ReadFrom(buf)
103+
n, _, err := c.ReadFrom(buf)
107104
if err != nil {
108105
if !s.shutdown {
109106
s.l.Fatalln("Read error:", err)
110107
}
111108
return
112109
}
113-
pkt := buf[:n]
114-
115-
m := new(Message)
116-
m.Source = addr
117-
m.Time = time.Now()
118-
119-
// Parse priority (if exists)
120-
prio := 13 // default priority
121-
hasPrio := false
122-
if pkt[0] == '<' {
123-
n = 1 + bytes.IndexByte(pkt[1:], '>')
124-
if n > 1 && n < 5 {
125-
p, err := strconv.Atoi(string(pkt[1:n]))
126-
if err == nil && p >= 0 {
127-
hasPrio = true
128-
prio = p
129-
pkt = pkt[n+1:]
130-
}
131-
}
132-
}
133-
m.Severity = Severity(prio & 0x07)
134-
m.Facility = Facility(prio >> 3)
135-
136-
// Parse header (if exists)
137-
if hasPrio && len(pkt) >= 16 && pkt[15] == ' ' {
138-
// Get timestamp
139-
layout := "Jan _2 15:04:05"
140-
ts, err := time.Parse(layout, string(pkt[:15]))
141-
if err == nil && !ts.IsZero() {
142-
// Get hostname
143-
n = 16 + bytes.IndexByte(pkt[16:], ' ')
144-
if n != 15 {
145-
m.Timestamp = ts
146-
m.Hostname = string(pkt[16:n])
147-
pkt = pkt[n+1:]
148-
}
149-
}
150-
// TODO: check for version an new format of header as
151-
// described in RFC 5424.
152-
}
153-
154-
// Parse msg part
155-
msg := string(bytes.TrimRightFunc(pkt, isNulCrLf))
156-
n = strings.IndexFunc(msg, isNotAlnum)
157-
if n != -1 {
158-
m.Tag = msg[:n]
159-
m.Content = msg[n:]
160-
} else {
161-
m.Content = msg
162-
}
163-
msg = strings.TrimFunc(msg, unicode.IsSpace)
164-
n = strings.IndexFunc(msg, unicode.IsSpace)
165-
if n != -1 {
166-
m.Tag1 = msg[:n]
167-
m.Content1 = strings.TrimLeftFunc(msg[n+1:], unicode.IsSpace)
168-
} else {
169-
m.Content1 = msg
170-
}
171-
172-
s.passToHandlers(m)
110+
// pass along the incoming syslog message
111+
s.passToHandlers(&Message{string(buf[:n])})
173112
}
174113
}

logger/syslogd/syslogd.go

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@ type handler struct {
2222
}
2323

2424
// Simple fiter for named/bind messages which can be used with BaseHandler
25-
func filter(m *syslog.Message) bool {
26-
// return m.Tag == "named" || m.Tag == "bind"
25+
func filter(m syslog.SyslogMessage) bool {
2726
return true
2827
}
2928

@@ -45,11 +44,11 @@ func fileExists(path string) (bool, error) {
4544
return false, err
4645
}
4746

48-
func getLogFile(m *syslog.Message) (io.Writer, error) {
47+
func getLogFile(message string) (io.Writer, error) {
4948
r := regexp.MustCompile(`^.* ([-a-z0-9]+)\[[a-z0-9-_\.]+\].*`)
50-
match := r.FindStringSubmatch(m.String())
49+
match := r.FindStringSubmatch(message)
5150
if match == nil {
52-
return nil, fmt.Errorf("Could not find app name in message: %s", m)
51+
return nil, fmt.Errorf("Could not find app name in message: %s", message)
5352
}
5453
appName := match[1]
5554
filePath := path.Join(logRoot, appName+".log")
@@ -68,8 +67,8 @@ func getLogFile(m *syslog.Message) (io.Writer, error) {
6867
return file, err
6968
}
7069

71-
func writeToDisk(m *syslog.Message) error {
72-
file, err := getLogFile(m)
70+
func writeToDisk(m syslog.SyslogMessage) error {
71+
file, err := getLogFile(m.String())
7372
if err != nil {
7473
return err
7574
}

0 commit comments

Comments
 (0)