Skip to content

Commit 61a9913

Browse files
Merge pull request #473 from gliderlabs/master
release 3.2.10
2 parents 67fdc40 + 46cbf90 commit 61a9913

File tree

4 files changed

+117
-3
lines changed

4 files changed

+117
-3
lines changed

CHANGELOG.md

+9-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@ All notable changes to this project will be documented in this file.
1010

1111
### Changed
1212

13+
## [v3.2.10] - 2020-05-1
14+
### Added
15+
- @jszwedko Add optional TCP framing to syslog adapter
16+
17+
### Fixed
18+
- @bbigras add missing syntax highlighting in README.md
19+
1320
## [v3.2.9] - 2020-04-30
1421
### Fixed
1522
- @bbigras add missing syntax highlighting in README.md
@@ -227,7 +234,8 @@ All notable changes to this project will be documented in this file.
227234
- Base container is now Alpine
228235
- Moved to gliderlabs organization
229236

230-
[unreleased]: https://github.com/gliderlabs/logspout/compare/v3.2.9...HEAD
237+
[unreleased]: https://github.com/gliderlabs/logspout/compare/v3.2.10...HEAD
238+
[v3.2.10]: https://github.com/gliderlabs/logspout/compare/v3.2.9...v3.2.10
231239
[v3.2.9]: https://github.com/gliderlabs/logspout/compare/v3.2.8...v3.2.9
232240
[v3.2.8]: https://github.com/gliderlabs/logspout/compare/v3.2.7...v3.2.8
233241
[v3.2.7]: https://github.com/gliderlabs/logspout/compare/v3.2.6...v3.2.7

VERSION

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
v3.2.9
1+
v3.2.10

adapters/syslog/syslog.go

+56-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package syslog
22

33
import (
44
"bytes"
5+
"crypto/tls"
56
"errors"
67
"fmt"
78
"io/ioutil"
@@ -19,14 +20,25 @@ import (
1920
"github.com/gliderlabs/logspout/router"
2021
)
2122

22-
const defaultRetryCount = 10
23+
const (
24+
// TraditionalTCPFraming is the traditional LF framing of syslog messages on the wire
25+
TraditionalTCPFraming TCPFraming = "traditional"
26+
// OctetCountedTCPFraming prepends the size of each message before the message. https://tools.ietf.org/html/rfc6587#section-3.4.1
27+
OctetCountedTCPFraming TCPFraming = "octet-counted"
28+
29+
defaultRetryCount = 10
30+
)
2331

2432
var (
2533
hostname string
2634
retryCount uint
35+
tcpFraming TCPFraming
2736
econnResetErrStr string
2837
)
2938

39+
// TCPFraming represents the type of framing to use for syslog messages
40+
type TCPFraming string
41+
3042
func init() {
3143
hostname, _ = os.Hostname()
3244
econnResetErrStr = fmt.Sprintf("write: %s", syscall.ECONNRESET.Error())
@@ -89,6 +101,12 @@ func NewSyslogAdapter(route *router.Route) (router.LogAdapter, error) {
89101
structuredData = fmt.Sprintf("[%s]", structuredData)
90102
}
91103

104+
if isTCPConnecion(conn) {
105+
if err = setTCPFraming(); err != nil {
106+
return nil, err
107+
}
108+
}
109+
92110
var tmplStr string
93111
switch format {
94112
case "rfc5424":
@@ -120,6 +138,19 @@ func NewSyslogAdapter(route *router.Route) (router.LogAdapter, error) {
120138
}, nil
121139
}
122140

141+
func setTCPFraming() error {
142+
switch s := cfg.GetEnvDefault("SYSLOG_TCP_FRAMING", "traditional"); s {
143+
case "traditional":
144+
tcpFraming = TraditionalTCPFraming
145+
return nil
146+
case "octet-counted":
147+
tcpFraming = OctetCountedTCPFraming
148+
return nil
149+
default:
150+
return fmt.Errorf("unknown SYSLOG_TCP_FRAMING value: %s", s)
151+
}
152+
}
153+
123154
// Adapter streams log output to a connection in the Syslog format
124155
type Adapter struct {
125156
conn net.Conn
@@ -137,6 +168,19 @@ func (a *Adapter) Stream(logstream chan *router.Message) {
137168
log.Println("syslog:", err)
138169
return
139170
}
171+
172+
if isTCPConnecion(a.conn) {
173+
switch tcpFraming {
174+
case OctetCountedTCPFraming:
175+
buf = append([]byte(fmt.Sprintf("%d ", len(buf))), buf...)
176+
case TraditionalTCPFraming:
177+
// leave as-is
178+
default:
179+
// should never get here, validated above
180+
panic("unknown framing format: " + tcpFraming)
181+
}
182+
}
183+
140184
if _, err = a.conn.Write(buf); err != nil {
141185
log.Println("syslog:", err)
142186
switch a.conn.(type) {
@@ -226,6 +270,17 @@ func retryExp(fun func() error, tries uint) error {
226270
}
227271
}
228272

273+
func isTCPConnecion(conn net.Conn) bool {
274+
switch conn.(type) {
275+
case *net.TCPConn:
276+
return true
277+
case *tls.Conn:
278+
return true
279+
default:
280+
return false
281+
}
282+
}
283+
229284
// Message extends router.Message for the syslog standard
230285
type Message struct {
231286
*router.Message

adapters/syslog/syslog_test.go

+51
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package syslog
22

33
import (
44
"bufio"
5+
"fmt"
56
"io"
67
"io/ioutil"
78
"log"
@@ -40,6 +41,56 @@ var (
4041
badHostnameContent = "hostname\r\n"
4142
)
4243

44+
func TestSyslogOctetFraming(t *testing.T) {
45+
os.Setenv("SYSLOG_TCP_FRAMING", "octet-counted")
46+
defer os.Unsetenv("SYSLOG_TCP_FRAMING")
47+
48+
done := make(chan string)
49+
addr, sock, srvWG := startServer("tcp", "", done)
50+
defer srvWG.Wait()
51+
defer os.Remove(addr)
52+
defer sock.Close()
53+
54+
route := &router.Route{Adapter: "syslog+tcp", Address: addr}
55+
adapter, err := NewSyslogAdapter(route)
56+
if err != nil {
57+
t.Fatal(err)
58+
}
59+
defer adapter.(*Adapter).conn.Close()
60+
61+
stream := make(chan *router.Message)
62+
go adapter.Stream(stream)
63+
64+
count := 1
65+
messages := make(chan string, count)
66+
go sendLogstream(stream, messages, adapter, count)
67+
68+
timeout := time.After(6 * time.Second)
69+
msgnum := 1
70+
select {
71+
case msg := <-done:
72+
sizeStr := ""
73+
_, err := fmt.Sscan(msg, &sizeStr)
74+
if err != nil {
75+
t.Fatal("unable to scan size from message: ", err)
76+
}
77+
78+
size, err := strconv.ParseInt(sizeStr, 10, 32)
79+
if err != nil {
80+
t.Fatal("unable to scan size from message: ", err)
81+
}
82+
83+
expectedOctetFrame := len(sizeStr) + 1 + int(size)
84+
if len(msg) != expectedOctetFrame {
85+
t.Errorf("expected octet frame to be %d. got %d instead for message %s", expectedOctetFrame, size, msg)
86+
}
87+
return
88+
case <-timeout:
89+
t.Fatal("timeout after", msgnum, "messages")
90+
return
91+
}
92+
}
93+
4394
func TestSyslogRetryCount(t *testing.T) {
4495
newRetryCount := uint(20)
4596
os.Setenv("RETRY_COUNT", strconv.Itoa(int(newRetryCount)))

0 commit comments

Comments
 (0)